[comp.mail.elm] Elm 2.1 PL1 Part 11 of 22

syd@dsinc.UUCP (Syd Weinstein) (12/12/88)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 11 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/edit.c continued
#
CurArch=11
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file src/edit.c"
sed 's/^X//' << 'SHAR_EOF' >> src/edit.c
X	  Raw(ON);
X	  sleep(2);
X	  return(0);
X	}
X
X	Raw(ON);
X
X	if (mbox_specified == 0) {	/* uh oh... now the toughie...  */
X
X#ifdef        NOSU
X          sprintf(temp_infile, "%s%s.temp", temp_lock_dir, username);
X#else
X	  sprintf(temp_infile, "%s%s.temp", mailhome, username);
X#endif
X	  unlink(temp_infile);	/* remove it if it's there... */
X
X	  if (bytes(infile) != mailfile_size) {
X
X	     /* SIGH.  We've received mail since we invoked the editor
X		on the mailbox.  We'll have to do some strange stuff to
X	        remedy the problem... */
X
X	     PutLine0(LINES, 0, "Warning: new mail received...");
X	     CleartoEOLN();
X
X	     if ((temp_mailbox = fopen(filename, "a")) == NULL) {
X	       dprint(1, (debugfile, 
X			"Attempt to open \"%s\" to append failed in %s\n", 
X			filename, "edit_mailbox"));
X	       set_error("Couldn't reopen tempfile.  Edit LOST!");
X	       return(1);
X	     }
X	     /** Now let's lock the mailbox up and stream the new stuff 
X		 into the temp file... **/
X
X           chown( filename, userid, groupid);
X
X	     lock(OUTGOING);	
X	     if ((real_mailbox = fopen(infile, "r")) == NULL) {
X	       dprint(1, (debugfile, 
X	           "Attempt to open \"%s\" for reading new mail failed in %s\n",
X 		   infile, "edit_mailbox"));
X	       sprintf(buffer, "Couldn't open %s for reading!  Edit LOST!", 
X		       infile);
X	       set_error(buffer);
X	       unlock();
X	       return(1);
X	     }
X	     if (fseek(real_mailbox, mailfile_size, 0) == -1) {
X	       dprint(1, (debugfile,
X			"Couldn't seek to end of infile (offset %ld) (%s)\n",
X			mailfile_size, "edit_mailbox"));
X	       set_error("Couldn't seek to end of mailbox.  Edit LOST!");
X	       unlock();
X	       return(1);
X	     }
X	
X	     /** Now we can finally stream the new mail into the tempfile **/
X
X	     while (fgets(buffer, LONG_SLEN, real_mailbox) != NULL)
X	       fprintf(temp_mailbox, "%s", buffer);
X
X	     fclose(real_mailbox);
X	     fclose(temp_mailbox);
X 	   }
X	   else
X	     lock(OUTGOING); /* create a lock file if we're replacing mailbox */
X
X	   /** link to the temporary mailbox in the mailhome directory... **/
X
X	   if (link(filename, temp_infile) != 0) 
X	     if (errno == EXDEV || errno == EEXIST) {   /* attempt to link across file systems */
X   	       if (copy(filename, temp_infile) != 0) {
X	         error("Couldn't copy temp file to mailbox!");
X	         unlock();					/* ciao!*/
X	   	 emergency_exit();
X	       }
X	     }
X	     else {
X		Write_to_screen("\n\rCouldn't link %s to mailfile %s...\n\r",2,
X			filename, temp_infile);
X		Write_to_screen("** %s - %s **\n\r", 2,
X			error_name(errno), error_description(errno));
X	        emergency_exit();
X	     }
X	
X	   /***  G U L P ... let's remove the incoming mail file... ***/
X	     
X	   if (unlink(infile) != 0) {
X   	       if (copy(temp_infile, infile) != 0) {
X	         error("Couldn't copy temp file to mailbox!");
X	         unlock();					/* ciao!*/
X	   	 emergency_exit();
X	       }
X	     }
X	   else {
X	   /** and quickly now... **/
X
X	     if (link(temp_infile, infile) != 0) {
X	       Write_to_screen(
X		      "\n\rCouldn't internally link %s to mailfile %s...\n\r",
X		      2, temp_infile, infile);
X	       Write_to_screen(
X		      "\n\rYou'll need to check out %s for your mail...\n\r",
X		      1, temp_infile);
X	       Write_to_screen("** %s - %s **\n\r", 2,
X		      error_name(errno), error_description(errno));
X	       emergency_exit();
X	     }
X	   }
X
X	   /** And let's remove the lock file!  We're DONE!!!  **/
X
X	   unlock();
X	   unlink(temp_infile);	/* remove the temp file too */
X	   unlink(filename);	/* remove the temp file too */
X	   error("edit changes incorporated into new mail...");
X	}
X	else
X	  error("Resynchronizing with new version of mailbox...");
X
X	sleep(2);
X	newmbox(3, TRUE, TRUE);
X	mailfile_size = bytes(infile);	
X	showscreen();
X
X	current = 1;		/* don't leave the user hanging! */
X
X	/** finally restore the permissions... **/
X
X	if (loaded_stat_buffer) {	/* if not, it's junk! */
X	  chown(infile, stat_buffer.st_uid, stat_buffer.st_gid);
X	  chmod(infile, stat_buffer.st_mode);
X	}
X
X	return(1);
X}
X
X#endif
SHAR_EOF
echo "File src/edit.c is complete"
chmod 0444 src/edit.c || echo "restore of src/edit.c fails"
echo "x - extracting src/editmsg.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/editmsg.c &&
X
Xstatic char rcsid[] = "@(#)$Id: editmsg.c,v 2.1 88/09/15 20:28:00 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * 			Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	editmsg.c,v $
X * Revision 2.1  88/09/15  20:28:00  syd
X * checked in with -k by syd at 88.09.15.20.28.00.
X * 
X * 88/08/27 ssw
X *	add deluth patches
X *
X * Revision 2.1  88/07/21  09:58:15  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:24:58  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/** This contains routines to do with starting up and using an editor (or two)
X    from within Elm.  This stuff used to be in mailmsg2.c...
X**/
X
X#include "headers.h"
X#include <errno.h>
X#include <setjmp.h>
X#include <signal.h>
X#include <ctype.h>
X
X#ifdef BSD
X#undef        tolower
X#endif
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy(), *format_long();
Xunsigned long sleep();
X
Xint
Xedit_the_message(filename, already_has_text)
Xchar *filename;
Xint  already_has_text;
X{
X	/** Invoke the users editor on the filename.  Return when done. 
X	    If 'already has text' then we can't use the no-editor option
X	    and must use 'alternative editor' (e.g. $EDITOR or default_editor)
X	    instead... **/
X
X	char buffer[SLEN];
X	register int stat, return_value = 0;
X        int     old_raw;
X
X	buffer[0] = '\0';
X
X	if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
X	  if (already_has_text) 
X	    sprintf(buffer, "%s %s", alternative_editor, filename);
X	  else
X	    return(no_editor_edit_the_message(filename));
X	}
X
X	PutLine0(LINES, 0, "invoking editor...");  fflush(stdout);
X	if (strlen(buffer) == 0)
X	  sprintf(buffer,"%s %s", editor, filename);
X
X      if( (old_raw = RawState()) == ON)
X	Raw(OFF);
X
X	chown(filename, userid, groupid);	/* file was owned by root! */
X
X	if (cursor_control)
X	  transmit_functions(OFF);		/* function keys are local */
X
X	if ((stat = system_call(buffer, SH)) != 0) { 
X	  dprint(1,(debugfile, 
X		  "System call failed with stat %d (edit_the_message)\n", 
X		  stat));
X	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno), 
X		error_description(errno)));
X	  ClearLine(LINES-1);
X	  error1("Can't invoke editor '%s' for composition", editor);
X	  sleep(2);
X	  return_value = 1;
X	}
X
X	if (cursor_control)
X	  transmit_functions(ON);		/* function keys are local */
X	
X      if ( old_raw == ON)
X	Raw(ON);
X
X	return(return_value);
X}
X
Xextern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], 
X	    expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING], 
X            subject[SLEN];
X
Xint      interrupts_while_editing;	/* keep track 'o dis stuff         */
Xjmp_buf  edit_location;		        /* for getting back from interrupt */
X
X#ifdef ALLOW_BCC
Xextern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
X#endif
X
Xchar *strip_commas();
Xlong  fsize();
X
Xint
Xno_editor_edit_the_message(filename)
Xchar *filename;
X{
X	/** If the current editor is set to either "builtin" or "none", then
X	    invoke this program instead.  As it turns out, this and the 
X	    routine above have a pretty incestuous relationship (!)...
X	**/
X
X	FILE *edit_fd;
X	char buffer[SLEN], editor_name[SLEN], buf[SLEN];
X	int      edit_interrupt(), (*oldint)(), (*oldquit)();
X        int     old_raw;
X
X        if (( old_raw = RawState()) == ON)
X	Raw(OFF);
X
X	if ((edit_fd = fopen(filename, "a")) == NULL) {
X	  error2("Couldn't open %s for appending [%s]", filename, 
X		  error_name(errno));
X	  sleep (2);
X	  dprint(1, (debugfile,
X		"Error encountered trying to open file %s;\n", filename));
X	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X		    error_description(errno)));
X          if ( old_raw == ON)
X	  Raw(ON);
X	  return(1);
X	}
X
X	/** is there already text in this file? **/
X
X	if (fsize(edit_fd) > 0L)
X	  printf(
X         "\nPlease continue message, ^D or '.' to end, %cp to list, %c? for help;\n\n",
X		escape_char, escape_char);
X	else
X	  printf(
X          "\nPlease enter message, ^D or '.' to end, or %c? <RETURN> for help;\n\n",
X		escape_char);
X
X	oldint  = signal(SIGINT,  edit_interrupt);
X	oldquit = signal(SIGQUIT, edit_interrupt);
X
X	interrupts_while_editing = 0;
X
X	if (setjmp(edit_location) != 0) {
X	  if (interrupts_while_editing > 1) {
X	    Raw(ON);
X
X	    (void) signal(SIGINT,  oldint);
X	    (void) signal(SIGQUIT, oldquit);
X
X	    if (edit_fd != NULL)	/* insurance... */
X	      fclose(edit_fd);
X	    return(1);
X	  }
X	  goto more_input;	/* read input again, please! */
X	}
X	
Xraw_input : Raw(ON);
X
Xmore_input: buffer[0] = '\0';
X
X	while (optionally_enter(buffer, -1,-1, FALSE) == 0) {
X
X	  interrupts_while_editing = 0;	/* reset to zero... */
X
X	  if (strcmp(buffer, ".") == 0)
X	    break;	/* '.' is as good as a ^D to us dumb programs :-) */
X	  if (buffer[0] == escape_char) {
X	    Raw(OFF);
X	    switch (tolower(buffer[1])) {
X              case '?' : tilde_help();
X                       printf("(continue)\n"); goto raw_input;
X
X	      case TILDE: move_left(buffer, 1); 
X			  Raw(ON); 		goto tilde_input;	/*!!*/
X
X	      case 't' : get_with_expansion("\nTo: ", to, expanded_to, buffer);
X			 goto raw_input;
X#ifdef ALLOW_BCC
X	      case 'b' : get_with_expansion("\nBcc: ",bcc,expanded_bcc, buffer);
X			 goto raw_input;
X#endif
X	      case 'c' : get_with_expansion("\nCc: ", cc, expanded_cc, buffer);
X			 goto raw_input;
X	      case 's' : get_with_expansion("\nSubject: ", subject,NULL,buffer);
X   			 goto raw_input;
X
X	      case 'h' : get_with_expansion("\nTo: ", to, expanded_to, NULL);	
X	                 get_with_expansion("Cc: ", cc, expanded_cc, NULL);
X#ifdef ALLOW_BCC
X	                 get_with_expansion("Bcc: ", bcc,expanded_bcc, NULL);
X#endif
X	                 get_with_expansion("Subject: ", subject,NULL, NULL);
X			 goto raw_input;
X
X	      case 'r' : read_in_file(edit_fd, (char *) buffer + 2, 1);
X		  	 goto raw_input;
X	      case 'e' : if (strlen(emacs_editor) > 0) 
X	                   if (access(emacs_editor, ACCESS_EXISTS) == 0) {
X	                     strcpy(buffer, editor);
X			     strcpy(editor, emacs_editor);
X	  		     fclose(edit_fd);
X			     (void) edit_the_message(filename,0);
X			     strcpy(editor, buffer);
X			     edit_fd = fopen(filename, "a");
X                             printf("(continue entering message, ^D or '.' to end)\n");
X	                     goto raw_input;
X		           }
X		           else
X	                     printf(
X			  "\n(Can't find Emacs on this system!  continue)\n");
X			 else
X			   printf(
X			  "\n(Don't know where Emacs would be...continue)\n");	
X			 goto raw_input;
X
X	       case 'v' : strcpy(buffer, editor);
X			  strcpy(editor, default_editor);
X			  fclose(edit_fd);
X			  (void) edit_the_message(filename,0);
X			  strcpy(editor, buffer);
X			  edit_fd = fopen(filename, "a");
X                          printf("(continue entering message, ^D or '.' to end)\n");
X	                  goto raw_input;
X
X	       case 'o' : printf("\nPlease enter the name of the editor : ");
X			  editor_name[0] = '\0';
X			  optionally_enter(editor_name,-1,-1, FALSE);
X	                  if (strlen(editor_name) > 0) {
X	                    strcpy(buffer, editor);
X			    strcpy(editor, editor_name);
X			    fclose(edit_fd);
X			    (void) edit_the_message(filename,0);
X			    strcpy(editor, buffer);
X			    edit_fd = fopen(filename, "a");
X                            printf("(continue entering message, ^D or '.' to end)\n");
X	                    goto raw_input;
X		          }
X	  		  printf("(continue)\n");
X	                  goto raw_input; 
X
X		case '<' : putchar('\n');
X			   if (strlen(buffer) < 3)
X			     (void) printf(
X	           "(you need to use a specific command here.  Continue...)\n");
X			   else {
X			     sprintf(buf, " > %s.%d 2>&1", temp_edit, getpid());
X			     strcat(buffer, buf);
X			     (void) system_call((char *) buffer+2, SH);
X			     sprintf(buffer, "~r %s.%d", temp_edit, getpid());
X	      	             read_in_file(edit_fd, (char *) buffer + 3, 0);
X			     (void) unlink((char *) buffer+3);
X			   }
X	                   goto raw_input; 
X
X		case '!' : putchar('\n');
X			   if (strlen(buffer) < 3) 
X			     (void) system_call(shell, USER_SHELL);
X			   else
X	                     (void) system_call((char *) buffer+2, USER_SHELL);
X	    		   printf("(continue)\n");
X			   goto raw_input;
X
X		 case 'm' : /* same as 'f' but with leading prefix added */
X
X	         case 'f' : /* this can be directly translated into a
X			       'readmsg' call with the same params! */
X			    putchar('\n');
X			    read_in_messages(edit_fd, (char *) buffer + 1);
X			    goto raw_input;
X
X	         case 'p' : /* print out message so far.  Soooo simple! */
X			    print_message_so_far(edit_fd, filename);
X			    goto raw_input;
X
X		 default  : printf(
X			     "\n(don't know what %c%c is.  Try %c? for help)\n",
X				    escape_char, buffer[1], escape_char);
X	       }
X	     }
X	     else {
Xtilde_input:
X	       fprintf(edit_fd, "%s\n", buffer);
X	       printf("\r\n");
X	     }
X	  buffer[0] = '\0';
X	}
X
X	printf("\n<end-of-message>\n\r\n\r");
X
X        if ( old_raw == ON)
X	Raw(ON);
X
X	(void) signal(SIGINT,  oldint);
X	(void) signal(SIGQUIT, oldquit);
X
X	if (edit_fd != NULL)	/* insurance... */
X	  fclose(edit_fd);
X
X	return(0);
X}
X
Xtilde_help()
X{
X	/* a simple routine to print out what is available at this level */
X
X        int     old_raw;
X
X        if ( (old_raw = RawState()) == ON)
X	Raw(OFF);
X
X	printf("\n(Available options at this point are;\n\n");
X	printf("\t%c?\tPrint this help menu\n", escape_char);
X	if (escape_char == TILDE)
X	  printf("\t~~\tAdd line prefixed by a single '~' character\n");
X	/* doesn't make sense otherwise... */
X
X#ifdef ALLOW_BCC
X	printf("\
X\t%cb\tChange the addresses in the Blind-carbon-copy list\n", escape_char);
X#endif
X
X	printf("\t%cc\tChange the addresses in the Carbon-copy list\n",
X		escape_char);
X	printf("\t%ce\tInvoke the Emacs editor on the message, if possible\n",
X		escape_char);
X	printf("\t%cf\tadd the specified list of messages, or current\n",
X		escape_char);
X	printf("\t%ch\tchange all available headers (to,cc%s,subject)\n",
X		escape_char,
X#ifdef ALLOW_BCC
X	 	",bcc");
X#else
X		"");
X#endif
X	printf("\t%cm\tsame as '%cf', but with the current 'prefix'\n",
X		escape_char, escape_char);
X	printf("\t%co\tInvoke a user specified editor on the message\n",
X		escape_char);
X	printf("\t%cp\tprint out message as typed in so far\n", escape_char);
X	printf("\t%cr\tRead in the specified file\n", escape_char);
X	printf("\t%cs\tChange the subject of the message\n", escape_char);
X	printf("\t%ct\tChange the addresses in the To list\n",
X		escape_char);
X	printf("\t%cv\tInvoke the Vi visual editor on the message\n\n",
X		escape_char);
X	printf(
X          "\t%c!\texecute a unix command (or give a shell if no command)\n",
X	  escape_char);
X	printf(
X          "\t%c<\texecute a unix command adding the output to the message\n\n",
X	  escape_char);
X	printf(
X	  "\t.  \tby itself on a line (or a control-D) ends the message\n\n");
X
X        if ( old_raw == ON)
X	Raw(ON);
X}
X
Xread_in_file(fd, filename, show_user_filename)
XFILE *fd;
Xchar *filename;
Xint   show_user_filename;
X{
X	/** Open the specified file and stream it in to the already opened 
X	    file descriptor given to us.  When we're done output the number
X	    of lines we added, if any... **/
X
X	FILE *myfd;
X	char myfname[SLEN], buffer[LONG_SLEN];
X	register int lines = 0;
X
X	while (whitespace(filename[lines])) lines++;
X
X	/** expand any shell variables, '~' or other notation... **/
X
X	expand_env(myfname, (char *) filename + lines);
X
X	if (strlen(myfname) == 0) {
X	  printf("\n(no filename specified for file read!  Continue...)\n");
X	  return;
X	}
X
X	if ((myfd = fopen(myfname,"r")) == NULL) {
X	  printf("\n(Couldn't read file '%s'!  Continue...)\n",
X		 myfname);
X	  return;
X	}
X
X	lines = 0;
X
X	while (fgets(buffer, LONG_SLEN, myfd) != NULL) {
X	  lines++;
X  	  fputs(buffer, fd);
X	  fflush(stdout);
X	}
X
X	fclose(myfd);
X
X	if (show_user_filename)
X	  printf("\n(added %d line%s from file %s.  Please continue...)\n",
X		lines, plural(lines), myfname);
X	else
X	  printf("\n(added %d line%s to message.  Please continue...)\n",
X		lines, plural(lines));
X
X	return;
X}
X
Xprint_message_so_far(edit_fd, filename)
XFILE *edit_fd;
Xchar *filename;
X{
X	/** This prints out the message typed in so far.  We accomplish
X	    this in a cheap manner - close the file, reopen it for reading,
X	    stream it to the screen, then close the file, and reopen it
X	    for appending.  Simple, but effective!
X
X	    A nice enhancement would be for this to -> page <- the message
X	    if it's sufficiently long.  Too much work for now, though.
X	**/
X	
X	char buffer[LONG_SLEN];
X
X	fclose(edit_fd);
X
X	if ((edit_fd = fopen(filename, "r")) == NULL) {
X	  printf("\nMayday!  Mayday!  Mayday!\n");
X	  printf("\nPanic: Can't open file for reading!  Bail!\n");
X	  emergency_exit();
X	}
X
X	printf("\nTo: %s\n", format_long(to, 4));
X	printf("Cc: %s\n", format_long(cc, 4));
X#ifdef ALLOW_BCC
X	printf("Bcc: %s\n", format_long(bcc, 5));
X#endif
X	printf("Subject: %s\n\n", subject);
X
X	while (fgets(buffer, LONG_SLEN, edit_fd) != NULL)
X	  printf("%s", buffer);
X
X	fclose(edit_fd);
X
X	if ((edit_fd = fopen(filename, "a")) == NULL) {
X	  printf("Mayday!  Mayday!  Abandon Ship!  Aiiieeeeee\n");
X	  printf("\nPanic: Can't reopen file for appending!\n");
X	  emergency_exit();
X	}
X
X	printf("\n(continue entering message, please)\n");
X}
X
Xread_in_messages(fd, buffer)
XFILE *fd;
Xchar *buffer;
X{
X	/** Read the specified messages into the open file.  If the
X	    first character of "buffer" is 'm' then prefix it, other-
X	    wise just stream it in straight...Since we're using the
X	    pipe to 'readmsg' we can also allow the user to specify
X	    patterns and such too...
X	**/
X
X	FILE *myfd, *popen();
X	char  local_buffer[LONG_SLEN];
X	register int lines = 0, add_prefix=0, mindex;
X
X	add_prefix = (tolower(buffer[0]) == 'm');
X
X	if (strlen(++buffer) == 0) {
X	  if (mail_only) {
X	    printf("(you need to specify what message(s) to include)\n");
X	    return;
X	  }
X	  /** else give us the current message number as a default **/
X	}
X
X	if (mail_only || ! isdigit(buffer[0])) 
X	  sprintf(local_buffer, "%s %s", readmsg, buffer);
X	else {
X	  mindex = atoi(buffer);	/* map requested # to real # */
X	  sprintf(local_buffer, "%s %d", readmsg, 
X		  header_table[mindex-1].index_number);
X	}
X
X	if ((myfd = popen(local_buffer, "r")) == NULL) {
X	   printf("(can't get to 'readmsg' command.  Sorry...)\n");
X	   return;	
X	}
X
X	dprint(5, (debugfile, "** readmsg call: \"%s\" **\n", local_buffer));
X
X	while (fgets(local_buffer, LONG_SLEN, myfd) != NULL) {
X	  lines++;
X	  if (add_prefix)
X	    fprintf(fd, "%s%s", prefixchars, local_buffer);
X	  else 
X	    fputs(local_buffer, fd);
X	}
X
X	pclose(myfd);
X	
X	if (lines == 0)
X	  printf("(Couldn't add the requested message.   Continue)\n");
X	else
X	  printf("(added %d line%s to message...  Please continue)\n",
X		lines, plural(lines));
X
X	return;
X}
X
Xget_with_expansion(prompt, buffer, expanded_buffer, sourcebuf)
Xchar *prompt, *buffer, *expanded_buffer, *sourcebuf;
X{
X	/** This is used to prompt for a new value of the specified field.
X	    If expanded_buffer == NULL then we won't bother trying to expand
X	    this puppy out!  (sourcebuf could be an initial addition)
X	**/
X
X	char mybuffer[VERY_LONG_STRING];
X        int     old_raw;
X
X        if ( (old_raw = RawState()) == OFF)
X	  Raw(ON);
X
X	printf(prompt);	fflush(stdout);	/* output! */
X
X	if (sourcebuf != NULL) {
X	  while (!whitespace(*sourcebuf) && *sourcebuf != '\0') 
X	    sourcebuf++;
X	  if (*sourcebuf != '\0') {
X	    while (whitespace(*sourcebuf)) 
X	      sourcebuf++;
X	    if (strlen(sourcebuf) > 0) {
X	      strcat(buffer, " ");
X	      strcat(buffer, sourcebuf);
X	    }
X	  }
X	}
X
X	strcpy(mybuffer, buffer);
X
X	optionally_enter(buffer, -1, -1, TRUE);	/* already data! */
X
X        if ( old_raw == OFF)
X          Raw(OFF);
X
X	putchar('\n');
X
X	/** if it's changed and we're supposed to expand addresses... **/
X
X	if (strcmp(buffer, mybuffer) != 0 && expanded_buffer != NULL) 
X	  if (build_address(strip_commas(buffer), expanded_buffer))
X	    printf("%s%s\n\r", prompt, expanded_buffer);
X
X	return;
X}
X
Xedit_interrupt()
X{
X	/** This routine is called when the user hits an interrupt key
X	    while in the builtin editor...it increments the number of 
X	    times an interrupt is hit and returns it.
X	**/
X
X	signal(SIGINT, edit_interrupt);
X	signal(SIGQUIT, edit_interrupt);
X
X	if (interrupts_while_editing++ == 0)
X	  printf("(Interrupt.  One more to cancel this letter...)\n\r");
X
X	longjmp(edit_location, 1);		/* get back */
X}
SHAR_EOF
chmod 0444 src/editmsg.c || echo "restore of src/editmsg.c fails"
echo "x - extracting src/elm.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/elm.c &&
X
Xstatic char rcsid[] = "@(#)$Id: elm.c,v 2.1.1.2 88/09/23 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
X *
X * This file and all associated files and documentation:
X *	(C) Copyright 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X *	Syd Weinstein, Elm Corrdinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	elm.c,v $
X * Revision 2.1  88/09/15  20:28:04  syd
X * checked in with -k by syd at 88.09.15.20.28.04.
X * 
X * 88/09/01 Rob Bernardo <gatech!pbhyf.PacBell.COM!rob>
X *	1. It allows the user to use the -z flags and -f [filename] flag
X *	2. Puts elm in raw mode earlier on than before so that any commands
X *	3. forward a message without editing it, fix redraw after no edit
X *
X * 88/08/27 ssw
X *	add deluth patches
X *
X * 88/08/27 various
X *	changes for j,k commands
X *
X * Revision 2.1  88/07/21  09:58:17  edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X * 
X * Revision 2.0  88/06/27  17:24:59  edc
X * The original 2.0 gamma sources as leaked from HP
X * 
X *
X *
X ******************************************************************************/
X
X/* Main program of the ELM mail system! 
X*/
X
X#include "elm.h"
X
X#ifdef BSD
X#undef        toupper
X#undef        tolower
X#endif
X
Xlong bytes();
Xchar *format_long();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X	{
X	int  ch;
X	char address[SLEN], to_whom[LONG_SLEN];
X	int  key_offset;        /** Position offset within keyboard string   **/
X	int  redraw, 		/** do we need to rewrite the entire screen? **/
X	     nuhead, 		/** or perhaps just the headers section...   **/
X	     nucurr, 		/** or just the current message pointer...   **/
X	     nufoot; 		/** clear lines 16 thru bottom and new menu  **/
X	int  i;      		/** Random counting variable (etc)           **/
X	int  pageon, 		/** for when we receive new mail...          **/
X	     last_in_mailbox;	/** for when we receive new mail too...      **/
X	long num;		/** another variable for fun..               **/
X
X	parse_arguments(argc, argv, to_whom);
X
X	if (mail_only) {
X
X	   initialize(FALSE);
X
X	   dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", 
X		   format_long(to_whom, 3)));
X	   (void) sendmsg(to_whom, "", "", TRUE, NO, FALSE); 
X	   leave(0);
X	}
X
X	initialize(TRUE);
X
X	ScreenSize(&LINES, &COLUMNS);
X
X	showscreen();
X
X	/* mailfile_size = bytes(infile); */	/* done in newmbox.c now */
X
X	while (1) {
X	  redraw = 0;
X	  nuhead = 0;
X	  nufoot = 0;
X	  nucurr = 0;
X	  if ((num = bytes(infile)) != mailfile_size) {
X	    dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", 
X		    num - mailfile_size));
X	    error("New mail has arrived!   Hang on...");
X	    fflush(stdin);	/* just to be sure... */
X	    last_in_mailbox = message_count;
X	    pageon = header_page;
X	    newmbox(2, FALSE, TRUE);	/* last won't be touched! */
X	    clear_error();
X	    header_page = pageon;
X
X	    if (on_page(current))   /* do we REALLY have to rewrite? */
X	      showscreen();
X	    else {
X	      update_title();
X	      ClearLine(LINES-1);	     /* remove reading message... */
X	      error2("%d new message%s received", 
X		     message_count - last_in_mailbox,
X		     plural(message_count - last_in_mailbox));
X	    }
X	    /* mailfile_size = num; */
X	    if (cursor_control)
X	      transmit_functions(ON);	/* insurance */
X	  }
X
X	  prompt("Command: ");
X
X	  CleartoEOLN();
X	  ch = GetPrompt();
X	  CleartoEOS();
X#ifdef DEBUG
X	  if (! movement_command(ch))
X	    dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
X#endif
X
X	  set_error("");	/* clear error buffer */
X
X	  MoveCursor(LINES-3,strlen("Command: "));
X
X	  switch (ch) {
X
X	    case '?' 	:  if (help())
X	  		     redraw++;
X			   else
X			     nufoot++;
X			   break;
X
X	    case '$'    : resync();	break;
X
X	    case ' '    : 
X	    case '+'	:  header_page++; nuhead++;	
X			   if (move_when_paged && header_page <=
X			      ((message_count-1) / headers_per_page)) {
X			     current = header_page*headers_per_page + 1;
X			     if (selected)
X			       current = visible_to_index(current)+1;
X	                   }
X			   break;
X
X	    case '-'    :  header_page--; nuhead++;	
X			   if (move_when_paged && header_page >= 0) {
X			     current = header_page*headers_per_page + 1;
X			     if (selected)
X			       current = visible_to_index(current)+1;
X			   }
X			   break;
X
X	    case '='    :  if (selected)
X			     current = visible_to_index(1)+1;
X	                   else
X			     current = 1;
X	                   if (get_page(current))
X			     nuhead++;	
X			   else
X			     nucurr++;	break;
X
X	    case '*'    :  if (selected) 
X			     current = (visible_to_index(selected)+1);
X			   else
X			     current = message_count;	
X	                   if (get_page(current))
X			     nuhead++;	
X			   else
X			     nucurr++; 	break;
X
X	    case '|'    :  Writechar('|'); 
X	    		   softkeys_off();
X                           redraw = do_pipe();		
X	                   softkeys_on(); break;
X
X	    case '!'    :  Writechar('!'); 
X	    		   softkeys_off();
X                           redraw = subshell();		
X	                   softkeys_on(); break;
X
X	    case '%'    :  get_return(address);
X			   clear_error();
X			   PutLine1(LINES,(COLUMNS-strlen(address))/2,
X			            "%.78s", address);	
X		           break;
X
X	    case '/'    :  if (pattern_match()) {
X	                     if (get_page(current))
X			       nuhead++;
X	                     else
X	                       nucurr++;
X	                   }
X			   else {
X			      error("pattern not found!");
X			      fflush(stdin);
X			   }
X			   break;
X
X	    case '<'    :  /* scan current message for calendar information */
X#ifdef ENABLE_CALENDAR
X			   PutLine0(LINES-3, strlen("Command: "), 	
X				   "Scan message for calendar entries...");
X			   scan_calendar();
X#else
X	 		   error("Sorry - calendar function disabled");
X			   fflush(stdin);
X#endif
X			   break;
X
X	    case 'a'    :  if(alias()) redraw++;
X			   else nufoot++; 	
X			   define_softkeys(MAIN); 	break;
X			
X	    case 'b'    :  PutLine0(LINES-3, strlen("Command: "), 
X		             "Bounce message");
X			   fflush(stdout);
X			   if (message_count < 1) {
X	  		     error("No mail to bounce!");
X			     fflush(stdin);
X			   }
X			   else 
X			     nufoot = remail();
X			   break;
X
X	    case 'c'    :  PutLine0(LINES-3, strlen("Command: "), 
X			      "Change mailbox");
X			   if ((file_changed = leave_mbox(FALSE)) != -1) {
X			     define_softkeys(CHANGE);
X	                     redraw = newmbox(0, TRUE, TRUE);
X			     /* mailfile_size = bytes(infile); */
X	      	           }
X			   else {
X			     file_changed = 0;
X			     sort_mailbox(message_count, FALSE);
X			   }
X			   define_softkeys(MAIN);
X			   break;
X
X	    case '^'    :
X	    case 'd'    :  if (message_count < 1) {
X			     error("No mail to delete!");
X			     fflush(stdin);
X			   }
X			   else {
X 	                     delete_msg((ch == 'd'), TRUE);
X			     if (resolve_mode) 	/* move after mail resolved */
X			       if (current < message_count) {
X			         i = current;
X			         while (++current <= message_count &&
X			            (header_table[current-1].status & DELETED))
X	                           /** continue moving forward, please **/ ;
X			         if (current > message_count)
X			           current = i;	/* reset - overshot! */
X			         if (get_page(current))
X			           nuhead++;
X			         else
X			           nucurr++;
X			       }
X	                   }
X			   break;
X
X	    case ctrl('D') : if (message_count < 1) {
X			       error("No mail to delete!");
X			       fflush(stdin);
X			     }
X			     else 
X			       meta_match(DELETED);
X			     break;
X
X#ifdef ALLOW_MAILBOX_EDITING
X	    case 'e'    :  PutLine0(LINES-3,strlen("Command: "),"Edit mailbox");
X			   if (current > 0) {
X			     edit_mailbox();
X	    		     if (cursor_control)
X	                       transmit_functions(ON);	/* insurance */
X	   		   }
X			   else {
X			     error("Mailbox is empty!");
X			     fflush(stdin);
X			   }
X			   break;
X#else
X	    case 'e'    : error(
X		    "mailbox editing isn't configured in this version of Elm");
X			  fflush(stdin);
X			  break;
X#endif
X		
X	    case 'f'    :  PutLine0(LINES-3, strlen("Command: "), "Forward");
X			   define_softkeys(YESNO);
X			   if (current > 0) {
X			     if(forward()) redraw++;
X			     else nufoot++;
X			   } else {
X	                     error("No mail to forward!");
X			     fflush(stdin);
X			   }
X			   define_softkeys(MAIN);
X			   break;
X
X	    case 'g'    :  PutLine0(LINES-3,strlen("Command: "), "Group reply");
X		           fflush(stdout);
X			   if (current > 0) {
X			     if (header_table[current-1].status & FORM_LETTER) {
X			       error("Can't group reply to a Form!!");
X			       fflush(stdin);
X			     }
X			     else {
X			       PutLine0(LINES-3,COLUMNS-40,
X                                       "building addresses...");
X			       define_softkeys(YESNO);
X	                       redraw = reply_to_everyone();	
X			       define_softkeys(MAIN);
X	                     }
X	                   }
X			   else {
X			     error("No mail to reply to!"); 
X			     fflush(stdin);
X			   }
X			   break;
X
X	    case 'h'    :  if (filter)
X	                     PutLine0(LINES-3, strlen("Command: "), 
X				"Message with headers...");
X	                   else
X			     PutLine0(LINES-3, strlen("Command: "),"Read message");
X			   fflush(stdout);
X			   i = filter;
X			   filter = FALSE;
X                           redraw = show_msg(current);
X                           if (((redraw == ESCAPE) || ( redraw > ' ')) &&
X   			   redraw < 127) {
X                             while ((redraw == ESCAPE) || (redraw > ' '))
X                                redraw = process_showmsg_cmd(redraw);
X			   }
X			   redraw = 1; /* always */
X			   filter = i;
X			   break;
X
X	    case 'J'    : if (selected) {
X			     if ((current = next_visible(current)) < 0)
X	                       current = visible_to_index(selected)+1;
X			   }
X			   else 
X			     current++;
X
X			   if (get_page(current))
X			     nuhead++;
X			   else
X			     nucurr++;	break;
X
X	    case 'j'    :  if (selected) {
X			     if ((current = next_visible(current)) < 0)
X	                       current = visible_to_index(selected)+1;
X			   }
X			   else {
X			     i = current;
X			     while (++current <= message_count &&
X			        (header_table[current-1].status & DELETED))
X	                       /** continue moving forward, please **/ ;
X			     if (current > message_count)
X			       current = i;	/* reset - overshot! */
X			   }
X			   if (get_page(current))
X			     nuhead++;
X			   else
X			     nucurr++;	break;
X
X	    case 'K'    :  if (selected) 
X			     current = previous_visible(current);
X	     		   else
X			     current--;
X
X			   if (get_page(current))
X			     nuhead++;
X			   else
X			     nucurr++;	break;
X
X	    case 'k'    :  if (selected) 
X			     current = previous_visible(current);
X	     		   else {
X			     i = current;
X			     while ( --current > 0 &&
X			        header_table[current-1].status & DELETED)
X	                       /* continue searching */ ;
X			     if (current <= 0) current = i;/* reset */
X	                   }
X			   if (get_page(current))
X			     nuhead++;
X			   else
X			     nucurr++;	break;
X
X	    case 'l'    :  PutLine0(LINES-3, strlen("Command: "),
X			           "Limit displayed messages by...");
X			   if (limit() != 0) {
X	                     nuhead++;
X	   		     update_title();	/* poof! */
X			   }
X			   else
X	    		     nufoot++;
X			   redraw++;
X			   break;
X
X	    case 'm'    :  PutLine0(LINES-3, strlen("Command: "), "Mail");
X			   redraw = sendmsg("", "", "", TRUE,allow_forms,FALSE); 
X			   break;
X
X	    case ctrl('J'):
X	    case ctrl('M'):PutLine0(LINES-3,strlen("Command: "),"Read Message");	
X			   fflush(stdout);
X			   define_softkeys(READ);
X
X                           redraw = show_msg(current);
X                           if (((redraw == ESCAPE) || (redraw > ' ')) &&
X				redraw < 127) {
X
X                             while ((redraw == ESCAPE) || (redraw > ' '))
X                                redraw = process_showmsg_cmd(redraw);
X			   }
X			   redraw = 1; /* always.. */
X			   (void) get_page(current);
X			   break;
X
X	    case 'n'    :  PutLine0(LINES-3,strlen("Command: "),"Next Message");
X			   fflush(stdout);
X			   define_softkeys(READ);
X
X                           redraw = show_msg(current);
X                           if (((redraw == ESCAPE) || (redraw > ' ')) &&
X				redraw < 127) {
X  
X                             while ((redraw == ESCAPE) || (redraw > ' '))
X                                redraw = process_showmsg_cmd(redraw);
X			   }
X			   redraw = 1; /* always.. */
X			   current += redraw;		
X			   if (current > message_count)
X			     current = message_count;
X			   (void) get_page(current); /* rewrites ANYway */
X			   break;
X
X	    case 'o'    :  PutLine0(LINES-3, strlen("Command: "), "Options");
X			   options();
X			   redraw++;	/* always fix da screen... */
X			   break;
X
X	    case 'p'    :  PutLine0(LINES-3, strlen("Command: "), "Print mail");
X			   fflush(stdout);
X			   if (message_count < 1) {
X			     error("No mail to print!");
X			     fflush(stdin);
X			   }
X			   else
X			     print_msg();			
X			   break;
X
X	    case 'q'    :  PutLine0(LINES-3, strlen("Command: "), "Quit");
X
X			   if (mailfile_size != bytes(infile)) {
X			     error("New Mail!  Quit cancelled...");
X			     fflush(stdin);
X	  		     if (mbox_specified == 0) unlock();
X	                   }
X		           else
X			     quit();		
X
X			   break;
X
X	    case 'r'    :  PutLine0(LINES-3, strlen("Command: "), 
X			      "Reply to message");
X			   if (current > 0) 
X	                     redraw = reply();	
X			   else {
X			     error("No mail to reply to!"); 
X			     fflush(stdin);
X			   }
X			   softkeys_on();
X			   break;
X
X	    case '>'    : /** backwards compatibility **/
X
X	    case 's'    :  if  (message_count < 1) {
X			     error("No mail to save!");
X			     fflush(stdin);
X			   }
X			   else {
X	                     PutLine0(LINES-3, strlen("Command: "),
X				      "Save Message");
X			     PutLine0(LINES-3,COLUMNS-40,
X				"(Use '?' to list your folders)");
X			     if (save(&redraw, FALSE) && resolve_mode) {
X
X			       i = current;
X			       while (++current <= message_count &&
X			             (header_table[current-1].status & DELETED))
X	                          /** continue moving forward, please **/ ;
X			       if (current > message_count)
X			         current = i;	/* reset - overshot! */
X			     
X			       if (get_page(current))
X			         nuhead++;
X			       else
X			         nucurr++;		
X			     }
X			   }
X			   ClearLine(LINES-2);		
X			   break;
X
X            case ctrl('T') :
X	    case 't'       :  if (message_count < 1) {
X			        error("no mail to tag!");
X			        fflush(stdin);
X			      }
X			      else if (ch == 't')
X			        tag_message(); 
X			      else
X			        meta_match(TAGGED);
X	                      break;
X
X	    case 'u'    :  if (message_count < 1) {
X			     error("no mail to mark as undeleted!");
X			     fflush(stdin);
X			   }
X			   else {
X	                     undelete_msg(TRUE);
X			     if (resolve_mode) 	/* move after mail resolved */
X			       if (current < message_count) {
X				 current++;
X/*************************************************************************
X **  What we've done here is to special case the "U)ndelete" command to
X **  ignore whether the next message is marked for deletion or not.  The
X **  reason is obvious upon usage - it's a real pain to undelete a series
X **  of messages without this quirk.  Thanks to Jim Davis @ HPLabs for
X **  suggesting this more intuitive behaviour.
X **
X **  The old code, for those people that might want to see what the previous
X **  behaviour was, is:
X
X			         i = current;
X			         while (++current <= message_count &&
X			            (header_table[current-1].status & DELETED))
X	                           /** continue moving forward, please ** / ;
X			         if (current > message_count)
X			           current = i;	/* reset - we overshot! * /
X**************************************************************************/
X			         if (get_page(current))
X			           nuhead++;
X			         else
X			           nucurr++;
X			       }
X			   }
X			   break;
X
X	    case ctrl('U') : if (message_count < 1) {
X			       error("No mail to undelete!");
X			       fflush(stdin);
X			     }
X			     else 
X			       meta_match(UNDELETE);
X			     break;
X
X	    case ctrl('Q') :
X	    case '\177' : 
X	    case 'x'    :  PutLine0(LINES-3, strlen("Command: "), "Exit");  
X                           fflush(stdout);              leave();
X
X	    case ctrl('L') : redraw++;	break;
X
X            case EOF :  leave();  /* Read failed, control tty died? */
X                        break;
X	    
X	    case '@'    : debug_screen();  redraw++;	break;
X	
X	    case '#'    : if (message_count) {
X			    debug_message(); 
X			    redraw++;	
X			  } 
X			  else {
X			    error("no mail to check");
X			    fflush(stdin);
X			  }
X			  break;
X
X	    case NO_OP_COMMAND : break;	/* noop for timeout loop */
X
X	    case ESCAPE : if (cursor_control) {
X			    key_offset = 1;
X			    ch = ReadCh(); 
X  
X                            if ( ch == '[' || ch == 'O')
X                            {
X                              ch = ReadCh();
X                              key_offset++;
X                            }
X  
X                            if (ch == up[key_offset]) {
X			      if (selected)
X			        current = previous_visible(current);
X			      else {
X			        i = current;
X			        while ( --current > 0 &&
X			           header_table[current-1].status & DELETED)
X	                          /* continue searching */ ;
X			        if (current <= 0) current = i;/* reset */
X			      }
X			      if (get_page(current))
X			        nuhead++;
X			      else
X			        nucurr++;			
X	                    }
X			    else if (ch == down[key_offset]) {
X			      if (selected) {
X			        if ((current = next_visible(current)) < 0)
X	                          current = visible_to_index(selected)+1;
X			      }
X			      else {
X			         i = current;
X			         while (++current <= message_count &&
X			            (header_table[current-1].status & DELETED))
X	                           /** continue moving forward, please **/ ;
X			         if (current > message_count)
X			           current = i;	/* reset - overshot! */
X			      }
X			      if (get_page(current))
X			        nuhead++;
X			      else
X			        nucurr++;			
X			    }
X			    else if (hp_terminal) { 
X
X			     switch (ch) {
X			      case 'U' :	/* <NEXT> */
X	    			 header_page++; 
X				 nuhead++;
X			         if (move_when_paged && header_page 
X			             <= (message_count / headers_per_page)) {
X			           current = header_page*headers_per_page + 1;
X			           if (selected)
X			             current = visible_to_index(current)+1;
X			         }
X				 break;
X
X			      case 'V' :       /* <PREV> */
X	    			header_page--; 
X				nuhead++;
X			        if (move_when_paged && header_page >= 0) {
X			           current = header_page*headers_per_page + 1;
X			           if (selected)
X			             current = visible_to_index(current)+1;
X			         }
X				break;
X
X			      case 'h' : 	
X			      case 'H' : 	/* <HOME UP> */
X	    		        if (selected)
X			          current = visible_to_index(1)+1;
X	                        else
X			          current = 1;
X	                        if (get_page(current))
X			          nuhead++;
X	                        else
X	                          nucurr++;
X				break;
X
X			      case 'F' : 	/* <HOME DOWN> */
X	    		        if (selected)
X			          current = visible_to_index(selected)+1;
X	                        else
X			          current = message_count;
X	                        if (get_page(current))
X			          nuhead++;
X	                        else
X	                          nucurr++;
X			        break;
X
X			      /** let's continue, what the heck... **/
X
X			      case 'A' : 	/* <UP> */
X			      case 'D' : 	/* <BACKTAB> */
X			      case 'i' : 	/* <LEFT> */
X			         if (selected)
X			           current = previous_visible(current);
X			         else {
X			           i = current;
X			           while ( --current > 0 &&
X			             header_table[current-1].status & DELETED)
X	                               /* continue searching */ ;
X			           if (current <= 0) current = i;/* reset */
X			         }
X			         if (get_page(current))
X			           nuhead++;
X			         else
X			           nucurr++;			
X				 break;
X
X			      case 'B' : 	/* <UP> */
X			      case 'I' : 	/* <BACKTAB> */
X			      case 'C' : 	/* <LEFT> */
X			         if (selected) {
X			           if ((current = next_visible(current)) < 0)
X	                             current = visible_to_index(selected)+1;
X			         }
X			         else { 
X			           i = current;
X			           while (++current <= message_count &&
X			             (header_table[current-1].status & DELETED))
X	                             /** continue moving forward, please **/ ;
X			           if (current > message_count)
X			             current = i;	/* reset - overshot! */
X				 }
X			         if (get_page(current))
X			           nuhead++;
X			         else
X			           nucurr++;			
X			         break;
X
X			      default: PutLine2(LINES-3, strlen("Command: "), 
X				          "%c%c", ESCAPE, ch);
X			     }
X			    }
X			    else /* false hit - output */
X			      PutLine2(LINES-3, strlen("Command: "), 
X				          "%c%c", ESCAPE, ch);
X			    break;
X			  }
X
X			  /* else fall into the default error message! */
X
X	    default	: if (ch > '0' && ch <= '9') {
X			    PutLine0(LINES-3, strlen("Command: "), 
X				    "New Current Message");
X			    current = read_number(ch);
X			    if (selected) {
X			      if ((current = visible_to_index(current)+1) >
X				  message_count)
X			        goto too_big;
X	                    }
X	                    if (get_page(current))
X			      nuhead++;
X	                    else
X	                      nucurr++;
X			  }
X			  else {
X	 		    error("Unknown command: Use '?' for commands");
X			    fflush(stdin);
X			  }
X	  }
X
X	  if (redraw)
X	    showscreen();
X
X	  if (current < 1) {
X	    if (message_count > 0) {
X	      error("already at message #1!");
X	      fflush(stdin);
X	      if (selected)
X	        current = compute_visible(0);	/* get to #0 */
X	      else
X	        current = 1;
X	    }
X	    else if (current < 0) {
X	      error("No messages to read!");
X	      fflush(stdin);
X	      current = 0;
X	    }
X	  }
X	  else if (current > message_count) {
X	    if (message_count > 0) {
Xtoo_big:
X	      if (selected) {
X	        error2("only %d message%s selected!", selected, 
X			plural(selected));
X	        fflush(stdin);
X	        current = compute_visible(selected);
X	      }
X	      else {
X	        error2("only %d message%s!", message_count, 
X		       plural(message_count));
X	        dprint(8, (debugfile,"[user selected %d, but only %d msgs]\n",
X			current, message_count));
X	        fflush(stdin);
X	        current = message_count;
X	      }
X	    }
X	    else {
X	      error("No messages to read!");
X	      fflush(stdin);
X	      current = 0;
X	    }
X	  }
X	  else if (selected && (i=visible_to_index(selected)) > message_count) {
X	    error2("only %d message%s selected!", selected, plural(selected));
X	    fflush(stdin);
X	    current = i+1;	/* FIXED!  Phew! */
X	  }
X	    
X	  if (nuhead) 
X	    show_headers();
X	  else if (nucurr)
X	    show_current();
X	  else if (nufoot) {
X	    if (mini_menu) {
X	      MoveCursor(LINES-7, 0);  
X              CleartoEOS();
X	      show_menu();
X	    }
X	    else {
X	      MoveCursor(LINES-4, 0);
X	      CleartoEOS();
X	    }
X	  }
X
X	} /* the BIG while loop! */
X}
X
Xdebug_screen()
X{
X	/**** spit out all the current variable settings and the table
X	      entries for the current 'n' items displayed. ****/
X
X	register int i, j;
X	char     buffer[SLEN];
X
X	ClearScreen();
X	Raw(OFF);
X
X	PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n",
X	        current, message_count);
X	PutLine2(2,0,"Header_page = %d           \t\t%d possible page(s)\n",
X		header_page, (int) (message_count / headers_per_page) + 1);
X
X	PutLine1(4,0,"\nCurrent mailfile is %s.\n\n", infile);
X
X	i = header_page*headers_per_page;	/* starting header */
X
X	if ((j = i + (headers_per_page-1)) >= message_count) 
X	  j = message_count-1;
X
X	Write_to_screen(
X"Num      From                 	Subject                         Lines  Offset\n\n",0);
X
X	while (i <= j) {
X	   sprintf(buffer, 
X	   "%3d  %-16.16s  %-40.40s  %4d  %d\n",
X		    i+1,
X	            header_table[i].from, 
X	            header_table[i].subject,
X		    header_table[i].lines,
X		    header_table[i].offset);
X	    Write_to_screen(buffer, 0);
X	  i++;
X	}
X	
X	Raw(ON);
X
X	PutLine0(LINES,0,"Press any key to return: ");
X	(void) ReadCh();
X}
X
X
Xdebug_message()
X{
X	/**** Spit out the current message record.  Include EVERYTHING
X	      in the record structure. **/
X	
X	char buffer[SLEN];
X
X	ClearScreen();
X	Raw(OFF);
X
X	Write_to_screen("\t\t\t----- Message %d -----\n\n\n\n", 1,
X		current);
X
X	Write_to_screen("Lines : %-5d\t\t\tStatus: A  C  D  E  F  N  P  T  U  V\n", 1,
X		header_table[current-1].lines);
X	Write_to_screen("            \t\t\t        c  o  e  x  o  e  r  a  r  i\n", 0);
X	Write_to_screen("            \t\t\t        t  n  l  p  r  w  i  g  g  s\n", 0);
X	Write_to_screen("            \t\t\t        n  f  d  d  m     v  d  n  i\n", 0);
X
X	sprintf(buffer, 
X		"\nOffset: %ld\t\t\t        %d  %d  %d  %d  %d  %d  %d  %d  %d  %d\n",
X		header_table[current-1].offset,
X		(header_table[current-1].status & ACTION) != 0,
X		(header_table[current-1].status & CONFIDENTIAL) != 0,
X		(header_table[current-1].status & DELETED) != 0,
X		(header_table[current-1].status & EXPIRED) != 0,
X		(header_table[current-1].status & FORM_LETTER) != 0,
X		(header_table[current-1].status & NEW) != 0,
X		(header_table[current-1].status & PRIVATE) != 0,
X		(header_table[current-1].status & TAGGED) != 0,
X		(header_table[current-1].status & URGENT) != 0,
SHAR_EOF
echo "End of part 11"
echo "File src/elm.c is continued in part 12"
echo "12" > s2_seq_.tmp
exit 0
-- 
=====================================================================
Sydney S. Weinstein, CDP, CCP                   Elm Coordinator
Datacomp Systems, Inc.				Voice: (215) 947-9900
{allegra,bellcore,bpa,vu-vlsi}!dsinc!syd	FAX:   (215) 938-0235