Annotation of OpenXM_contrib2/fep/fep_edit.c, Revision 1.3
1.1 noro 1: /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
2:
3: #ifndef lint
4: static char rcsid[]=
5: "$Id: fep_edit.c,v 4.10 1995/01/20 08:15:55 utashiro Exp $ (SRA)";
6: #endif /* lint */
7:
8: #include <stdio.h>
9: #include <sys/types.h>
10: #include <sys/stat.h>
11: #include <sys/ioctl.h>
12: #ifdef TERMIOS
13: #include <termios.h>
14: #if defined(__linux__) || defined(__CYGWIN__)
15: #ifndef _POSIX_VDISABLE
16: #define _POSIX_VDISABLE '\0'
17: #endif
18: #endif
19: #else
20: #include <sgtty.h>
21: #endif
22: #include <sys/time.h>
23: #include <ctype.h>
24: #if defined(__CYGWIN__)
25: #include <sys/dirent.h>
26: #define direct dirent
1.2 noro 27: #elif defined(sun)
28: #include <dirent.h>
29: #define direct dirent
30: #include <unistd.h>
1.1 noro 31: #else
32: #include <sys/dir.h>
33: #endif
34: #include <sys/file.h>
35: #include <setjmp.h>
36: #include "fep_defs.h"
37: #include "fep_glob.h"
38: #include "fep_funcs.h"
39:
40: CHAR *CommandLine; /* pointer to command line buffer */
41: CHAR *KillBuffer; /* pointer to kill buffer */
42: int CurrentPosition; /* current cursor position */
43: int MarkPosition = -1; /* Marked position */
44: EDITMODE editmode = NOTYET; /* edtimode EMACS, VI */
45: EDITSTATUS editstatus = NOTEDITING;/* EDITING, NOTEDITING */
46:
47: int maxline = MAXCMDLEN; /* maximum length of command line */
48: int NeedNewLine; /* add new line flag */
49: int NeedSave; /* need to save to history */
50: int Transparency = OFF; /* transparent flag */
51: int Through = OFF; /* through flag */
52: int eof_occured = 0; /* eof has been occured */
53: jmp_buf jbuf; /* jump buffer */
54:
55: FUNC *curFuncTab; /* current function table */
56: FUNC *altFuncTab; /* alternative function table */
57:
58: /*
59: * Default binding table
60: */
61: BINDENT emacsBindings[] = {
62: /* NULL */ {"\0", mark},
63: /* ^A */ {"\\^A", beginning_of_line},
64: /* ^B */ {"\\^B", backward_character},
65: /* ^D */ {"\\^D", delete_next_character},
66: /* ^E */ {"\\^E", end_of_line},
67: /* ^F */ {"\\^F", forward_character},
68: /* ^I */ {"\\^I", insert_tab},
69: /* ^J */ {"\\^J", new_line},
70: /* ^K */ {"\\^K", kill_to_end_of_line},
71: /* ^L */ {"\\^L", clear_screen},
72: /* ^M */ {"\\^M", new_line},
73: /* ^N */ {"\\^N", next_history},
74: /* ^P */ {"\\^P", previous_history},
75: /* ^T */ {"\\^T", previous_history},
76: /* ^Y */ {"\\^Y", yank_from_kill_buffer},
77: /* ^^ */ {"\\^^", toggle_through},
78: /* esc-b */ {"\\^[b", backward_word},
79: /* esc-B */ {"\\^[B", backward_Word},
80: /* esc-d */ {"\\^[d", delete_next_word},
81: /* esc-D */ {"\\^[D", delete_next_Word},
82: /* esc-f */ {"\\^[f", forward_word},
83: /* esc-F */ {"\\^[F", forward_Word},
84: /* esc-h */ {"\\^[h", delete_previous_word},
85: /* esc-H */ {"\\^[H", delete_previous_Word},
86: /* esc-l */ {"\\^[l", list_file_name},
87: /* esc-L */ {"\\^[L", list_file_name},
88: /* esc-n */ {"\\^[n", insert_next_history},
89: /* esc-N */ {"\\^[N", insert_next_history},
90: /* esc-p */ {"\\^[p", insert_previous_history},
91: /* esc-P */ {"\\^[P", insert_previous_history},
92: /* esc-. */ {"\\^[.", insert_current_history},
93: /* esc-esc */ {"\\^[\\^[", expand_file_name},
94: /* esc-"-" */ {"\\^[-", toggle_through},
95: /* esc-_ */ {"\\^[_", invoke_shell},
96: /* esc-< */ {"\\^[<", search_reverse},
97: /* esc-> */ {"\\^[>", search_forward},
98: /* esc-? */ {"\\^[?", show_help},
99: /* ^X-^B */ {"\\^X\\^B", show_bindings},
100: /* ^X-B */ {"\\^XB", show_bindings},
101: /* ^X-b */ {"\\^Xb", show_bindings},
102: /* ^X-^H */ {"\\^X\\^H", show_history},
103: /* ^X-H */ {"\\^XH", show_history},
104: /* ^X-h */ {"\\^Xh", show_history},
105: /* ^X-^V */ {"\\^X\\^V", view_buffer},
106: /* ^X-^K */ {"\\^X\\^K", kill_to_top_of_line},
107: /* ^X-^L */ {"\\^X\\^L", fep_repaint},
108: /* ^X-^C */ {"\\^X\\^C", (FUNC)terminate},
109: /* ^X-^D */ {"\\^X\\^D", send_eof},
110: /* ^X-( */ {"\\^X(", fep_start_script},
111: /* ^X-) */ {"\\^X)", fep_end_script},
112: /* */ {NULL, NULL}
113: };
114:
115: /*
116: * Initialize function table buffer
117: */
118: init_bind_table ()
119: {
120:
121: curFuncTab = (FUNC *) calloc (sizeof (FUNC), 256);
122: altFuncTab = (FUNC *) calloc (sizeof (FUNC), 256);
123: if (curFuncTab == 0 || altFuncTab == 0) {
124: printf ("Can't allocate space for function table\n");
125: exit (1);
126: }
127: }
128:
129: /*
130: * Initialize function table
131: */
132: char strspace [256], *strspace_addr = strspace;
133:
134: init_edit_params ()
135: {
136: struct indirect *idp;
137: char *cp, *getenv();
138: char sbuf[2048], *term, *tgetstr();
139:
140: if (term = look_var ("term")) {
141: if (tgetent (sbuf, term) == 1) {
142: if (lines == 0)
143: lines = tgetnum ("li");
144: if (columns == 0)
145: columns = tgetnum ("co");
146: term_clear = tgetstr ("cl", &strspace_addr);
147: }
148: }
149:
150: if (lines == 0)
151: lines = 24;
152: if (columns == 0)
153: columns = 80;
154:
155: sprintf (sbuf, "%d", lines);
156: set_var ("crt", sbuf);
157:
158: if (editmode == NOTYET) {
159: if (look_var ("editmode"))
160: set_var ("editmode", look_var ("editmode"));
161: else
162: set_var ("editmode", "emacs");
163: }
164:
165: set_var ("showhist", itoa (lines - 1));
166:
167: /*
168: * Read startup file
169: */
170: sourceRcFile ();
171:
172: /*
173: * Read history if 'history-file' is set
174: */
175: {
176: char *cp, *mk_home_relative ();
177:
178: if (look_var ("savehist") && (cp = look_var ("history-file"))) {
179: cp = mk_home_relative (cp);
180:
181: if (access (cp, R_OK) == 0)
182: read_history (cp);
183: }
184: }
185:
186: /*
187: * Initialize command line buffer
188: */
189: CommandLine = (CHAR *) calloc (maxline, 1);
190: KillBuffer = (CHAR *) calloc (maxline, 1);
191: if (CommandLine == 0 || KillBuffer == 0) {
192: perror ("Edit line buffer");
193: exit (1);
194: }
195: (void) strcpy (CommandLine, "");
196: (void) strcpy (KillBuffer, "");
197: CurrentPosition = 0;
198: }
199:
200: /*
201: * Initialize emacs bindings
202: */
203: initEmacsBindings (cft, aft)
204: FUNC cft[], aft[];
205: {
206: register int i;
207: BINDENT *ftp;
208:
209: for (i = 0; i < 256; i++)
210: cft[i] = self_insert;
211:
212: #define import(table,key,fn) if((int)key>0)table[(int)key]=fn
213:
214: #ifdef TERMIOS
215: /* Now, using cbreak mode
216: import (cft, initial_ttymode.c_cc[VSTART], ignore);
217: import (cft, initial_ttymode.c_cc[VSTOP], ignore);
218: */
219: #if 0
220: import (cft, initial_ttymode.c_cc[VINTR], insert_and_flush);
221: #else
222: /* added by noro */
223: import (cft, initial_ttymode.c_cc[VINTR], send_int_sig);
224: /* XXX : this may not be necessary */
225: import (aft, initial_ttymode.c_cc[VINTR], send_int_sig);
226: #endif
227: import (cft, initial_ttymode.c_cc[VQUIT], insert_and_flush);
228: /* Now, EOF will be sent on empty line.
229: import (cft, initial_ttymode.c_cc[VEOF], send_eof);
230: */
231: #ifdef VSWTC
232: import (cft, initial_ttymode.c_cc[VSWTC], insert_and_flush);
233: #endif
234: import (cft, initial_ttymode.c_cc[VSUSP], insert_and_flush);
235: /* ^Y is used for yank-from-kill-buffer
236: import (cft, initial_ttymode.c_cc[VDSUSP], self_insert);
237: */
238: import (cft, initial_ttymode.c_cc[VREPRINT], reprint);
1.3 ! ohara 239: #ifdef VDISCARD
1.1 noro 240: import (cft, initial_ttymode.c_cc[VDISCARD], self_insert);
1.3 ! ohara 241: #endif
1.1 noro 242: import (cft, initial_ttymode.c_cc[VWERASE], delete_previous_word);
243: import (cft, initial_ttymode.c_cc[VLNEXT], literal_next);
244: import (cft, initial_ttymode.c_cc[VERASE], delete_previous_character);
245: import (cft, initial_ttymode.c_cc[VKILL], delete_line);
246: #else
247: /* Now, using cbreak mode
248: import (cft, tchars_buf.t_startc, ignore);
249: import (cft, tchars_buf.t_stopc, ignore);
250: */
251: #if 0
252: import (cft, tchars_buf.t_intrc, insert_and_flush);
253: #else
254: import (cft, tchars_buf.t_intrc, send_int_sig);
255: import (aft, tchars_buf.t_intrc, send_int_sig);
256: #endif
257: import (cft, tchars_buf.t_quitc, insert_and_flush);
258: /* Now, EOF will be sent on empty line.
259: import (cft, tchars_buf.t_eofc, send_eof);
260: */
261: import (cft, tchars_buf.t_brkc, insert_and_flush);
262: import (cft, ltchars_buf.t_suspc, insert_and_flush);
263: /* ^Y is used for yank-from-kill-buffer
264: import (cft, ltchars_buf.t_dsuspc, self_insert);
265: */
266: import (cft, ltchars_buf.t_rprntc, reprint);
267: import (cft, ltchars_buf.t_flushc, self_insert);
268: import (cft, ltchars_buf.t_werasc, delete_previous_word);
269: import (cft, ltchars_buf.t_lnextc, literal_next);
270: import (cft, initial_ttymode.sg_erase, delete_previous_character);
271: import (cft, initial_ttymode.sg_kill, delete_line);
272: #endif
273:
274: #undef import
275:
276: /*
277: * Set default bindings
278: */
279: for (ftp = emacsBindings; ftp->bt_s; ftp++) {
280: bind_key (cft, ftp->bt_func, ftp->bt_s, fep_abort);
281: }
282: }
283:
284: /*
285: * Main function of front end program
286: */
287: CHAR *
288: getline()
289: {
290: int c;
291: CHAR *execute_command, *check_alias();
292: char *remained;
293: int processed;
294:
295: (void) strcpy (CommandLine, "");
296: CurrentPosition = 0;
297: resetCurrentHistory ();
298:
299: RETRY:
300: (void) fflush (stdout);
301: NeedNewLine = 0;
302: NeedSave = 0;
303: editstatus = EDITING;
304: processed = 0;
305: (void) setjmp (jbuf);
306:
307: /*
308: * If there is file pointer for I/O redirection,
309: * read input from the pointer and return
310: */
311: if (redirect_fp) {
312:
313: /*
314: * Check output from sub-process
315: */
316: swallow_output();
317:
318: if (fgets (CommandLine, MAXCMDLEN, redirect_fp)) {
319: ++redirect_line;
320: execute_command = CommandLine;
321: goto RETURN;
322: }
323: else {
324: if (look_var ("verbose"))
325: printf ("%d lines redirected\n", redirect_line);
326: errorBell ();
327: if (redirect_pid) {
328: pclose (redirect_fp);
329: redirect_pid = 0;
330: }
331: else
332: fclose (redirect_fp);
333: redirect_fp = NULL;
334: }
335: }
336:
337: while ((c = getcharacter ()) >= (CHAR) 0) {
338: int status;
339:
340: /*
341: * In transparet mode
342: */
343: if (Through == ON || Transparency == ON) {
344: if (*curFuncTab[(int) c] == toggle_through ||
345: *curFuncTab[(int) c] == fix_transparency) {
346: (*curFuncTab[(int) c])();
347: goto RETRY;
348: }
349: else {
350: CommandLine[CurrentPosition] = c;
351: CommandLine[CurrentPosition + 1] = '\0';
352: return (CommandLine);
353: }
354: }
355:
356: /*
357: * If find EOF character on top of empty line
358: * and the variable "send-eof-on-empty-line" is set
359: * call send_eof
360: */
361: if (
362: #ifdef TERMIOS
363: c == initial_ttymode.c_cc[VEOF]
364: #else
365: c == tchars_buf.t_eofc
366: #endif
367: && curFuncTab[c] != send_eof
368: && ! look_var ("ignore-eof")
369: && CommandLine [0] == '\0'
370: ) {
371: if (!eof_occured && look_var ("alarm-on-eof")) {
372: eof_occured = 1;
373: status = alarm_on_eof (c);
374: }
375: else
376: status = send_eof (c);
377: }
378: else {
379: eof_occured = 0;
380: status = callfunc (curFuncTab, c);
381: }
382:
383: (void) fflush (stdout);
384: if (status == 1) /* end of line editing */
385: break;
386: else /* continue line editing */
387: continue;
388: }
389: editstatus = NOTEDITING;
390:
391: REPROCESS:
392:
393: /*
394: * Check command line refer history or not
395: */
396: if (refer_history () == PROCESSED)
397: goto RETRY;
398:
399: /*
400: * Check alias list
401: */
402: if (!processed && !look_var ("noalias")
403: && (execute_command = check_alias (CommandLine))
404: ) {
405: if (look_var ("verbose"))
406: printf ("%s\n", execute_command);
407: }
408: else
409: execute_command = CommandLine;
410:
411:
412: /*
413: * Check builtin function, and execute it.
414: */
415: if (executeBuiltInFunction (execute_command, &remained) == PROCESSED) {
416: if (!processed)
417: addHistory (CommandLine);
418: CommandLine[0] = '\0';
419: CurrentPosition = 0;
420: if (remained && *remained) {
421: strcpy (CommandLine, remained);
422: processed = 1;
423: goto REPROCESS;
424: }
425: if (!redirect_fp)
426: fputs (prompt, stdout);
427: goto RETRY;
428: }
429:
430: if (NeedSave) {
431: if (!is_empty_line (CommandLine) || !look_var ("ignore-empty-line"))
432: if (!processed)
433: addHistory (CommandLine);
434: /*
435: * put string to buffer
436: */
437: buf_put (output_buffer, CommandLine);
438: if (NeedNewLine == 1)
439: buf_put (output_buffer, "\n");
440: }
441:
442: if (NeedNewLine == 1)
443: (void) strcat (execute_command, "\n");
444:
445: RETURN:
446: return (execute_command);
447: }
448:
449: /*
450: * Invoke appropliate function according to fucntion table
451: * Return value 1 means exit from line editing
452: */
453: callfunc (ft, c)
454: FUNC ft[];
455: int c;
456: {
457:
458: if (isIndirect(ft[(int) c])) {
459: FUNC *nft = maskIndirect (ft[(int)c]);
460: char nc;
461:
462: nc = (CHAR) getcharacter();
463: return (callfunc (nft, nc));
464: }
465: else
466: return ((*ft[(int) c]) (c));
467: }
468:
469: /*
470: * Beep and do nothing
471: */
472: fep_abort()
473: {
474: (void) errorBell ();
475: return (0);
476: }
477:
478: /*
479: * Insert the character self
480: */
481: self_insert(c)
482: CHAR c;
483: {
484: register int i, nbyte = 1, currentNull;
485: #ifdef KANJI
486: CHAR byte2;
487: #endif /* KANJI */
488:
489: currentNull = strlen (CommandLine);
490:
491: if (currentNull >= maxline) {
492: errorBell();
493: return (0);
494: }
495:
496: if (isctlchar(CommandLine[CurrentPosition]))
497: (void) putchar (BS);
498: #ifdef KANJI
499: if (iskanji (c)) {
500: byte2 = (CHAR) getcharacter ();
501: putchar (c);
502: putchar (byte2);
503: nbyte = 2;
504: }
505: else
506: #endif /* KANJI */
507: putChar (c);
508: reverse_strcpy (
509: &CommandLine[CurrentPosition] + nbyte,
510: &CommandLine[CurrentPosition]
511: );
512: CurrentPosition += nbyte;
513: CommandLine[CurrentPosition - nbyte] = c;
514: #ifdef KANJI
515: if (nbyte > 1) {
516: CommandLine[CurrentPosition - 1] = byte2;
517: }
518: #endif /* KANJI */
519: printS (&CommandLine [CurrentPosition]);
520:
521: if (CommandLine[CurrentPosition] != '\0') {
522: repeat (BS, howlong (&CommandLine[CurrentPosition + 1], 0));
523: (void) putchar (BS);
524: }
525: return (0);
526: }
527:
528: /*
529: * Insert string in current position
530: */
531: insert_string (s)
532: CHAR *s;
533: {
534: register int i, nbyte = strlen (s), currentNull;
535:
536: currentNull = strlen (CommandLine);
537:
538: if (currentNull + nbyte >= maxline - 1) {
539: errorBell();
540: return (0);
541: }
542:
543: if (isctlchar(CommandLine[CurrentPosition]))
544: (void) putchar (BS);
545: printS (s);
546: reverse_strcpy (
547: &CommandLine[CurrentPosition] + nbyte, /* to */
548: &CommandLine[CurrentPosition] /* from */
549: );
550: bcopy (s, &CommandLine[CurrentPosition], nbyte);
551: CurrentPosition += nbyte;
552:
553: if (CommandLine[CurrentPosition] != '\0') {
554: printS (&CommandLine[CurrentPosition]);
555: repeat (BS, howlong (&CommandLine[CurrentPosition], 0));
556: }
557: return (0);
558: }
559:
560: /*
561: * Yank string from kill buffer.
562: */
563: yank_from_kill_buffer ()
564: {
565: insert_string (KillBuffer);
566: }
567:
568: /*
569: * Set mark to current position
570: */
571: mark ()
572: {
573: set_mark (CurrentPosition);
574: return (0);
575: }
576:
577: /*
578: * Set mark to specified position
579: */
580: set_mark (pos)
581: int pos;
582: {
583: MarkPosition = pos;
584: return (0);
585: }
586:
587: /*
588: * Delete area from mark to current position to kill buffer
589: */
590: delete_to_kill_buffer ()
591: {
592: int n = abs (CurrentPosition - MarkPosition);
593:
594: if (MarkPosition < 0) {
595: errorBell();
596: return (0);
597: }
598:
599: if (CurrentPosition == MarkPosition)
600: return;
601:
602: if (CurrentPosition > MarkPosition) {
603: (void) moveto (MarkPosition);
604: }
605:
606: return (delete_next_n_character (n));
607: }
608:
609: /*
610: * Move to specified position.
611: */
612: moveto (position)
613: {
614: if (position < CurrentPosition)
615: while (position < CurrentPosition)
616: (void) backward_n_character (1);
617: else
618: while (position > CurrentPosition
619: #ifdef KANJI
620: && !(CurrentPosition + 1 == position
621: && iskanji (CommandLine[CurrentPosition]))
622: #endif /* KANJI */
623: )
624: (void) forward_n_character (1);
625: }
626:
627: /*
628: * Move cursor to top of line
629: */
630: beginning_of_line()
631: {
632: register int i;
633:
634: for (i = CurrentPosition; i > 0; i--) {
635: if (isctlchar (CommandLine[i]))
636: (void) putchar (BS);
637: (void) putchar (BS);
638: }
639: CurrentPosition = 0;
640: return (0);
641: }
642:
643: #ifdef KANJI
644: #define INC(i) if(iskanji(CommandLine[i])) i+=2; else i++;
645: #define DEC(i) if(i>=2 && iskanji_in_string(CommandLine, i-2)) i-=2; else i--;
646: #else /* KANJI */
647: #define INC(i) i++
648: #define DEC(i) i--
649: #endif /* KANJI */
650:
651: /*
652: * Move cursor to end of line
653: */
654: end_of_line()
655: {
656: register int i;
657:
658: for (i = CurrentPosition; CommandLine[i]; i++) {
659: if (isctlchar (CommandLine[i]))
660: (void) putchar (unctl(CommandLine[i]));
661: else
662: (void) putchar (CommandLine[i]);
663: if (isctlchar(CommandLine[i+1]))
664: (void) putchar ('^');
665: }
666: CurrentPosition = i;
667: return (0);
668: }
669:
670: /*
671: * Move cursor left one space
672: */
673: backward_character()
674: {
675:
676: return (backward_n_character (1));
677: }
678:
679: /*
680: * Move cursor left "n" space
681: */
682: backward_n_character(n)
683: int n;
684: {
685: int space;
686: int i = CurrentPosition;
687:
688: if (n == 0)
689: return (0);
690: else if (n < 0)
691: return (forward_n_character (-n));
692: else if (n > CurrentPosition) {
693: errorBell ();
694: return (0);
695: }
696:
697: while (n-- && i >= 0) {
698: if (isctlchar (CommandLine[i]))
699: putchar (BS);
700: #ifdef KANJI
701: if (i > 0 && iskanji_in_string (CommandLine, i-2)) {
702: (void) putchar (BS);
703: (void) putchar (BS);
704: i--;
705: }
706: else
707: #endif /* KANJI */
708: putchar (BS);
709: i--;
710: }
711: CurrentPosition = i;
712: return (0);
713: }
714:
715: /*
716: * Move cursor backward one word
717: */
718: backward_word ()
719: {
720:
721: return (backward_n_word (1));
722: }
723:
724: /*
725: * Move cursor backward n word
726: */
727: backward_n_word (n)
728: int n;
729: {
730: register int i = CurrentPosition, nchars = 0;
731:
732: if (i == 0) {
733: errorBell ();
734: return (0);
735: }
736:
737: #ifdef KANJI
738: while (n--) {
739: DEC(i);
740: nchars++;
741:
742: while (1) {
743: if (i >= 2 && iskanji_in_string (CommandLine, i-2))
744: break;
745: else if (i > 0 && !iswordchar (CommandLine[i]))
746: i -= 1;
747: else
748: break;
749:
750: nchars++;
751: }
752: while (1) {
753: if (i >= 2 && iskanji_in_string (CommandLine, i - 2))
754: i -= 2;
755: else if (i > 0 && iswordchar (CommandLine [i -1]))
756: i -= 1;
757: else
758: break;
759: nchars++;
760: }
761: }
762: #else /* KANJI */
763: while (n--) {
764: i--, nchars++;
765: while (i > 0 && !iswordchar (CommandLine [i])) {
766: i--, nchars++;
767: }
768: while (i > 0 && iswordchar (CommandLine [i - 1])) {
769: i--, nchars++;
770: }
771: }
772: #endif /* KANJI */
773: return (backward_n_character (nchars));
774: }
775:
776: /*
777: * Move cursor backward one Word
778: */
779: backward_Word ()
780: {
781:
782: return (backward_n_Word (1));
783: }
784:
785: /*
786: * Move cursor backward n Word
787: */
788: backward_n_Word (n)
789: int n;
790: {
791: register int i = CurrentPosition, nchars = 0;
792:
793: if (i == 0) {
794: errorBell ();
795: return (0);
796: }
797:
798: #ifdef KANJI
799: while (n--) {
800: DEC(i);
801: nchars++;
802:
803: while (1) {
804: if (i > 1 && iskanji_in_string (CommandLine, i - 2))
805: break;
806: else if (i > 0 && !iswordchar (CommandLine[i]))
807: i -= 1;
808: else
809: break;
810:
811: nchars++;
812: }
813: while (1) {
814: if (i > 2 && iskanji_in_string (CommandLine, i - 2))
815: i -= 2;
816: else if (i > 0 && iswordchar (CommandLine [i - 1]))
817: i -= 1;
818: else
819: break;
820: nchars++;
821: }
822: }
823: #else /* KANJI */
824: while (n--) {
825: i--, nchars++;
826: while (i > 0 && !isWordchar (CommandLine [i]))
827: i--, nchars++;
828: while (i > 0 && isWordchar (CommandLine [i - 1]))
829: i--, nchars++;
830: }
831: #endif /* KANJI */
832: return (backward_n_character (nchars));
833: }
834:
835: /*
836: * Move cursor forward one character
837: */
838: forward_character()
839: {
840:
841: return (forward_n_character (1));
842: }
843:
844: /*
845: * Move cursor forward n character
846: */
847: forward_n_character(n)
848: int n;
849: {
850: int space;
851: register int i = CurrentPosition;
852:
853: if (n == 0)
854: return (0);
855: else if (n < 0)
856: return (backward_n_character (-n));
857:
858: if (CommandLine [CurrentPosition] == '\0') {
859: errorBell ();
860: return (0);
861: }
862:
863: #ifdef KANJI
864: if (iskanji (CommandLine[i])) {
865: (void) putchar (CommandLine[i++]);
866: (void) putchar (CommandLine[i++]);
867: }
868: else
869: #endif /* KANJI */
870: if (isctlchar(CommandLine[i])) {
871: (void) putchar (unctl (CommandLine [i]));
872: i++;
873: }
874: else
875: (void) putchar (CommandLine[i++]);
876:
877: while (--n && CommandLine [i]) {
878: #ifdef KANJI
879: if (iskanji (CommandLine[i])) {
880: (void) putchar (CommandLine[i++]);
881: (void) putchar (CommandLine[i++]);
882: }
883: else
884: #endif /* KANJI */
885: putChar (CommandLine [i++]);
886: }
887:
888: if (isctlchar (CommandLine [i]))
889: putchar ('^');
890:
891: CurrentPosition = i;
892:
893: return (0);
894: }
895:
896: /*
897: * Move cursor forward one word
898: */
899: forward_word ()
900: {
901: return (forward_n_word (1));
902: }
903:
904: /*
905: * Move cursor forward n word
906: */
907: forward_n_word (n)
908: int n;
909: {
910: register int i = CurrentPosition, nchars = 0;
911:
912: if (CommandLine [i] == '\0') {
913: errorBell ();
914: return (0);
915: }
916:
917: while (n--) {
918: while (CommandLine [i] && iswordchar (CommandLine [i])) {
919: INC(i);
920: nchars++;
921: }
922: while (CommandLine [i] && !iswordchar (CommandLine [i])) {
923: INC(i);
924: nchars++;
925: }
926: }
927: return (forward_n_character (nchars));
928: }
929:
930: /*
931: * Move cursor forward one word
932: */
933: forward_Word ()
934: {
935: return (forward_n_Word (1));
936: }
937:
938: /*
939: * Move cursor forward n word
940: */
941: forward_n_Word (n)
942: int n;
943: {
944: register int i = CurrentPosition, nchars = 0;
945:
946: if (CommandLine [i] == '\0') {
947: errorBell ();
948: return (0);
949: }
950:
951: while (n--) {
952: while (CommandLine [i] && isWordchar (CommandLine [i])) {
953: INC(i);
954: nchars++;
955: }
956: while (CommandLine [i] && !isWordchar (CommandLine [i])) {
957: INC(i);
958: nchars++;
959: }
960: }
961: return (forward_n_character (nchars));
962: }
963:
964: /*
965: * Forward to end of word
966: */
967: forward_to_end_of_word ()
968: {
969:
970: return (forward_to_end_of_n_word (1));
971: }
972:
973: /*
974: * Forward to end of n word
975: */
976: forward_to_end_of_n_word (n)
977: {
978: register int i = CurrentPosition, nchars = 0;
979:
980: if (CommandLine [i] == '\0') {
981: errorBell ();
982: return (0);
983: }
984:
985: INC(i);
986: while (n--) {
987: while (CommandLine [i] && !iswordchar (CommandLine [i])) {
988: INC(i);
989: nchars++;
990: }
991: while (CommandLine [i] && iswordchar (CommandLine [i])) {
992: INC(i);
993: nchars++;
994: }
995: }
996: DEC(i);
997: return (forward_n_character (nchars));
998: }
999:
1000: /*
1001: * Forward to end of word
1002: */
1003: forward_to_end_of_Word ()
1004: {
1005:
1006: return (forward_to_end_of_n_Word (1));
1007: }
1008:
1009: /*
1010: * Forward to end of n word
1011: */
1012: forward_to_end_of_n_Word (n)
1013: {
1014: register int i = CurrentPosition, nchars = 0;
1015:
1016: if (CommandLine [i] == '\0') {
1017: errorBell ();
1018: return (0);
1019: }
1020:
1021: INC(i);
1022: while (n--) {
1023: while (CommandLine [i] && !isWordchar (CommandLine [i])) {
1024: INC(i);
1025: nchars++;
1026: }
1027: while (CommandLine [i] && isWordchar (CommandLine [i])) {
1028: INC(i);
1029: nchars++;
1030: }
1031: }
1032: DEC(i);
1033: return (forward_n_character (nchars));
1034: }
1035:
1036: /*
1037: * Delete previous one character
1038: */
1039: delete_previous_character()
1040: {
1041:
1042: return (delete_previous_n_character (1));
1043: }
1044:
1045: /*
1046: * Delete previous n characters
1047: */
1048: delete_previous_n_character(n)
1049: int n;
1050: {
1051: register int i, nbyte;
1052: int deleteArea, restArea;
1053:
1054: if (CurrentPosition < n) {
1055: errorBell ();
1056: return (0);
1057: }
1058:
1059: #ifdef KANJI
1060: for (nbyte = 0, i = CurrentPosition; n-- > 0 && i;)
1061: if (i > 1 && iskanji_in_string (CommandLine, i - 2))
1062: i -= 2, nbyte += 2;
1063: else
1064: i -= 1, nbyte += 1;
1065: #else /* KANJI */
1066: nbyte = n;
1067: #endif /* KANJI */
1068:
1069: deleteArea = howlong (&CommandLine[CurrentPosition - nbyte], nbyte);
1070: restArea = howlong (&CommandLine[CurrentPosition], 0);
1071: if (isctlchar(CommandLine[CurrentPosition]))
1072: (void) putchar (BS);
1073: repeat(BS, deleteArea);
1074: CurrentPosition -= nbyte;
1075: strcpy (KillBuffer, &CommandLine [CurrentPosition]);
1076: KillBuffer [nbyte] = '\0';
1077: for (i = CurrentPosition; CommandLine[i + nbyte]; i++) {
1078: CommandLine[i] = CommandLine[i + nbyte];
1079: putChar (CommandLine[i]);
1080: }
1081: CommandLine[i] = '\0';
1082: repeat(SP, deleteArea);
1083: repeat(BS, deleteArea);
1084: if (isctlchar (CommandLine[CurrentPosition]))
1085: repeat(BS, restArea - 1);
1086: else
1087: repeat(BS, restArea);
1088:
1089: return (0);
1090: }
1091:
1092: /*
1093: * Delete previous one word
1094: */
1095: delete_previous_word()
1096: {
1097:
1098: return (delete_previous_n_word (1));
1099: }
1100:
1101: /*
1102: * Delete previous n word
1103: */
1104: delete_previous_n_word(n)
1105: int n;
1106: {
1107: register int i = CurrentPosition, nchars = 0;
1108:
1109: if (i == 0) {
1110: errorBell();
1111: return (0);
1112: }
1113:
1114: #ifdef KANJI
1115: while (n--) {
1116: if (i>1 && iskanji_in_string (CommandLine, i-2))
1117: i--;
1118: i--, nchars++;
1119:
1120: while (1) {
1121: if (i > 1 && iskanji_in_string (CommandLine, i-2))
1122: break;
1123: else if (i > 0 && !iswordchar (CommandLine[i]))
1124: i -= 1;
1125: else
1126: break;
1127:
1128: nchars++;
1129: }
1130: while (1) {
1131: if (i > 2 && iskanji_in_string (CommandLine, i - 2))
1132: i -= 2;
1133: else if (i > 0 && iswordchar (CommandLine [i -1]))
1134: i -= 1;
1135: else
1136: break;
1137: nchars++;
1138: }
1139: }
1140: #else /* KANJI */
1141: while (n--) {
1142: i--, nchars++;
1143: while (i > 0 && !iswordchar (CommandLine [i]))
1144: i--, nchars++;
1145: while (i > 0 && iswordchar (CommandLine [i - 1]))
1146: i--, nchars++;
1147: }
1148: #endif /* KANJI */
1149:
1150: return (delete_previous_n_character (nchars));
1151: }
1152:
1153: /*
1154: * Delete previous one word
1155: */
1156: delete_previous_Word()
1157: {
1158:
1159: return (delete_previous_n_Word (1));
1160: }
1161:
1162: /*
1163: * Delete previous n word
1164: */
1165: delete_previous_n_Word(n)
1166: int n;
1167: {
1168: register int i = CurrentPosition, nchars = 0;
1169:
1170: if (i == 0) {
1171: errorBell();
1172: return (0);
1173: }
1174:
1175: #ifdef KANJI
1176: while (n--) {
1177: if (i>1 && iskanji_in_string (CommandLine, i-2))
1178: i--;
1179: i--, nchars++;
1180:
1181: while (1) {
1182: if (i > 1 && iskanji_in_string (CommandLine, i-2))
1183: break;
1184: else if (i > 0 && !isWordchar (CommandLine[i]))
1185: i -= 1;
1186: else
1187: break;
1188:
1189: nchars++;
1190: }
1191: while (1) {
1192: if (i > 2 && iskanji_in_string (CommandLine, i - 2))
1193: i -= 2;
1194: else if (i > 0 && isWordchar (CommandLine [i -1]))
1195: i -= 1;
1196: else
1197: break;
1198: nchars++;
1199: }
1200: }
1201: #else /* KANJI */
1202: while (n--) {
1203: i--, nchars++;
1204: while (i > 0 && !isWordchar (CommandLine [i]))
1205: i--, nchars++;
1206: while (i > 0 && isWordchar (CommandLine [i - 1]))
1207: i--, nchars++;
1208: }
1209: #endif /* KANJI */
1210:
1211: return (delete_previous_n_character (nchars));
1212: }
1213:
1214: /*
1215: * Delete next one character
1216: */
1217: delete_next_character ()
1218: {
1219:
1220: return (delete_next_n_character (1));
1221: }
1222:
1223: /*
1224: * Delete next n character
1225: */
1226: delete_next_n_character (n)
1227: int n;
1228: {
1229: register int i, nbyte;
1230: int deleteArea, restArea;
1231:
1232: if (strlen (&CommandLine [CurrentPosition]) < n) {
1233: errorBell ();
1234: return (0);
1235: }
1236:
1237: #ifdef KANJI
1238: {
1239: register CHAR *cp = &CommandLine[CurrentPosition];
1240:
1241: nbyte = 0;
1242: while (n-- > 0 && *cp)
1243: if (iskanji (*cp))
1244: cp += 2, nbyte += 2;
1245: else
1246: cp++, nbyte++;
1247: }
1248: #else /* KANJI */
1249: nbyte = n;
1250: #endif /* KANJI */
1251:
1252: deleteArea = howlong (&CommandLine[CurrentPosition], nbyte);
1253: restArea = howlong (&CommandLine[CurrentPosition + nbyte], 0);
1254: if (isctlchar(CommandLine[CurrentPosition]))
1255: (void) putchar (BS);
1256: strcpy (KillBuffer, CommandLine + CurrentPosition);
1257: KillBuffer [nbyte] = '\0';
1258: for (i = CurrentPosition; CommandLine[i + nbyte]; i++) {
1259: CommandLine[i] = CommandLine[i + nbyte];
1260: putChar (CommandLine[i]);
1261: }
1262: CommandLine[i] = '\0';
1263: repeat(SP, deleteArea);
1264: repeat(BS, deleteArea);
1265: if (isctlchar (CommandLine[CurrentPosition]))
1266: repeat(BS, restArea - 1);
1267: else
1268: repeat(BS, restArea);
1269:
1270: return (0);
1271: }
1272:
1273: /*
1274: * Delete next one word
1275: */
1276: delete_next_word ()
1277: {
1278: return (delete_next_n_word (1));
1279: }
1280:
1281: /*
1282: * Delete next n word
1283: */
1284: delete_next_n_word (n)
1285: int n;
1286: {
1287: register int i = CurrentPosition, nchars = 0;
1288:
1289: if (CommandLine [i] == '\0') {
1290: errorBell ();
1291: return (0);
1292: }
1293:
1294: while (n--) {
1295: while (CommandLine [i] && iswordchar (CommandLine [i])) {
1296: INC(i);
1297: nchars++;
1298: }
1299: while (CommandLine [i] && !iswordchar (CommandLine [i])) {
1300: INC(i);
1301: nchars++;
1302: }
1303: }
1304: return (delete_next_n_character (nchars));
1305: }
1306:
1307: /*
1308: * Delete next one word
1309: */
1310: delete_next_Word ()
1311: {
1312: return (delete_next_n_Word (1));
1313: }
1314:
1315: /*
1316: * Delete next n word
1317: */
1318: delete_next_n_Word (n)
1319: int n;
1320: {
1321: register int i = CurrentPosition, nchars = 0;
1322:
1323: if (CommandLine [i] == '\0') {
1324: errorBell ();
1325: return (0);
1326: }
1327:
1328: while (n--) {
1329: while (CommandLine [i] && isWordchar (CommandLine [i])) {
1330: INC(i);
1331: nchars++;
1332: }
1333: while (CommandLine [i] && !isWordchar (CommandLine [i])) {
1334: INC(i);
1335: nchars++;
1336: }
1337: }
1338: return (delete_next_n_character (nchars));
1339: }
1340:
1341: /*
1342: * Erase whole line
1343: */
1344: delete_line()
1345: {
1346: register int i = CurrentPosition;
1347: register int len;
1348:
1349: len = howlong (CommandLine, 0);
1350:
1351: /*
1352: * If cursor is there right part of line, move it to end of line
1353: * and erase character by character from end
1354: */
1355: if (howlong (CommandLine, CurrentPosition + 1) > len / 2) {
1356: (void) end_of_line ();
1357: repeat_string ("\b \b", len);
1358: }
1359: /*
1360: * If cursor is there on left part of line, move it to top of line
1361: * and erase line at once
1362: */
1363: else {
1364: (void) beginning_of_line ();
1365: if (isctlchar (CommandLine[0]))
1366: putchar (BS);
1367: repeat (SP, len);
1368: repeat (BS, len);
1369: }
1370: strcpy (KillBuffer, CommandLine);
1371: CurrentPosition = 0;
1372: CommandLine [0] = '\0';
1373: return (0);
1374: }
1375:
1376: /*
1377: * Delete characters from current position to top of line
1378: */
1379: kill_to_top_of_line()
1380: {
1381: int i = CurrentPosition;
1382:
1383: (void) beginning_of_line();
1384: return (delete_next_n_character (i));
1385: }
1386:
1387: /*
1388: * Delete characters from current position to end of line
1389: */
1390: kill_to_end_of_line()
1391: {
1392: register int i, backCnt = 0;
1393:
1394: if (isctlchar(CommandLine[CurrentPosition])) {
1395: (void) putchar(BS);
1396: }
1397: for (i = CurrentPosition; CommandLine[i]; i++) {
1398: if (isctlchar(CommandLine[i])) {
1399: fputs(" ", stdout);
1400: backCnt++;
1401: }
1402: else
1403: (void) putchar (SP);
1404: backCnt++;
1405: }
1406: for (; backCnt; backCnt--)
1407: (void) putchar (BS);
1408: strcpy (KillBuffer, CommandLine + CurrentPosition);
1409: CommandLine[CurrentPosition] = '\0';
1410: return (0);
1411: }
1412:
1413: /*
1414: * Insert tab to current cursor position
1415: */
1416: insert_tab()
1417: {
1418:
1419: /* sorry, not implemented */
1420: return (self_insert ('\t'));
1421: }
1422:
1423: /*
1424: * Process new line
1425: */
1426: new_line()
1427: {
1428:
1429: (void) end_of_line;
1430: fputs ("\r\n", stdout);
1431: NeedNewLine = 1;
1432: NeedSave = 1;
1433:
1434: return (1);
1435: }
1436:
1437: /*
1438: * Check current position is top-of-line
1439: */
1440: is_tol()
1441: {
1442: return (CurrentPosition == 0);
1443: }
1444:
1445: /*
1446: * Check current position is end-of-line
1447: */
1448: is_eol()
1449: {
1450: return (CommandLine [CurrentPosition] == '\0');
1451: }
1452:
1453: /*
1454: * Check command line if it refer history or not
1455: */
1456: refer_history()
1457: {
1458: char *historyExtract ();
1459: char *his;
1460:
1461: if (CommandLine[0] != '!')
1462: return (NOT_PROCESSED);
1463:
1464: if (his = historyExtract (CommandLine)) {
1465: (void) strcpy (CommandLine, his);
1466: CurrentPosition = strlen (CommandLine);
1467: }
1468: else {
1469: fputs (CommandLine, stdout);
1470: fputs (" : Event not found.\r\n", stdout);
1471: (void) strcpy (CommandLine, "");
1472: CurrentPosition = 0;
1473: }
1474: fputs (prompt, stdout);
1475: print_com_line ();
1476: return (PROCESSED);
1477: }
1478:
1479: #define FORWARD 1
1480: #define REVERSE 2
1481:
1482: search_reverse ()
1483: {
1484: return (search_history (REVERSE));
1485: }
1486:
1487: search_forward ()
1488: {
1489: return (search_history (FORWARD));
1490: }
1491:
1492: search_history (direct)
1493: int direct;
1494: {
1495: char *his, *search_reverse_history(), *search_forward_history();
1496: char *(*func)();
1497:
1498: if (direct == FORWARD)
1499: func = search_forward_history;
1500: else
1501: func = search_reverse_history;
1502:
1503: AGAIN:
1504: if (his = (*func) (0)) {
1505: if (eq (his, CommandLine))
1506: goto AGAIN;
1507:
1508: (void) delete_line ();
1509: (void) insert_string (his);
1510: CurrentPosition = strlen (CommandLine);
1511: }
1512: else {
1513: (void) errorBell ();
1514:
1515: if (look_var ("verbose")) {
1516: char *cp;
1517:
1518: if ((cp = look_var ("search-string")) == NULL)
1519: cp = "";
1520: (void) clear_edit_line ();
1521: fprintf (stdout, "\"%s\": No match.\r\n", cp);
1522: (void) recover_edit_line (1);
1523: }
1524: }
1525:
1526: return 0;
1527: }
1528:
1529:
1530: /*
1531: * Insert the character and flush buffer
1532: */
1533: insert_and_flush(c)
1534: char c;
1535: {
1536: (void) self_insert (c);
1537: return (1);
1538: }
1539:
1540: /*
1541: * Insert the character, but it means EOL. Therefore move cursor backward and
1542: * flush buffer
1543: */
1544: send_eof()
1545: {
1546: #ifdef TERMIOS
1547: char c = initial_ttymode.c_cc[VEOF];
1548: #else
1549: char c = tchars_buf.t_eofc;
1550: #endif
1551:
1552: (void) self_insert (c);
1553: if (isctlchar (c))
1554: fputs ("\b\b", stdout);
1555: else
1556: fputs ("\b", stdout);
1557: return (1);
1558: }
1559:
1560: /*
1561: * Alarm for EOF on only the first time finding eof character
1562: */
1563: alarm_on_eof ()
1564: {
1565:
1566: errorBell ();
1567: (void) clear_edit_line ();
1568: printf ("EOF -- one more eof character to send eof to the process.\n");
1569: (void) recover_edit_line (1);
1570: }
1571:
1572: /*
1573: * Clear screen
1574: */
1575: clear_screen()
1576: {
1577:
1578: if (term_clear) {
1579: (void) clear_edit_line ();
1580: fputs (term_clear, stdout);
1581: (void) recover_edit_line (1);
1582: }
1583: else
1584: errorBell ();
1585:
1586: return (0);
1587: }
1588:
1589: typedef enum {HOP_INSERT, HOP_REPLACE} HISTOP;
1590: typedef enum {HDIR_PREV, HDIR_CURRENT, HDIR_NEXT} HISTDIR;
1591:
1592: /*
1593: * Get next history entry
1594: */
1595: next_history()
1596: {
1597: return (serv_history (HOP_REPLACE, HDIR_NEXT));
1598: }
1599:
1600: /*
1601: * Get next history entry
1602: */
1603: previous_history()
1604: {
1605: return (serv_history (HOP_REPLACE, HDIR_PREV));
1606: }
1607:
1608: /*
1609: * Insert next history entry
1610: */
1611: insert_current_history()
1612: {
1613: return (serv_history (HOP_INSERT, HDIR_CURRENT));
1614: }
1615:
1616: /*
1617: * Insert next history entry
1618: */
1619: insert_next_history()
1620: {
1621: return (serv_history (HOP_INSERT, HDIR_NEXT));
1622: }
1623:
1624: /*
1625: * Insert next history entry
1626: */
1627: insert_previous_history()
1628: {
1629: return (serv_history (HOP_INSERT, HDIR_PREV));
1630: }
1631:
1632: /*
1633: * Get previous history
1634: */
1635: serv_history(op, dir)
1636: HISTOP op;
1637: HISTDIR dir;
1638: {
1639: register char *cp;
1640: char *getPreviousHistory (), *getNextHistory (), *getCurrentHistory ();
1641: int diff;
1642:
1643: switch (dir) {
1644: case HDIR_PREV: cp = getPreviousHistory (); break;
1645: case HDIR_NEXT: cp = getNextHistory (); break;
1646: case HDIR_CURRENT: cp = getCurrentHistory (); break;
1647: default: cp = (char*)0;
1648: }
1649:
1650: if (cp == (char *)0) {
1651: errorBell ();
1652: return (0);
1653: }
1654:
1655: if (op == HOP_REPLACE)
1656: (void) delete_line ();
1657: (void) insert_string (cp);
1658: return (0);
1659: }
1660:
1661: /*
1662: * Show history
1663: */
1664: show_history()
1665: {
1666:
1667: (void) clear_edit_line ();
1668: hist_showHistory (lookd_var ("showhist"));
1669: (void) recover_edit_line (1);
1670: }
1671:
1672: /*
1673: * Do nothing
1674: */
1675: ignore()
1676: {
1677: return(0);
1678: }
1679:
1680: /*
1681: * Next character is literal
1682: */
1683: literal_next()
1684: {
1685:
1686: return (self_insert (getcharacter ()));
1687: }
1688:
1689: /*
1690: * Reprint command line
1691: */
1692: reprint()
1693: {
1694:
1695: (void) clear_edit_line ();
1696: (void) recover_edit_line (1);
1697: return (0);
1698: }
1699:
1700: /*
1701: * Print whole command line and move cursor to the current position
1702: */
1703: print_com_line()
1704: {
1705:
1706: printS (CommandLine);
1707: if (CommandLine[CurrentPosition] != '\0') {
1708: repeat (BS, howlong(&CommandLine[CurrentPosition + 1], 0));
1709: (void) putchar (BS);
1710: }
1711: }
1712:
1713: /*
1714: * Calcurate space of string using "^" for control character
1715: */
1716: howlong(s, n)
1717: char *s;
1718: int n;
1719: {
1720: register char *sp;
1721: register int area = 0;
1722:
1723: if (n == 0)
1724: n = -1;
1725: for (sp = s; *sp && n; sp++, n--) {
1726: if (isctlchar(*sp))
1727: area += 2;
1728: else
1729: area += 1;
1730: }
1731: return (area);
1732: }
1733:
1734: /*
1735: * Repeat puting character n times
1736: */
1737: repeat(c, n)
1738: char c;
1739: register int n;
1740: {
1741: for (n = n; n; n--)
1742: (void) putchar(c);
1743: }
1744:
1745: /*
1746: * Repeat putting string n times
1747: */
1748: repeat_string(s, n)
1749: char *s;
1750: register int n;
1751: {
1752: for (n = n; n; n--)
1753: fputs(s, stdout);
1754: }
1755:
1756: /*
1757: * Expand file name
1758: */
1759: expand_file_name ()
1760: {
1761: CHAR *cp, *start_expand;
1762: char *x_dirname();
1763: char dir[256];
1764: char *fileList[256];
1765: CHAR line[256];
1766: DIR *dirp, *x_opendir();
1767: struct direct *dp;
1768: int found = 0;
1769: int i;
1770: int tilde_expanded = 0;
1771: CHAR *index(), *rindex();
1772:
1773: if (delimiters == NULL)
1774: delimiters = DEFAULT_DELIMITERS;
1775: strcpy (line, CommandLine);
1776: for (cp = &line[CurrentPosition] - 1; cp > line ; --cp) {
1777: if (index (delimiters, *(cp - 1)))
1778: break;
1779: }
1780: start_expand = cp;
1781: if (any ('/', cp)) {
1782: (void) strcpy (dir, cp);
1783: *(rindex (dir, '/') + 1) = '\0';
1784: cp = (CHAR *) (rindex (cp, '/') + 1);
1785: }
1786: else
1787: strcpy (dir, ".");
1788:
1789: if ((dirp = x_opendir (dir)) == NULL) {
1790: errorBell ();
1791: return (0);
1792: }
1793:
1794: for (dp = readdir(dirp), i = 0; dp != NULL; dp = readdir(dirp)) {
1795:
1796: if (*cp == '\0')
1797: break;
1798:
1799: if (*cp != '.' && *(dp->d_name) == '.')
1800: continue;
1801:
1802: if (prefix (cp, dp->d_name)) {
1803: char *fcp;
1804:
1805: # ifdef ALLOCA
1806: fcp = (char *) alloca (strlen (dp->d_name) + 1);
1807: # else /* ALLOCA */
1808: fcp = (char *) malloc (strlen (dp->d_name) + 1);
1809: # endif /* ALLOCA */
1810: if (fcp == 0) {
1811: fputs ("\r\n", stdout);
1812: perror ("alloca:");
1813: reprint ();
1814: longjmp (jbuf, 1);
1815: }
1816: strcpy (fcp, dp->d_name);
1817: fileList [i++] = fcp;
1818: }
1819: }
1820: fileList [i] = (char *) 0;
1821:
1822: if (*start_expand == '~' && look_var ("expand-tilde")) {
1823: char buf [256], *p;
1824:
1825: strcpy (buf, start_expand);
1826: p = x_dirname (buf);
1827: if (!eq (p, buf)) {
1828: (void) moveto (start_expand - line);
1829: (void) kill_to_end_of_line ();
1830: (void) insert_string (x_dirname (buf));
1831: tilde_expanded = 1;
1832: }
1833: }
1834:
1835: switch (i) {
1836:
1837: case 0:
1838: if (tilde_expanded == 0)
1839: errorBell ();
1840: break;
1841:
1842: case 1:
1843: (void) end_of_line ();
1844: (void) insert_string (fileList[0] + strlen (cp));
1845: break;
1846:
1847: default:
1848: {
1849: char *one, *other;
1850: char *c1, *c2;
1851: int i;
1852:
1853: one = fileList [0];
1854: for (i = 1; other = fileList [i]; i++) {
1855: for (c1 = one, c2 = other; *c1 && *c2; c1++, c2++)
1856: if (*c1 != *c2)
1857: break;
1858: *c1 = '\0';
1859: }
1860: errorBell ();
1861: (void) end_of_line ();
1862: (void) insert_string (fileList[0] + strlen (cp));
1863: }
1864: break;
1865: }
1866:
1867: # ifndef ALLOCA
1868: for (i = 0; fileList [i]; i++)
1869: free (fileList [i]);
1870: # endif /* ALLOCA */
1871:
1872: closedir(dirp);
1873: return (0);
1874: }
1875:
1876: /*
1877: * List file name
1878: */
1879: list_file_name ()
1880: {
1881: CHAR *cp;
1882: char dir[256];
1883: DIR *dirp, *x_opendir();
1884: CHAR *index(), *rindex();
1885:
1886: if (delimiters == NULL)
1887: delimiters = DEFAULT_DELIMITERS;
1888: for (cp = (CHAR *) index (CommandLine, '\0'); cp > CommandLine ; --cp) {
1889: if (index (delimiters, *(cp - 1))) {
1890: break;
1891: }
1892: }
1893: #ifdef RINFO
1894: /*
1895: * This is an experimental code for rinfod, which serves remote
1896: * information about file, process, etc.
1897: */
1898: if (any (':', cp)) {
1899: char *host, *pattern;
1900:
1901: (void) strcpy (dir, cp);
1902: host = dir;
1903: *(index (host, ':')) = '\0';
1904: pattern = (index (cp, ':') + 1);;
1905:
1906: (void) clear_edit_line();
1907: list_remote_file (host, pattern);
1908: (void) recover_edit_line (1);
1909: return;
1910: }
1911: #endif
1912: if (any ('/', cp)) {
1913: (void) strcpy (dir, cp);
1914: *(rindex (dir, '/') + 1) = '\0';
1915: cp = (CHAR *) (rindex (cp, '/') + 1);
1916: }
1917: else
1918: strcpy (dir, ".");
1919:
1920:
1921: if ((dirp = x_opendir (dir)) == NULL) {
1922: errorBell ();
1923: return (0);
1924: }
1925:
1926: (void) clear_edit_line();
1927: ls (dirp, cp);
1928: closedir(dirp);
1929: (void) recover_edit_line (1);
1930:
1931: return (0);
1932: }
1933:
1934: int rememberPosition;
1935:
1936: clear_edit_line ()
1937: {
1938:
1939: if (editstatus == NOTEDITING)
1940: return;
1941:
1942: rememberPosition = CurrentPosition;
1943: (void) end_of_line ();
1944: (void) fputs ("\r\n", stdout);
1945: }
1946:
1947: recover_edit_line (put_prompt)
1948: int put_prompt;
1949: {
1950:
1951: if (editstatus == NOTEDITING)
1952: return;
1953:
1954: if (rememberPosition < 0)
1955: return;
1956: CurrentPosition = rememberPosition;
1957: rememberPosition = -1;
1958: if (put_prompt && prompt)
1959: fputs (prompt, stdout);
1960: (void) print_com_line();
1961: }
1962:
1963: #define MAXFILES 256
1964:
1965: /*
1966: * Do ls
1967: */
1968: ls (dirp, prefixstring)
1969: DIR *dirp;
1970: char *prefixstring;
1971: {
1972: struct direct *dp;
1973: char *fileList[MAXFILES + 1];
1974: int i, j;
1975: int maxlen = 0;
1976: int files; /* number of file */
1977: int fpl; /* file par line */
1978: int cpf; /* column par file */
1979: int fpc; /* file par column */
1980: int COL = 80;
1981: char format[10];
1982: int scmp();
1983:
1984: for (dp = readdir(dirp), i = 0; dp != NULL; dp = readdir(dirp)) {
1985: char *fcp;
1986:
1987: if (i >= MAXFILES) {
1988: printf ("Too many files\n");
1989: break;
1990: }
1991:
1992: if (dp->d_ino == (unsigned long) 0
1993: || (prefixstring[0] != '.' && dp->d_name[0] == '.'))
1994: continue;
1995: if (prefix (prefixstring, dp->d_name)) {
1996: # ifdef ALLOCA
1997: fcp = (char *) alloca (strlen (dp->d_name) + 1);
1998: # else /* ALLOCA */
1999: fcp = (char *) malloc (strlen (dp->d_name) + 1);
2000: # endif /* ALLOCA */
2001: if (fcp == 0) {
2002: fputs ("\r\n", stdout);
2003: perror ("alloca:");
2004: reprint ();
2005: longjmp (jbuf, 1);
2006: }
2007: strcpy (fcp, dp->d_name);
2008: fileList [i++] = fcp;
2009: maxlen = max (maxlen, strlen (dp->d_name));
2010: }
2011: }
2012: fileList [i] = (char *) 0;
2013:
2014: if (i == 0)
2015: goto BACK;
2016:
2017: files = i;
2018:
2019: qsort (fileList, i, sizeof (char *), scmp);
2020:
2021: if (debug)
2022: printf ("%d files\n", files);
2023:
2024: cpf = maxlen + 1;
2025: fpl = COL / cpf;
2026: if (fpl == 0) fpl = 1;
2027: fpc = (files + fpl - 1) / fpl;
2028:
2029: sprintf (format, "%%-%ds", cpf);
2030: for (i = 0; i < fpc; i++) {
2031: for (j = 0; j < fpl - 1; j++)
2032: if (i + j * fpc < files)
2033: printf (format, fileList[i + (j * fpc)]);
2034: if (i + (fpc * (fpl - 1)) < files)
2035: printf ("%s", fileList[i + (fpc * (fpl - 1))]);
2036: fputs ("\n", stdout);
2037: }
2038:
2039: BACK:
2040:
2041: # ifndef ALLOCA
2042: for (i = 0; fileList [i]; i++)
2043: free (fileList [i]);
2044: # endif /* ALLOCA */
2045: return;
2046: }
2047:
2048: #ifdef RINFO
2049:
2050: #include "../rinfo/rinfo.h"
2051:
2052: list_remote_file (host, pattern)
2053: char *host, *pattern;
2054: {
2055: struct slist *slp, *getfilelist();
2056: int i, j;
2057: char format [64];
2058: int COL = 80;
2059: int maxlen, cpf, fpl, fpc;
2060: int files;
2061:
2062: slp = getfilelist (host, pattern);
2063: files = slp->s_cnt;
2064:
2065: COL = 80;
2066: maxlen = 0;
2067: for (i = 0; i < files; i++) {
2068: int len;
2069:
2070: if ((len = strlen (*(slp->s_list + i))) > maxlen)
2071: maxlen = len;
2072: }
2073:
2074: cpf = maxlen + 1;
2075: fpl = COL / cpf;
2076: if (fpl == 0)
2077: fpl = 1;
2078: fpc = (files + fpl - 1) / fpl;
2079:
2080: sprintf (format, "%%-%ds", cpf);
2081: for (i = 0; i < fpc; i++) {
2082: for (j = 0; j < fpl - 1; j++) {
2083: if (i + j * fpc < slp->s_cnt)
2084: printf (format, *(slp->s_list + (i + (j * fpc))));
2085: }
2086: if (i + (fpc * (fpl - 1)) < files)
2087: printf ("%s", slp->s_list[i + (fpc * (fpl - 1))]);
2088: fputs ("\n", stdout);
2089: }
2090: }
2091: #endif /* RINFO */
2092:
2093: bind_key (ft, func, s, dfunc)
2094: FUNC ft[]; /* Function table */
2095: FUNC func; /* Function to be binded */
2096: char *s; /* String to bind */
2097: FUNC dfunc; /* Default function for table allocating */
2098: {
2099: char tmps[16];
2100:
2101: if (s[0] == '\\' && s[1] == '^' && s[2] != '\0') {
2102: tmps[0] = toctrl (s[2]);
2103: strcpy (&tmps[1], &s[3]);
2104: s = tmps;
2105: }
2106:
2107: /*
2108: * If the string contain only one character, put the function to
2109: * appropriate position in the table.
2110: */
2111: if (*(s+1) == '\0') {
2112: if (isIndirect (ft[(int) *s]))
2113: free (maskIndirect (ft[(int) *s]));
2114:
2115: ft[(int) *s] = func;
2116: return (1);
2117: }
2118: else {
2119: FUNC *nft = (FUNC *) 0;
2120: int status;
2121:
2122: /*
2123: * If the entry doesn't have indirect function table, allocate it.
2124: */
2125: if (! (isIndirect (ft[(int) *s]))) {
2126: register int i;
2127:
2128: nft = (FUNC *) calloc (sizeof (FUNC), 256);
2129: /*
2130: * If failed in allocating, return 0.
2131: */
2132: if (nft == 0)
2133: return (0);
2134:
2135: /*
2136: * Initialize the table with default function
2137: */
2138: for (i = 0; i < 256; i++)
2139: nft [i] = dfunc;
2140: ft[(int) *s] = setIndirect (nft);
2141: }
2142:
2143: status = bind_key (maskIndirect (ft[(int) *s]), func, s+1, dfunc);
2144: /*
2145: * If the binding failed and the table was allocated in this function
2146: * free the table and return with same status.
2147: */
2148: if (status == 0 && nft)
2149: free (nft);
2150: return (status);
2151: }
2152: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>