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