[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.9

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