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

Annotation of /trunk/js/editline/editline.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 332 - (hide annotations)
Thu Oct 23 19:03:33 2008 UTC (10 years, 11 months 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 siliconforks 332 /* -*- 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