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