home *** CD-ROM | disk | FTP | other *** search
- /*
- * Program: Main Pine Composer routines
- *
- * Modifier: Michael Seibel
- * Networks and Distributed Computing
- * Computing & Communications
- * University of Washington
- * Administration Building, AG-44
- * Seattle, WA 98195
- * Internet: mikes@cac.washington.edu
- *
- * Date: Nov 1989
- * Last Edited: 9 September 1991
- *
- * Copyright 1991 by the University of Washington
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appears in all copies and that both the
- * above copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington not be
- * used in advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. This software is made
- * available "as is", and
- * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
- * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
- * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
- * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- *
- * WEEMACS/PICO NOTES:
- *
- * 01 Nov 89 - MicroEmacs 3.6 vastly pared down and becomes a function call
- * weemacs() and plugged into the Pine mailer. Lots of unused
- * MicroEmacs code laying around.
- *
- * 17 Jan 90 - weemacs() became weemacs() the composer. Header editing
- * functions added.
- *
- * 09 Sep 91 - weemacs() renamed pico() for the PIne COmposer.
- *
- */
-
-
- /*
- * This program is in public domain; written by Dave G. Conroy.
- * This file contains the main driving routine, and some keyboard processing
- * code, for the MicroEMACS screen editor.
- *
- * REVISION HISTORY:
- *
- * 1.0 Steve Wilhite, 30-Nov-85
- * - Removed the old LK201 and VT100 logic. Added code to support the
- * DEC Rainbow keyboard (which is a LK201 layout) using the the Level
- * 1 Console In ROM INT. See "rainbow.h" for the function key defs
- * Steve Wilhite, 1-Dec-85
- * - massive cleanup on code in display.c and search.c
- *
- * 2.0 George Jones, 12-Dec-85
- * - Ported to Amiga.
- *
- * 3.0 Daniel Lawrence, 29-Dec-85
- * 16-apr-86
- * - updated documentation and froze development for 3.6 net release
- */
-
- #include <stdio.h>
- #include <setjmp.h>
-
- /* make global definitions not external */
- #define maindef
-
- #include "osdep.h" /* operating system dependent includes */
- #include "estruct.h" /* global structures and defines */
- #include "efunc.h" /* function declarations and name table */
- #include "pico.h" /* PIne COmposer definitions */
- #include "edef.h" /* global definitions */
- #include "ebind.h" /* default key bindings */
-
-
- /*
- * function key mappings
- */
- static int pfkm[12][2] = {
- { F1, (CTRL|'G')},
- { F2, (CTRL|'X')},
- { F3, (CTRL|'C')},
- { F4, (CTRL|'J')},
- { F5, (CTRL|'R')},
- { F6, (CTRL|'W')},
- { F7, (CTRL|'Y')},
- { F8, (CTRL|'V')},
- { F9, (CTRL|'K')},
- { F10, (CTRL|'U')},
- { F11, (CTRL|'O')},
- #ifdef SPELLER
- { F12, (CTRL|'T')}
- #else
- { F12, (CTRL|'D')}
- #endif
- };
-
-
- /*
- * common place for the various functions in pico() to jump to when ready
- * for pico() to return...
- */
- jmp_buf finstate; /* stack environment to return codes */
-
-
- /*
- * pico - the main routine for Pine's composer.
- *
- */
- pico(pm)
- PICO *pm;
- {
- register int c;
- register int f;
- register int n;
- register BUFFER *bp;
- int i;
- int viewflag = FALSE; /* are we starting in view mode? */
- char bname[NBUFN]; /* buffer name of file to read */
- extern struct on_display ods;
-
- Pmaster = pm;
- gmode |= pm->pine_flags;/* high 4 bits rsv'd by pine composer */
-
- vtinit(); /* Init Displays. */
-
- strcpy(bname, "main"); /* default buffer name */
- edinit(bname); /* Buffers, windows. */
-
- InitMailHeader(pm); /* init mail header structure */
-
- /* setup to process commands */
- lastflag = 0; /* Fake last flags. */
- curbp->b_mode |= gmode; /* and set default modes*/
-
- if(pm->messagebuf[0] != '\0'){ /* any text to start with? */
- readbuf(&pm->messagebuf);
- gotobob(FALSE, 1);
- }
-
- switch(setjmp(finstate)){ /* prepare for/handle final events */
- case COMP_EXIT :
- vttidy(); /* already confirmed */
- packheader();
- return((packbuf(&pm->messagebuf, &pm->messbuflen,
- pm->pine_flags&P_LOCALLF)| COMP_EXIT));
- case COMP_SUSPEND :
- vttidy(); /* suspend it! */
- packheader();
- return((packbuf(&pm->messagebuf, &pm->messbuflen,
- pm->pine_flags&P_LOCALLF)| COMP_SUSPEND));
- case COMP_CANCEL :
- writeout(MAILGRAVE); /* already confirmed */
- vttidy();
- zotedit();
- return(COMP_CANCEL);
-
- case COMP_GOTHUP:
- /*
- * pack up and let caller know that we've received a SIGHUP
- */
- if(ComposerEditing) /* expand addr if needed */
- resolve_niks(ods.cur_e);
- vttidy();
- packheader();
- return((packbuf(&pm->messagebuf, &pm->messbuflen,
- pm->pine_flags&P_LOCALLF)| COMP_GOTHUP));
-
- default:
- break;
- }
-
- if(pm->pine_flags&P_REPLY){ /* begin editing the header? */
- ArrangeHeader(); /* line up pointers */
- }
- else{
- update(); /* paint screen, */
- HeaderEditor(0, 0); /* start editing... */
- }
-
- while(1){
- update(); /* Fix up the screen */
-
- c = GetKey();
-
- if(c == NODATA || time_to_check()){ /* new mail ? */
- if((*Pmaster->newmail)(&i, 0, c == NODATA ? 0 : 2) >= 0){
- mlerase();
- (*Pmaster->showmsg)(c);
- mpresf = 1;
- }
-
- if(i || mpresf) /* let em know cursor moved */
- movecursor(0, 0);
-
- if(c == NODATA) /* no op, getkey timed out */
- continue;
- }
-
- if (mpresf != FALSE) { /* message stay around only */
- if (mpresf++ > MESSDELAY) /* so long! */
- mlerase();
- }
-
- f = FALSE; /* vestigial */
- n = 1;
-
- execute(normal(c, pfkm, 2), f, n); /* Do it. */
- }
- }
-
- /*
- * Initialize all of the buffers and windows. The buffer name is passed down
- * as an argument, because the main routine may have been told to read in a
- * file by default, and we want the buffer name to be right.
- */
-
- /*
- * For the pine composer, we don't want to take over the whole screen
- * for editing. the first some odd lines are to be used for message
- * header information editing.
- */
- edinit(bname)
- char bname[];
- {
- register BUFFER *bp;
- register WINDOW *wp;
-
- if(Pmaster)
- func_init();
-
- bp = bfind(bname, TRUE, 0); /* First buffer */
-
- if(Pmaster == NULL)
- blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */
-
- wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */
-
- if(Pmaster){
- if (bp==NULL || wp==NULL)
- return(0);
- }
- else{
- if (bp==NULL || wp==NULL || blistp==NULL)
- exit(1);
- }
-
- curbp = bp; /* Make this current */
- wheadp = wp;
- curwp = wp;
- wp->w_wndp = NULL; /* Initialize window */
- wp->w_bufp = bp;
- bp->b_nwnd = 1; /* Displayed. */
- wp->w_linep = bp->b_linep;
- wp->w_dotp = bp->b_linep;
- wp->w_doto = 0;
- wp->w_markp = NULL;
- wp->w_marko = 0;
-
- if(Pmaster){
- wp->w_toprow = COMPOSER_TOP_LINE;
- wp->w_ntrows = term.t_nrow - COMPOSER_TOP_LINE - 2;
- fillcol = (term.t_ncol > 80) ? 80 : term.t_ncol - 6;
- }
- else{
- wp->w_toprow = 2;
- wp->w_ntrows = term.t_nrow-4; /* "-1" for mode line. */
- fillcol = term.t_ncol - 6; /* set fill column */
- }
-
- wp->w_force = 0;
- wp->w_flag = WFMODE|WFHARD; /* Full. */
- }
-
-
- /*
- * This is the general command execution routine. It handles the fake binding
- * of all the keys to "self-insert". It also clears out the "thisflag" word,
- * and arranges to move it to the "lastflag", so that the next command can
- * look at it. Return the status of command.
- */
- execute(c, f, n)
- {
- register KEYTAB *ktp;
- register int status;
-
- ktp = (Pmaster) ? &keytab[0] : &pkeytab[0];
-
- while (ktp->k_fp != NULL) {
- if (ktp->k_code == c) {
-
- if(lastflag&CFFILL){
- curwp->w_flag |= WFMODE;
- if(Pmaster == NULL)
- sgarbk = TRUE;
- }
-
- thisflag = 0;
- status = (*ktp->k_fp)(f, n);
- lastflag = thisflag;
-
- return (status);
- }
- ++ktp;
- }
-
-
- /*
- * Check to make sure that we're not going to go off of the screen
- * with our next character. If so wrap the line...
- * note: in pico, fillcol and wrap-mode are always set and
- * wrapword behaves somewhat differently
- */
- if(((llength(curwp->w_dotp)+2 >= term.t_ncol)
- || (c == ' ' && getccol(FALSE) > fillcol))
- && (curwp->w_bufp->b_mode & MDWRAP))
- wrapword();
-
-
- if ((c>=0x20 && c<=0x7E) /* Self inserting. */
- || (c>=0xA0 && c<=0xFE)) {
-
- if (n <= 0) { /* Fenceposts. */
- lastflag = 0;
- return (n<0 ? FALSE : TRUE);
- }
- thisflag = 0; /* For the future. */
-
- /* if we are in overwrite mode, not at eol,
- and next char is not a tab or we are at a tab stop,
- delete a char forword */
- if (curwp->w_bufp->b_mode & MDOVER &&
- curwp->w_doto < curwp->w_dotp->l_used &&
- (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
- (curwp->w_doto) % 8 == 7))
- ldelete(1, FALSE);
-
- /* do the appropriate insertion */
- /* pico never does C mode, this is simple */
- status = linsert(n, c);
-
- lastflag = thisflag;
- return (status);
- }
-
- if(c&CTRL)
- emlwrite("\007Unknown Command: ^%c", c&0xff);
- else
- emlwrite("\007Unknown Command", NULL);
-
- lastflag = 0; /* Fake last flags. */
- return (FALSE);
- }
-
-
-
- /*
- * Fancy quit command, as implemented by Norm. If the any buffer has
- * changed do a write on that buffer and exit emacs, otherwise simply exit.
- */
- quickexit(f, n)
- {
- register BUFFER *bp; /* scanning pointer to buffers */
-
- bp = bheadp;
- while (bp != NULL) {
- if ((bp->b_flag&BFCHG) != 0 /* Changed. */
- && (bp->b_flag&BFTEMP) == 0) { /* Real. */
- curbp = bp; /* make that buffer cur */
- filesave(f, n);
- }
- bp = bp->b_bufp; /* on to the next buffer */
- }
- wquit(f, n); /* conditionally quit */
- }
-
-
-
- /*
- * abort_composer - ask the question here, then go quit or
- * return FALSE
- */
- abort_composer(f,n)
- {
- switch(mlyesno("Cancelling will abandon your mail message. Cancel",
- FALSE)){
- case TRUE:
- longjmp(finstate, COMP_CANCEL);
- break;
- case ABORT:
- emlwrite("\007Cancel Aborted", NULL);
- break;
- default:
- mlerase();
- break;
- }
- return(FALSE);
- }
-
-
- /*
- * suspend_composer - return to pine with what's been edited so far
- */
- suspend_composer(f, n)
- {
- longjmp(finstate, COMP_SUSPEND);
- }
-
-
-
- /*
- * Quit command. If an argument, always quit. Otherwise confirm if a buffer
- * has been changed and not written out. Normally bound to "C-X C-C".
- */
- wquit(f, n)
- {
- register int s;
-
- if(Pmaster){
- /*
- * if we're not in header, show some of it as we verify sending...
- */
- setmark(FALSE, 1);
- if(ComposerTopLine == COMPOSER_TOP_LINE){
- gotobob(FALSE, 1);
- update();
- }
-
- switch(mlyesno("Send message", TRUE)){
- case TRUE:
- longjmp(finstate, COMP_EXIT);
- break;
- case ABORT:
- emlwrite("\007Send Message Aborted", NULL);
- break;
- default:
- mlerase();
- break;
- }
-
- swapmark(FALSE, 1);
- }
- else{
- if (f != FALSE /* Argument forces it. */
- || anycb() == FALSE /* All buffers clean. */
- /* User says it's OK. */
- || (s=mlyesno("Modified buffer: Save before leaving", -1)) == FALSE) {
- vttidy();
- exit(0);
- }
-
- if(s == TRUE){
- if(filewrite(0,1) == TRUE)
- wquit(1, 0);
- }
- else if(s == ABORT){
- emlwrite("\007Exit Aborted");
- }
- return(s);
- }
- }
-
-
- /*
- * Abort.
- * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
- * Sometimes called as a routine, to do general aborting of stuff.
- */
- ctrlg(f, n)
- {
- (*term.t_beep)();
- if (kbdmip != NULL) {
- kbdm[0] = (CTLX|')');
- kbdmip = NULL;
- }
- emlwrite("Aborted");
- return (ABORT);
- }
-
-
- /* tell the user that this command is illegal while we are in
- * VIEW (read-only) mode
- */
- rdonly()
- {
- (*term.t_beep)();
- emlwrite("Key illegal in VIEW mode");
- return(FALSE);
- }
-
-
-
- /*
- * reset all globals to their initial values
- */
- func_init()
- {
- extern int vtrow;
- extern int vtcol;
- extern int lbound;
- extern int ttrow;
- extern int ttcol;
-
- /*
- * re-initialize global buffer type variables ....
- */
- fillcol = (term.t_ncol > 80) ? 80 : term.t_ncol - 6;
- eolexist = TRUE;
- revexist = FALSE;
- sgarbf = TRUE;
- mpresf = FALSE;
- mline_open = FALSE;
- ComposerEditing = FALSE;
-
- /*
- * re-initialize hardware display variables ....
- */
- vtrow = vtcol = lbound = 0;
- ttrow = ttcol = HUGE;
-
- pat[0] = rpat[0] = '\0';
- }
-
-
- /*
- * pico_help - help function for standalone composer
- */
- pico_help(text, title, i)
- char *text[], *title;
- int i;
- {
- register int numline = 0;
- char **p;
-
- p = text;
- while(*p++ != NULL)
- numline++;
- return(wscrollw(COMPOSER_TOP_LINE, term.t_nrow-1, text, numline));
-
- }
-
-
-
- #if TERMCAP
- /*
- * zottree() - kills the key pad function key search tree
- * and frees all lines associated with it!!!
- */
- zottree(nodeptr)
- struct KBSTREE *nodeptr;
- {
- if(nodeptr != NULL){
- zottree(nodeptr->left);
- zottree(nodeptr->down);
- free((char *) nodeptr);
- }
- }
- #endif
-
-
- /*
- * zotedit() - kills the buffer and frees all lines associated with it!!!
- */
- zotedit()
- {
- register BUFFER *bp;
- register WINDOW *wp;
- register LINE *lp;
- register int s;
-
- /*
- * clean up the lines and buffer ...
- */
- curbp->b_flag &= ~BFCHG;
-
- if ((s=bclear(curbp)) != TRUE) /* Blow text away. */
- return(s);
-
- free((char *) wheadp); /* clean up window */
- wheadp = NULL;
- curwp = NULL;
-
- free((char *) bheadp); /* clean up buffers */
- bheadp = NULL;
- curbp = NULL;
-
- zotheader(); /* blast header lines */
-
- zotdisplay(); /* blast display buffers */
-
- #if TERMCAP
- zottree(kpadseqs);
- kpadseqs = NULL;
- #endif
- }
-