[BACK]Return to mail.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/mail.c, Revision 1.6

1.6     ! kjell       1: /* $OpenBSD: mail.c,v 1.5 2005/04/03 02:09:28 db Exp $ */
1.1       vincent     2: /*
                      3:  * This file is in the public domain.
                      4:  *
                      5:  * Author: Vincent Labrecque, April 2003
                      6:  */
                      7: #include <ctype.h>
                      8:
                      9: #include "def.h"
                     10: #include "kbd.h"
                     11: #include "funmap.h"
                     12:
                     13: static int      fake_self_insert(int, int);
                     14: static int      mail(int, int);
                     15:
1.3       vincent    16: int limit = 72;
                     17:
1.1       vincent    18: /* mappings for all "printable" characters ('-' -> '~') */
                     19: static PF mail_fake[] = {
                     20:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     21:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     22:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     23:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     24:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     25:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     26:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     27:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     28:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     29:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     30:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     31:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     32:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     33:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     34:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     35:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     36:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     37:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     38:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     39:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     40:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     41:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
                     42:        fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert,
1.3       vincent    43:        fake_self_insert, fake_self_insert, fake_self_insert
1.1       vincent    44: };
                     45:
                     46: static struct KEYMAPE (1 + IMAPEXT) mailmap = {
                     47:        1,
                     48:        1 + IMAPEXT,
                     49:        rescan,
                     50:        {
1.5       db         51:                { ' ', '~', mail_fake, NULL }
1.1       vincent    52:        }
                     53: };
                     54:
1.3       vincent    55: int
                     56: mail_set_limit(int f, int n)
                     57: {
1.4       vincent    58:        char buf[32], *rep;
1.3       vincent    59:
                     60:        if ((f & FFARG) != 0) {
                     61:                limit = n;
                     62:        } else {
1.6     ! kjell      63:                if ((rep = eread("Margin: ", buf, sizeof(buf),
        !            64:                    EFNEW | EFCR)) == NULL)
1.5       db         65:                        return (ABORT);
1.6     ! kjell      66:                else if (rep[0] == '\0')
1.5       db         67:                        return (FALSE);
1.4       vincent    68:                limit = atoi(rep);
1.3       vincent    69:        }
1.5       db         70:        return (TRUE);
1.3       vincent    71: }
                     72:
1.1       vincent    73: void
                     74: mail_init(void)
                     75: {
                     76:        funmap_add(mail, "mail-mode");
1.3       vincent    77:        funmap_add(mail_set_limit, "mail-set-margin");
1.1       vincent    78:        maps_add((KEYMAP *)&mailmap, "mail-mode");
                     79: }
                     80:
                     81: static int
                     82: mail(int f, int n)
                     83: {
                     84:        curbp->b_modes[0] = name_mode("fundamental");
                     85:        curbp->b_modes[1] = name_mode("mail-mode");
                     86:        if (curbp->b_modes[1] == NULL) {
                     87:                panic("can't happen");
                     88:                mail_init();
                     89:                curbp->b_modes[1] = name_mode("mail-mode");
                     90:        }
                     91:        curbp->b_nmodes = 1;
1.2       vincent    92:        curwp->w_flag |= WFMODE;
1.1       vincent    93:        return (TRUE);
                     94: }
                     95:
                     96: static int
                     97: fake_self_insert(int f, int n)
                     98: {
1.3       vincent    99:        int len = llength(curwp->w_dotp), col;
1.1       vincent   100:
1.3       vincent   101:        if (len + 1 > limit) {
1.1       vincent   102:                /*
1.5       db        103:                 * Find the column at which we should cut, taking
                    104:                 * word boundaries into account.
1.1       vincent   105:                 */
1.3       vincent   106:                for (col = limit; col > 0; col--)
                    107:                        if (isspace(curwp->w_dotp->l_text[col])) {
                    108:                                col++;  /* XXX - skip the space */
                    109:                                break;
                    110:                        }
                    111:
                    112:                if (curbp->b_doto == len) {
                    113:                        /*
1.5       db        114:                         * User is appending to the line; simple case.
1.3       vincent   115:                         */
                    116:                        if (col) {
                    117:                                curwp->w_doto = col;
                    118:                                lnewline();
                    119:                                gotoeol(0, 1);
                    120:                        }
                    121:                        curwp->w_wrapline = NULL;
                    122:                } else if ((len - col) > 0) {
                    123:                        /*
1.5       db        124:                         * User is shifting words by inserting in the middle.
1.3       vincent   125:                         */
                    126:                        const char *trail;
                    127:                        int save_doto = curwp->w_doto;
                    128:                        LINE *save_dotp = curwp->w_dotp;
                    129:                        int tlen = len - col;
                    130:
                    131:                        trail = curwp->w_dotp->l_text + col;
                    132:
                    133:                        /*
                    134:                         * Create a new line or reuse the last wrapping line
                    135:                         * unless we could fill it.
                    136:                         */
                    137:                        if (curwp->w_wrapline != lforw(curwp->w_dotp) ||
                    138:                            llength(curwp->w_wrapline) + tlen >= limit) {
                    139:                                curwp->w_doto = col;
                    140:                                lnewline();
                    141:                                curwp->w_wrapline = curwp->w_dotp;
                    142:                                curwp->w_dotp = save_dotp;
                    143:                        } else {
                    144:                                curwp->w_dotp = curwp->w_wrapline;
                    145:                                curwp->w_doto = 0;
                    146:
                    147:                                /* insert trail */
                    148:                                linsert_str(trail, tlen);
                    149:
                    150:                                /* delete trail */
                    151:                                curwp->w_dotp = save_dotp;
                    152:                                curwp->w_doto = col;
                    153:                                ldelete(tlen, KNONE);   /* don't store in kill ring */
                    154:                        }
                    155:
                    156:                        /*
1.5       db        157:                         * Readjust dot to point at where the user expects
1.3       vincent   158:                         * it to be after an insertion.
                    159:                         */
                    160:                        curwp->w_doto = save_doto;
                    161:                        if (curwp->w_doto >= col) {
                    162:                                curwp->w_dotp = curwp->w_wrapline;
                    163:                                curwp->w_doto -= col;
                    164:                        }
                    165:                }
1.1       vincent   166:        }
                    167:        selfinsert(f, n);
                    168:        return (TRUE);
                    169: }