* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)ex_vget.c 6.10 (Berkeley) %G%";
* Input routines for open/visual.
* We handle upper case only terminals in visual and reading from the
* echo area here as well as notification on large changes
* which appears in the echo area.
int c
; /* mjm: char --> int */
* Return a keystroke, but never a ^@.
register int c
; /* mjm: char --> int */
* Tell whether next keystroke would be a ^@.
* Get a keystroke, including a ^@.
* If an key was returned with ungetkey, that
* comes back first. Next comes unread input (e.g.
* from repeating commands with .), and finally new
* The hard work here is in mapping of \ escaped
* characters on upper case only terminals.
extern short slevel
, ttyindes
;
return (lastvgk
= *vglobp
++);
/* End of a macro or set of nested macros */
if (inopen
== -1) /* don't screw up undo for esc esc */
inopen
= 1; /* restore old setting now that macro done */
c
= read(slevel
== 0 ? 0 : ttyindes
, &ch
, 1);
c
= vms_read(slevel
== 0 ? 0 : ttyindes
, &ch
, 1);
error("Input read error");
if (XB
&& slevel
==0 && c
== ESCAPE
) {
if (read(0, &Peek2key
, 1) != 1)
case 'C': /* SPOW mode sometimes sends \EC for space */
case 'p': /* f1 -> esc */
* The algorithm here is that of the UNIX kernel.
* See the description in the programmers manual.
fprintf(trace
, "*** Input: ");
* Get a key, but if a delete, quit or attention
* is typed return 0 so we will abort a partial command.
* Peek at the next keystroke.
* Read a line from the echo area, with single character prompt c.
* A return value of 1 means the user blewit or blewit away.
register char *sc
= cursor
;
cursor
= linebuf
; linebuf
[0] = 0; genbuf
[0] = c
;
if (!INS
[0] || (INS
[0] & (QUOTE
|TRIM
)) == OVERBUF
)
OP
= Pline
; Pline
= normline
;
ignore(vgetline(0, genbuf
+ 1, &waste
, c
));
if (Peek_key
!= ATTN
&& Peek_key
!= QUIT
&& Peek_key
!= CTRL('h')) {
OPeek
= Peek_key
==CTRL('h') ? 0 : Peek_key
; Peek_key
= 0;
* A complete command has been defined for
* the purposes of repeat, so copy it from
* the working to the previous command buffer.
* Gather up some more text from an insert.
* If the insertion buffer oveflows, then destroy
* the repeatability of the insert.
if ((INS
[0] & (QUOTE
|TRIM
)) == OVERBUF
)
* Put text from cursor upto wcursor in BUF.
register char *wp
= wcursor
;
register char *buf
, *str
;
if ((buf
[0] & (QUOTE
|TRIM
)) == OVERBUF
)
if (strlen(buf
) + strlen(str
) + 1 >= VBSIZE
) {
ignore(strcat(buf
, str
));
* Note a change affecting a lot of lines, or non-visible
* lines. If the parameter must is set, then we only want
* to do this for open modes now; return and save for later
* notification in visual.
register int sdl
= destline
, sdc
= destcol
;
if (notecnt
< 2 || !must
&& state
== VISUAL
)
ex_printf("%d %sline", notecnt
, notesgn
);
ex_printf(" %s", notenam
);
if (*(strend(notenam
) - 1) != 'e')
if (state
== ONEOPEN
|| state
== CRTOPEN
)
destline
= sdl
; destcol
= sdc
;
* If possible, use flash (VB).
* Map the command input character c,
* for keypads and labelled keys which do cursor
* motions. I.e. on an adm3a we might map ^K to ^P.
* DM1520 for example has a lot of mappable characters.
register struct maps
*maps
;
char b
[10]; /* Assumption: no keypad sends string longer than 10 */
* Mapping for special keys on the terminal only.
* BUG: if there's a long sequence and it matches
* some chars and then misses, we lose some chars.
* For this to work, some conditions must be met.
* 1) Keypad sends SHORT (2 or 3 char) strings
* 2) All strings sent are same length & similar
* 3) The user is unlikely to type the first few chars of
* one of these strings very fast.
* Note: some code has been fixed up since the above was laid out,
* so conditions 1 & 2 are probably not required anymore.
* However, this hasn't been tested with any first char
* that means anything else except escape.
fprintf(trace
,"map(%c): ",c
);
* If c==0, the char came from getesc typing escape. Pass it through
* unchanged. 0 messes up the following code anyway.
for (d
=0; maps
[d
].mapto
; d
++) {
fprintf(trace
,"\ntry '%s', ",maps
[d
].cap
);
for (q
=b
; *p
; p
++, q
++) {
fprintf(trace
,"q->b[%d], ",q
-b
);
* Is there another char waiting?
* This test is oversimplified, but
* should work mostly. It handles the
* case where we get an ESCAPE that
* wasn't part of a keypad string.
if ((c
=='#' ? peekkey() : fastpeekkey()) == 0) {
fprintf(trace
,"fpk=0: will return '%c'",c
);
* Nothing waiting. Push back
* what we peeked at & return
* We want to be able to undo
* commands, but it's nonsense
* to undo part of an insertion
* so if in input mode don't.
fprintf(trace
, "Call macpush, b %d %d %d\n", b
[0], b
[1], b
[2]);
macpush(&b
[1],maps
== arrows
);
fprintf(trace
, "return %d\n", c
);
macpush(maps
[d
].mapto
,maps
== arrows
);
fprintf(trace
,"Success: push(%s), return %c",maps
[d
].mapto
, c
);
return(c
); /* first char of map string */
fprintf(trace
,"Fail: push(%s), return %c", &b
[1], c
);
* Push st onto the front of vmacp. This is tricky because we have to
* worry about where vmacp was previously pointing. We also have to
* check for overflow (which is typically from a recursive macro)
* Finally we have to set a flag so the whole thing can be undone.
* canundo is 1 iff we want to be able to undo the macro. This
* is false for, for example, pushing back lookahead from fastpeekkey(),
* since otherwise two fast escapes can clobber our undo.
fprintf(trace
, "macpush(%s), canundo=%d\n",st
,canundo
);
if ((vmacp
? strlen(vmacp
) : 0) + strlen(st
) > BUFSIZ
)
error("Macro too long@ - maybe recursive?");
canundo
= 0; /* can't undo inside a macro anyway */
/* arrange to be able to undo the whole macro */
inopen
= -1; /* no need to save since it had to be 1 or -1 before */
fprintf(trace
, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n",
s
, basWTOP
, basWLINES
, WTOP
, WBOT
, WLINES
, WCOLS
, WECHO
);
fprintf(trace
, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n",
vcnt
, vcline
, cursor
-linebuf
, wcursor
-linebuf
, wdot
-zero
);
for (i
=0; i
<TUBELINES
; i
++)
if (vtube
[i
] && *vtube
[i
])
fprintf(trace
, "%d: '%s'\n", i
, vtube
[i
]);
fprintf(trace
, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n",
s
, undkind
, vundkind
, lineno(unddel
), lineno(undap1
), lineno(undap2
));
fprintf(trace
, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n",
lineno(undadot
), lineno(dot
), lineno(dol
), lineno(unddol
), lineno(truedol
));
fprintf(trace
, "linebuf = '%s'\n", linebuf
);
for (p
=zero
+1; p
<=truedol
; p
++) {
fprintf(trace
, "%o ", *p
);
fprintf(trace
, "'%s'\n", linebuf
);
* Get a count from the keyed input stream.
* A zero count is indistinguishable from no count.
cnt
*= 10, cnt
+= c
- '0';
* fastpeekkey is just like peekkey but insists the character come in
* fast (within 1 second). This will succeed if it is the 2nd char of
* a machine generated sequence (such as a function pad from an escape
* flavor terminal) but fail for a human hitting escape then waiting.
* If the user has set notimeout, we wait forever for a key.
* If we are in a macro we do too, but since it's already
* buffered internally it will return immediately.
* In other cases we force this to die in 1 second.
* This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs,
* but UNIX truncates it to 0 - 1 secs) but due to system delays
* there are times when arrow keys or very fast typing get counted
* as separate. notimeout is provided for people who dislike such
fprintf(trace
,"\nfastpeekkey: ",c
);
Oint
= signal(SIGINT
, trapalarm
);
if (value(TIMEOUT
) && inopen
>= 0) {
signal(SIGALRM
, trapalarm
);
fprintf(trace
, "set alarm ");
fprintf(trace
,"[TIMEOUT]",c
);
fprintf(trace
,"[fpk:%o]",c
);