Edinburgh Speech Tools  2.1-release
editline.c
Go to the documentation of this file.
1 /****************************************************************************/
2 /* */
3 /* Copyright 1992 Simmule Turner and Rich Salz. All rights reserved. */
4 /* */
5 /* This software is not subject to any license of the American Telephone */
6 /* and Telegraph Company or of the Regents of the University of California. */
7 /* */
8 /* Permission is granted to anyone to use this software for any purpose on */
9 /* any computer system, and to alter it and redistribute it freely, subject */
10 /* to the following restrictions: */
11 /* 1. The authors are not responsible for the consequences of use of this */
12 /* software, no matter how awful, even if they arise from flaws in it. */
13 /* 2. The origin of this software must not be misrepresented, either by */
14 /* explicit claim or by omission. Since few users ever read sources, */
15 /* credits must appear in the documentation. */
16 /* 3. Altered versions must be plainly marked as such, and must not be */
17 /* misrepresented as being the original software. Since few users */
18 /* ever read sources, credits must appear in the documentation. */
19 /* 4. This notice may not be removed or altered. */
20 /* */
21 /****************************************************************************/
22 /* */
23 /* This is a line-editing library, it can be linked into almost any */
24 /* program to provide command-line editing and recall. */
25 /* */
26 /* Posted to comp.sources.misc Sun, 2 Aug 1992 03:05:27 GMT */
27 /* by rsalz@osf.org (Rich $alz) */
28 /* */
29 /****************************************************************************/
30 /* */
31 /* The version contained here has some modifications by awb@cstr.ed.ac.uk */
32 /* (Alan W Black) in order to integrate it with the Edinburgh Speech Tools */
33 /* library and Scheme-in-one-defun in particular, though these changes */
34 /* have a much more general use that just us. All modifications to */
35 /* to this work are continued with the same copyright above. That is */
36 /* this version of editline does not have the the "no commercial use" */
37 /* restriction that some of the rest of the EST library may have */
38 /* awb Dec 30 1998 */
39 /* */
40 /* Specific additions (there are other smaller ones too, all marked): */
41 /* some ansificiation and prototypes added */
42 /* storage and retrieval of history over sessions */
43 /* user definable history completion */
44 /* possibles listing in completion */
45 /* reverse incremental search */
46 /* lines longer than window width (mostly) */
47 /* reasonable support for 8 bit chars in languages other than English */
48 /* */
49 /****************************************************************************/
50 
51 /* $Revision: 1.6 $
52 **
53 ** Main editing routines for editline library.
54 */
55 #include "editline.h"
56 #include "EST_unix.h"
57 #include <ctype.h>
58 
59 /*
60 ** Manifest constants.
61 */
62 #define SCREEN_WIDTH 80
63 #define SCREEN_ROWS 24
64 #define NO_ARG (-1)
65 #define DEL 127
66 #define ESC 0x1b
67 #define CTL(x) (char)((x) & 0x1F)
68 #define ISCTL(x) ((x) && (x) < ' ')
69 #define UNCTL(x) (char)((x) + 64)
70 #define META(x) (char)((x) | 0x80)
71 #define ISMETA(x) ((x) & 0x80)
72 #define UNMETA(x) (char)((x) & 0x7F)
73 /* modified by awb to allow specifcation of history size at run time */
74 /* (though only once) */
77 /* If this is defined it'll be called for completion first, before the */
78 /* internal file name completion will be */
80 
81 /*
82 ** The type of case-changing to perform.
83 */
84 typedef enum _CASE {
86 } CASE;
87 
88 /*
89 ** Key to command mapping.
90 */
91 typedef struct _KEYMAP {
92  ECHAR Key;
93  STATUS (*Function)();
94 } KEYMAP;
95 
96 /*
97 ** Command history structure.
98 */
99 typedef struct _HISTORY {
100  int Size;
101  int Pos;
102  ECHAR **Lines;
103 } HISTORY;
104 
105 /*
106 ** Globals.
107 */
108 int rl_eof;
112 
113 ECHAR el_NIL[] = "";
114 extern CONST ECHAR *el_Input;
119 /* STATIC char NEWLINE[]= CRLF; */
120 STATIC HISTORY H;
127 extern int el_PushBack;
128 extern int el_Pushed;
129 FORWARD KEYMAP Map[33];
130 FORWARD KEYMAP MetaMap[64];
146 int el_no_echo = 0; /* e.g under emacs */
147 
148 /* A little ansification with prototypes -- awb */
149 extern void TTYflush();
150 STATIC void TTYput(ECHAR c);
151 STATIC void TTYputs(ECHAR *p);
152 STATIC void TTYshow(ECHAR c);
153 STATIC void TTYstring(ECHAR *p);
154 extern int TTYget();
155 STATIC void TTYinfo();
156 STATIC void print_columns(int ac, char **av);
157 STATIC void reposition(int reset);
158 STATIC void left(STATUS Change);
159 STATIC void right(STATUS Change);
161 #if 0
162 STATIC STATUS do_macro(unsigned int c);
163 #endif
165 STATIC STATUS do_case(ECHAR type);
168 STATIC void ceol();
169 STATIC void clear_line();
174 STATIC STATUS do_hist(ECHAR *(*move)());
179 STATIC int substrcmp(char *text, char *pat, int len);
180 STATIC ECHAR *search_hist(ECHAR *search, ECHAR *(*move)());
183 STATIC void save_yank(int begin, int i);
184 STATIC STATUS delete_string(int count);
189 STATIC char *rsearch_hist(char *patt, int *lpos,int *cpos);
191 STATIC STATUS insert_char(int c);
192 STATIC STATUS meta();
193 STATIC STATUS emacs(unsigned int c);
194 STATIC STATUS TTYspecial(int c);
196 STATIC void hist_add(ECHAR *p);
206 STATIC STATUS wipe();
209 STATIC STATUS yank();
216 STATIC int argify(ECHAR *line, ECHAR ***avp);
218 
219 /* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
221 
222 /*
223 ** Declarations.
224 */
226 #if defined(USE_TERMCAP)
227 extern char *getenv();
228 extern char *tgetstr();
229 extern int tgetent();
230 extern int tgetnum();
231 #endif /* defined(USE_TERMCAP) */
232 
233 /*
234 ** TTY input/output functions.
235 */
236 
237 void TTYflush()
238 {
239  int i;
240  if (ScreenCount) {
241  if (el_no_echo == 0) {
242  while(ScreenCount > 0)
243  {
244  i = write(1, Screen, ScreenCount);
245  if (i >= 0)
246  ScreenCount -= i;
247  }
248  ScreenCount = 0;
249  }
250  }
251 }
252 
254 {
255  Screen[ScreenCount] = c;
256  if (++ScreenCount >= ScreenSize - 1) {
258  RENEW(Screen, char, ScreenSize);
259  }
260 }
261 
263 {
264  while (*p)
265  TTYput(*p++);
266 }
267 
269 {
270  if (c == DEL) {
271  TTYput('^');
272  TTYput('?');
273  }
274  else if (ISCTL(c)) {
275  TTYput('^');
276  TTYput(UNCTL(c));
277  }
278  else if (rl_meta_chars && ISMETA(c)) {
279  TTYput('M');
280  TTYput('-');
281  TTYput(UNMETA(c));
282  }
283  else
284  TTYput(c);
285 }
286 
288 {
289  while (*p)
290  TTYshow(*p++);
291 }
292 
293 #if 0
294 /* Old one line version */
295 #define TTYback() (backspace ? TTYputs((ECHAR *)backspace) : TTYput('\b'))
296 #endif
297 
298 STATIC int printlen(CONST char *p)
299 {
300  int len = 0;
301 
302  for (len=0; *p; p++)
303  if ((*p == DEL) || (ISCTL(*p)))
304  len += 2;
305  else if (rl_meta_chars && ISMETA(*p))
306  len += 3;
307  else
308  len += 1;
309 
310  return len;
311 }
312 
314 {
315  /* Returns the number of characters printed from beginning of line */
316  /* includes the size of the prompt and and meta/ctl char expansions */
317  int p = strlen(Prompt);
318  int i;
319 
320  for (i=0; i < Point; i++)
321  if ((Line[i] == DEL) ||
322  (ISCTL(Line[i])))
323  p += 2;
324  else if (rl_meta_chars && ISMETA(Line[i]))
325  p += 3;
326  else
327  p += 1;
328 
329  return p;
330 }
331 
333 {
334  /* awb: added upline (if supported) when back goes over line boundary */
335  int i;
336  int sp = screen_pos();
337 
338  if (upline && sp && (sp%TTYwidth == 0))
339  { /* move up a line and move to the end */
340  TTYputs(upline);
341  TTYputs(bol);
342  for (i=0; i < TTYwidth; i++)
344  }
345  else if (backspace)
346  TTYputs((ECHAR *)backspace);
347  else
348  TTYput('\b');
349 }
350 
352 {
353  static int init;
354 #if defined(USE_TERMCAP)
355  char *term;
356  char *buff;
357  char *buff2;
358  char *bp;
359 #endif /* defined(USE_TERMCAP) */
360 #if defined(TIOCGWINSZ)
361  struct winsize W;
362 #endif /* defined(TIOCGWINSZ) */
363 
364  if (init) {
365 #if defined(TIOCGWINSZ)
366  /* Perhaps we got resized. */
367  if (ioctl(0, TIOCGWINSZ, &W) >= 0
368  && W.ws_col > 0 && W.ws_row > 0) {
369  TTYwidth = (int)W.ws_col;
370  TTYrows = (int)W.ws_row;
371  }
372 #endif /* defined(TIOCGWINSZ) */
373  return;
374  }
375  init++;
376 
377  TTYwidth = TTYrows = 0;
378 #if defined(USE_TERMCAP)
379  buff = walloc(char,2048);
380  buff2 = walloc(char,2048);
381  bp = &buff2[0];
382  if ((term = getenv("TERM")) == NULL)
383  term = "dumb";
384  if (tgetent(buff, term) < 0) {
387  wfree(buff2);
388  return;
389  }
390  backspace = (ECHAR *)tgetstr("le", &bp);
391  upline = (ECHAR *)tgetstr("up", &bp);
392  clrpage = (ECHAR *)tgetstr("cl", &bp);
393  nextline = (ECHAR *)tgetstr("nl", &bp);
394  if (nextline==NULL)
395  nextline = (ECHAR *)"\n";
396  if (strncmp(term, "pcansi", 6)==0 || strncmp(term, "cygwin", 6)==0)
397  {
398  bol = (ECHAR *)"\033[0G";
399  RequireNLforWrap = 0; /* doesn't require nl to get to next line */
400  }
401  else
402  bol = (ECHAR *)tgetstr("cr", &bp);
403  if (bol==NULL)
404  bol = (ECHAR *)"\r";
405 
406  newline= walloc(ECHAR, 20);
407  strcpy((char *)newline,(char *)bol);
408  strcat((char *)newline,(char *)nextline);
409 
410  downline = (ECHAR *)newline;
411  move_right = (ECHAR *)tgetstr("nd", &bp);
412  if (!move_right || !downline)
413  upline = NULL; /* terminal doesn't support enough so fall back */
414  TTYwidth = tgetnum("co");
415  TTYrows = tgetnum("li");
416 #endif /* defined(USE_TERMCAP) */
417 
418 #if defined(TIOCGWINSZ)
419  if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
420  TTYwidth = (int)W.ws_col;
421  TTYrows = (int)W.ws_row;
422  }
423 #endif /* defined(TIOCGWINSZ) */
424 
425  if (TTYwidth <= 0 || TTYrows <= 0) {
428  }
429 }
430 
431 
432 /*
433 ** Print an array of words in columns.
434 */
435 STATIC void print_columns(int ac, char **av)
436 {
437  ECHAR *p;
438  int i,c;
439  int j;
440  int k;
441  int len;
442  int skip;
443  int longest;
444  int cols;
445  char info1[1024];
446 
447  if (ac > 99)
448  {
449  TTYputs((ECHAR *)newline);
450  sprintf(info1,"There are %d possibilities. Do you really \n",ac);
451  TTYputs((ECHAR *)info1);
452  TTYputs((ECHAR *)"want to see them all (y/n) ? ");
453  while (((c = TTYget()) != EOF) && ((strchr("YyNn ",c) == NULL)))
454  ring_bell();
455  if (strchr("Nn",c) != NULL)
456  {
457  TTYputs((ECHAR *)newline);
458  return;
459  }
460  }
461 
462  /* Find longest name, determine column count from that. */
463  for (longest = 0, i = 0; i < ac; i++)
464  if ((j = strlen((char *)av[i])) > longest)
465  longest = j;
466  cols = TTYwidth / (longest + 3);
467  if (cols < 1) cols = 1;
468 
469  TTYputs((ECHAR *)newline);
470  for (skip = ac / cols + 1, i = 0; i < skip; i++) {
471  for (j = i; j < ac; j += skip) {
472  for (p = (ECHAR *)av[j], len = strlen((char *)p), k = len;
473  --k >= 0; p++)
474  TTYput(*p);
475  if (j + skip < ac)
476  while (++len < longest + 3)
477  TTYput(' ');
478  }
479  TTYputs((ECHAR *)newline);
480  }
481 }
482 
483 STATIC void reposition(int reset)
484 {
485  int i,PPoint;
486  int pos;
487  char ppp[2];
488 
489  if (reset)
490  {
491  TTYputs(bol);
492  for (i=screen_pos()/TTYwidth; i > 0; i--)
493  if (upline) TTYputs(upline);
494  }
495  TTYputs((ECHAR *)Prompt);
496  pos = printlen(Prompt);
497  ppp[1] = '\0';
498  for (i = 0; i < End; i++)
499  {
500  ppp[0] = Line[i];
501  TTYshow(Line[i]);
502  pos += printlen(ppp);
503  if ((pos%TTYwidth) == 0)
505  }
506  PPoint = Point;
507  for (Point = End;
508  Point > PPoint;
509  Point--)
510  {
511  if (rl_meta_chars && ISMETA(Line[Point]))
512  {
513  TTYback();
514  TTYback();
515  }
516  else if (ISCTL(Line[Point]))
517  TTYback();
518  TTYback();
519  }
520  Point = PPoint;
521 }
522 
523 STATIC void left(STATUS Change)
524 {
525  TTYback();
526  if (Point) {
527  if (ISCTL(Line[Point - 1]))
528  TTYback();
529  else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
530  TTYback();
531  TTYback();
532  }
533  }
534  if (Change == CSmove)
535  Point--;
536 }
537 
538 STATIC void right(STATUS Change)
539 {
540  TTYshow(Line[Point]);
541  if (Change == CSmove)
542  Point++;
543  if ((screen_pos())%TTYwidth == 0)
545 }
546 
548 {
549  TTYput('\07');
550  TTYflush();
551  return CSstay;
552 }
553 
554 #if 0
555 STATIC STATUS do_macro(unsigned int c)
556 {
557  ECHAR name[4];
558 
559  name[0] = '_';
560  name[1] = c;
561  name[2] = '_';
562  name[3] = '\0';
563 
564  if ((el_Input = (ECHAR *)getenv((char *)name)) == NULL) {
565  el_Input = el_NIL;
566  return ring_bell();
567  }
568  return CSstay;
569 }
570 #endif
571 
573 {
574  int i;
575  ECHAR *p;
576  (void) move;
577 
578  i = 0;
579  do {
580  p = &Line[Point];
581  for ( ; Point < End && (*p == ' ' || !isalnum(*p)); p++)
582  right(CSmove);
583 
584  for (; Point < End && isalnum(*p); p++)
585  right(CSmove);
586 
587  if (Point == End)
588  break;
589  } while (++i < Repeat);
590 
591  return CSstay;
592 }
593 
595 {
596  int i;
597  int end;
598  int count;
599  ECHAR *p;
600  int OP;
601 
602  OP = Point;
603  (void)do_forward(CSstay);
604  if (OP != Point) {
605  if ((count = Point - OP) < 0)
606  count = -count;
607  for ( ; Point > OP; Point --)
608  TTYback();
609  if ((end = Point + count) > End)
610  end = End;
611  for (i = Point, p = &Line[Point]; Point < end; p++) {
612  if ((type == TOupper) ||
613  ((type == TOcapitalize) && (Point == i)))
614  {
615  if (islower(*p))
616  *p = toupper(*p);
617  }
618  else if (isupper(*p))
619  *p = tolower(*p);
620  right(CSmove);
621  }
622  }
623  return CSstay;
624 }
625 
627 {
628  return do_case(TOlower);
629 }
630 
632 {
633  return do_case(TOupper);
634 }
635 
637 {
638  return do_case(TOcapitalize);
639 }
640 
641 STATIC void ceol()
642 {
643  int extras;
644  int i, PPoint;
645  ECHAR *p;
646 
647  PPoint = Point;
648  for (extras = 0, i = Point, p = &Line[i]; i < End; i++, p++) {
649  Point++;
650  TTYput(' ');
651  if (ISCTL(*p)) {
652  TTYput(' ');
653  extras++;
654  }
655  else if (rl_meta_chars && ISMETA(*p)) {
656  TTYput(' ');
657  TTYput(' ');
658  extras += 2;
659  }
660  else if ((screen_pos())%TTYwidth == 0)
662  }
663 
664  Point = End;
665  for (Point = End;
666  Point > PPoint;
667  Point--)
668  {
669  if (rl_meta_chars && ISMETA(Line[Point-1]))
670  {
671  TTYback();
672  TTYback();
673  }
674  else if (ISCTL(Line[Point-1]))
675  TTYback();
676  TTYback();
677  }
678  Point = PPoint;
679 
680 }
681 
683 {
684  size_t i;
685  TTYputs(bol);
686  for (i=screen_pos()/TTYwidth; i > 0; i--)
687  if (upline) TTYputs(upline);
688  for (i=0; i < strlen(Prompt); i++)
689  TTYput(' ');
690  Point = 0;
691  ceol();
692  TTYputs(bol);
693  /* In case the prompt is more than one line long */
694  for (i=screen_pos()/TTYwidth; i > 0; i--)
695  if (upline) TTYputs(upline);
696  Point = 0;
697  End = 0;
698  Line[0] = '\0';
699 }
700 
702 {
703  ESIZE_T len;
704  int i,pos0,pos1;
705  ECHAR *new;
706  ECHAR *q;
707 
708  len = strlen((char *)p);
709  if (End + len >= Length) {
710  if ((new = NEW(ECHAR, Length + len + MEM_INC)) == NULL)
711  return CSstay;
712  if (Length) {
713  COPYFROMTO(new, Line, Length);
714  DISPOSE(Line);
715  }
716  Line = new;
717  Length += len + MEM_INC;
718  }
719 
720  for (q = &Line[Point], i = End - Point; --i >= 0; )
721  q[len + i] = q[i];
722  COPYFROMTO(&Line[Point], p, len);
723  End += len;
724  Line[End] = '\0';
725  pos0 = screen_pos();
726  pos1 = printlen((char *)&Line[Point]);
727  TTYstring(&Line[Point]);
728  Point += len;
729  if ((pos0+pos1)%TTYwidth == 0)
731  /* if the line is longer than TTYwidth this may put the cursor */
732  /* on the next line and confuse some other parts, so put it back */
733  /* at Point */
734  if (upline && (Point != End))
735  {
736  pos0 = screen_pos();
737  pos1 = printlen((char *)&Line[Point]);
738  for (i=((pos0%TTYwidth)+pos1)/TTYwidth; i > 0; i--)
739  if (upline) TTYputs(upline);
740  TTYputs(bol);
741  for (i=0 ; i < (pos0%TTYwidth); i++)
743  }
744 
745  return Point == End ? CSstay : CSmove;
746 }
747 
748 
750 {
751  return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
752 }
753 
755 {
756  return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
757 }
758 
760 {
761  int i;
762  if (p == NULL)
763  return ring_bell();
764  for (i=screen_pos()/TTYwidth; i > 0; i--)
765  if (upline) TTYputs(upline);
766  Point = 0;
767  reposition(1);
768  ceol();
769  End = 0;
770  return insert_string(p);
771 }
772 
774 {
775  ECHAR *p;
776  int i;
777 
778  i = 0;
779  do {
780  if ((p = (*move)()) == NULL)
781  return ring_bell();
782  } while (++i < Repeat);
783  return do_insert_hist(p);
784 }
785 
787 {
788  return do_hist(next_hist);
789 }
790 
792 {
793  return do_hist(prev_hist);
794 }
795 
797 {
798  return do_insert_hist(H.Lines[H.Pos = 0]);
799 }
800 
802 {
803  return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
804 }
805 
806 /*
807 ** Return zero if pat appears as a substring in text.
808 */
809 STATIC int substrcmp(char *text, char *pat, int len)
810 {
811  ECHAR c;
812 
813  if ((c = *pat) == '\0')
814  return *text == '\0';
815  for ( ; *text; text++)
816  if (*text == c && strncmp(text, pat, len) == 0)
817  return 0;
818  return 1;
819 }
820 
821 STATIC ECHAR *search_hist(ECHAR *search, ECHAR *(*move)())
822 {
823  static ECHAR *old_search;
824  int len;
825  int pos;
826  int (*match)();
827  char *pat;
828 
829  /* Save or get remembered search pattern. */
830  if (search && *search) {
831  if (old_search)
832  DISPOSE(old_search);
833  old_search = (ECHAR *)STRDUP((const char *)search);
834  }
835  else {
836  if (old_search == NULL || *old_search == '\0')
837  return NULL;
838  search = old_search;
839  }
840 
841  /* Set up pattern-finder. */
842  if (*search == '^') {
843  match = strncmp;
844  pat = (char *)(search + 1);
845  }
846  else {
847  match = substrcmp;
848  pat = (char *)search;
849  }
850  len = strlen(pat);
851 
852  for (pos = H.Pos; (*move)() != NULL; )
853  if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
854  return H.Lines[H.Pos];
855  H.Pos = pos;
856  return NULL;
857 }
858 
860 {
861  static int Searching;
862  CONST char *old_prompt;
863  ECHAR *(*move)();
864  ECHAR *p;
865 
866  if (Searching)
867  return ring_bell();
868  Searching = 1;
869 
870  clear_line();
871  old_prompt = Prompt;
872  Prompt = "Search: ";
873  TTYputs((ECHAR *)Prompt);
874  move = Repeat == NO_ARG ? prev_hist : next_hist;
875  p = search_hist(editinput(), move);
876  clear_line();
877  Prompt = old_prompt;
878  TTYputs((ECHAR *)Prompt);
879 
880  Searching = 0;
881  return do_insert_hist(p);
882 }
883 
885 {
886  int i;
887 
888  i = 0;
889  do {
890  if (Point >= End)
891  break;
892  right(CSmove);
893  } while (++i < Repeat);
894  return CSstay;
895 }
896 
897 STATIC void save_yank(int begin, int i)
898 {
899  if (Yanked) {
900  DISPOSE(Yanked);
901  Yanked = NULL;
902  }
903 
904  if (i < 1)
905  return;
906 
907  if ((Yanked = NEW(ECHAR, (ESIZE_T)i + 1)) != NULL) {
908  COPYFROMTO(Yanked, &Line[begin], i);
909  Yanked[i] = '\0';
910  }
911 }
912 
914 {
915  int i;
916  int pos0,pos1,q;
917  char *tLine;
918 
919  if (count <= 0 || End == Point)
920  return ring_bell();
921 
922  if (Point + count > End && (count = End - Point) <= 0)
923  return CSstay;
924 
925  if (count > 1)
926  save_yank(Point, count);
927 
928  tLine = STRDUP((char *)Line);
929  ceol();
930  for (q = Point, i = End - (Point + count) + 1; --i >= 0; q++)
931  Line[q] = tLine[q+count];
932  wfree(tLine);
933  End -= count;
934  pos0 = screen_pos();
935  pos1 = printlen((char *)&Line[Point]);
936  TTYstring(&Line[Point]);
937  if ((pos1 > 0) && (pos0+pos1)%TTYwidth == 0)
939  /* if the line is longer than TTYwidth this may put the cursor */
940  /* on the next line and confuse some other parts, so put it back */
941  /* at Point */
942  if (upline)
943  {
944  for (i=((pos0%TTYwidth)+pos1)/TTYwidth; i > 0; i--)
945  if (upline) TTYputs(upline);
946  TTYputs(bol);
947  for (i=0 ; i < (pos0%TTYwidth); i++)
949  }
950 
951  return CSmove;
952 }
953 
955 {
956  int i;
957 
958  i = 0;
959  do {
960  if (Point == 0)
961  break;
962  left(CSmove);
963  } while (++i < Repeat);
964 
965  return CSstay;
966 }
967 
969 {
970  int i;
971 
972  i = 0;
973  do {
974  if (Point == 0)
975  break;
976  left(CSmove);
977  } while (++i < Repeat);
978 
979  return delete_string(i);
980 }
981 
983 {
984  if (clrpage) TTYputs(clrpage);
985  else
986  TTYputs((ECHAR *)newline);
987 /* TTYputs((ECHAR *)Prompt);
988  TTYstring(Line); */
989  return CSmove;
990 }
991 
993 {
994  int i;
995 
996  if (Repeat != NO_ARG) {
997  if (Repeat < Point) {
998  i = Point;
999  Point = Repeat;
1000  reposition(1);
1001  (void)delete_string(i - Point);
1002  }
1003  else if (Repeat > Point) {
1004  right(CSmove);
1005  (void)delete_string(Repeat - Point - 1);
1006  }
1007  return CSmove;
1008  }
1009 
1010  save_yank(Point, End - Point);
1011  ceol();
1012  Line[Point] = '\0';
1013  End = Point;
1014  return CSstay;
1015 }
1016 
1017 STATIC char *rsearch_hist(char *patt, int *lpos,int *cpos)
1018 {
1019  /* Extension by awb to do reverse incremental searches */
1020 
1021  for (; *lpos > 0; (*lpos)--)
1022  {
1023  for ( ; (*cpos) >= 0 ; (*cpos)--)
1024  {
1025 /* fprintf(stderr,"comparing %d %s %s\n",*lpos,patt,H.Lines[*lpos]+*cpos); */
1026  if (strncmp(patt,(char *)H.Lines[*lpos]+*cpos,strlen(patt)) == 0)
1027  { /* found a match */
1028  return (char *)H.Lines[*lpos];
1029  }
1030  }
1031  if ((*lpos) > 0)
1032  *cpos = strlen((char *)H.Lines[(*lpos)-1]);
1033  }
1034  return NULL; /* no match found */
1035 }
1036 
1038 {
1039  STATUS s;
1040  CONST char *old_prompt;
1041  char *pat, *hist, *nhist;
1042  char *nprompt;
1043  int patend, i;
1044  ECHAR c;
1045  int lpos,cpos;
1046 
1047  old_prompt = Prompt;
1048 
1049  nprompt = walloc(char,80+160);
1050  pat = walloc(char,80);
1051  patend=0;
1052  pat[0] = '\0';
1053  hist = "";
1054  lpos = H.Pos; /* where the search has to start from */
1055  cpos = strlen((char *)H.Lines[lpos]);
1056  do
1057  {
1058  sprintf(nprompt,"(reverse-i-search)`%s': ",pat);
1059  Prompt = nprompt;
1060  kill_line();
1061  do_insert_hist((ECHAR *)hist);
1062  if (patend != 0)
1063  for (i=strlen((char *)H.Lines[lpos]); i>cpos; i--) bk_char();
1064  c = TTYget();
1065  if ((c >= ' ') || (c == CTL('R')))
1066  {
1067  if (c == CTL('R'))
1068  cpos--;
1069  else if (patend < 79)
1070  {
1071  pat[patend]=c;
1072  patend++;
1073  pat[patend]='\0';
1074  }
1075  else /* too long */
1076  {
1077  ring_bell();
1078  continue;
1079  }
1080  nhist = rsearch_hist(pat,&lpos,&cpos);
1081  if (nhist != NULL)
1082  {
1083  hist = nhist;
1084  H.Pos = lpos;
1085  }
1086  else
1087  { /* oops, no match */
1088  ring_bell();
1089  if (c != CTL('R'))
1090  {
1091  patend--;
1092  pat[patend] = '\0';
1093  }
1094  }
1095  }
1096  } while ((c >= ' ') || (c == CTL('R')));
1097 
1098  /* Tidy up */
1099  clear_line();
1100  Prompt = old_prompt;
1101  TTYputs((ECHAR *)Prompt);
1102  wfree(nprompt);
1103 
1104  kill_line();
1105  s = do_insert_hist((ECHAR *)hist);
1106  if (patend != 0)
1107  for (i=strlen((char *)H.Lines[lpos]); i>cpos; i--) s = bk_char();
1108  wfree(pat);
1109  if (c != ESC)
1110  return emacs(c);
1111  else
1112  return s;
1113 }
1114 
1116 {
1117  STATUS s;
1118  ECHAR buff[2];
1119  ECHAR *p;
1120  ECHAR *q;
1121  int i;
1122 
1123  if (Repeat == NO_ARG || Repeat < 2) {
1124  buff[0] = c;
1125  buff[1] = '\0';
1126  return insert_string(buff);
1127  }
1128 
1129  if ((p = NEW(ECHAR, Repeat + 1)) == NULL)
1130  return CSstay;
1131  for (i = Repeat, q = p; --i >= 0; )
1132  *q++ = c;
1133  *q = '\0';
1134  Repeat = 0;
1135  s = insert_string(p);
1136  DISPOSE(p);
1137  return s;
1138 }
1139 
1141 {
1142  int c;
1143  KEYMAP *kp;
1144 
1145  if ((c = TTYget()) == EOF)
1146  return CSeof;
1147 #if defined(ANSI_ARROWS)
1148  /* Also include VT-100 arrows. */
1149  if (c == '[' || c == 'O')
1150  switch (c = TTYget()) {
1151  default: return ring_bell();
1152  case EOF: return CSeof;
1153  case 'A': return h_prev();
1154  case 'B': return h_next();
1155  case 'C': return fd_char();
1156  case 'D': return bk_char();
1157  }
1158 #endif /* defined(ANSI_ARROWS) */
1159 
1160  if (isdigit(c)) {
1161  for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
1162  Repeat = Repeat * 10 + c - '0';
1163  el_Pushed = 1;
1164  el_PushBack = c;
1165  return CSstay;
1166  }
1167 
1168 /* if (isupper(c))
1169  return do_macro(c); */
1170  for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
1171  if (kp->Key == c)
1172  return (*kp->Function)();
1173  if (rl_meta_chars == 0)
1174  {
1175  insert_char(META(c));
1176  return CSmove;
1177  }
1178 
1179  return ring_bell();
1180 }
1181 
1182 STATIC STATUS emacs(unsigned int c)
1183 {
1184  STATUS s;
1185  KEYMAP *kp;
1186 
1187  if (ISMETA(c) && rl_meta_chars)
1188  {
1189  el_Pushed = 1;
1190  el_PushBack = UNMETA(c);
1191  return meta();
1192  }
1193  for (kp = Map; kp->Function; kp++)
1194  if (kp->Key == c)
1195  break;
1196  s = kp->Function ? (*kp->Function)() : insert_char((int)c);
1197  if (!el_Pushed)
1198  /* No pushback means no repeat count; hacky, but true. */
1199  Repeat = NO_ARG;
1200  return s;
1201 }
1202 
1204 {
1205  int i;
1206 
1207  if (ISMETA(c))
1208  return CSdispatch;
1209 
1210  if (c == rl_erase || c == DEL)
1211  return bk_del_char();
1212  if (c == rl_kill) {
1213  if (Point != 0) {
1214  for (i=screen_pos()/TTYwidth; i > 0; i--)
1215  if (upline) TTYputs(upline);
1216  Point = 0;
1217  reposition(1);
1218  }
1219  Repeat = NO_ARG;
1220  return kill_line();
1221  }
1222  if (c == rl_intr || c == rl_quit) {
1223  Point = End = 0;
1224  Line[0] = '\0';
1225  if (c == rl_intr)
1226  {
1227  el_intr_pending = 1;
1228  return CSdone;
1229  }
1230  else
1231  return redisplay();
1232  }
1233  if (c == rl_eof && Point == 0 && End == 0)
1234  return CSeof;
1235 
1236  return CSdispatch;
1237 }
1238 
1240 {
1241  int c;
1242 
1243  Repeat = NO_ARG;
1244  OldPoint = Point = Mark = End = 0;
1245  Line[0] = '\0';
1246 
1247  while ((c = TTYget()) != EOF)
1248  {
1249  switch (TTYspecial(c)) {
1250  case CSdone:
1251  return Line;
1252  case CSeof:
1253  return NULL;
1254  case CSmove:
1255  reposition(1);
1256  break;
1257  case CSstay:
1258  break;
1259  case CSdispatch:
1260  switch (emacs(c)) {
1261  case CSdone:
1262  return Line;
1263  case CSeof:
1264  return NULL;
1265  case CSmove:
1266  reposition(1);
1267  break;
1268  case CSstay:
1269  case CSdispatch:
1270  break;
1271  }
1272  break;
1273  }
1274  }
1275  return NULL;
1276 }
1277 
1279 {
1280  int i;
1281 
1282  if ((p = (ECHAR *)STRDUP((char *)p)) == NULL)
1283  return;
1284  if (H.Size < editline_histsize)
1285  H.Lines[H.Size++] = p;
1286  else {
1287  DISPOSE(H.Lines[0]);
1288  for (i = 0; i < editline_histsize - 1; i++)
1289  H.Lines[i] = H.Lines[i + 1];
1290  H.Lines[i] = p;
1291  }
1292  H.Pos = H.Size - 1;
1293 }
1294 
1295 /* Added by awb 29/12/98 to get saved history file */
1296 void write_history(const char *history_file)
1297 {
1298  FILE *fd;
1299  int i;
1300 
1301  if ((fd = fopen(history_file,"wb")) == NULL)
1302  {
1303  fprintf(stderr,"editline: can't access history file \"%s\"\n",
1304  history_file);
1305  return;
1306  }
1307 
1308  for (i=0; i < H.Size; i++)
1309  fprintf(fd,"%s\n",H.Lines[i]);
1310  fclose(fd);
1311 }
1312 
1313 void read_history(const char *history_file)
1314 {
1315  FILE *fd;
1316  char buff[2048];
1317  int c,i;
1318 
1319  H.Lines = NEW(ECHAR *,editline_histsize);
1320  H.Size = 0;
1321  H.Pos = 0;
1322 
1323  if ((fd = fopen(history_file,"rb")) == NULL)
1324  return; /* doesn't have a history file yet */
1325 
1326  while ((c=getc(fd)) != EOF)
1327  {
1328  ungetc(c,fd);
1329  for (i=0; ((c=getc(fd)) != '\n') && (c != EOF); i++)
1330  if (i < 2046)
1331  buff[i] = c;
1332  buff[i] = '\0';
1333  add_history(buff);
1334  }
1335 
1336  fclose(fd);
1337 }
1338 
1339 /*
1340 ** For compatibility with FSF readline.
1341 */
1342 /* ARGSUSED0 */
1343 void
1345 {
1346  (void)p;
1347 }
1348 
1349 void
1351 {
1352 }
1353 
1354 char *readline(CONST char *prompt)
1355 {
1356  ECHAR *line;
1357 
1358  if (Line == NULL) {
1359  Length = MEM_INC;
1360  if ((Line = NEW(ECHAR, Length)) == NULL)
1361  return NULL;
1362  }
1363 
1364  TTYinfo();
1365  rl_ttyset(0);
1366  hist_add(el_NIL);
1368  Screen = NEW(char, ScreenSize);
1369  Prompt = prompt ? prompt : (char *)el_NIL;
1370  el_intr_pending = 0;
1371  if (el_no_echo == 1)
1372  {
1373  el_no_echo = 0;
1374  TTYputs((ECHAR *)Prompt);
1375  TTYflush();
1376  el_no_echo = 1;
1377  }
1378  else
1379  TTYputs((ECHAR *)Prompt);
1380  line = editinput();
1381  if (line != NULL) {
1382  line = (ECHAR *)STRDUP((char *)line);
1383  TTYputs((ECHAR *)newline);
1384  TTYflush();
1385  }
1386  rl_ttyset(1);
1387  DISPOSE(Screen);
1388  DISPOSE(H.Lines[--H.Size]);
1389  if (el_intr_pending)
1390  do_user_intr();
1391  return (char *)line;
1392 }
1393 
1394 void
1395 add_history(char *p)
1396 {
1397  if (p == NULL || *p == '\0')
1398  return;
1399 
1400 #if defined(UNIQUE_HISTORY)
1401  if (H.Pos && strcmp(p, H.Lines[H.Pos - 1]) == 0)
1402  return;
1403 #endif /* defined(UNIQUE_HISTORY) */
1404  hist_add((ECHAR *)p);
1405 }
1406 
1407 
1409 {
1410  int i;
1411  if (Point) {
1412  for (i=screen_pos()/TTYwidth; i > 0; i--)
1413  if (upline) TTYputs(upline);
1414  Point = 0;
1415  return CSmove;
1416  }
1417  return CSstay;
1418 }
1419 
1421 {
1422  return delete_string(Repeat == NO_ARG ? 1 : Repeat);
1423 }
1424 
1426 {
1427  if (Point != End) {
1428  while (Point < End)
1429  {
1430  TTYput(Line[Point]);
1431  Point++;
1432  }
1433  return CSmove;
1434  }
1435  return CSstay;
1436 }
1437 
1438 /*
1439 ** Move back to the beginning of the current word and return an
1440 ** allocated copy of it.
1441 */
1443 {
1444  static char SEPS[] = "#;&|^$=`'{}()<>\n\t ";
1445  ECHAR *p;
1446  ECHAR *new;
1447  ESIZE_T len;
1448 
1449  for (p = &Line[Point]; p > Line && strchr(SEPS, (char)p[-1]) == NULL; p--)
1450  continue;
1451  len = Point - (p - Line) + 1;
1452  if ((new = NEW(ECHAR, len)) == NULL)
1453  return NULL;
1454  COPYFROMTO(new, p, len);
1455  new[len - 1] = '\0';
1456  return new;
1457 }
1458 
1460 {
1461  reposition(0); /* redisplay assuming already on newline */
1462 }
1463 
1465 {
1466  /* Get current symbol at point -- awb*/
1467  char *symbol = NULL;
1468  int i,j;
1469 
1470  if (End == 0)
1471  return NULL;
1472  if (Point == End)
1473  i=Point-1;
1474  else
1475  i=Point;
1476 
1477  for ( ;
1478  ((i >= 0) &&
1479  (strchr("()' \t\n\r",Line[i]) != NULL));
1480  i--);
1481  /* i will be on final or before final character */
1482  if (i < 0)
1483  return NULL;
1484  /* But if its not at the end of the current symbol move it there */
1485  for (; i < End; i++)
1486  if (strchr("()' \t\n\r\"",Line[i]) != NULL)
1487  break;
1488  for (j=i-1; j >=0; j--)
1489  if (strchr("()' \t\n\r\"",Line[j]) != NULL)
1490  break;
1491 
1492  symbol = walloc(char,i-j);
1493  strncpy(symbol,(char *)&Line[j+1],i-(j+1));
1494  symbol[i-(j+1)] = '\0';
1495 
1496  return symbol;
1497 }
1498 
1499 static char *completion_to_ambiguity(int index,char **possibles)
1500 {
1501  /* Find the string that extends from index in possibles until an */
1502  /* ambiguity is found -- awb */
1503  char *p;
1504  int e,i;
1505  int extending;
1506 
1507  extending = 1;
1508  e = index;
1509 
1510  for ( ; extending; e++)
1511  {
1512  for (i=0; possibles[i] != NULL; i++)
1513  if (possibles[i][e] != possibles[0][e])
1514  {
1515  extending = 0;
1516  e--;
1517  break;
1518  }
1519  }
1520 
1521  if (e==index)
1522  return NULL; /* already at ambiguity */
1523  else
1524  {
1525  p = walloc(char,(e-index)+1);
1526  strncpy(p,possibles[0]+index,e-index);
1527  p[e-index] = '\0';
1528  return p;
1529  }
1530 }
1531 
1532 static char **el_file_completion_function(char * text, int start, int end)
1533 {
1534  /* Interface to editline rl_list_possib which looks up possible */
1535  /* file name completions. */
1536  char *word;
1537  char **matches1;
1538  char **matches2;
1539  int ac,i;
1540 
1541  word = walloc(char,(end-start)+1);
1542  strncpy(word,text+start,end-start);
1543  word[end-start]='\0';
1544 
1545  ac = rl_list_possib(word,&matches1);
1546  wfree(word);
1547  if (ac == 0)
1548  return NULL;
1549  else
1550  {
1551  matches2 = walloc(char *,ac+1);
1552  for (i=0; i < ac; i++)
1553  matches2[i] = matches1[i];
1554  matches2[i] = NULL;
1555  wfree(matches1);
1556  return matches2;
1557  }
1558 }
1559 
1561 {
1562  /* Modified by awb 30/12/98 to allow listing of possibles and */
1563  /* a user definable completion method */
1564  char *p;
1565  char *word;
1566  int start;
1567  char **possibles=NULL;
1568  int possiblesc=0;
1569  int started_with_quote = 0;
1570  STATUS s;
1571  int i;
1572 
1573  for (start=Point; start > 0; start--)
1574  if (strchr("()' \t\n\r\"",Line[start-1]) != NULL)
1575  break;
1576  word = walloc(char,(Point-start)+1);
1577  strncpy(word,(char *)(Line+start),Point-start);
1578  word[Point-start]='\0';
1579  if ((start > 0) && (Line[start-1] == '"'))
1580  started_with_quote = 1;
1581 
1583  /* May need to look at previous char so pass in Line */
1584  possibles = el_user_completion_function((char *)Line,start,Point);
1585  if (possibles == NULL)
1586  {
1587  possibles = el_file_completion_function((char *)Line,start,Point);
1588  /* As filename completions only complete the final file name */
1589  /* not the full path we need to set a new start position */
1590  for (start=Point; start > 0; start--)
1591  if (strchr("()' \t\n\r\"/",Line[start-1]) != NULL)
1592  break;
1593  }
1594  if (possibles)
1595  for (possiblesc=0; possibles[possiblesc] != NULL; possiblesc++);
1596 
1597  if ((!possibles) || (possiblesc == 0)) /* none or none at all */
1598  s = ring_bell();
1599  else if (possiblesc == 1) /* a single expansion */
1600  {
1601  p = walloc(char,strlen(possibles[0])-(Point-start)+2);
1602  sprintf(p,"%s ",possibles[0]+(Point-start));
1603  if ((strlen(p) > 1) && (p[strlen(p)-2] == '/'))
1604  p[strlen(p)-1] = '\0';
1605  else if (started_with_quote)
1606  p[strlen(p)-1] = '"';
1607 
1608  s = insert_string((ECHAR *)p);
1609  wfree(p);
1610  }
1611  else if ((p = completion_to_ambiguity(Point-start,possibles)) != NULL)
1612  { /* an expansion to a later ambiguity */
1613  s = insert_string((ECHAR *)p);
1614  wfree(p);
1615  ring_bell();
1616  }
1617  else /* list of possibilities and we can't expand any further */
1618  {
1619  print_columns(possiblesc,possibles); /* display options */
1620  reposition(0); /* display whole line again */
1621  s = CSmove;
1622  }
1623 
1624  for (i=0; possibles && possibles[i] != NULL; i++)
1625  wfree(possibles[i]);
1626  wfree(possibles);
1627  wfree(word);
1628 
1629  return s;
1630 }
1631 
1632 #if 0
1633 /* Original version without automatic listing of possible completions */
1634 STATIC STATUS c_complete_old()
1635 {
1636  ECHAR *p;
1637  ECHAR *word;
1638  int unique;
1639  STATUS s;
1640 
1641  word = find_word();
1642  p = (ECHAR *)rl_complete((char *)word, &unique);
1643  if (word)
1644  DISPOSE(word);
1645  if (p && *p) {
1646  s = insert_string(p);
1647  if (!unique)
1648  (void)ring_bell();
1649  DISPOSE(p);
1650  return s;
1651  }
1652  return ring_bell();
1653 }
1654 #endif
1655 
1657 {
1658  ECHAR **av;
1659  ECHAR *word;
1660  int ac;
1661  ac = 0;
1662  word = find_word();
1663  /* The (char ***) ((void *) &av) below is to avoid a warning
1664  * from GCC about casting an unsigned char *** to char ***
1665  */
1666  if (word != NULL) {
1667  ac = rl_list_possib((char *)word, (char ***) ((void *) &av));
1668  DISPOSE(word);
1669  }
1670  if (ac) {
1671  print_columns(ac, (char **)av);
1672  reposition(0);
1673  while (--ac >= 0)
1674  DISPOSE(av[ac]);
1675  DISPOSE(av);
1676  return CSmove;
1677  }
1678  return ring_bell();
1679 }
1680 
1682 {
1683  Line[End] = '\0';
1684  return CSdone;
1685 }
1686 
1687 #ifdef SYSTEM_IS_WIN32
1688 STATIC STATUS end_of_input()
1689 {
1690  Line[End] = '\0';
1691  return CSeof;
1692 }
1693 #endif
1694 
1696 {
1697  ECHAR c;
1698 
1699  if (Point) {
1700  if (Point == End)
1701  left(CSmove);
1702  c = Line[Point - 1];
1703  left(CSstay);
1704  Line[Point - 1] = Line[Point];
1705  TTYshow(Line[Point - 1]);
1706  Line[Point++] = c;
1707  TTYshow(c);
1708  }
1709  return CSstay;
1710 }
1711 
1713 {
1714  int c;
1715 
1716  return (c = TTYget()) == EOF ? CSeof : insert_char(c);
1717 }
1718 
1720 {
1721  int i;
1722 
1723  if (Mark > End)
1724  return ring_bell();
1725 
1726  if (Point > Mark) {
1727  i = Point;
1728  Point = Mark;
1729  Mark = i;
1730  reposition(1);
1731  }
1732 
1733  return delete_string(Mark - Point);
1734 }
1735 
1737 {
1738  Mark = Point;
1739  return CSstay;
1740 }
1741 
1743 {
1744  int c;
1745 
1746  if ((c = TTYget()) != CTL('X'))
1747  return c == EOF ? CSeof : ring_bell();
1748 
1749  if ((c = Mark) <= End) {
1750  Mark = Point;
1751  Point = c;
1752  return CSmove;
1753  }
1754  return CSstay;
1755 }
1756 
1758 {
1759  if (Yanked && *Yanked)
1760  return insert_string(Yanked);
1761  return CSstay;
1762 }
1763 
1765 {
1766  if (Mark > End)
1767  return ring_bell();
1768 
1769  if (Point > Mark)
1770  save_yank(Mark, Point - Mark);
1771  else
1772  save_yank(Point, Mark - Point);
1773 
1774  return CSstay;
1775 }
1776 
1778 {
1779  int c;
1780  int i;
1781  ECHAR *p;
1782 
1783  if ((c = TTYget()) == EOF)
1784  return CSeof;
1785  for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
1786  if (*p == c) {
1787  Point = i;
1788  return CSmove;
1789  }
1790  return CSstay;
1791 }
1792 
1794 {
1795  return do_forward(CSmove);
1796 }
1797 
1799 {
1800  int i;
1801  int OP;
1802 
1803  OP = Point;
1804  (void)do_forward(CSmove);
1805  if (OP != Point) {
1806  i = Point - OP;
1807  for ( ; Point > OP; Point --)
1808  TTYback();
1809  return delete_string(i);
1810  }
1811  return CSmove;
1812 }
1813 
1815 {
1816  int i;
1817  ECHAR *p;
1818 
1819  i = 0;
1820  do {
1821  for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
1822  left(CSmove);
1823 
1824  for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
1825  left(CSmove);
1826 
1827  if (Point == 0)
1828  break;
1829  } while (++i < Repeat);
1830 
1831  return CSstay;
1832 }
1833 
1835 {
1836  (void)bk_word();
1837  if (OldPoint != Point)
1838  return delete_string(OldPoint - Point);
1839  return CSstay;
1840 }
1841 
1842 STATIC int argify(ECHAR *line, ECHAR ***avp)
1843 {
1844  ECHAR *c;
1845  ECHAR **p;
1846  ECHAR **new;
1847  int ac;
1848  int i;
1849 
1850  i = MEM_INC;
1851  if ((*avp = p = NEW(ECHAR*, i))== NULL)
1852  return 0;
1853 
1854  for (c = line; isspace(*c); c++)
1855  continue;
1856  if (*c == '\n' || *c == '\0')
1857  return 0;
1858 
1859  for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
1860  if (isspace(*c)) {
1861  *c++ = '\0';
1862  if (*c && *c != '\n') {
1863  if (ac + 1 == i) {
1864  new = NEW(ECHAR*, i + MEM_INC);
1865  if (new == NULL) {
1866  p[ac] = NULL;
1867  return ac;
1868  }
1869  COPYFROMTO(new, p, i * sizeof (char *));
1870  i += MEM_INC;
1871  DISPOSE(p);
1872  *avp = p = new;
1873  }
1874  p[ac++] = c;
1875  }
1876  }
1877  else
1878  c++;
1879  }
1880  *c = '\0';
1881  p[ac] = NULL;
1882  return ac;
1883 }
1884 
1886 {
1887  ECHAR **av = NULL;
1888  ECHAR *p;
1889  STATUS s;
1890  int ac;
1891 
1892  if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
1893  return ring_bell();
1894 
1895  if ((p = (ECHAR *)STRDUP((char *)p)) == NULL)
1896  return CSstay;
1897  ac = argify(p, &av);
1898 
1899  if (Repeat != NO_ARG)
1900  s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
1901  else
1902  s = ac ? insert_string(av[ac - 1]) : CSstay;
1903 
1904  if (av != NULL)
1905  DISPOSE(av);
1906  DISPOSE(p);
1907  return s;
1908 }
1909 
1910 STATIC KEYMAP Map[33] = {
1911  { CTL('@'), ring_bell },
1912  { CTL('A'), beg_line },
1913  { CTL('B'), bk_char },
1914  { CTL('D'), del_char },
1915  { CTL('E'), end_line },
1916  { CTL('F'), fd_char },
1917  { CTL('G'), ring_bell },
1918  { CTL('H'), bk_del_char },
1919  { CTL('I'), c_complete },
1920  { CTL('J'), accept_line },
1921  { CTL('K'), kill_line },
1922  { CTL('L'), redisplay },
1923  { CTL('M'), accept_line },
1924  { CTL('N'), h_next },
1925  { CTL('O'), ring_bell },
1926  { CTL('P'), h_prev },
1927  { CTL('Q'), ring_bell },
1928  { CTL('R'), h_risearch },
1929  { CTL('S'), h_search },
1930  { CTL('T'), transpose },
1931  { CTL('U'), ring_bell },
1932  { CTL('V'), quote },
1933  { CTL('W'), wipe },
1934  { CTL('X'), exchange },
1935  { CTL('Y'), yank },
1936 #ifdef SYSTEM_IS_WIN32
1937  { CTL('Z'), end_of_input },
1938 #else
1939  { CTL('Z'), ring_bell },
1940 #endif
1941  { CTL('['), meta },
1942  { CTL(']'), move_to_char },
1943  { CTL('^'), ring_bell },
1944  { CTL('_'), ring_bell },
1945  { 0, NULL }
1946 };
1947 
1948 STATIC KEYMAP MetaMap[64]= {
1949  { CTL('H'), bk_kill_word },
1950  { DEL, bk_kill_word },
1951  { ' ', mk_set },
1952  { '.', last_argument },
1953  { '<', h_first },
1954  { '>', h_last },
1955  { '?', c_possible },
1956  { 'b', bk_word },
1957  { 'c', case_cap_word },
1958  { 'd', fd_kill_word },
1959  { 'f', fd_word },
1960  { 'l', case_down_word },
1961  { 'u', case_up_word },
1962  { 'y', yank },
1963  { 'w', copy_region },
1964  { 0, NULL }
1965 };
1966 
1968 {
1969  /* Add given function to key map for META keys */
1970  int i;
1971 
1972  for (i=0; MetaMap[i].Key != 0; i++)
1973  {
1974  if (MetaMap[i].Key == c)
1975  {
1976  MetaMap[i].Function = func;
1977  return;
1978  }
1979  }
1980 
1981  /* A new key so have to add it to end */
1982  if (i == 63)
1983  {
1984  fprintf(stderr,"editline: MetaMap table full, requires increase\n");
1985  return;
1986  }
1987 
1988  MetaMap[i].Function = func;
1989  MetaMap[i].Key = c;
1990  MetaMap[i+1].Function = 0; /* Zero the last location */
1991  MetaMap[i+1].Key = 0; /* Zero the last location */
1992 
1993 }
1994 
1995 
STATIC void TTYstring(ECHAR *p)
Definition: editline.c:287
int tgetnum()
int el_no_echo
Definition: editline.c:146
STATIC STATUS fd_kill_word()
Definition: editline.c:1798
STATIC int el_intr_pending
Definition: editline.c:145
STATIC STATUS yank()
Definition: editline.c:1757
#define OP(p)
Definition: regexp.cc:129
float end(const EST_Item &item)
Definition: EST_item_aux.cc:96
STATIC ECHAR * nextline
Definition: editline.c:141
STATIC void TTYput(ECHAR c)
Definition: editline.c:253
STATIC STATUS h_risearch()
Definition: editline.c:1037
STATIC ESIZE_T ScreenCount
Definition: editline.c:132
STATIC int screen_pos()
Definition: editline.c:313
int rl_list_possib(char *pathname, char ***avp)
Definition: el_complete.c:240
#define walloc(TYPE, SIZE)
Definition: EST_walloc.h:52
STATIC STATUS kill_line()
Definition: editline.c:992
void read_history(const char *history_file)
Definition: editline.c:1313
STATIC STATUS quote()
Definition: editline.c:1712
char * tgetstr()
STATIC STATUS bk_del_char()
Definition: editline.c:968
STATIC STATUS emacs(unsigned int c)
Definition: editline.c:1182
STATIC int RequireNLforWrap
Definition: editline.c:144
int TTYget()
Definition: el_sys_unix.c:134
STATIC void print_columns(int ac, char **av)
Definition: editline.c:435
STATIC ECHAR * bol
Definition: editline.c:140
EL_USER_COMPLETION_FUNCTION_TYPE * el_user_completion_function
Definition: editline.c:79
STATIC STATUS fd_char()
Definition: editline.c:884
STATIC int Repeat
Definition: editline.c:122
STATIC void TTYback()
Definition: editline.c:332
STATIC STATUS do_case(ECHAR type)
Definition: editline.c:594
STATIC STATUS do_forward(STATUS move)
Definition: editline.c:572
FORWARD KEYMAP Map[33]
Definition: editline.c:129
STATIC void ceol()
Definition: editline.c:641
#define ESC
Definition: editline.c:66
STATIC ESIZE_T Length
Definition: editline.c:131
int rl_quit
Definition: editline.c:121
STATIC STATUS do_insert_hist(ECHAR *p)
Definition: editline.c:759
STATIC int TTYrows
Definition: editline.c:143
void el_redisplay()
Definition: editline.c:1459
STATIC STATUS insert_string(ECHAR *p)
Definition: editline.c:701
STATIC void hist_add(ECHAR *p)
Definition: editline.c:1278
char * editline_history_file
Definition: editline.c:76
STATIC STATUS delete_string(int count)
Definition: editline.c:913
STATIC ECHAR * next_hist()
Definition: editline.c:749
STATIC void left(STATUS Change)
Definition: editline.c:523
STATIC STATUS fd_word()
Definition: editline.c:1793
int editline_histsize
Definition: editline.c:75
STATIC STATUS transpose()
Definition: editline.c:1695
STATIC STATUS exchange()
Definition: editline.c:1742
#define DEL
Definition: editline.c:65
STATIC void right(STATUS Change)
Definition: editline.c:538
#define NO_ARG
Definition: editline.c:64
STATIC char * Screen
Definition: editline.c:118
int rl_kill
Definition: editline.c:111
STATIC STATUS ring_bell()
Definition: editline.c:547
STATIC ECHAR * search_hist(ECHAR *search, ECHAR *(*move)())
Definition: editline.c:821
STATIC void save_yank(int begin, int i)
Definition: editline.c:897
#define ESIZE_T
Definition: editline.h:80
STATIC STATUS case_down_word()
Definition: editline.c:626
STATIC int TTYwidth
Definition: editline.c:142
STATIC void TTYinfo()
Definition: editline.c:351
#define UNCTL(x)
Definition: editline.c:69
STATIC STATUS last_argument()
Definition: editline.c:1885
STATIC STATUS c_possible()
Definition: editline.c:1656
STATIC ECHAR * backspace
Definition: editline.c:134
char * getenv()
int index(EST_TList< T > &l, T &val, bool(*eq)(const EST_UItem *, const EST_UItem *)=NULL)
Definition: EST_TList.h:286
STATIC STATUS h_last()
Definition: editline.c:801
STATIC int Point
Definition: editline.c:126
#define NEW(T, c)
Definition: editline.h:116
STATIC ECHAR * newline
Definition: editline.c:139
void write_history(const char *history_file)
Definition: editline.c:1296
#define UNMETA(x)
Definition: editline.c:72
Definition: editline.h:61
#define STRDUP(X)
Definition: editline.h:118
int rl_eof
Definition: editline.c:108
STATIC void reposition(int reset)
Definition: editline.c:483
#define SCREEN_WIDTH
Definition: editline.c:62
void do_user_intr()
Definition: el_sys_unix.c:168
ECHAR el_NIL[]
Definition: editline.c:113
STATIC ECHAR * Line
Definition: editline.c:115
#define RENEW(p, T, c)
Definition: editline.h:117
#define MEM_INC
Definition: editline.h:100
STATIC ECHAR * prev_hist()
Definition: editline.c:754
STATIC HISTORY H
Definition: editline.c:120
STATIC int Mark
Definition: editline.c:124
STATIC STATUS mk_set()
Definition: editline.c:1736
STATIC STATUS bk_kill_word()
Definition: editline.c:1834
int rl_intr
Definition: editline.c:110
void el_bind_key_in_metamap(char c, Keymap_Function func)
Definition: editline.c:1967
unsigned char ECHAR
Definition: editline.h:83
#define STATIC
Definition: regexp.cc:171
STATIC STATUS move_to_char()
Definition: editline.c:1777
FORWARD KEYMAP MetaMap[64]
Definition: editline.c:130
STATIC STATUS case_up_word()
Definition: editline.c:631
STATIC STATUS case_cap_word()
Definition: editline.c:636
STATIC ECHAR * editinput()
Definition: editline.c:1239
STATIC int argify(ECHAR *line, ECHAR ***avp)
Definition: editline.c:1842
STATIC int End
Definition: editline.c:123
int tgetent()
STATIC STATUS end_line()
Definition: editline.c:1425
void TTYflush()
Definition: editline.c:237
#define CTL(x)
Definition: editline.c:67
#define ISMETA(x)
Definition: editline.c:71
STATIC void TTYshow(ECHAR c)
Definition: editline.c:268
int rl_meta_chars
Definition: editline.c:220
NULL
Definition: EST_WFST.cc:55
#define CONST
Definition: editline.h:95
STATIC STATUS redisplay()
Definition: editline.c:982
#define DISPOSE(p)
Definition: editline.h:115
STATIC STATUS h_search()
Definition: editline.c:859
#define SCREEN_INC
Definition: editline.h:101
STATIC char * rsearch_hist(char *patt, int *lpos, int *cpos)
Definition: editline.c:1017
STATUS(* Keymap_Function)()
Definition: editline.h:64
void rl_ttyset(int Reset)
Definition: el_sys_unix.c:63
STATUS
Definition: editline.h:60
STATIC ECHAR * downline
Definition: editline.c:137
STATIC CONST char * Prompt
Definition: editline.c:116
STATIC ECHAR * find_word()
Definition: editline.c:1442
getString int
Definition: EST_item_aux.cc:50
CONST ECHAR * el_Input
Definition: el_sys_unix.c:56
int el_PushBack
Definition: el_sys_unix.c:54
STATIC STATUS del_char()
Definition: editline.c:1420
STATIC STATUS bk_word()
Definition: editline.c:1814
STATIC STATUS bk_char()
Definition: editline.c:954
void add_history(char *p)
Definition: editline.c:1395
STATIC ECHAR * Yanked
Definition: editline.c:117
STATIC STATUS meta()
Definition: editline.c:1140
void rl_reset_terminal(char *p)
Definition: editline.c:1344
float start(const EST_Item &item)
Definition: EST_item_aux.cc:52
STATIC ECHAR * move_right
Definition: editline.c:138
#define ISCTL(x)
Definition: editline.c:68
STATIC void TTYputs(ECHAR *p)
Definition: editline.c:262
STATIC STATUS do_hist(ECHAR *(*move)())
Definition: editline.c:773
STATIC STATUS accept_line()
Definition: editline.c:1681
STATIC STATUS c_complete()
Definition: editline.c:1560
STATIC int substrcmp(char *text, char *pat, int len)
Definition: editline.c:809
void rl_initialize()
Definition: editline.c:1350
char ** EL_USER_COMPLETION_FUNCTION_TYPE(char *text, int start, int end)
Definition: editline.h:159
int rl_erase
Definition: editline.c:109
STATIC void clear_line()
Definition: editline.c:682
#define META(x)
Definition: editline.c:70
#define COPYFROMTO(new, p, len)
Definition: editline.h:111
char * readline(CONST char *prompt)
Definition: editline.c:1354
int el_Pushed
Definition: el_sys_unix.c:55
STATIC ESIZE_T ScreenSize
Definition: editline.c:133
STATIC ECHAR * clrpage
Definition: editline.c:136
STATIC STATUS beg_line()
Definition: editline.c:1408
STATIC STATUS TTYspecial(int c)
Definition: editline.c:1203
void wfree(void *p)
Definition: walloc.c:131
#define SCREEN_ROWS
Definition: editline.c:63
char * el_current_sym()
Definition: editline.c:1464
STATIC STATUS h_first()
Definition: editline.c:796
STATIC STATUS insert_char(int c)
Definition: editline.c:1115
STATIC ECHAR * upline
Definition: editline.c:135
STATIC int OldPoint
Definition: editline.c:125
STATIC STATUS h_next()
Definition: editline.c:786
STATIC int printlen(CONST char *p)
Definition: editline.c:298
#define FORWARD
Definition: el_unix.h:46
STATIC STATUS h_prev()
Definition: editline.c:791
CASE
Definition: editline.c:84
STATIC STATUS copy_region()
Definition: editline.c:1764
char * rl_complete(char *pathname, int *unique)
Definition: el_complete.c:171
STATIC STATUS wipe()
Definition: editline.c:1719