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: }