[comp.sources.bugs] elm 2.2 Patch #3

syd@dsinc.DSI.COM (Syd Weinstein) (04/27/89)

Summary: This is an official patch for elm 2.2 system.  Please apply it.
Priority: LOW

This fixes a number of bugs with the builtin editor. (1) It used to use
stdio functions and not curses functions to write to the screen causing
the homebrew curses to loose track of where the cursor was - which
showed up when trying to back up over input, (2) the ~m and ~f commands
were nearly completely broken, (3) expanded addresses are displayed
under a wider range of appropriate circumstances, (4) the index screen
needed to be redrawn when the editor is killed by two interrupts. A related
curses bug was also fixed, and user messages in the builtin editor were
made consistent.
From: Rob Bernardo <clib!rob>

Fix:	From rn, say "| patch -p -N -d DIR", where DIR is your elm source
	directory.  Outside of rn, say "cd DIR; patch -p -N <thisarticle".
	If you don't have the patch program, apply the following by hand,
	or get patch (version 2.0, latest patchlevel).

	After patching:
		make
		make install

	If patch indicates that patchlevel is the wrong version, you may need
	to apply one or more previous patches, or the patch may already
	have been applied.  See the patchlevel.h file to find out what has or
	has not been applied.  In any event, don't continue with the patch.

	If you are missing previous patches they can be obtained from me:

	Syd Weinstein
	syd@dsinc.UUCP

	The patches are available from the dsinc archive server
	Send the following message to archive-server@dsinc.UUCP for
	a list of available patches:

	Subject: patch list
	send index elm

Index: hdrs/patchlevel.h
Prereq:
*** ../elm2.2/hdrs/patchlevel.h	Mon Apr 24 20:03:57 1989
--- hdrs/patchlevel.h	Mon Apr 24 21:18:04 1989
***************
*** 1 ****
! #define PATCHLEVEL 2
--- 1 ----
! #define PATCHLEVEL 3

Index: src/curses.c
Prereq:
*** ../elm2.2/src/curses.c	Mon Apr 24 20:04:01 1989
--- src/curses.c	Mon Apr 24 21:18:36 1989
***************
*** 1,8 ****
  
! static char rcsid[] = "@(#)$Id: curses.c,v 2.16 89/04/24 20:00:58 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.16 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
--- 1,8 ----
  
! static char rcsid[] = "@(#)$Id: curses.c,v 2.17 89/04/24 21:18:29 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.17 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
***************
*** 14,19 ****
--- 14,31 ----
   *
   *******************************************************************************
   * $Log:	curses.c,v $
+  * Revision 2.17  89/04/24  21:18:29  syd
+  * This fixes a number of bugs with the builtin editor. (1) It used to use
+  * stdio functions and not curses functions to write to the screen causing
+  * the homebrew curses to loose track of where the cursor was - which
+  * showed up when trying to back up over input, (2) the ~m and ~f commands
+  * were nearly completely broken, (3) expanded addresses are displayed
+  * under a wider range of appropriate circumstances, (4) the index screen
+  * needed to be redrawn when the editor is killed by two interrupts. A related
+  * curses bug was also fixed, and user messages in the builtin editor were
+  * made consistent.
+  * From: Rob Bernardo <clib!rob>
+  * 
   * Revision 2.16  89/04/24  20:00:58  syd
   * add back some 8bit functions
   * 
***************
*** 617,623 ****
  	if(ch == '\n') {
  	  if (!autonewlinedlastchar) {
  	    putchar('\n');
! 	    _line = min(_line+1, LINES-1);
  	  }
  
  	/* if return, move to column 0 */
--- 629,635 ----
  	if(ch == '\n') {
  	  if (!autonewlinedlastchar) {
  	    putchar('\n');
! 	    _line = min(_line+1, LINES);
  	  }
  
  	/* if return, move to column 0 */

Index: src/editmsg.c
Prereq:
*** ../elm2.2/src/editmsg.c	Mon Apr 24 20:04:02 1989
--- src/editmsg.c	Mon Apr 24 21:18:43 1989
***************
*** 1,8 ****
  
! static char rcsid[] = "@(#)$Id: editmsg.c,v 2.13 89/04/24 19:08:50 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.13 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
--- 1,8 ----
  
! static char rcsid[] = "@(#)$Id: editmsg.c,v 2.14 89/04/24 21:18:36 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.14 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
***************
*** 14,19 ****
--- 14,31 ----
   *
   *******************************************************************************
   * $Log:	editmsg.c,v $
+  * Revision 2.14  89/04/24  21:18:36  syd
+  * This fixes a number of bugs with the builtin editor. (1) It used to use
+  * stdio functions and not curses functions to write to the screen causing
+  * the homebrew curses to loose track of where the cursor was - which
+  * showed up when trying to back up over input, (2) the ~m and ~f commands
+  * were nearly completely broken, (3) expanded addresses are displayed
+  * under a wider range of appropriate circumstances, (4) the index screen
+  * needed to be redrawn when the editor is killed by two interrupts. A related
+  * curses bug was also fixed, and user messages in the builtin editor were
+  * made consistent.
+  * From: Rob Bernardo <clib!rob>
+  * 
   * Revision 2.13  89/04/24  19:08:50  syd
   * Change direct output of newline to curses call to allow curses to know
   * buffer has been reset
***************
*** 55,61 ****
  
  	char buffer[SLEN];
  	register int stat, return_value = 0;
-         int     old_raw;
  
  	buffer[0] = '\0';
  
--- 67,72 ----
***************
*** 70,78 ****
  	if (strlen(buffer) == 0)
  	  sprintf(buffer,"%s %s", editor, filename);
  
-       if( (old_raw = RawState()) == ON)
- 	Raw(OFF);
- 
  	chown(filename, userid, groupid);	/* file was owned by root! */
  
  	if (cursor_control)
--- 81,86 ----
***************
*** 93,104 ****
  	if (cursor_control)
  	  transmit_functions(ON);		/* function keys are local */
  	
-       if ( old_raw == ON)
- 	Raw(ON);
- 
  	return(return_value);
  }
  
  extern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], 
  	    expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING], 
  	    bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
--- 101,112 ----
  	if (cursor_control)
  	  transmit_functions(ON);		/* function keys are local */
  	
  	return(return_value);
  }
  
+ #define SIMPLE_CONTINUE	 "(Continue.)\n\r"
+ #define POST_ED_CONTINUE "(Continue entering message, ^D or '.' to end.)\n\r"
+ 
  extern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], 
  	    expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING], 
  	    bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
***************
*** 122,128 ****
  	FILE *edit_fd;
  	char buffer[SLEN], editor_name[SLEN], buf[SLEN];
  	int      edit_interrupt();
-         int     old_raw;
  #ifdef VOIDSIG
  	void	(*oldint)(), (*oldquit)();
  #else
--- 130,135 ----
***************
*** 129,137 ****
  	int	(*oldint)(), (*oldquit)();
  #endif
  
-         if (( old_raw = RawState()) == ON)
- 	Raw(OFF);
- 
  	if ((edit_fd = fopen(filename, "a")) == NULL) {
  	  error2("Couldn't open %s for appending [%s].", filename, 
  		  error_name(errno));
--- 136,141 ----
***************
*** 140,147 ****
  		"Error encountered trying to open file %s;\n", filename));
  	  dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
  		    error_description(errno)));
-           if ( old_raw == ON)
- 	  Raw(ON);
  	  return(1);
  	}
  
--- 144,149 ----
***************
*** 148,160 ****
  	/** is there already text in this file? **/
  
  	if (fsize(edit_fd) > 0L)
! 	  printf(
!          "\nPlease continue message, ^D or '.' to end, %cp to list, %c? for help;\n\n",
  		escape_char, escape_char);
  	else
! 	  printf(
!           "\nPlease enter message, ^D or '.' to end, or %c? <RETURN> for help;\n\n",
  		escape_char);
  
  	oldint  = signal(SIGINT,  edit_interrupt);
  	oldquit = signal(SIGQUIT, edit_interrupt);
--- 150,164 ----
  	/** is there already text in this file? **/
  
  	if (fsize(edit_fd) > 0L)
! 	  sprintf(buf,
! "\n\rPlease continue message, ^D or '.' to end, %cp to list, %c? for help.\n\r\n\r",
  		escape_char, escape_char);
  	else
! 	  sprintf(buf,
! 	"\n\rPlease enter message, ^D or '.' to end, or %c? for help.\n\r\n\r",
  		escape_char);
+ 	CleartoEOS();
+ 	Write_to_screen(buf, 0);
  
  	oldint  = signal(SIGINT,  edit_interrupt);
  	oldquit = signal(SIGQUIT, edit_interrupt);
***************
*** 163,169 ****
  
  	if (setjmp(edit_location) != 0) {
  	  if (interrupts_while_editing > 1) {
- 	    Raw(ON);
  
  	    (void) signal(SIGINT,  oldint);
  	    (void) signal(SIGQUIT, oldquit);
--- 167,172 ----
***************
*** 175,182 ****
  	  goto more_input;	/* read input again, please! */
  	}
  	
- raw_input : Raw(ON);
- 
  more_input: buffer[0] = '\0';
  
  	while (optionally_enter(buffer, -1,-1, FALSE, FALSE) == 0) {
--- 178,183 ----
***************
*** 186,216 ****
  	  if (strcmp(buffer, ".") == 0)
  	    break;	/* '.' is as good as a ^D to us dumb programs :-) */
  	  if (buffer[0] == escape_char) {
- 	    Raw(OFF);
  	    switch (tolower(buffer[1])) {
                case '?' : tilde_help();
!                        printf("(continue)\n"); goto raw_input;
  
  	      case TILDE_ESCAPE: move_left(buffer, 1); 
! 			  Raw(ON); 		goto tilde_input;	/*!!*/
  
! 	      case 't' : get_with_expansion("\nTo: ", to, expanded_to, buffer);
! 			 goto raw_input;
! 	      case 'b' : get_with_expansion("\nBcc: ",bcc,expanded_bcc, buffer);
! 			 goto raw_input;
! 	      case 'c' : get_with_expansion("\nCc: ", cc, expanded_cc, buffer);
! 			 goto raw_input;
! 	      case 's' : get_with_expansion("\nSubject: ", subject,NULL,buffer);
!    			 goto raw_input;
  
! 	      case 'h' : get_with_expansion("\nTo: ", to, expanded_to, NULL);	
  	                 get_with_expansion("Cc: ", cc, expanded_cc, NULL);
! 	                 get_with_expansion("Bcc: ", bcc,expanded_bcc, NULL);
! 	                 get_with_expansion("Subject: ", subject,NULL, NULL);
! 			 goto raw_input;
  
  	      case 'r' : read_in_file(edit_fd, (char *) buffer + 2, 1);
! 		  	 goto raw_input;
  	      case 'e' : if (strlen(emacs_editor) > 0) 
  	                   if (access(emacs_editor, ACCESS_EXISTS) == 0) {
  	                     strcpy(buffer, editor);
--- 187,222 ----
  	  if (strcmp(buffer, ".") == 0)
  	    break;	/* '.' is as good as a ^D to us dumb programs :-) */
  	  if (buffer[0] == escape_char) {
  	    switch (tolower(buffer[1])) {
                case '?' : tilde_help();
! 			 goto more_input;
  
  	      case TILDE_ESCAPE: move_left(buffer, 1); 
! 			  	 goto tilde_input;	/*!!*/
  
! 	      case 't' : get_with_expansion("\n\rTo: ",
! 	      		   to, expanded_to, buffer);
! 			 goto more_input;
! 	      case 'b' : get_with_expansion("\n\rBcc: ",
! 			   bcc, expanded_bcc, buffer);
! 			 goto more_input;
! 	      case 'c' : get_with_expansion("\n\rCc: ",
! 			   cc, expanded_cc, buffer);
! 			 goto more_input;
! 	      case 's' : get_with_expansion("\n\rSubject: ",
! 			   subject,NULL,buffer);
!    			 goto more_input;
  
! 	      case 'h' : get_with_expansion("\n\rTo: ", to, expanded_to, NULL);	
  	                 get_with_expansion("Cc: ", cc, expanded_cc, NULL);
! 	                 get_with_expansion("Bcc: ",
! 			   bcc,expanded_bcc, NULL);
! 	                 get_with_expansion("Subject: ",
! 			   subject, NULL, NULL);
! 			 goto more_input;
  
  	      case 'r' : read_in_file(edit_fd, (char *) buffer + 2, 1);
! 		  	 goto more_input;
  	      case 'e' : if (strlen(emacs_editor) > 0) 
  	                   if (access(emacs_editor, ACCESS_EXISTS) == 0) {
  	                     strcpy(buffer, editor);
***************
*** 219,247 ****
  			     (void) edit_the_message(filename,0);
  			     strcpy(editor, buffer);
  			     edit_fd = fopen(filename, "a");
!                              printf("(continue entering message, ^D or '.' to end)\n");
! 	                     goto raw_input;
  		           }
  		           else
! 	                     printf(
! 			  "\n(Can't find Emacs on this system!  continue)\n");
  			 else
! 			   printf(
! 			  "\n(Don't know where Emacs would be...continue)\n");	
! 			 goto raw_input;
  
! 	       case 'v' : strcpy(buffer, editor);
  			  strcpy(editor, default_editor);
  			  fclose(edit_fd);
  			  (void) edit_the_message(filename,0);
  			  strcpy(editor, buffer);
  			  edit_fd = fopen(filename, "a");
!                           printf("(continue entering message, ^D or '.' to end)\n");
! 	                  goto raw_input;
  
! 	       case 'o' : printf("\nPlease enter the name of the editor : ");
  			  editor_name[0] = '\0';
  			  optionally_enter(editor_name,-1,-1, FALSE, FALSE);
  	                  if (strlen(editor_name) > 0) {
  	                    strcpy(buffer, editor);
  			    strcpy(editor, editor_name);
--- 225,258 ----
  			     (void) edit_the_message(filename,0);
  			     strcpy(editor, buffer);
  			     edit_fd = fopen(filename, "a");
!                              Write_to_screen(POST_ED_CONTINUE, 0);
! 	                     goto more_input;
  		           }
  		           else
! 	                     Write_to_screen(
! 			"\n\r(Can't find Emacs on this system! Continue.)\n\r",
! 			0);
  			 else
! 			   Write_to_screen(
! 			"\n\r(Don't know where Emacs would be. Continue.)\n\r",
! 			0);	
! 			 goto more_input;
  
! 	       case 'v' : NewLine();
! 			  strcpy(buffer, editor);
  			  strcpy(editor, default_editor);
  			  fclose(edit_fd);
  			  (void) edit_the_message(filename,0);
  			  strcpy(editor, buffer);
  			  edit_fd = fopen(filename, "a");
!                           Write_to_screen(POST_ED_CONTINUE, 0);
! 	                  goto more_input;
  
! 	       case 'o' : Write_to_screen(
! 			     "\n\rPlease enter the name of the editor: ", 0);
  			  editor_name[0] = '\0';
  			  optionally_enter(editor_name,-1,-1, FALSE, FALSE);
+ 			  NewLine();
  	                  if (strlen(editor_name) > 0) {
  	                    strcpy(buffer, editor);
  			    strcpy(editor, editor_name);
***************
*** 249,264 ****
  			    (void) edit_the_message(filename,0);
  			    strcpy(editor, buffer);
  			    edit_fd = fopen(filename, "a");
!                             printf("(continue entering message, ^D or '.' to end)\n");
! 	                    goto raw_input;
  		          }
! 	  		  printf("(continue)\n");
! 	                  goto raw_input; 
  
! 		case '<' : putchar('\n');
  			   if (strlen(buffer) < 3)
! 			     (void) printf(
! 	           "(you need to use a specific command here.  Continue...)\n");
  			   else {
  			     sprintf(buf, " > %s.%d 2>&1", temp_edit, getpid());
  			     strcat(buffer, buf);
--- 260,275 ----
  			    (void) edit_the_message(filename,0);
  			    strcpy(editor, buffer);
  			    edit_fd = fopen(filename, "a");
!                             Write_to_screen(POST_ED_CONTINUE, 0);
! 	                    goto more_input;
  		          }
! 	  		  Write_to_screen(SIMPLE_CONTINUE, 0);
! 	                  goto more_input; 
  
! 		case '<' : NewLine();
  			   if (strlen(buffer) < 3)
! 			     Write_to_screen(
! 		 "(You need to use a specific command here. Continue.)\n\r");
  			   else {
  			     sprintf(buf, " > %s.%d 2>&1", temp_edit, getpid());
  			     strcat(buffer, buf);
***************
*** 267,298 ****
  	      	             read_in_file(edit_fd, (char *) buffer + 3, 0);
  			     (void) unlink((char *) buffer+3);
  			   }
! 	                   goto raw_input; 
  
! 		case '!' : putchar('\n');
  			   if (strlen(buffer) < 3) 
  			     (void) system_call(shell, USER_SHELL, TRUE);
  			   else
  	                     (void) system_call((char *) buffer+2,
  			       USER_SHELL, TRUE);
! 	    		   printf("(continue)\n");
! 			   goto raw_input;
  
  		 case 'm' : /* same as 'f' but with leading prefix added */
  
  	         case 'f' : /* this can be directly translated into a
  			       'readmsg' call with the same params! */
! 			    putchar('\n');
  			    read_in_messages(edit_fd, (char *) buffer + 1);
! 			    goto raw_input;
  
  	         case 'p' : /* print out message so far.  Soooo simple! */
  			    print_message_so_far(edit_fd, filename);
! 			    goto raw_input;
  
! 		 default  : printf(
! 			     "\n(don't know what %c%c is.  Try %c? for help)\n",
  				    escape_char, buffer[1], escape_char);
  	       }
  	     }
  	     else {
--- 278,310 ----
  	      	             read_in_file(edit_fd, (char *) buffer + 3, 0);
  			     (void) unlink((char *) buffer+3);
  			   }
! 	                   goto more_input; 
  
! 		case '!' : NewLine();
  			   if (strlen(buffer) < 3) 
  			     (void) system_call(shell, USER_SHELL, TRUE);
  			   else
  	                     (void) system_call((char *) buffer+2,
  			       USER_SHELL, TRUE);
! 	    		   Write_to_screen(SIMPLE_CONTINUE, 0);
! 			   goto more_input;
  
  		 case 'm' : /* same as 'f' but with leading prefix added */
  
  	         case 'f' : /* this can be directly translated into a
  			       'readmsg' call with the same params! */
! 			    NewLine();
  			    read_in_messages(edit_fd, (char *) buffer + 1);
! 			    goto more_input;
  
  	         case 'p' : /* print out message so far.  Soooo simple! */
  			    print_message_so_far(edit_fd, filename);
! 			    goto more_input;
  
! 		 default  : sprintf(buf,
! 			 "\n\r(Don't know what %c%c is. Try %c? for help.)\n\r",
  				    escape_char, buffer[1], escape_char);
+ 			    Write_to_screen(buf, 0);
  	       }
  	     }
  	     else {
***************
*** 303,312 ****
  	  buffer[0] = '\0';
  	}
  
- 	printf("\n<end-of-message>\n\r\n\r");
  
!         if ( old_raw == ON)
! 	Raw(ON);
  
  	(void) signal(SIGINT,  oldint);
  	(void) signal(SIGQUIT, oldquit);
--- 315,322 ----
  	  buffer[0] = '\0';
  	}
  
  
! 	Write_to_screen("\n\r<end-of-message>\n\r\n\r\n\r\n\r", 0);
  
  	(void) signal(SIGINT,  oldint);
  	(void) signal(SIGQUIT, oldquit);
***************
*** 321,370 ****
  {
  	/* a simple routine to print out what is available at this level */
  
!         int     old_raw;
  
!         if ( (old_raw = RawState()) == ON)
! 	Raw(OFF);
  
! 	printf("\n(Available options at this point are;\n\n");
! 	printf("\t%c?\tPrint this help menu\n", escape_char);
! 	if (escape_char == TILDE_ESCAPE)
! 	  printf("\t~~\tAdd line prefixed by a single '~' character\n");
! 	/* doesn't make sense otherwise... */
! 
! 	printf("\t%cb\tChange the addresses in the Blind-carbon-copy list\n",
  	  escape_char);
  
! 	printf("\t%cc\tChange the addresses in the Carbon-copy list\n",
  		escape_char);
! 	printf("\t%ce\tInvoke the Emacs editor on the message, if possible\n",
  		escape_char);
! 	printf("\t%cf\tadd the specified list of messages, or current\n",
  		escape_char);
! 	printf("\t%ch\tchange all available headers (to,cc,bcc,subject)\n",
  		escape_char);
! 	printf("\t%cm\tsame as '%cf', but with the current 'prefix'\n",
  		escape_char, escape_char);
! 	printf("\t%co\tInvoke a user specified editor on the message\n",
  		escape_char);
! 	printf("\t%cp\tprint out message as typed in so far\n", escape_char);
! 	printf("\t%cr\tRead in the specified file\n", escape_char);
! 	printf("\t%cs\tChange the subject of the message\n", escape_char);
! 	printf("\t%ct\tChange the addresses in the To list\n",
  		escape_char);
! 	printf("\t%cv\tInvoke the Vi visual editor on the message\n\n",
  		escape_char);
! 	printf(
!           "\t%c!\texecute a unix command (or give a shell if no command)\n",
  	  escape_char);
! 	printf(
!           "\t%c<\texecute a unix command adding the output to the message\n\n",
  	  escape_char);
! 	printf(
! 	  "\t.  \tby itself on a line (or a control-D) ends the message\n\n");
! 
!         if ( old_raw == ON)
! 	Raw(ON);
  }
  
  read_in_file(fd, filename, show_user_filename)
--- 331,403 ----
  {
  	/* a simple routine to print out what is available at this level */
  
! 	char	buf[SLEN];
  
! 	Write_to_screen("\n\r(Available options at this point are:\n\r\n\r", 0);
! 	sprintf(buf, "\t%c?\tPrint this help menu.\n\r", escape_char);
! 	Write_to_screen(buf, 0);
! 	if (escape_char == TILDE_ESCAPE) /* doesn't make sense otherwise... */
! 	  Write_to_screen(
! 	      "\t~~\tAdd line prefixed by a single '~' character.\n\r", 0);
  
! 	sprintf(buf,
! 	  "\t%cb\tChange the addresses in the Blind-carbon-copy list.\n\r",
  	  escape_char);
+ 	Write_to_screen(buf, 0);
  
! 	sprintf(buf,
! 		"\t%cc\tChange the addresses in the Carbon-copy list.\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 	      "\t%ce\tInvoke the Emacs editor on the message, if possible.\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%cf\tAdd the specified message or current.\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 	      "\t%ch\tChange all available headers (to, cc, bcc, subject).\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%cm\tSame as '%cf', but with the current 'prefix'.\n\r",
  		escape_char, escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%co\tInvoke a user specified editor on the message.\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 	      "\t%cp\tPrint out message as typed in so far.\n\r", escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%cr\tRead in the specified file.\n\r", escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%cs\tChange the subject of the message.\n\r", escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%ct\tChange the addresses in the To list.\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
! 		"\t%cv\tInvoke the Vi visual editor on the message.\n\r",
  		escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
!           "\t%c!\tExecute a unix command (or give a shell if no command).\n\r",
  	  escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
!       "\t%c<\tExecute a unix command adding the output to the message.\n\r",
  	  escape_char);
! 	Write_to_screen(buf, 0);
! 	sprintf(buf,
!       "\t.  \tby itself on a line (or a control-D) ends the message).\n\r");
! 	Write_to_screen(buf, 0);
! 	Write_to_screen("Continue.)\n\r", 0);
  }
  
  read_in_file(fd, filename, show_user_filename)
***************
*** 388,399 ****
  	expand_env(myfname, buffer);
  
  	if (strlen(myfname) == 0) {
! 	  printf("\n(no filename specified for file read!  Continue...)\n");
  	  return;
  	}
  
  	if ((myfd = fopen(myfname,"r")) == NULL) {
! 	  printf("\n(Couldn't read file '%s'!  Continue...)\n",
  		 myfname);
  	  return;
  	}
--- 421,433 ----
  	expand_env(myfname, buffer);
  
  	if (strlen(myfname) == 0) {
! 	  Write_to_screen(
! 	      "\n\r(No filename specified for file read! Continue.)\n\r", 0);
  	  return;
  	}
  
  	if ((myfd = fopen(myfname,"r")) == NULL) {
! 	  Write_to_screen("\n\r(Couldn't read file '%s'! Continue.)\n\r", 1,
  		 myfname);
  	  return;
  	}
***************
*** 409,419 ****
  	fclose(myfd);
  
  	if (show_user_filename)
! 	  printf("\n(added %d line%s from file %s.  Please continue...)\n",
  		lines, plural(lines), myfname);
  	else
! 	  printf("\n(added %d line%s to message.  Please continue...)\n",
  		lines, plural(lines));
  
  	return;
  }
--- 443,456 ----
  	fclose(myfd);
  
  	if (show_user_filename)
! 	  sprintf(buffer,
! 		"\n\r(Added %d line%s from file %s. Continue.)\n\r",
  		lines, plural(lines), myfname);
  	else
! 	  sprintf(buffer,
! 		"\n\r(Added %d line%s to message. Continue.)\n\r",
  		lines, plural(lines));
+ 	Write_to_screen(buffer, 0);
  
  	return;
  }
***************
*** 436,463 ****
  	fclose(edit_fd);
  
  	if ((edit_fd = fopen(filename, "r")) == NULL) {
! 	  printf("\nMayday!  Mayday!  Mayday!\n");
! 	  printf("\nPanic: Can't open file for reading!  Bail!\n");
  	  emergency_exit();
  	}
  
! 	printf("\nTo: %s\n", format_long(to, 4));
! 	printf("Cc: %s\n", format_long(cc, 4));
! 	printf("Bcc: %s\n", format_long(bcc, 5));
! 	printf("Subject: %s\n\n", subject);
  
  	while (fgets(buffer, SLEN, edit_fd) != NULL)
! 	  printf("%s", buffer);
  
  	fclose(edit_fd);
  
  	if ((edit_fd = fopen(filename, "a")) == NULL) {
! 	  printf("Mayday!  Mayday!  Abandon Ship!  Aiiieeeeee\n");
! 	  printf("\nPanic: Can't reopen file for appending!\n");
  	  emergency_exit();
  	}
  
! 	printf("\n(continue entering message, please)\n");
  }
  
  read_in_messages(fd, buffer)
--- 473,501 ----
  	fclose(edit_fd);
  
  	if ((edit_fd = fopen(filename, "r")) == NULL) {
! 	  Write_to_screen("\n\rMayday!  Mayday!  Mayday!\n\r", 0);
! 	  Write_to_screen("\n\rPanic: Can't open file for reading!  Bail!\n\r",
! 	      0);
  	  emergency_exit();
  	}
  
! 	Write_to_screen("\n\rTo: %s\n\r", 1, format_long(to, 4));
! 	Write_to_screen("Cc: %s\n\r", 1, format_long(cc, 4));
! 	Write_to_screen("Bcc: %s\n\r", 1, format_long(bcc, 5));
! 	Write_to_screen("Subject: %s\n\r\n\r", 1, subject);
  
  	while (fgets(buffer, SLEN, edit_fd) != NULL)
! 	  Write_to_screen(buffer, 0);
  
  	fclose(edit_fd);
  
  	if ((edit_fd = fopen(filename, "a")) == NULL) {
! 	  Write_to_screen("Mayday!  Mayday!  Abandon Ship!  Aiiieeeeee\n\r", 0);
! 	  Write_to_screen("\n\rPanic: Can't reopen file for appending!\n\r", 0);
  	  emergency_exit();
  	}
  
! 	Write_to_screen("\n\r(Continue entering message.)\n\r", 0);
  }
  
  read_in_messages(fd, buffer)
***************
*** 472,493 ****
  	**/
  
  	FILE *myfd, *popen();
! 	char  local_buffer[SLEN];
  	register int lines = 0, add_prefix=0, mindex;
  
  	if (add_prefix = (tolower(buffer[0]) == 'm'))
  		buffer++;
  
! 	if (! isdigit(buffer[0])) 
! 	  sprintf(local_buffer, "%s %s", readmsg, buffer);
! 	else {
! 	  mindex = atoi(buffer);	/* map requested # to real # */
! 	  sprintf(local_buffer, "%s %d", readmsg, 
  		  headers[mindex-1]->index_number);
- 	}
  
  	if ((myfd = popen(local_buffer, "r")) == NULL) {
! 	   printf("(can't get to 'readmsg' command.  Sorry...)\n");
  	   return;	
  	}
  
--- 510,555 ----
  	**/
  
  	FILE *myfd, *popen();
! 	char  local_buffer[SLEN], *arg;
  	register int lines = 0, add_prefix=0, mindex;
  
  	if (add_prefix = (tolower(buffer[0]) == 'm'))
  		buffer++;
  
! 	/* strip whitespace to get argument */
! 	for(arg = &buffer[1]; whitespace(*arg); arg++)
! 		;
! 
! 	/* if no argument or begins with a digit, then retrieve the
! 	 * appropriate message from the current folder, else
! 	 * just take the arguments literally for readmsg.
! 	 */
! 	if(isdigit(*arg) || *arg == '\0') {
! 	  if(message_count < 1) {
! 	    Write_to_screen("(No messages to read in! Continue.)\n\r", 0);
! 	    return;
! 	  }
! 	  if((mindex = atoi(arg)) == 0)	/* no argument - read in current msg */
! 	    mindex = current;
! 	  else if(mindex < 1 || mindex > message_count) {
! 	    sprintf(local_buffer,
! 	      "(Valid messsage numbers are between 1 and %d. Continue.)\n\r",
! 	      message_count);
! 	    Write_to_screen(local_buffer, 0);
! 	    return;
! 	  }
! 
! 	  sprintf(local_buffer, "%s -f %s %d", readmsg, cur_folder,
  		  headers[mindex-1]->index_number);
  
+ 	} else
+ 	  sprintf(local_buffer, "%s %s", readmsg, arg);
+ 
+ 
+ 	/* now get output of readmsg */
  	if ((myfd = popen(local_buffer, "r")) == NULL) {
! 	   Write_to_screen("(Can't find 'readmsg' command! Continue.)\n\r",
! 	       0);
  	   return;	
  	}
  
***************
*** 504,513 ****
  	pclose(myfd);
  	
  	if (lines == 0)
! 	  printf("(Couldn't add the requested message.   Continue)\n");
  	else
! 	  printf("(added %d line%s to message...  Please continue)\n",
  		lines, plural(lines));
  
  	return;
  }
--- 566,578 ----
  	pclose(myfd);
  	
  	if (lines == 0)
! 	  sprintf(local_buffer,
! 	 	 "(Couldn't add the requested message. Continue.)\n\r");
  	else
! 	  sprintf(local_buffer,
! 		"(Added %d line%s to message. Continue.)\n\r",
  		lines, plural(lines));
+ 	Write_to_screen(local_buffer, 0);
  
  	return;
  }
***************
*** 520,533 ****
  	    this puppy out!  (sourcebuf could be an initial addition)
  	**/
  
! 	char mybuffer[VERY_LONG_STRING];
!         int     old_raw;
  
-         if ( (old_raw = RawState()) == OFF)
- 	  Raw(ON);
- 
- 	printf(prompt);	fflush(stdout);	/* output! */
- 
  	if (sourcebuf != NULL) {
  	  while (!whitespace(*sourcebuf) && *sourcebuf != '\0') 
  	    sourcebuf++;
--- 585,592 ----
  	    this puppy out!  (sourcebuf could be an initial addition)
  	**/
  
! 	Write_to_screen(prompt, 0);	fflush(stdout);	/* output! */
  
  	if (sourcebuf != NULL) {
  	  while (!whitespace(*sourcebuf) && *sourcebuf != '\0') 
  	    sourcebuf++;
***************
*** 541,561 ****
  	  }
  	}
  
- 	strcpy(mybuffer, buffer);
- 
  	optionally_enter(buffer, -1, -1, TRUE, FALSE);	/* already data! */
  
!         if ( old_raw == OFF)
!           Raw(OFF);
  
- 	putchar('\n');
- 
- 	/** if it's changed and we're supposed to expand addresses... **/
- 
- 	if (strcmp(buffer, mybuffer) != 0 && expanded_buffer != NULL) 
- 	  if (build_address(strip_commas(buffer), expanded_buffer))
- 	    printf("%s%s\n\r", prompt, expanded_buffer);
- 
  	return;
  }
  
--- 600,614 ----
  	  }
  	}
  
  	optionally_enter(buffer, -1, -1, TRUE, FALSE);	/* already data! */
  
! 	if(expanded_buffer != NULL) {
! 	  build_address(strip_commas(buffer), expanded_buffer);
! 	  if(*expanded_buffer != '\0')
! 	    Write_to_screen("%s%s", 2, prompt, expanded_buffer);
! 	}
! 	NewLine();
  
  	return;
  }
  
***************
*** 570,576 ****
  	signal(SIGQUIT, edit_interrupt);
  
  	if (interrupts_while_editing++ == 0)
! 	  printf("(Interrupt.  One more to cancel this letter...)\n\r");
  
  	longjmp(edit_location, 1);		/* get back */
  }
--- 623,632 ----
  	signal(SIGQUIT, edit_interrupt);
  
  	if (interrupts_while_editing++ == 0)
! 	  Write_to_screen("(Interrupt. One more to cancel this letter.)\n\r",
! 	  	0);
! 	else
! 	  Write_to_screen("(Interrupt. Letter cancelled.)\n\r", 0);
  
  	longjmp(edit_location, 1);		/* get back */
  }

Index: src/in_utils.c
Prereq:
*** ../elm2.2/src/in_utils.c	Mon Apr 24 20:04:03 1989
--- src/in_utils.c	Mon Apr 24 21:18:48 1989
***************
*** 1,8 ****
  
! static char rcsid[] = "@(#)$Id: in_utils.c,v 2.14 89/04/24 19:48:39 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.14 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
--- 1,8 ----
  
! static char rcsid[] = "@(#)$Id: in_utils.c,v 2.15 89/04/24 21:18:45 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.15 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
***************
*** 14,19 ****
--- 14,31 ----
   *
   *******************************************************************************
   * $Log:	in_utils.c,v $
+  * Revision 2.15  89/04/24  21:18:45  syd
+  * This fixes a number of bugs with the builtin editor. (1) It used to use
+  * stdio functions and not curses functions to write to the screen causing
+  * the homebrew curses to loose track of where the cursor was - which
+  * showed up when trying to back up over input, (2) the ~m and ~f commands
+  * were nearly completely broken, (3) expanded addresses are displayed
+  * under a wider range of appropriate circumstances, (4) the index screen
+  * needed to be redrawn when the editor is killed by two interrupts. A related
+  * curses bug was also fixed, and user messages in the builtin editor were
+  * made consistent.
+  * From: Rob Bernardo <clib!rob>
+  * 
   * Revision 2.14  89/04/24  19:48:39  syd
   * put back in some 8bit support
   * From: Marius Olafsson, University of Iceland
***************
*** 113,120 ****
  	    what the user types.   The various flags are:
  	         string    is the buffer to use (with optional initial value)
  	 	 x,y	   is the location we're at on the screen (-1,-1 means
! 			   that we can't use this info and need to explicitly
! 			   use backspace-space-backspace sequences)
  		 append_current  means that we have an initial string and that
  			   the cursor should be placed at the END of the line,
  			   not the beginning (the default).
--- 125,132 ----
  	    what the user types.   The various flags are:
  	         string    is the buffer to use (with optional initial value)
  	 	 x,y	   is the location we're at on the screen (-1,-1 means
! 			   that we can't use this info and need to find out
! 			   the current location)
  		 append_current  means that we have an initial string and that
  			   the cursor should be placed at the END of the line,
  			   not the beginning (the default).
***************
*** 125,149 ****
  	**/
  
  	int ch;
! 	register int ch_count = 0, iindex = 0,
! 	  use_cursor_control, escaped = OFF;
  
  	clearerr(stdin);
  
  	if(!passwd) {
! 	  if(use_cursor_control = (x >=0 && y >= 0))
! 	    PutLine1(x, y, "%s", string);	
! 	  else
! 	    printf("%s", string);
  	}
  
  	CleartoEOLN();
  
  	if (! append_current) {
! 	  if (use_cursor_control)
! 	    MoveCursor(x,y);
! 	  else if(!passwd)
! 	    non_destructive_back_up(strlen(string));
  	}
  	else
  	  iindex = strlen(string);
--- 137,156 ----
  	**/
  
  	int ch;
! 	register int ch_count = 0, iindex = 0, escaped = OFF;
  
  	clearerr(stdin);
  
  	if(!passwd) {
! 	  if(!(x >=0 && y >= 0))
! 	    GetXYLocation(&x, &y);
! 	  PutLine1(x, y, "%s", string);	
  	}
  
  	CleartoEOLN();
  
  	if (! append_current) {
! 	  MoveCursor(x,y);
  	}
  	else
  	  iindex = strlen(string);
***************
*** 237,248 ****
  	  else if (!passwd && ch == ctrl('R')) {
  	    escaped = OFF;
  	    string[iindex] = '\0';
! 	    if (use_cursor_control) {
! 	      PutLine1(x,y, "%s", string);	
! 	      CleartoEOLN();
! 	    }
! 	    else
! 	      printf("\n\r%s", string);	
  	  }
  	  else if (!escaped && ch == kill_line) {
  	    /* needed to test if escaped since kill_line character could
--- 244,251 ----
  	  else if (!passwd && ch == ctrl('R')) {
  	    escaped = OFF;
  	    string[iindex] = '\0';
! 	    PutLine1(x,y, "%s", string);	
! 	    CleartoEOLN();
  	  }
  	  else if (!escaped && ch == kill_line) {
  	    /* needed to test if escaped since kill_line character could
***************
*** 249,258 ****
  	     * be a desired valid printing character */
  	    escaped = OFF;
  	    if(!passwd) {
! 	      if (use_cursor_control)
! 		 MoveCursor(x,y);
! 	      else
! 		 back_up(iindex);
  	      CleartoEOLN();
  	    }
  	    iindex = 0;
--- 252,258 ----
  	     * be a desired valid printing character */
  	    escaped = OFF;
  	    if(!passwd) {
! 	      MoveCursor(x,y);
  	      CleartoEOLN();
  	    }
  	    iindex = 0;

Index: src/mailmsg2.c
Prereq:
*** ../elm2.2/src/mailmsg2.c	Thu Mar 30 10:36:28 1989
--- src/mailmsg2.c	Mon Apr 24 21:18:55 1989
***************
*** 1,8 ****
  
! static char rcsid[] = "@(#)$Id: mailmsg2.c,v 2.29 89/03/25 21:46:43 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.29 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
--- 1,8 ----
  
! static char rcsid[] = "@(#)$Id: mailmsg2.c,v 2.30 89/04/24 21:18:49 syd Exp $";
  
  /*******************************************************************************
!  *  The Elm Mail System  -  $Revision: 2.30 $   $State: Exp $
   *
   * 			Copyright (c) 1986, 1987 Dave Taylor
   * 			Copyright (c) 1988, 1989 USENET Community Trust
***************
*** 14,19 ****
--- 14,31 ----
   *
   *******************************************************************************
   * $Log:	mailmsg2.c,v $
+  * Revision 2.30  89/04/24  21:18:49  syd
+  * This fixes a number of bugs with the builtin editor. (1) It used to use
+  * stdio functions and not curses functions to write to the screen causing
+  * the homebrew curses to loose track of where the cursor was - which
+  * showed up when trying to back up over input, (2) the ~m and ~f commands
+  * were nearly completely broken, (3) expanded addresses are displayed
+  * under a wider range of appropriate circumstances, (4) the index screen
+  * needed to be redrawn when the editor is killed by two interrupts. A related
+  * curses bug was also fixed, and user messages in the builtin editor were
+  * made consistent.
+  * From: Rob Bernardo <clib!rob>
+  * 
   * Revision 2.29  89/03/25  21:46:43  syd
   * Initial 2.2 Release checkin
   * 
***************
*** 182,192 ****
  	if (! batch_only) {
  	  do {
  	    switch (ch) {
! 	      case 'e': if (edit_the_message(filename, already_has_text)) {
  			  cancelled_msg = TRUE;
  			  return(need_redraw);
  			}
- 			need_redraw++;
  			break;
  
  	      case 'c': need_redraw += name_copy_file(copy_file);
--- 194,204 ----
  	if (! batch_only) {
  	  do {
  	    switch (ch) {
! 	      case 'e': need_redraw++;
! 			if (edit_the_message(filename, already_has_text)) {
  			  cancelled_msg = TRUE;
  			  return(need_redraw);
  			}
  			break;
  
  	      case 'c': need_redraw += name_copy_file(copy_file);

-- 
=====================================================================
Sydney S. Weinstein, CDP, CCP                   Elm Coordinator
Datacomp Systems, Inc.				Voice: (215) 947-9900
syd@DSI.COM or {bpa,vu-vlsi}!dsinc!syd	        FAX:   (215) 938-0235