4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 /* Copyright (c) 1981 Regents of the University of California */
37 * Input routines for open/visual.
38 * We handle upper case only terminals in visual and reading from the
39 * echo area here as well as notification on large changes
40 * which appears in the echo area.
55 * Return a keystroke, but never a ^@.
60 int c
; /* char --> int */
71 * Tell whether next keystroke would be a ^@.
78 return (Peekkey
== 0);
84 * Get a keystroke, including a ^@.
85 * If an key was returned with ungetkey, that
86 * comes back first. Next comes unread input (e.g.
87 * from repeating commands with .), and finally new
90 * The hard work here is in mapping of \ escaped
91 * characters on upper case only terminals.
100 static unsigned char Peek2key
;
101 extern short slevel
, ttyindes
;
116 return (lastvgk
= *vglobp
++);
123 /* End of a macro or set of nested macros */
125 if (inopen
== -1) /* don't mess up undo for esc esc */
127 inopen
= 1; /* restore old setting now that macro done */
128 vch_mac
= VC_NOTINMAC
;
132 if ((c
=read(slevel
== 0 ? 0 : ttyindes
, &ch
, 1)) != 1) {
135 else if (errno
== EIO
)
136 kill(getpid(), SIGHUP
);
138 error(gettext("Input read error"));
141 if (beehive_glitch
&& slevel
==0 && c
== ESCAPE
) {
142 if (read(0, &Peek2key
, 1) != 1)
145 case 'C': /* SPOW mode sometimes sends \EC for space */
149 case 'q': /* f2 -> ^C */
153 case 'p': /* f1 -> esc */
160 * The algorithm here is that of the UNIX kernel.
161 * See the description in the programmers manual.
171 } else if (precbksl
) {
176 colp
= (unsigned char *)"({)}!|^~'~";
206 fprintf(trace
, "*** Input: ");
216 * Get a key, but if a delete, quit or attention
217 * is typed return 0 so we will abort a partial command.
244 * Peek at the next keystroke.
255 * Read a line from the echo area, with single character prompt c.
256 * A return value of 1 means the user blewit or blewit away.
262 unsigned char *sc
= cursor
;
276 cursor
= linebuf
; linebuf
[0] = 0; genbuf
[0] = c
;
279 if (!INS
[0] || (unsigned char)INS
[128] == 0200) {
285 OP
= Pline
; Pline
= normline
;
286 (void)vgetline(0, genbuf
+ 1, &waste
, c
);
287 doomed
= 0; /* don't care about doomed characters in echo line */
289 if (Outchar
== termchar
)
293 if (Peekkey
!= ATTN
&& Peekkey
!= QUIT
&& Peekkey
!= CTRL('h')) {
299 OPeek
= Peekkey
==CTRL('h') ? 0 : Peekkey
; Peekkey
= 0;
309 * A complete command has been defined for
310 * the purposes of repeat, so copy it from
311 * the working to the previous command buffer.
323 CP(lastcmd
, workcmd
);
327 * Gather up some more text from an insert.
328 * If the insertion buffer oveflows, then destroy
329 * the repeatability of the insert.
332 addtext(unsigned char *cp
)
338 if ((unsigned char)INS
[128] == 0200)
350 * Put text from cursor upto wcursor in BUF.
353 setBUF(unsigned char *BUF
)
356 unsigned char *wp
= wcursor
;
367 addto(unsigned char *buf
, unsigned char *str
)
370 if ((unsigned char)buf
[128] == 0200)
372 if (strlen(buf
) + strlen(str
) + 1 >= VBSIZE
) {
376 (void)strcat(buf
, str
);
381 * Verbalize command name and embed it in message.
384 verbalize(cnt
, cmdstr
, sgn
)
388 if (cmdstr
[0] == '\0')
389 cmdstr
= (char *)Command
;
390 if (sgn
[0] == '\0') {
393 if (cmdstr
[1] == 'h') {
394 viprintf((cnt
== 1) ?
395 gettext("1 line changed") :
396 gettext("%d lines changed"), cnt
);
398 } else if (cmdstr
[1] != 'o') {
402 if (cmdstr
[1] != '\0')
404 viprintf((cnt
== 1) ? gettext("1 line copied") :
405 gettext("%d lines copied"), cnt
);
408 viprintf((cnt
== 1) ? gettext("1 line deleted") :
409 gettext("%d lines deleted"), cnt
);
412 viprintf((cnt
== 1) ? gettext("1 line joined") :
413 gettext("%d lines joined"), cnt
);
416 viprintf((cnt
== 1) ? gettext("1 line moved") :
417 gettext("%d lines moved"), cnt
);
420 viprintf((cnt
== 1) ? gettext("1 line put") :
421 gettext("%d lines put"), cnt
);
424 viprintf((cnt
== 1) ? gettext("1 line yanked") :
425 gettext("%d lines yanked"), cnt
);
428 viprintf((cnt
== 1) ? gettext("1 line >>ed") :
429 gettext("%d lines >>ed"), cnt
);
432 viprintf((cnt
== 1) ? gettext("1 line =ed") :
433 gettext("%d lines =ed"), cnt
);
436 viprintf((cnt
== 1) ? gettext("1 line <<ed") :
437 gettext("%d lines <<ed"), cnt
);
441 viprintf((cnt
== 1) ? gettext("1 line") :
442 gettext("%d lines"), cnt
);
445 } else if (sgn
[0] == 'm') {
446 viprintf((cnt
== 1) ? gettext("1 more line") :
447 gettext("%d more lines"), cnt
);
449 viprintf((cnt
== 1) ? gettext("1 fewer line") :
450 gettext("%d fewer lines"), cnt
);
456 * Note a change affecting a lot of lines, or non-visible
457 * lines. If the parameter must is set, then we only want
458 * to do this for open modes now; return and save for later
459 * notification in visual.
465 int sdl
= destline
, sdc
= destcol
;
467 if (notecnt
< 1 || !must
&& state
== VISUAL
)
474 verbalize(notecnt
, notenam
, notesgn
);
480 if (state
== ONEOPEN
|| state
== CRTOPEN
)
482 destline
= sdl
; destcol
= sdc
;
488 * If possible, flash screen.
494 if (flash_screen
&& value(vi_FLASH
))
495 vputp(flash_screen
, 0);
502 * Map the command input character c,
503 * for keypads and labelled keys which do cursor
504 * motions. I.e. on an adm3a we might map ^K to ^P.
505 * DM1520 for example has a lot of mappable characters.
512 unsigned char commch
; /* indicate if in append/insert/replace mode */
515 unsigned char *p
, *q
;
516 unsigned char b
[10]; /* Assumption: no keypad sends string longer than 10 */
520 * Mapping for special keys on the terminal only.
521 * BUG: if there's a long sequence and it matches
522 * some chars and then misses, we lose some chars.
524 * For this to work, some conditions must be met.
525 * 1) Keypad sends SHORT (2 or 3 char) strings
526 * 2) All strings sent are same length & similar
527 * 3) The user is unlikely to type the first few chars of
528 * one of these strings very fast.
529 * Note: some code has been fixed up since the above was laid out,
530 * so conditions 1 & 2 are probably not required anymore.
531 * However, this hasn't been tested with any first char
532 * that means anything else except escape.
536 fprintf(trace
,"map(%c): ",c
);
539 * If c==0, the char came from getesc typing escape. Pass it through
540 * unchanged. 0 messes up the following code anyway.
547 for (d
=0; d
< MAXNOMACS
&& maps
[d
].mapto
; d
++) {
550 fprintf(trace
,"\ntry '%s', ",maps
[d
].cap
);
552 if (p
= maps
[d
].cap
) {
553 for (q
=b
; *p
; p
++, q
++) {
556 fprintf(trace
,"q->b[%d], ",q
-b
);
560 * Is there another char waiting?
562 * This test is oversimplified, but
563 * should work mostly. It handles the
564 * case where we get an ESCAPE that
565 * wasn't part of a keypad string.
567 if ((c
=='#' ? peekkey() : fastpeekkey()) == 0) {
570 fprintf(trace
,"fpk=0: will return '%c'",c
);
573 * Nothing waiting. Push back
574 * what we peeked at & return
577 * We want to be able to undo
578 * commands, but it's nonsense
579 * to undo part of an insertion
580 * so if in input mode don't.
584 fprintf(trace
, "Call macpush, b %d %d %d\n", b
[0], b
[1], b
[2]);
586 macpush(&b
[1],maps
== arrows
);
589 fprintf(trace
, "return %d\n", c
);
599 macpush(maps
[d
].mapto
,maps
== arrows
);
601 * For all macros performed within insert,
602 * append, or replacement mode, we must end
603 * up returning back to that mode when we
604 * return (except that append will become
605 * insert for <home> key, so cursor is not
608 * In order to preserve backward movement
609 * when leaving insert mode, an 'l' must be
610 * done to compensate for the left done by
611 * the <esc> (except when cursor is already
612 * in the first column: i.e., outcol = 0).
615 && strcmp(maps
[d
].descr
, maps
[d
].cap
)) {
618 if (!strcmp(maps
[d
].descr
, "home"))
619 st
= (unsigned char *)"R";
622 st
= (unsigned char *)"R";
624 st
= (unsigned char *)"lR";
627 if (!strcmp(maps
[d
].descr
, "home"))
628 st
= (unsigned char *)"i";
631 st
= (unsigned char *)"i";
633 st
= (unsigned char *)"li";
636 if (!strcmp(maps
[d
].descr
, "home"))
637 st
= (unsigned char *)"i";
639 st
= (unsigned char *)"a";
642 st
= (unsigned char *)"i";
644 if(strlen(vmacbuf
) + strlen(st
) > BUFSIZE
)
645 error(value(vi_TERSE
) ?
646 gettext("Macro too long") : gettext("Macro too long - maybe recursive?"));
649 * Macros such as function keys are
650 * performed by leaving the insert,
651 * replace, or append mode, executing
652 * the proper cursor movement commands
653 * and returning to the mode we are
654 * currently in (commch).
661 fprintf(trace
,"Success: push(%s), return %c",maps
[d
].mapto
, c
);
663 return(c
); /* first char of map string */
669 fprintf(trace
,"Fail: push(%s), return %c", &b
[1], c
);
676 * Push st onto the front of vmacp. This is tricky because we have to
677 * worry about where vmacp was previously pointing. We also have to
678 * check for overflow (which is typically from a recursive macro)
679 * Finally we have to set a flag so the whole thing can be undone.
680 * canundo is 1 iff we want to be able to undo the macro. This
681 * is false for, for example, pushing back lookahead from fastpeekkey(),
682 * since otherwise two fast escapes can clobber our undo.
685 macpush(unsigned char *st
, int canundo
)
687 unsigned char tmpbuf
[BUFSIZE
];
693 fprintf(trace
, "macpush(%s), canundo=%d\n",st
,canundo
);
695 if ((vmacp
? strlen(vmacp
) : 0) + strlen(st
) > BUFSIZE
)
696 error(value(vi_TERSE
) ? gettext("Macro too long") :
697 gettext("Macro too long - maybe recursive?"));
699 strcpy(tmpbuf
, vmacp
);
701 canundo
= 0; /* can't undo inside a macro anyway */
705 strcat(vmacbuf
, tmpbuf
);
707 /* arrange to be able to undo the whole macro */
713 inopen
= -1; /* no need to save since it had to be 1 or -1 before */
716 vch_mac
= VC_NOCHANGE
;
728 fprintf(trace
, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n",
729 s
, basWTOP
, basWLINES
, WTOP
, WBOT
, WLINES
, WCOLS
, WECHO
);
730 fprintf(trace
, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n",
731 vcnt
, vcline
, cursor
-linebuf
, wcursor
-linebuf
, wdot
-zero
);
732 for (i
=0; i
<TUBELINES
; i
++)
733 if (vtube
[i
] && *vtube
[i
])
734 fprintf(trace
, "%d: '%s'\n", i
, vtube
[i
]);
742 unsigned char savelb
[1024];
746 fprintf(trace
, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n",
747 s
, undkind
, vundkind
, lineno(unddel
), lineno(undap1
), lineno(undap2
));
748 fprintf(trace
, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n",
749 lineno(undadot
), lineno(dot
), lineno(dol
), lineno(unddol
), lineno(truedol
));
750 fprintf(trace
, " [\n");
752 fprintf(trace
, "linebuf = '%s'\n", linebuf
);
753 for (p
=zero
+1; p
<=truedol
; p
++) {
754 fprintf(trace
, "%o ", *p
);
756 fprintf(trace
, "'%s'\n", linebuf
);
758 fprintf(trace
, "]\n");
764 * Get a count from the keyed input stream.
765 * A zero count is indistinguishable from no count.
777 cnt
*= 10, cnt
+= c
- '0';
786 * fastpeekkey is just like peekkey but insists the character come in
787 * fast (within 1 second). This will succeed if it is the 2nd char of
788 * a machine generated sequence (such as a function pad from an escape
789 * flavor terminal) but fail for a human hitting escape then waiting.
798 * If the user has set notimeout, we wait forever for a key.
799 * If we are in a macro we do too, but since it's already
800 * buffered internally it will return immediately.
801 * In other cases we force this to die in 1 second.
802 * This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs,
803 * but UNIX truncates it to 0 - 1 secs) but due to system delays
804 * there are times when arrow keys or very fast typing get counted
805 * as separate. notimeout is provided for people who dislike such
809 if (value(vi_TIMEOUT
) && inopen
>= 0) {
810 signal(SIGALRM
, trapalarm
);
818 /* Should have an alternative method based on select for 4.2BSD */
829 * Arrange for SIGALRM to come in shortly, so we don't
830 * hang very long if the user didn't type anything. There are
831 * various ways to do this on different systems.
836 unsigned char ftname
[20];
837 struct requestbuf rb
;
841 * Use nonstandard "fast timer" to get better than
842 * one second resolution. We must wait at least
843 * 1/15th of a second because some keypads don't
844 * transmit faster than this.
847 /* Open ft psuedo-device - we need our own copy. */
849 strcpy(ftname
, "/dev/ft0");
850 while (ftfd
<= 0 && ftname
[7] <= '~') {
851 ftfd
= open(ftname
, 0);
856 if (ftfd
<= 0) { /* Couldn't open a /dev/ft? */
859 rb
.time
= 6; /* 6 ticks = 100 ms > 67 ms. */
861 ioctl(ftfd
, FTIOCSET
, &rb
);
865 * No special capabilities, so we use alarm, with 1 sec. resolution.
872 * Get rid of any impending incoming SIGALRM.
877 struct requestbuf rb
;
882 ioctl(ftfd
, FTIOCCANCEL
, &rb
);
885 alarm(0); /* Have to do this whether or not FTIOCSET */