1 /* ********************************************
  2    *                                          *
  3    * Copyright, (C) Honeywell Bull Inc., 1988 *
  4    *                                          *
  5    ******************************************** */
  6 
  7 /* HISTORY COMMENTS:
  8   1) change(88-06-13,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
  9      install(88-10-12,MR12.2-1160):
 10      created.
 11   2) change(88-07-11,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 12      install(88-10-12,MR12.2-1160):
 13      Added calls to history recall routines.
 14   3) change(88-07-22,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 15      install(88-10-12,MR12.2-1160):
 16      Added command keys to capitalize, upper case, lower case,
 17      transpose words and to transpose characters.
 18   4) change(88-07-25,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 19      install(88-10-12,MR12.2-1160):
 20      Documentation additions only. Added header comments to all routines.
 21   5) change(88-08-09,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 22      install(88-10-12,MR12.2-1160):
 23      Fix references to include files; "wstdefs.h" was split into
 24      "wstdefs.h" and "wsttype.h" to avoid declaration clash; also,
 25      various constants defined to descriptive names.
 26   6) change(88-09-16,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel),
 27      install(88-10-12,MR12.2-1160):
 28      Linefeed key (^J) modified to send input line, just like carriage
 29      return.
 30   7) change(89-01-18,Lee), approve(89-01-02,MCR8043), audit(89-03-14,Flegel),
 31      install(89-04-24,MR12.3-1033):
 32      phx21233 - Modified to support the displaying and re-displaying of echoed
 33      input only.
 34                                                    END HISTORY COMMENTS */
 35 
 36 #include <dos.h>
 37 #include <ctype.h>
 38 #include "wstdefs.h"
 39 #include "wstglob.h"
 40 #include <wsmincap.h>
 41 
 42 /*^L
 43 **********************************************************************
 44 
 45   Routine:            PROCESS_EDIT_LINE
 46 
 47   Function:
 48       This routine calls checks for keyboard input and if detected,
 49   passes it to the edit mode keyboard routines for processing.
 50 
 51   Parameters:
 52      (input/output)   line - pointer to the structure containing the
 53                           line being edited in edit mode
 54 
 55   Returns:            1 if the <RETURN> key was processed, signifying
 56                           the end of editing for the current input
 57                           line.
 58                       0 otherwise
 59 
 60   Note 1 - All error handling is done within this module. Line
 61       editing errors such as buffer overflow, invalid key, etc. are
 62       normally handled by beeping and discarding of the invalid
 63       input.
 64 **********************************************************************/
 65 
 66 process_edit_line(line)
 67 EDIT_LINE *line;
 68 {
 69     int ch;      /* character read in */
 70     int code;    /* error code */
 71 
 72     /* process only if keyboard key hit */
 73     if ((ch = getkey(KB_NO_BLOCK)) < 0)
 74         return(0);
 75 
 76     /* initialize if getting a new line of input; new line if not
 77        currently handling escape arguments and no input buffered
 78     */
 79     if (line->length == 0 && !line->escape_flag && line->escape_arg < 0) {
 80         init_curpos(line);
 81         line->index = ZERO_INDEX_VALUE;
 82     }
 83 
 84     /* handle the character read in */
 85     code = proc_input(line,ch);
 86     return(code);
 87 }
 88 
 89 
 90 
 91 /*^L
 92 **********************************************************************
 93 
 94   Routine:            UPDATE_NUM_LITERAL
 95 
 96   Function:
 97       This routine is called to handle the case of the backslash
 98   character followed by an octal value. The octal value is converted
 99   to an ASCII character and placed into the line buffer. The screen
100   is then updated.
101 
102   Parameters:
103      (input/output)   line - pointer to the structure containing the
104                           line (buffer) and information about the
105                           line being edited in edit mode
106 
107   Returns:            NONE
108 
109 **********************************************************************/
110 
111 update_num_literal(line)
112 EDIT_LINE *line;
113 {
114     CURPOS tpos;
115 
116     /* if there are octal digits in backslash escape */
117     if (line->literal_dex > 0) {
118 
119         /* back up the cursor to whatever number of octal digits were
120            entered plus one more for the backslash in preparation for
121            over-writing the backslash escape sequence
122         */
123         if (kb.echo)    /* phx21233 R.L. - backup only if echo enabled */
124             backup_cursor(line,line->literal_dex+1);
125 
126         /* initialize cursor information structure */
127         init_temp_curpos(&tpos,line);
128 
129         /* null terminate the octal string entered */
130         line->literal_buff[line->literal_dex] = NUL_TERMINATOR;
131 
132         /* convert octal string to ASCII value and assign to current
133            character in keyboard buffer
134         */
135         line->line[line->index] = octal_val(line->literal_buff);
136 
137         /* redisplay it */
138         line->size[line->index] = display_char(&tpos,line->line[line->index]);
139 
140         /* position to next keyboard character */
141         line->index++;
142 
143         /* update screen cursor position in line structure */
144         line->cur_row = tpos.cur_row;
145         line->cur_col = tpos.cur_col;
146         line->orig_row -= tpos.scroll_flag;
147         if (line->orig_row < ss.top)
148             line->scrolled_flag = TRUE;
149 
150         /* redisplay rest of line after the current character */
151         redisplay(line,line->index,&(line->max_row),&(line->max_col));
152 
153         /* reset index to indicate not processing backslash escape */
154         line->literal_dex = ZERO_INDEX_VALUE;
155     }
156 
157     /* no octal digits, only backslash entered; backslash is already
158        displayed, just position to next keyboard character
159     */
160     else
161         line->index++;
162 
163     /* reset escape argument flags */
164     line->escape_flag = NO_ESC_FUNC;
165     line->escape_arg = NO_ESC_ARG;
166 }
167 
168 
169 
170 /*^L
171 **********************************************************************
172 
173   Routine:            UPDATE_NON_PRT_LITERAL
174 
175   Function:
176       This routine handles input from the keyboard for the case of a
177   backslash followed by a non-printable character. The character is
178   put into the line buffer and the screen is then updated.
179 
180   Parameters:
181      (input/output)   line - pointer to the structure containing the
182                           line (buffer) and information about the
183                           line being edited in edit mode
184      (input)          ch - specifies the non-printable ASCII
185                           character following the backslash that was
186                           entered
187 
188   Returns:            NONE
189 
190 **********************************************************************/
191 
192 update_non_prt_literal(line,ch)
193 EDIT_LINE *line;
194 int ch;          /* the non-printable character following backslash */
195 {
196     CURPOS tpos;
197 
198     /* back the cursor over the backslash */
199     if (kb.echo)    /* phx21233 R.L. - backup only if echo enabled */
200         backup_cursor(line,1);
201 
202     /* initialize cursor information */
203     init_temp_curpos(&tpos,line);
204 
205     /* current keyboard character is assigned the non-printable character */
206     line->line[line->index] = ch;
207 
208     /* display the non-printable character */
209     line->size[line->index] = display_char(&tpos,ch);
210 
211     /* position to next keyboard character */
212     line->index++;
213 
214     /* update the cursor information in the line structure */
215     line->cur_row = tpos.cur_row;
216     line->cur_col = tpos.cur_col;
217     line->orig_row -= tpos.scroll_flag;
218     if (line->orig_row < ss.top)
219         line->scrolled_flag = TRUE;
220 
221     /* display the line following the non-printable character */
222     redisplay(line,line->index,&(line->max_row),&(line->max_col));
223 
224     /* reset escape argument flags */
225     line->escape_flag = NO_ESC_FUNC;
226     line->escape_arg = NO_ESC_ARG;
227 }
228 
229 
230 
231 /*^L
232 **********************************************************************
233 
234   Routine:            PROC_INPUT
235 
236   Function:
237       This routine handles keyboard input in edit mode a key at a
238   time. The module examines the key to determine whether it is to be
239   handled as text input or as an editing key. Also, numeric escape
240   argument (such as "<ESC> 3" to repeat a command 3 times) and
241   literal escaping (such as "\ <BACKSPACE>") is detected and
242   processed by this routine.
243 
244   Parameters:
245      (input/output)   line - pointer to the structure containing the
246                           line and information about the line being
247                           edited in edit mode
248      (input)          key - specifies the keyboard key, ASCII or
249                           function or ALT key, which was entered
250                           while in edit mode
251 
252   Returns:            1 if the <RETURN> key was processed, signifying
253                           the end of editing for the current line
254                       0 otherwise
255 
256   Note 1 - All error handling is done within this module. Line
257       editing errors such as buffer overflow, invalid key, etc. are
258       normally handled by beeping and discarding the invalid input.
259 **********************************************************************/
260 
261 proc_input(line,key)
262 EDIT_LINE *line;
263 int key;
264 {
265     int ch;
266     int code;
267 
268     ch = key;
269 
270     /* check and map DEL, ^2 and ^BREAK keys */
271     if (ch > ASCII_EXTEND_CODE) {
272 
273         /* map PC's DEL key to ASCII DEL */
274         if (ch == DEL_KEY)
275             ch = ASCII_DEL;
276 
277         /* map PC's ^2 key to ASCII NUL */
278         else if (ch == NULL_KEY)
279             ch = ASCII_NUL;
280 
281         /* map PC's ^BREAK to ALT_B; BREAK_KEY code is generated only
282            if WSTERM's /B command argument is specified
283         */
284         else if (ch == BREAK_KEY)
285             ch = ALT_B;
286     }
287 
288     /* check if previous key was an escape or literal escape and
289        that current key is not a function or ALT key
290     */
291     if (line->escape_flag > NO_ESC_FUNC) {
292 
293         /* previous key was a backslash */
294         if (line->escape_flag == KB_LITERAL_ESC) {
295 
296             /* if function or ALT key, update the backslash and fall through */
297             if (ch > ASCII_EXTEND_CODE)
298                 update_num_literal(line);
299 
300             /* check for octal digit */
301             else if (ch >= SMALLEST_OCTAL_DIGIT && ch <= LARGEST_OCTAL_DIGIT) {
302                 /* display the digit and insert keep track in line structure */
303                 insert_display_char(line,ch);
304 
305                 /* if three octal digits entered, process octal sequence */
306                 if (line->literal_dex >= MAX_OCTAL_SEQ_DIGITS) {
307                     update_num_literal(line);
308                 }
309                 return(0);
310             }
311 
312             /* handle backslash followed by non-printable character */
313             else if (line->literal_dex == ZERO_INDEX_VALUE &&
314                 (ch < MIN_PRINTABLE_ASCII ||
315                  ch > MAX_PRINTABLE_ASCII ||
316                  ch == char_erase ||
317                  ch == line_kill)) {
318                 update_non_prt_literal(line,ch);
319                 return(0);
320             }
321 
322             /* backslash followed by a printable character */
323             else if (ch < ASCII_DEL) {
324 
325                 if (line->literal_dex == ZERO_INDEX_VALUE) {
326 
327                     /* update line structure */
328                     update_num_literal(line);
329 
330                     /* if backslash followed by backslash, don't process
331                        second backslash
332                     */
333                     if (ch == lnc) return(0);
334 
335                     /* fall through and handle the printable character */
336                 }
337 
338                 /* backslash octal sequence followed by printable */
339                 else
340                     /* update backslash sequence character first */
341                     update_num_literal(line);
342 
343                     /* fall through and handle the printable char */
344             }
345         }
346 
347         /* check for escape key numeric argument */
348         else if (ch >= SMALLEST_DECI_DIGIT && ch <= LARGEST_DECI_DIGIT) {
349 
350             /* if previous key was the escape key and no previous arguments */
351             if (line->escape_flag == KB_PREV_KEY_ESC && line->escape_arg < 0)
352                 /* set initial escape argument */
353                 line->escape_arg = ch - '0';
354 
355             /* calculate into previously initialize escape argument */
356             else if (line->escape_arg < MAX_ARG_LIMIT) {
357                 line->escape_arg *= 10;
358                 line->escape_arg += ch - '0';
359             }
360 
361             /* change flag to indicate currently handling numeric arg */
362             line->escape_flag = KB_HANDLING_ESC_ARG;
363             return(0);
364         }
365 
366         /* previous key was escape key, check for escape editing sequence */
367         else if (line->escape_flag == KB_PREV_KEY_ESC) {
368             code = handle_esc_editkeys(line,ch);
369             return(code);
370         }
371     }
372 
373     /* handle the character as an edit key */
374     code = handle_editkeys(line,ch);
375 
376     /* return if handled as an edit key */
377     if (code >= 0)
378         return(code);
379 
380     /* Handle adding straight text */
381     if (ch < ASCII_DEL) {
382         if (line->escape_arg < 0)
383             add_text(line,ch,1);
384         else
385             add_text(line,ch,line->escape_arg);
386 
387         line->escape_flag = NO_ESC_FUNC;
388         line->escape_arg = NO_ESC_ARG;
389         return(0);
390     }
391 
392     /* handle remaining function or ALT key hit */
393     else if (ch > ASCII_EXTEND_CODE) {
394         local_esc(ch - ASCII_EXTEND_CODE); /* pass it decoded scan code */
395         return(0);
396     }
397 
398     /* reinitialize escape argument flags and beep */
399     line->escape_flag = NO_ESC_FUNC;
400     line->escape_arg = NO_ESC_ARG;
401     beep();
402     return(0);
403 }
404 
405 
406 
407 /*^L
408 **********************************************************************
409 
410   Routine:            HANDLE_ESC_EDITKEYS
411 
412   Function:
413       This routine handles editing keys which are preceeded by the
414   ESC key, e.g. ESC D (delete word).
415 
416   Parameters:
417      (input/output)   line - pointer to the structure containing the
418                           line and information about the line being
419                           edited in edit mode
420      (input)          ch - specifies which escape edit key is being
421                           handled
422 
423   Returns:            -1 if the key specified is not a recognized
424                           escape editing key
425                       0 otherwise
426 
427   Note 1 - Unrecognized keys are handled by beeping. Flags in the
428       line structure indicating numeric escape arguments and esc key
429       being hit are all reset regardlessly before this routine
430       returns.
431 **********************************************************************/
432 
433 handle_esc_editkeys(line,ch)
434 EDIT_LINE *line;
435 int ch;
436 {
437     int arg_val;
438     int error_code;
439 
440     /* initialize error code to pass back */
441     error_code = 0;
442 
443     /* if no numeric argument given, assume action is done once */
444     if (line->escape_arg < 0)
445         arg_val = 1;
446 
447     /* otherwise perform as many times as specified by numeric argument */
448     else
449         arg_val = line->escape_arg;
450 
451     /* handle any recognized escape edit keys */
452     /*  ... the variable 'code' is set to zero if key is recognized */
453     switch (ch) {
454 
455         /* esc b, backward cursor word */
456         case 'b':
457         case 'B':
458             /* perform for specified number of times */
459             backward_word(line,arg_val);
460             break;
461 
462         /* esc f, forward cursor word */
463         case 'f':
464         case 'F':
465             /* perform for specified number of times */
466             forward_word(line,arg_val);
467             break;
468 
469         /* esc d, delete forward word */
470         case 'd':
471         case 'D':
472             /* perform for specified number of times */
473             forward_delete_word(line,arg_val);
474             break;
475 
476         /* esc DEL, delete backward word */
477         case BACKSPACE:
478         case ASCII_DEL:
479             /* perform for specified number of times */
480             backward_delete_word(line,arg_val);
481             break;
482 
483         /* esc U, upper case word */
484         case 'u':
485         case 'U':
486             change_case_word(line,KB_UPPER_CASE);
487             break;
488 
489         /* esc L, lower case word */
490         case 'l':
491         case 'L':
492             change_case_word(line,KB_LOWER_CASE);
493             break;
494 
495         /* esc C, capitalize word */
496         case 'c':
497         case 'C':
498             change_case_word(line,KB_CAPITALIZED);
499             break;
500 
501         /* esc T, transpose positions of previous two words */
502         case 't':
503         case 'T':
504             transpose_words(line);
505             break;
506 
507         /* esc Y, yank previous item from yank buffer */
508         case 'y':
509         case 'Y':
510             yank_previous(line);
511             break;
512 
513         /* key not a recognized escape edit key */
514         default:
515             beep();
516             error_code = -1;
517     }
518 
519     /* reset escape flag and argument */
520     line->escape_flag = NO_ESC_FUNC;
521     line->escape_arg = NO_ESC_ARG;
522 
523     return(error_code);
524 }
525 
526 
527 
528 /*^L
529 **********************************************************************
530 
531   Routine:            HANDLE_EDITKEYS
532 
533   Function:
534       This routine examines a specified key to see if it is an
535   editing or ALT key. If so, it calls the appropriate routines to
536   handle the editing or ALT function, otherwise nothing is changed
537   and an error code is returned.
538 
539   Parameters:
540      (input/output)   line - pointer to the structure containing the
541                           line and information about the line being
542                           edited in edit mode
543      (input)          ch - specifies the key whose function needs to
544                           be identified and handled
545 
546   Returns:            -1 if the key is not an editing key or special
547                           ALT key
548                       0 otherwise
549 
550 **********************************************************************/
551 
552 handle_editkeys(line,ch)
553 EDIT_LINE *line;
554 int ch;
555 {
556     int n_times;
557 
558     /* check for erase, kill or lnc; these characters are variable */
559     if (ch == lnc) {
560 
561         /* handle literal escape character */
562         /* add and display the literal escape character */
563         if (add_char(line,ch))
564             line->escape_flag = KB_LITERAL_ESC;
565 
566         /* error, must line must be full */
567         else {
568             /* reset escape argument and flag and beep */
569             line->escape_flag = NO_ESC_FUNC;
570             line->escape_arg = NO_ESC_ARG;
571             beep();
572         }
573         return(0);
574     }
575 
576     else if (ch == char_erase || ch == BACKSPACE || ch == ASCII_DEL) {
577         /* delete previous character */
578         /* check for escape numeric argument */
579         if (line->escape_arg < 0) {
580             if (cursor_left(line,1) > 0)
581                 delete_chars(line,1,NO_KILLBUFF_SAVE);
582         }
583         else {
584             n_times = cursor_left(line,line->escape_arg);
585             delete_chars(line,n_times,NO_KILLBUFF_SAVE);
586         }
587 
588         /* reset escape argument and flag */
589         line->escape_flag = NO_ESC_FUNC;
590         line->escape_arg = NO_ESC_ARG;
591         return(0);
592     }
593 
594     else if (ch == line_kill) {
595         /* kill line */
596         /* preceeded by literal escape char? */
597 
598         /* kill to beginning of line */
599         kill_to_bol(line);
600 
601         /* reset escape argument and flag */
602         line->escape_flag = NO_ESC_FUNC;
603         line->escape_arg = NO_ESC_ARG;
604         return(0);
605     }
606 
607     switch (ch) {
608 
609         /* handle escape character */
610         case ESC:
611             /* if not handling an escape sequence or handling an
612                escape numeric argument
613             */
614             if (line->escape_flag == NO_ESC_FUNC || line->escape_flag == 2)
615 
616                 /* set to indicate previous key was an escape key */
617                 line->escape_flag = KB_PREV_KEY_ESC;
618 
619             /* escape followed by escape, reset flags and beep */
620             else {
621                 line->escape_flag = NO_ESC_FUNC;
622                 line->escape_arg = NO_ESC_ARG;
623                 beep();
624             }
625             return(0);
626 
627         case TAB:
628             return(-1);   /* not an editing key, treat as text */
629 
630         /* handle return key */
631         case LINEFEED:
632         case RETURN_KEY:
633             kb_edit_lf_return(line,ch);
634 
635             /* reset escape argument and flag */
636             line->escape_flag = NO_ESC_FUNC;
637             line->escape_arg = NO_ESC_ARG;
638             return(1);
639 
640         /* move cursor one character to the left */
641         case LEFT_ARROW_KEY:
642         case CTRL_B:
643             /* check for escape numeric argument */
644             if (line->escape_arg < 0)
645                 cursor_left(line,1);
646             else
647                 cursor_left(line,line->escape_arg);
648 
649             /* reset escape argument and flag */
650             line->escape_flag = NO_ESC_FUNC;
651             line->escape_arg = NO_ESC_ARG;
652             return(0);
653 
654         /* move cursor one character to the right */
655         case RIGHT_ARROW_KEY:
656         case CTRL_F:
657             /* check for escape numeric argument */
658             if (line->escape_arg < 0)
659                 cursor_right(line,1);
660             else
661                 cursor_right(line,line->escape_arg);
662 
663             /* reset escape argument and flag */
664             line->escape_flag = NO_ESC_FUNC;
665             line->escape_arg = NO_ESC_ARG;
666             return(0);
667 
668         /* toggle editing replace/insert mode */
669         case ALT_I:
670         case INS_KEY:
671 
672             /* toggle line edit flag */
673             line->mode = !line->mode;
674 
675             /* update the mode change on status line */
676             update_status();
677             return(0);
678 
679         /* move cursor to beginning of line */
680         case CTRL_A:
681         case HOME_KEY:
682             cursor_bol(line);
683 
684             /* reset escape argument and flag */
685             line->escape_flag = NO_ESC_FUNC;
686             line->escape_arg = NO_ESC_ARG;
687             return(0);
688 
689         /* delete current character */
690         case CTRL_D:
691             /* check for escape numeric argument */
692             if (line->escape_arg < 0)
693                 delete_chars(line,1,NO_KILLBUFF_SAVE);
694             else
695                 delete_chars(line,line->escape_arg,NO_KILLBUFF_SAVE);
696 
697             /* reset escape argument and flag */
698             line->escape_flag = NO_ESC_FUNC;
699             line->escape_arg = NO_ESC_ARG;
700             return(0);
701 
702         /* move cursor to end of the line */
703         case CTRL_E:
704         case END_KEY:
705             cursor_eol(line);
706 
707             /* reset escape argument and flag */
708             line->escape_flag = NO_ESC_FUNC;
709             line->escape_arg = NO_ESC_ARG;
710             return(0);
711 
712         /* kill to the end of the line */
713         case CTRL_K:
714             kill_to_eol(line);
715 
716             /* reset escape argument and flag */
717             line->escape_flag = NO_ESC_FUNC;
718             line->escape_arg = NO_ESC_ARG;
719             return(0);
720 
721         /* forward word */
722         case CTRL_RIGHT_ARROW_KEY:
723 
724             /* handle no numeric argument */
725             if (line->escape_arg < 0)
726                 forward_word(line,1);
727 
728             /* handle numeric argument */
729             else
730                 forward_word(line,line->escape_arg);
731 
732             /* reset escape flag and argument */
733             line->escape_flag = NO_ESC_FUNC;
734             line->escape_arg = NO_ESC_ARG;
735             return(0);
736 
737         /* backward word */
738         case CTRL_LEFT_ARROW_KEY:
739 
740             /* handle no numeric argument */
741             if (line->escape_arg < 0)
742                 backward_word(line,1);
743 
744             /* handle numeric argument */
745             else
746                 backward_word(line,line->escape_arg);
747 
748             /* reset escape flag and argument */
749             line->escape_flag = NO_ESC_FUNC;
750             line->escape_arg = NO_ESC_ARG;
751             return(0);
752 
753         /* fetch and display previous history command */
754         case CTRL_P:
755         case UP_ARROW_KEY:
756 
757             /* no escape argument specified? */
758             if (line->escape_arg < 0) {
759 
760                 /* check for unsuccessful retrieval of history      */
761                 /* command                                          */
762                 if (fetch_previous_command(1,line->line,&(line->length)) < 0) {
763                     line->escape_flag = NO_ESC_FUNC;
764                     line->escape_arg = NO_ESC_ARG;
765                     return(0);
766                 }
767             }
768 
769             /* handle escape argument */
770             else {
771                 /* fetch unsuccessful? */
772                 if (fetch_nth_command(line->escape_arg,
773                     line->line,&(line->length)) < 0) {
774                     line->escape_flag = NO_ESC_FUNC;
775                     line->escape_arg = NO_ESC_ARG;
776                     return(0);
777                 }
778             }
779 
780             /* phx21233 R.L. - update echo flags to determine visibility */
781             /*    of chars redrawn */
782             update_echo_flags(line);
783 
784             /* history command successfully extracted, erase the    */
785             /* existing command from the screen, reset the escape   */
786             /* flags and display the new command                    */
787 
788             erase_edit_line(line);
789             line->index = 0;
790             line->escape_flag = NO_ESC_FUNC;
791             line->escape_arg = NO_ESC_ARG;
792             redraw_edit_line(line);
793             cursor_eol(line);
794             return(0);
795 
796 
797         /* fetch next history command */
798         case CTRL_N:
799         case DOWN_ARROW_KEY:
800 
801             /* no escape argument specified? */
802             if (line->escape_arg < 0) {
803 
804                 /* unsuccessful history command retrieval? */
805                 if (fetch_next_command(1,line->line,&(line->length)) < 0) {
806                     line->escape_flag = NO_ESC_FUNC;
807                     line->escape_arg = NO_ESC_ARG;
808                     return(0);
809                 }
810             }
811 
812             /* handle escape argument */
813             else {
814 
815                 /* unsuccessful history command retrieval? */
816                 if (fetch_next_command(line->escape_arg,
817                     line->line,&(line->length)) < 0) {
818                     line->escape_flag = NO_ESC_FUNC;
819                     line->escape_arg = NO_ESC_ARG;
820                     return(0);
821                 }
822             }
823 
824             /* phx21233 R.L. - update echo flags to determine visibility */
825             /*    of chars redrawn */
826             update_echo_flags(line);
827 
828             /* history line successfully retrieved, erase existing  */
829             /* input line from screen, initialize line flags and    */
830             /* display the new input line                           */
831 
832             erase_edit_line(line);
833             line->index = 0;
834             line->escape_flag = NO_ESC_FUNC;
835             line->escape_arg = NO_ESC_ARG;
836             redraw_edit_line(line);
837             cursor_eol(line);
838             return(0);
839 
840         /* transpose the two characters preceeding the cursor */
841         case CTRL_T:
842             transpose_chars(line);
843 
844             /* reset escape argument and flag */
845             line->escape_flag = NO_ESC_FUNC;
846             line->escape_arg = NO_ESC_ARG;
847             return(0);
848 
849         /* yank item from the kill buffer */
850         case CTRL_Y:
851             /* phx21233 R.L. - kill/yank disabled while not echoing */
852             if (!kb.echo) {
853                 beep();
854                 return(0);
855             }
856             yank(line);
857             line->escape_flag = NO_ESC_FUNC;
858             line->escape_arg = NO_ESC_ARG;
859             return(0);
860 
861         /* handle invalid editing key */
862         default:
863             /* handle any other control character by beeping */
864             if (ch < MIN_PRINTABLE_ASCII) {
865                 line->escape_flag = NO_ESC_FUNC;
866                 line->escape_arg = NO_ESC_ARG;
867                 beep();
868                 return(0);
869             }
870             /* Could be text or ALT or FUNCTION key; indicate not an */
871             /* editing key */
872             return(-1);
873     }
874 }
875 
876 
877 
878 /*^L
879 **********************************************************************
880 
881   Routine:            OCTAL_VAL
882 
883   Function:
884       This routine converts the ASCII string containing an octal
885   representation to an integer value.
886 
887   Parameters:
888      (input)          str - pointer to the ASCII string containing
889                           the representation of an octal value
890 
891   Returns:            the integer value after conversion
892 
893   Note 1 - The string is assumed to contain only octal digits.
894 **********************************************************************/
895 
896 octal_val(str)
897 char *str;
898 {
899     int sum;
900 
901     /* initialize sum */
902     sum = 0;
903 
904     /* while not end of string */
905     while (*str) {
906 
907         /* multiply by octal base */
908         sum *= OCTAL_BASE_VALUE;
909 
910         /* add value of current octal digit */
911         sum += *str - ASCII_ZERO_BASE;
912 
913         /* increment to next character */
914         str++;
915     }
916 
917     /* return the converted value */
918     return(sum);
919 }
920 
921 
922 /*^L
923 **********************************************************************
924 
925   Routine:            UPDATE_ECHO_FLAGS
926 
927   Function:
928      This function updates the echo status of all input characters
929   buffered in the edit mode input line.  If keyboard echoing is enabled,
930   all characters are flagged as visible otherwise they are flagged
931   invisible.
932 
933   Parameters:
934      (input)          line - pointer to the structure containing the
935                           edit mode input line
936 
937   Returns:            NONE
938 
939 **********************************************************************/
940 
941 update_echo_flags(line)
942 EDIT_LINE *line;
943 {
944     int i;
945     int echo_flag;
946 
947     /* determine echo status */
948     if (kb.echo)
949         echo_flag = TRUE;
950     else
951         echo_flag = FALSE;
952 
953     /* update display lengths of each character in the input line */
954     for (i = 0; i < line->length; i++)
955         line->size[i] = echo_flag;
956 }