/[jscoverage]/trunk/js/editline/editline.c
ViewVC logotype

Contents of /trunk/js/editline/editline.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 332 - (show annotations)
Thu Oct 23 19:03:33 2008 UTC (11 years ago) by siliconforks
File MIME type: text/plain
File size: 24051 byte(s)
Add SpiderMonkey from Firefox 3.1b1.

The following directories and files were removed:
correct/, correct.js
liveconnect/
nanojit/
t/
v8/
vprof/
xpconnect/
all JavaScript files (Y.js, call.js, if.js, math-partial-sums.js, md5.js, perfect.js, trace-test.js, trace.js)


1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
18 *
19 * The Initial Developer of the Original Code is
20 * Simmule Turner and Rich Salz.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40 /*
41 * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
42 *
43 * This software is not subject to any license of the American Telephone
44 * and Telegraph Company or of the Regents of the University of California.
45 *
46 * Permission is granted to anyone to use this software for any purpose on
47 * any computer system, and to alter it and redistribute it freely, subject
48 * to the following restrictions:
49 * 1. The authors are not responsible for the consequences of use of this
50 * software, no matter how awful, even if they arise from flaws in it.
51 * 2. The origin of this software must not be misrepresented, either by
52 * explicit claim or by omission. Since few users ever read sources,
53 * credits must appear in the documentation.
54 * 3. Altered versions must be plainly marked as such, and must not be
55 * misrepresented as being the original software. Since few users
56 * ever read sources, credits must appear in the documentation.
57 * 4. This notice may not be removed or altered.
58 */
59
60
61 /*
62 ** Main editing routines for editline library.
63 */
64 #include "editline.h"
65 #include <signal.h>
66 #include <ctype.h>
67 #include <unistd.h>
68
69 /*
70 ** Manifest constants.
71 */
72 #define SCREEN_WIDTH 80
73 #define SCREEN_ROWS 24
74 #define NO_ARG (-1)
75 #define DEL 127
76 #define CTL(x) ((x) & 0x1F)
77 #define ISCTL(x) ((x) && (x) < ' ')
78 #define UNCTL(x) ((x) + 64)
79 #define META(x) ((x) | 0x80)
80 #define ISMETA(x) ((x) & 0x80)
81 #define UNMETA(x) ((x) & 0x7F)
82 #if !defined(HIST_SIZE)
83 #define HIST_SIZE 20
84 #endif /* !defined(HIST_SIZE) */
85
86 /*
87 ** Command status codes.
88 */
89 typedef enum _STATUS {
90 CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
91 } STATUS;
92
93 /*
94 ** The type of case-changing to perform.
95 */
96 typedef enum _CASE {
97 TOupper, TOlower
98 } CASE;
99
100 /*
101 ** Key to command mapping.
102 */
103 typedef struct _KEYMAP {
104 CHAR Key;
105 STATUS (*Function)();
106 } KEYMAP;
107
108 /*
109 ** Command history structure.
110 */
111 typedef struct _HISTORY {
112 int Size;
113 int Pos;
114 CHAR *Lines[HIST_SIZE];
115 } HISTORY;
116
117 /*
118 ** Globals.
119 */
120 int rl_eof;
121 int rl_erase;
122 int rl_intr;
123 int rl_kill;
124 int rl_quit;
125
126 STATIC CHAR NIL[] = "";
127 STATIC CONST CHAR *Input = NIL;
128 STATIC CHAR *Line;
129 STATIC CONST char *Prompt;
130 STATIC CHAR *Yanked;
131 STATIC char *Screen;
132 STATIC char NEWLINE[]= CRLF;
133 STATIC HISTORY H;
134 STATIC int Repeat;
135 STATIC int End;
136 STATIC int Mark;
137 STATIC int OldPoint;
138 STATIC int Point;
139 STATIC int PushBack;
140 STATIC int Pushed;
141 STATIC int Signal;
142 FORWARD KEYMAP Map[32];
143 FORWARD KEYMAP MetaMap[16];
144 STATIC SIZE_T Length;
145 STATIC SIZE_T ScreenCount;
146 STATIC SIZE_T ScreenSize;
147 STATIC char *backspace;
148 STATIC int TTYwidth;
149 STATIC int TTYrows;
150
151 /* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
152 int rl_meta_chars = 0;
153
154 /*
155 ** Declarations.
156 */
157 STATIC CHAR *editinput();
158 #if defined(USE_TERMCAP)
159 #include <stdlib.h>
160 #include <curses.h>
161 #include <term.h>
162 #endif /* defined(USE_TERMCAP) */
163
164 /*
165 ** TTY input/output functions.
166 */
167
168 STATIC void
169 TTYflush()
170 {
171 if (ScreenCount) {
172 (void)write(1, Screen, ScreenCount);
173 ScreenCount = 0;
174 }
175 }
176
177 STATIC void
178 TTYput(c)
179 CHAR c;
180 {
181 Screen[ScreenCount] = c;
182 if (++ScreenCount >= ScreenSize - 1) {
183 ScreenSize += SCREEN_INC;
184 RENEW(Screen, char, ScreenSize);
185 }
186 }
187
188 STATIC void
189 TTYputs(p)
190 CHAR *p;
191 {
192 while (*p)
193 TTYput(*p++);
194 }
195
196 STATIC void
197 TTYshow(c)
198 CHAR c;
199 {
200 if (c == DEL) {
201 TTYput('^');
202 TTYput('?');
203 }
204 else if (ISCTL(c)) {
205 TTYput('^');
206 TTYput(UNCTL(c));
207 }
208 else if (rl_meta_chars && ISMETA(c)) {
209 TTYput('M');
210 TTYput('-');
211 TTYput(UNMETA(c));
212 }
213 else
214 TTYput(c);
215 }
216
217 STATIC void
218 TTYstring(p)
219 CHAR *p;
220 {
221 while (*p)
222 TTYshow(*p++);
223 }
224
225 STATIC unsigned int
226 TTYget()
227 {
228 CHAR c;
229
230 TTYflush();
231 if (Pushed) {
232 Pushed = 0;
233 return PushBack;
234 }
235 if (*Input)
236 return *Input++;
237 return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
238 }
239
240 #define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
241
242 STATIC void
243 TTYbackn(n)
244 int n;
245 {
246 while (--n >= 0)
247 TTYback();
248 }
249
250 STATIC void
251 TTYinfo()
252 {
253 static int init;
254 #if defined(USE_TERMCAP)
255 char *term;
256 char buff[2048];
257 char *bp, *p;
258 #endif /* defined(USE_TERMCAP) */
259 #if defined(TIOCGWINSZ)
260 struct winsize W;
261 #endif /* defined(TIOCGWINSZ) */
262
263 if (init) {
264 #if defined(TIOCGWINSZ)
265 /* Perhaps we got resized. */
266 if (ioctl(0, TIOCGWINSZ, &W) >= 0
267 && W.ws_col > 0 && W.ws_row > 0) {
268 TTYwidth = (int)W.ws_col;
269 TTYrows = (int)W.ws_row;
270 }
271 #endif /* defined(TIOCGWINSZ) */
272 return;
273 }
274 init++;
275
276 TTYwidth = TTYrows = 0;
277 #if defined(USE_TERMCAP)
278 bp = &buff[0];
279 if ((term = getenv("TERM")) == NULL)
280 term = "dumb";
281 if (tgetent(buff, term) < 0) {
282 TTYwidth = SCREEN_WIDTH;
283 TTYrows = SCREEN_ROWS;
284 return;
285 }
286 p = tgetstr("le", &bp);
287 backspace = p ? strdup(p) : NULL;
288 TTYwidth = tgetnum("co");
289 TTYrows = tgetnum("li");
290 #endif /* defined(USE_TERMCAP) */
291
292 #if defined(TIOCGWINSZ)
293 if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
294 TTYwidth = (int)W.ws_col;
295 TTYrows = (int)W.ws_row;
296 }
297 #endif /* defined(TIOCGWINSZ) */
298
299 if (TTYwidth <= 0 || TTYrows <= 0) {
300 TTYwidth = SCREEN_WIDTH;
301 TTYrows = SCREEN_ROWS;
302 }
303 }
304
305
306 STATIC void
307 reposition()
308 {
309 int i;
310 CHAR *p;
311
312 TTYput('\r');
313 TTYputs((CONST CHAR *)Prompt);
314 for (i = Point, p = Line; --i >= 0; p++)
315 TTYshow(*p);
316 }
317
318 STATIC void
319 left(Change)
320 STATUS Change;
321 {
322 TTYback();
323 if (Point) {
324 if (ISCTL(Line[Point - 1]))
325 TTYback();
326 else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
327 TTYback();
328 TTYback();
329 }
330 }
331 if (Change == CSmove)
332 Point--;
333 }
334
335 STATIC void
336 right(Change)
337 STATUS Change;
338 {
339 TTYshow(Line[Point]);
340 if (Change == CSmove)
341 Point++;
342 }
343
344 STATIC STATUS
345 ring_bell()
346 {
347 TTYput('\07');
348 TTYflush();
349 return CSstay;
350 }
351
352 STATIC STATUS
353 do_macro(c)
354 unsigned int c;
355 {
356 CHAR name[4];
357
358 name[0] = '_';
359 name[1] = c;
360 name[2] = '_';
361 name[3] = '\0';
362
363 if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
364 Input = NIL;
365 return ring_bell();
366 }
367 return CSstay;
368 }
369
370 STATIC STATUS
371 do_forward(move)
372 STATUS move;
373 {
374 int i;
375 CHAR *p;
376
377 i = 0;
378 do {
379 p = &Line[Point];
380 for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
381 if (move == CSmove)
382 right(CSstay);
383
384 for (; Point < End && isalnum(*p); Point++, p++)
385 if (move == CSmove)
386 right(CSstay);
387
388 if (Point == End)
389 break;
390 } while (++i < Repeat);
391
392 return CSstay;
393 }
394
395 STATIC STATUS
396 do_case(type)
397 CASE type;
398 {
399 int i;
400 int end;
401 int count;
402 CHAR *p;
403
404 (void)do_forward(CSstay);
405 if (OldPoint != Point) {
406 if ((count = Point - OldPoint) < 0)
407 count = -count;
408 Point = OldPoint;
409 if ((end = Point + count) > End)
410 end = End;
411 for (i = Point, p = &Line[i]; i < end; i++, p++) {
412 if (type == TOupper) {
413 if (islower(*p))
414 *p = toupper(*p);
415 }
416 else if (isupper(*p))
417 *p = tolower(*p);
418 right(CSmove);
419 }
420 }
421 return CSstay;
422 }
423
424 STATIC STATUS
425 case_down_word()
426 {
427 return do_case(TOlower);
428 }
429
430 STATIC STATUS
431 case_up_word()
432 {
433 return do_case(TOupper);
434 }
435
436 STATIC void
437 ceol()
438 {
439 int extras;
440 int i;
441 CHAR *p;
442
443 for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
444 TTYput(' ');
445 if (ISCTL(*p)) {
446 TTYput(' ');
447 extras++;
448 }
449 else if (rl_meta_chars && ISMETA(*p)) {
450 TTYput(' ');
451 TTYput(' ');
452 extras += 2;
453 }
454 }
455
456 for (i += extras; i > Point; i--)
457 TTYback();
458 }
459
460 STATIC void
461 clear_line()
462 {
463 Point = -strlen(Prompt);
464 TTYput('\r');
465 ceol();
466 Point = 0;
467 End = 0;
468 Line[0] = '\0';
469 }
470
471 STATIC STATUS
472 insert_string(p)
473 CHAR *p;
474 {
475 SIZE_T len;
476 int i;
477 CHAR *new;
478 CHAR *q;
479
480 len = strlen((char *)p);
481 if (End + len >= Length) {
482 if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
483 return CSstay;
484 if (Length) {
485 COPYFROMTO(new, Line, Length);
486 DISPOSE(Line);
487 }
488 Line = new;
489 Length += len + MEM_INC;
490 }
491
492 for (q = &Line[Point], i = End - Point; --i >= 0; )
493 q[len + i] = q[i];
494 COPYFROMTO(&Line[Point], p, len);
495 End += len;
496 Line[End] = '\0';
497 TTYstring(&Line[Point]);
498 Point += len;
499
500 return Point == End ? CSstay : CSmove;
501 }
502
503 STATIC STATUS
504 redisplay()
505 {
506 TTYputs((CONST CHAR *)NEWLINE);
507 TTYputs((CONST CHAR *)Prompt);
508 TTYstring(Line);
509 return CSmove;
510 }
511
512 STATIC STATUS
513 toggle_meta_mode()
514 {
515 rl_meta_chars = ! rl_meta_chars;
516 return redisplay();
517 }
518
519
520 STATIC CHAR *
521 next_hist()
522 {
523 return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
524 }
525
526 STATIC CHAR *
527 prev_hist()
528 {
529 return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
530 }
531
532 STATIC STATUS
533 do_insert_hist(p)
534 CHAR *p;
535 {
536 if (p == NULL)
537 return ring_bell();
538 Point = 0;
539 reposition();
540 ceol();
541 End = 0;
542 return insert_string(p);
543 }
544
545 STATIC STATUS
546 do_hist(move)
547 CHAR *(*move)();
548 {
549 CHAR *p;
550 int i;
551
552 i = 0;
553 do {
554 if ((p = (*move)()) == NULL)
555 return ring_bell();
556 } while (++i < Repeat);
557 return do_insert_hist(p);
558 }
559
560 STATIC STATUS
561 h_next()
562 {
563 return do_hist(next_hist);
564 }
565
566 STATIC STATUS
567 h_prev()
568 {
569 return do_hist(prev_hist);
570 }
571
572 STATIC STATUS
573 h_first()
574 {
575 return do_insert_hist(H.Lines[H.Pos = 0]);
576 }
577
578 STATIC STATUS
579 h_last()
580 {
581 return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
582 }
583
584 /*
585 ** Return zero if pat appears as a substring in text.
586 */
587 STATIC int
588 substrcmp(text, pat, len)
589 char *text;
590 char *pat;
591 int len;
592 {
593 char c;
594
595 if ((c = *pat) == '\0')
596 return *text == '\0';
597 for ( ; *text; text++)
598 if (*text == c && strncmp(text, pat, len) == 0)
599 return 0;
600 return 1;
601 }
602
603 STATIC CHAR *
604 search_hist(search, move)
605 CHAR *search;
606 CHAR *(*move)();
607 {
608 static CHAR *old_search;
609 int len;
610 int pos;
611 int (*match)();
612 char *pat;
613
614 /* Save or get remembered search pattern. */
615 if (search && *search) {
616 if (old_search)
617 DISPOSE(old_search);
618 old_search = (CHAR *)strdup((char *)search);
619 }
620 else {
621 if (old_search == NULL || *old_search == '\0')
622 return NULL;
623 search = old_search;
624 }
625
626 /* Set up pattern-finder. */
627 if (*search == '^') {
628 match = strncmp;
629 pat = (char *)(search + 1);
630 }
631 else {
632 match = substrcmp;
633 pat = (char *)search;
634 }
635 len = strlen(pat);
636
637 for (pos = H.Pos; (*move)() != NULL; )
638 if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
639 return H.Lines[H.Pos];
640 H.Pos = pos;
641 return NULL;
642 }
643
644 STATIC STATUS
645 h_search()
646 {
647 static int Searching;
648 CONST char *old_prompt;
649 CHAR *(*move)();
650 CHAR *p;
651
652 if (Searching)
653 return ring_bell();
654 Searching = 1;
655
656 clear_line();
657 old_prompt = Prompt;
658 Prompt = "Search: ";
659 TTYputs((CONST CHAR *)Prompt);
660 move = Repeat == NO_ARG ? prev_hist : next_hist;
661 p = editinput();
662 Prompt = old_prompt;
663 Searching = 0;
664 TTYputs((CONST CHAR *)Prompt);
665 if (p == NULL && Signal > 0) {
666 Signal = 0;
667 clear_line();
668 return redisplay();
669 }
670 p = search_hist(p, move);
671 clear_line();
672 if (p == NULL) {
673 (void)ring_bell();
674 return redisplay();
675 }
676 return do_insert_hist(p);
677 }
678
679 STATIC STATUS
680 fd_char()
681 {
682 int i;
683
684 i = 0;
685 do {
686 if (Point >= End)
687 break;
688 right(CSmove);
689 } while (++i < Repeat);
690 return CSstay;
691 }
692
693 STATIC void
694 save_yank(begin, i)
695 int begin;
696 int i;
697 {
698 if (Yanked) {
699 DISPOSE(Yanked);
700 Yanked = NULL;
701 }
702
703 if (i < 1)
704 return;
705
706 if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
707 COPYFROMTO(Yanked, &Line[begin], i);
708 Yanked[i] = '\0';
709 }
710 }
711
712 STATIC STATUS
713 delete_string(count)
714 int count;
715 {
716 int i;
717 CHAR *p;
718
719 if (count <= 0 || End == Point)
720 return ring_bell();
721
722 if (count == 1 && Point == End - 1) {
723 /* Optimize common case of delete at end of line. */
724 End--;
725 p = &Line[Point];
726 i = 1;
727 TTYput(' ');
728 if (ISCTL(*p)) {
729 i = 2;
730 TTYput(' ');
731 }
732 else if (rl_meta_chars && ISMETA(*p)) {
733 i = 3;
734 TTYput(' ');
735 TTYput(' ');
736 }
737 TTYbackn(i);
738 *p = '\0';
739 return CSmove;
740 }
741 if (Point + count > End && (count = End - Point) <= 0)
742 return CSstay;
743
744 if (count > 1)
745 save_yank(Point, count);
746
747 for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
748 p[0] = p[count];
749 ceol();
750 End -= count;
751 TTYstring(&Line[Point]);
752 return CSmove;
753 }
754
755 STATIC STATUS
756 bk_char()
757 {
758 int i;
759
760 i = 0;
761 do {
762 if (Point == 0)
763 break;
764 left(CSmove);
765 } while (++i < Repeat);
766
767 return CSstay;
768 }
769
770 STATIC STATUS
771 bk_del_char()
772 {
773 int i;
774
775 i = 0;
776 do {
777 if (Point == 0)
778 break;
779 left(CSmove);
780 } while (++i < Repeat);
781
782 return delete_string(i);
783 }
784
785 STATIC STATUS
786 kill_line()
787 {
788 int i;
789
790 if (Repeat != NO_ARG) {
791 if (Repeat < Point) {
792 i = Point;
793 Point = Repeat;
794 reposition();
795 (void)delete_string(i - Point);
796 }
797 else if (Repeat > Point) {
798 right(CSmove);
799 (void)delete_string(Repeat - Point - 1);
800 }
801 return CSmove;
802 }
803
804 save_yank(Point, End - Point);
805 Line[Point] = '\0';
806 ceol();
807 End = Point;
808 return CSstay;
809 }
810
811 STATIC STATUS
812 insert_char(c)
813 int c;
814 {
815 STATUS s;
816 CHAR buff[2];
817 CHAR *p;
818 CHAR *q;
819 int i;
820
821 if (Repeat == NO_ARG || Repeat < 2) {
822 buff[0] = c;
823 buff[1] = '\0';
824 return insert_string(buff);
825 }
826
827 if ((p = NEW(CHAR, Repeat + 1)) == NULL)
828 return CSstay;
829 for (i = Repeat, q = p; --i >= 0; )
830 *q++ = c;
831 *q = '\0';
832 Repeat = 0;
833 s = insert_string(p);
834 DISPOSE(p);
835 return s;
836 }
837
838 STATIC STATUS
839 meta()
840 {
841 unsigned int c;
842 KEYMAP *kp;
843
844 if ((c = TTYget()) == EOF)
845 return CSeof;
846 #if defined(ANSI_ARROWS)
847 /* Also include VT-100 arrows. */
848 if (c == '[' || c == 'O')
849 switch (c = TTYget()) {
850 default: return ring_bell();
851 case EOF: return CSeof;
852 case 'A': return h_prev();
853 case 'B': return h_next();
854 case 'C': return fd_char();
855 case 'D': return bk_char();
856 }
857 #endif /* defined(ANSI_ARROWS) */
858
859 if (isdigit(c)) {
860 for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
861 Repeat = Repeat * 10 + c - '0';
862 Pushed = 1;
863 PushBack = c;
864 return CSstay;
865 }
866
867 if (isupper(c))
868 return do_macro(c);
869 for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
870 if (kp->Key == c)
871 return (*kp->Function)();
872
873 return ring_bell();
874 }
875
876 STATIC STATUS
877 emacs(c)
878 unsigned int c;
879 {
880 STATUS s;
881 KEYMAP *kp;
882
883 if (rl_meta_chars && ISMETA(c)) {
884 Pushed = 1;
885 PushBack = UNMETA(c);
886 return meta();
887 }
888 for (kp = Map; kp->Function; kp++)
889 if (kp->Key == c)
890 break;
891 s = kp->Function ? (*kp->Function)() : insert_char((int)c);
892 if (!Pushed)
893 /* No pushback means no repeat count; hacky, but true. */
894 Repeat = NO_ARG;
895 return s;
896 }
897
898 STATIC STATUS
899 TTYspecial(c)
900 unsigned int c;
901 {
902 if (ISMETA(c))
903 return CSdispatch;
904
905 if (c == rl_erase || c == DEL)
906 return bk_del_char();
907 if (c == rl_kill) {
908 if (Point != 0) {
909 Point = 0;
910 reposition();
911 }
912 Repeat = NO_ARG;
913 return kill_line();
914 }
915 if (c == rl_eof && Point == 0 && End == 0)
916 return CSeof;
917 if (c == rl_intr) {
918 Signal = SIGINT;
919 return CSsignal;
920 }
921 if (c == rl_quit) {
922 Signal = SIGQUIT;
923 return CSeof;
924 }
925
926 return CSdispatch;
927 }
928
929 STATIC CHAR *
930 editinput()
931 {
932 unsigned int c;
933
934 Repeat = NO_ARG;
935 OldPoint = Point = Mark = End = 0;
936 Line[0] = '\0';
937
938 Signal = -1;
939 while ((c = TTYget()) != EOF)
940 switch (TTYspecial(c)) {
941 case CSdone:
942 return Line;
943 case CSeof:
944 return NULL;
945 case CSsignal:
946 return (CHAR *)"";
947 case CSmove:
948 reposition();
949 break;
950 case CSdispatch:
951 switch (emacs(c)) {
952 case CSdone:
953 return Line;
954 case CSeof:
955 return NULL;
956 case CSsignal:
957 return (CHAR *)"";
958 case CSmove:
959 reposition();
960 break;
961 case CSdispatch:
962 case CSstay:
963 break;
964 }
965 break;
966 case CSstay:
967 break;
968 }
969 return NULL;
970 }
971
972 STATIC void
973 hist_add(p)
974 CHAR *p;
975 {
976 int i;
977
978 if ((p = (CHAR *)strdup((char *)p)) == NULL)
979 return;
980 if (H.Size < HIST_SIZE)
981 H.Lines[H.Size++] = p;
982 else {
983 DISPOSE(H.Lines[0]);
984 for (i = 0; i < HIST_SIZE - 1; i++)
985 H.Lines[i] = H.Lines[i + 1];
986 H.Lines[i] = p;
987 }
988 H.Pos = H.Size - 1;
989 }
990
991 /*
992 ** For compatibility with FSF readline.
993 */
994 /* ARGSUSED0 */
995 void
996 rl_reset_terminal(p)
997 char *p;
998 {
999 }
1000
1001 void
1002 rl_initialize()
1003 {
1004 }
1005
1006 char *
1007 readline(prompt)
1008 CONST char *prompt;
1009 {
1010 CHAR *line;
1011 int s;
1012
1013 if (Line == NULL) {
1014 Length = MEM_INC;
1015 if ((Line = NEW(CHAR, Length)) == NULL)
1016 return NULL;
1017 }
1018
1019 TTYinfo();
1020 rl_ttyset(0);
1021 hist_add(NIL);
1022 ScreenSize = SCREEN_INC;
1023 Screen = NEW(char, ScreenSize);
1024 Prompt = prompt ? prompt : (char *)NIL;
1025 TTYputs((CONST CHAR *)Prompt);
1026 if ((line = editinput()) != NULL) {
1027 line = (CHAR *)strdup((char *)line);
1028 TTYputs((CHAR *)NEWLINE);
1029 TTYflush();
1030 }
1031 rl_ttyset(1);
1032 DISPOSE(Screen);
1033 DISPOSE(H.Lines[--H.Size]);
1034 if (Signal > 0) {
1035 s = Signal;
1036 Signal = 0;
1037 (void)kill(getpid(), s);
1038 }
1039 return (char *)line;
1040 }
1041
1042 void
1043 add_history(p)
1044 char *p;
1045 {
1046 if (p == NULL || *p == '\0')
1047 return;
1048
1049 #if defined(UNIQUE_HISTORY)
1050 if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0)
1051 return;
1052 #endif /* defined(UNIQUE_HISTORY) */
1053 hist_add((CHAR *)p);
1054 }
1055
1056
1057 STATIC STATUS
1058 beg_line()
1059 {
1060 if (Point) {
1061 Point = 0;
1062 return CSmove;
1063 }
1064 return CSstay;
1065 }
1066
1067 STATIC STATUS
1068 del_char()
1069 {
1070 return delete_string(Repeat == NO_ARG ? 1 : Repeat);
1071 }
1072
1073 STATIC STATUS
1074 end_line()
1075 {
1076 if (Point != End) {
1077 Point = End;
1078 return CSmove;
1079 }
1080 return CSstay;
1081 }
1082
1083 STATIC STATUS
1084 accept_line()
1085 {
1086 Line[End] = '\0';
1087 return CSdone;
1088 }
1089
1090 STATIC STATUS
1091 transpose()
1092 {
1093 CHAR c;
1094
1095 if (Point) {
1096 if (Point == End)
1097 left(CSmove);
1098 c = Line[Point - 1];
1099 left(CSstay);
1100 Line[Point - 1] = Line[Point];
1101 TTYshow(Line[Point - 1]);
1102 Line[Point++] = c;
1103 TTYshow(c);
1104 }
1105 return CSstay;
1106 }
1107
1108 STATIC STATUS
1109 quote()
1110 {
1111 unsigned int c;
1112
1113 return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
1114 }
1115
1116 STATIC STATUS
1117 wipe()
1118 {
1119 int i;
1120
1121 if (Mark > End)
1122 return ring_bell();
1123
1124 if (Point > Mark) {
1125 i = Point;
1126 Point = Mark;
1127 Mark = i;
1128 reposition();
1129 }
1130
1131 return delete_string(Mark - Point);
1132 }
1133
1134 STATIC STATUS
1135 mk_set()
1136 {
1137 Mark = Point;
1138 return CSstay;
1139 }
1140
1141 STATIC STATUS
1142 exchange()
1143 {
1144 unsigned int c;
1145
1146 if ((c = TTYget()) != CTL('X'))
1147 return c == EOF ? CSeof : ring_bell();
1148
1149 if ((c = Mark) <= End) {
1150 Mark = Point;
1151 Point = c;
1152 return CSmove;
1153 }
1154 return CSstay;
1155 }
1156
1157 STATIC STATUS
1158 yank()
1159 {
1160 if (Yanked && *Yanked)
1161 return insert_string(Yanked);
1162 return CSstay;
1163 }
1164
1165 STATIC STATUS
1166 copy_region()
1167 {
1168 if (Mark > End)
1169 return ring_bell();
1170
1171 if (Point > Mark)
1172 save_yank(Mark, Point - Mark);
1173 else
1174 save_yank(Point, Mark - Point);
1175
1176 return CSstay;
1177 }
1178
1179 STATIC STATUS
1180 move_to_char()
1181 {
1182 unsigned int c;
1183 int i;
1184 CHAR *p;
1185
1186 if ((c = TTYget()) == EOF)
1187 return CSeof;
1188 for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
1189 if (*p == c) {
1190 Point = i;
1191 return CSmove;
1192 }
1193 return CSstay;
1194 }
1195
1196 STATIC STATUS
1197 fd_word()
1198 {
1199 return do_forward(CSmove);
1200 }
1201
1202 STATIC STATUS
1203 fd_kill_word()
1204 {
1205 int i;
1206
1207 (void)do_forward(CSstay);
1208 if (OldPoint != Point) {
1209 i = Point - OldPoint;
1210 Point = OldPoint;
1211 return delete_string(i);
1212 }
1213 return CSstay;
1214 }
1215
1216 STATIC STATUS
1217 bk_word()
1218 {
1219 int i;
1220 CHAR *p;
1221
1222 i = 0;
1223 do {
1224 for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
1225 left(CSmove);
1226
1227 for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
1228 left(CSmove);
1229
1230 if (Point == 0)
1231 break;
1232 } while (++i < Repeat);
1233
1234 return CSstay;
1235 }
1236
1237 STATIC STATUS
1238 bk_kill_word()
1239 {
1240 (void)bk_word();
1241 if (OldPoint != Point)
1242 return delete_string(OldPoint - Point);
1243 return CSstay;
1244 }
1245
1246 STATIC int
1247 argify(line, avp)
1248 CHAR *line;
1249 CHAR ***avp;
1250 {
1251 CHAR *c;
1252 CHAR **p;
1253 CHAR **new;
1254 int ac;
1255 int i;
1256
1257 i = MEM_INC;
1258 if ((*avp = p = NEW(CHAR*, i))== NULL)
1259 return 0;
1260
1261 for (c = line; isspace(*c); c++)
1262 continue;
1263 if (*c == '\n' || *c == '\0')
1264 return 0;
1265
1266 for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
1267 if (isspace(*c)) {
1268 *c++ = '\0';
1269 if (*c && *c != '\n') {
1270 if (ac + 1 == i) {
1271 new = NEW(CHAR*, i + MEM_INC);
1272 if (new == NULL) {
1273 p[ac] = NULL;
1274 return ac;
1275 }
1276 COPYFROMTO(new, p, i * sizeof (char **));
1277 i += MEM_INC;
1278 DISPOSE(p);
1279 *avp = p = new;
1280 }
1281 p[ac++] = c;
1282 }
1283 }
1284 else
1285 c++;
1286 }
1287 *c = '\0';
1288 p[ac] = NULL;
1289 return ac;
1290 }
1291
1292 STATIC STATUS
1293 last_argument()
1294 {
1295 CHAR **av;
1296 CHAR *p;
1297 STATUS s;
1298 int ac;
1299
1300 if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
1301 return ring_bell();
1302
1303 if ((p = (CHAR *)strdup((char *)p)) == NULL)
1304 return CSstay;
1305 ac = argify(p, &av);
1306
1307 if (Repeat != NO_ARG)
1308 s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
1309 else
1310 s = ac ? insert_string(av[ac - 1]) : CSstay;
1311
1312 if (ac)
1313 DISPOSE(av);
1314 DISPOSE(p);
1315 return s;
1316 }
1317
1318 STATIC KEYMAP Map[32] = {
1319 { CTL('@'), ring_bell },
1320 { CTL('A'), beg_line },
1321 { CTL('B'), bk_char },
1322 { CTL('D'), del_char },
1323 { CTL('E'), end_line },
1324 { CTL('F'), fd_char },
1325 { CTL('G'), ring_bell },
1326 { CTL('H'), bk_del_char },
1327 { CTL('J'), accept_line },
1328 { CTL('K'), kill_line },
1329 { CTL('L'), redisplay },
1330 { CTL('M'), accept_line },
1331 { CTL('N'), h_next },
1332 { CTL('O'), ring_bell },
1333 { CTL('P'), h_prev },
1334 { CTL('Q'), ring_bell },
1335 { CTL('R'), h_search },
1336 { CTL('S'), ring_bell },
1337 { CTL('T'), transpose },
1338 { CTL('U'), ring_bell },
1339 { CTL('V'), quote },
1340 { CTL('W'), wipe },
1341 { CTL('X'), exchange },
1342 { CTL('Y'), yank },
1343 { CTL('Z'), ring_bell },
1344 { CTL('['), meta },
1345 { CTL(']'), move_to_char },
1346 { CTL('^'), ring_bell },
1347 { CTL('_'), ring_bell },
1348 { 0, NULL }
1349 };
1350
1351 STATIC KEYMAP MetaMap[16]= {
1352 { CTL('H'), bk_kill_word },
1353 { DEL, bk_kill_word },
1354 { ' ', mk_set },
1355 { '.', last_argument },
1356 { '<', h_first },
1357 { '>', h_last },
1358 { 'b', bk_word },
1359 { 'd', fd_kill_word },
1360 { 'f', fd_word },
1361 { 'l', case_down_word },
1362 { 'm', toggle_meta_mode },
1363 { 'u', case_up_word },
1364 { 'y', yank },
1365 { 'w', copy_region },
1366 { 0, NULL }
1367 };
1368

  ViewVC Help
Powered by ViewVC 1.1.24