[BACK]Return to mail.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

File: [local] / src / usr.bin / mg / Attic / mail.c (download)

Revision 1.9, Fri Nov 18 20:56:53 2005 UTC (18 years, 6 months ago) by deraadt
Branch: MAIN
CVS Tags: OPENBSD_4_3_BASE, OPENBSD_4_3, OPENBSD_4_2_BASE, OPENBSD_4_2, OPENBSD_4_1_BASE, OPENBSD_4_1, OPENBSD_4_0_BASE, OPENBSD_4_0, OPENBSD_3_9_BASE, OPENBSD_3_9
Changes since 1.8: +2 -2 lines

greedy use of typedef struct was making code harder to read; ok kjell cloder

/* $OpenBSD: mail.c,v 1.9 2005/11/18 20:56:53 deraadt Exp $ */
/*
 * This file is in the public domain.
 *
 * Author: Vincent Labrecque, April 2003
 */
#include <ctype.h>

#include "def.h"
#include "kbd.h"
#include "funmap.h"

void		 mail_init(void);
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 = eread("Margin: ", buf, sizeof(buf),
		    EFNEW | EFCR)) == NULL)
			return (ABORT);
		else if (rep[0] == '\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");
}

/* ARGSUSED */
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;
			struct 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);
}