/* $OpenBSD: mail.c,v 1.4 2004/07/22 01:25:25 vincent Exp $ */ /* * This file is in the public domain. * * Author: Vincent Labrecque, April 2003 */ #include #include "def.h" #include "kbd.h" #include "funmap.h" static int fake_self_insert(int, int); static int mail(int, int); int limit = 72; /* mappings for all "printable" characters ('-' -> '~') */ static PF mail_fake[] = { fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert, fake_self_insert }; static struct KEYMAPE (1 + IMAPEXT) mailmap = { 1, 1 + IMAPEXT, rescan, { { ' ', '~', mail_fake, NULL }, } }; int mail_set_limit(int f, int n) { char buf[32], *rep; if ((f & FFARG) != 0) { limit = n; } else { if ((rep = ereply("Margin: ", buf, sizeof(buf))) == NULL) return ABORT; else if (*rep == '\0') return FALSE; limit = atoi(rep); } return TRUE; } void mail_init(void) { funmap_add(mail, "mail-mode"); funmap_add(mail_set_limit, "mail-set-margin"); maps_add((KEYMAP *)&mailmap, "mail-mode"); } static int mail(int f, int n) { curbp->b_modes[0] = name_mode("fundamental"); curbp->b_modes[1] = name_mode("mail-mode"); if (curbp->b_modes[1] == NULL) { panic("can't happen"); mail_init(); curbp->b_modes[1] = name_mode("mail-mode"); } curbp->b_nmodes = 1; curwp->w_flag |= WFMODE; return (TRUE); } static int fake_self_insert(int f, int n) { int len = llength(curwp->w_dotp), col; if (len + 1 > limit) { /* * find the column at which we should cut, taking * word boundaries into account */ for (col = limit; col > 0; col--) if (isspace(curwp->w_dotp->l_text[col])) { col++; /* XXX - skip the space */ break; } if (curbp->b_doto == len) { /* * user is appending to the line; simple case. */ if (col) { curwp->w_doto = col; lnewline(); gotoeol(0, 1); } curwp->w_wrapline = NULL; } else if ((len - col) > 0) { /* * user is shifting words by inserting in the middle. */ const char *trail; int save_doto = curwp->w_doto; LINE *save_dotp = curwp->w_dotp; int tlen = len - col; trail = curwp->w_dotp->l_text + col; /* * Create a new line or reuse the last wrapping line * unless we could fill it. */ if (curwp->w_wrapline != lforw(curwp->w_dotp) || llength(curwp->w_wrapline) + tlen >= limit) { curwp->w_doto = col; lnewline(); curwp->w_wrapline = curwp->w_dotp; curwp->w_dotp = save_dotp; } else { curwp->w_dotp = curwp->w_wrapline; curwp->w_doto = 0; /* insert trail */ linsert_str(trail, tlen); /* delete trail */ curwp->w_dotp = save_dotp; curwp->w_doto = col; ldelete(tlen, KNONE); /* don't store in kill ring */ } /* * readjust dot to point at where the user expects * it to be after an insertion. */ curwp->w_doto = save_doto; if (curwp->w_doto >= col) { curwp->w_dotp = curwp->w_wrapline; curwp->w_doto -= col; } } } selfinsert(f, n); return (TRUE); }