Annotation of src/usr.bin/mg/mail.c, Revision 1.4
1.4 ! vincent 1: /* $OpenBSD: mail.c,v 1.3 2004/01/27 23:43:37 vincent 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: {
51: { ' ', '~', mail_fake, NULL },
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.4 ! vincent 63: if ((rep = ereply("Margin: ", buf, sizeof(buf))) == NULL)
! 64: return ABORT;
! 65: else if (*rep == '\0')
! 66: return FALSE;
! 67: limit = atoi(rep);
1.3 vincent 68: }
69: return TRUE;
70: }
71:
1.1 vincent 72: void
73: mail_init(void)
74: {
75: funmap_add(mail, "mail-mode");
1.3 vincent 76: funmap_add(mail_set_limit, "mail-set-margin");
1.1 vincent 77: maps_add((KEYMAP *)&mailmap, "mail-mode");
78: }
79:
80: static int
81: mail(int f, int n)
82: {
83: curbp->b_modes[0] = name_mode("fundamental");
84: curbp->b_modes[1] = name_mode("mail-mode");
85: if (curbp->b_modes[1] == NULL) {
86: panic("can't happen");
87: mail_init();
88: curbp->b_modes[1] = name_mode("mail-mode");
89: }
90: curbp->b_nmodes = 1;
1.2 vincent 91: curwp->w_flag |= WFMODE;
1.1 vincent 92: return (TRUE);
93: }
94:
95: static int
96: fake_self_insert(int f, int n)
97: {
1.3 vincent 98: int len = llength(curwp->w_dotp), col;
1.1 vincent 99:
1.3 vincent 100: if (len + 1 > limit) {
1.1 vincent 101: /*
1.3 vincent 102: * find the column at which we should cut, taking
103: * word boundaries into account
1.1 vincent 104: */
1.3 vincent 105: for (col = limit; col > 0; col--)
106: if (isspace(curwp->w_dotp->l_text[col])) {
107: col++; /* XXX - skip the space */
108: break;
109: }
110:
111: if (curbp->b_doto == len) {
112: /*
113: * user is appending to the line; simple case.
114: */
115: if (col) {
116: curwp->w_doto = col;
117: lnewline();
118: gotoeol(0, 1);
119: }
120: curwp->w_wrapline = NULL;
121: } else if ((len - col) > 0) {
122: /*
123: * user is shifting words by inserting in the middle.
124: */
125: const char *trail;
126: int save_doto = curwp->w_doto;
127: LINE *save_dotp = curwp->w_dotp;
128: int tlen = len - col;
129:
130: trail = curwp->w_dotp->l_text + col;
131:
132: /*
133: * Create a new line or reuse the last wrapping line
134: * unless we could fill it.
135: */
136: if (curwp->w_wrapline != lforw(curwp->w_dotp) ||
137: llength(curwp->w_wrapline) + tlen >= limit) {
138: curwp->w_doto = col;
139: lnewline();
140: curwp->w_wrapline = curwp->w_dotp;
141: curwp->w_dotp = save_dotp;
142: } else {
143: curwp->w_dotp = curwp->w_wrapline;
144: curwp->w_doto = 0;
145:
146: /* insert trail */
147: linsert_str(trail, tlen);
148:
149: /* delete trail */
150: curwp->w_dotp = save_dotp;
151: curwp->w_doto = col;
152: ldelete(tlen, KNONE); /* don't store in kill ring */
153: }
154:
155: /*
156: * readjust dot to point at where the user expects
157: * it to be after an insertion.
158: */
159: curwp->w_doto = save_doto;
160: if (curwp->w_doto >= col) {
161: curwp->w_dotp = curwp->w_wrapline;
162: curwp->w_doto -= col;
163: }
164: }
1.1 vincent 165: }
166: selfinsert(f, n);
167: return (TRUE);
168: }