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