terminal: Move kbd_timeout below set_kbd_event. This ought to make the diff of the next commit more readable.
---
commit 80b64b3270caeb8088c3a0e75e8545f0e902ccbe
tree 2ba7fc47eff56930cddcd6337e6323462d2ca0be
parent 67be6b8e03b34a73d3939fc32ba24171a7039bc5
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:15:46 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:15:46 +0300
src/terminal/kbd.c | 50 +++++++++++++++++++++++++-------------------------
1 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index e39896c..785b354 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -619,31 +619,6 @@ free_and_return:
}
-static void
-kbd_timeout(struct itrm *itrm)
-{
- struct term_event ev;
-
- itrm->timer = TIMER_ID_UNDEF;
-
- if (can_read(itrm->in.std)) {
- in_kbd(itrm);
- return;
- }
-
- assertm(itrm->in.queue.len, "timeout on empty queue");
- if_assert_failed return;
-
- set_kbd_term_event(&ev, KBD_ESC, KBD_MOD_NONE);
- itrm_queue_event(itrm, (char *) &ev, sizeof(ev));
-
- if (--itrm->in.queue.len)
- memmove(itrm->in.queue.data, itrm->in.queue.data + 1, itrm->in.queue.len);
-
- while (process_queue(itrm));
-}
-
-
/* Returns the length of the escape sequence */
static inline int
get_esc_code(unsigned char *str, int len, unsigned char *code, int *num)
@@ -833,6 +808,31 @@ #endif
set_kbd_term_event(ev, key, modifier);
}
+
+static void
+kbd_timeout(struct itrm *itrm)
+{
+ struct term_event ev;
+
+ itrm->timer = TIMER_ID_UNDEF;
+
+ if (can_read(itrm->in.std)) {
+ in_kbd(itrm);
+ return;
+ }
+
+ assertm(itrm->in.queue.len, "timeout on empty queue");
+ if_assert_failed return;
+
+ set_kbd_term_event(&ev, KBD_ESC, KBD_MOD_NONE);
+ itrm_queue_event(itrm, (char *) &ev, sizeof(ev));
+
+ if (--itrm->in.queue.len)
+ memmove(itrm->in.queue.data, itrm->in.queue.data + 1, itrm->in.queue.len);
+
+ while (process_queue(itrm));
+}
+
/* I feeeeeel the neeeed ... to rewrite this ... --pasky */
/* Just Do it ! --Zas */
static int
!-------------------------------------------------------------flip-
terminal doc: More comments about itrm->in.queue.
---
commit f700eee1e2cc78b0e37e1e33ad54f90f83c148c4
tree b5ca81ca5f6a8e24166033b15cdee8b7a6750005
parent 80b64b3270caeb8088c3a0e75e8545f0e902ccbe
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:27:26 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:27:26 +0300
src/terminal/itrm.h | 6 +++++-
src/terminal/kbd.c | 18 +++++++++++++++++-
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/terminal/itrm.h b/src/terminal/itrm.h
index b1af33d..a43e734 100644
--- a/src/terminal/itrm.h
+++ b/src/terminal/itrm.h
@@ -44,7 +44,11 @@ struct itrm_in {
/* Bytes that have been received from @std but not yet
* converted to events. queue.data is allocated for
* ITRM_IN_QUEUE_SIZE bytes and never resized. The itrm
- * layer cannot parse control sequences longer than that. */
+ * layer cannot parse control sequences longer than that.
+ * Anything that modifies queue.len should also call
+ * unhandle_itrm_stdin() if the queue becomes full, or
+ * handle_itrm_stdin() if the queue stops being full.
+ * Those functions are internal to kbd.c. */
struct itrm_queue queue;
};
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 785b354..f4eac74 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -690,7 +690,7 @@ #endif
case 'H': kbd.key = KBD_HOME; break;
case 'I': kbd.key = KBD_PAGE_UP; break;
case 'G': kbd.key = KBD_PAGE_DOWN; break;
-/* Free BSD */
+/* Free BSD (TERM=cons25 etc.) */
/* case 'M': kbd.key = KBD_F1; break;*/
case 'N': kbd.key = KBD_F2; break;
case 'O': kbd.key = KBD_F3; break;
@@ -835,6 +835,11 @@ kbd_timeout(struct itrm *itrm)
/* I feeeeeel the neeeed ... to rewrite this ... --pasky */
/* Just Do it ! --Zas */
+/* Parse one event from itrm->in.queue and append to itrm->out.queue.
+ * Return the number of bytes removed from itrm->in.queue; at least 0.
+ * If this function leaves the queue not full, it also reenables reading
+ * from itrm->in.std. (Because it does not add to the queue, it never
+ * need disable reading.) On entry, the itrm must not be blocked. */
static int
process_queue(struct itrm *itrm)
{
@@ -863,6 +868,10 @@ #ifdef DEBUG_ITRM_QUEUE
}
#endif /* DEBUG_ITRM_QUEUE */
+ /* ELinks should also recognize U+009B CONTROL SEQUENCE INTRODUCER
+ * as meaning the same as ESC [, and U+008F SINGLE SHIFT THREE as
+ * meaning the same as ESC O, but those cannot yet be implemented
+ * because of bug 777: the UTF-8 decoder is run too late. */
if (itrm->in.queue.data[0] == ASCII_ESC) {
if (itrm->in.queue.len < 2) goto ret;
if (itrm->in.queue.data[1] == '[' || itrm->in.queue.data[1] == 'O') {
@@ -961,6 +970,10 @@ in_kbd(struct itrm *itrm)
while (process_queue(itrm));
}
+/* Enable reading from itrm->in.std. ELinks will read any available
+ * bytes from the tty into itrm->in.queue and then parse them.
+ * Reading should be enabled whenever itrm->in.queue is not full and
+ * itrm->blocked is 0. */
static void
handle_itrm_stdin(struct itrm *itrm)
{
@@ -968,6 +981,9 @@ handle_itrm_stdin(struct itrm *itrm)
(select_handler_T) free_itrm, itrm);
}
+/* Disable reading from itrm->in.std. Reading should be disabled
+ * whenever itrm->in.queue is full (there is no room for the data)
+ * or itrm->blocked is 1 (other processes may read the data). */
static void
unhandle_itrm_stdin(struct itrm *itrm)
{
!-------------------------------------------------------------flip-
terminal: Kill the ESC timer when blocking the terminal.
Otherwise, the timeout could cause ELinks to resume reading from the
terminal device while another process is still using it.
This actually happened in a test.
P.S. assert(!itrm->blocked) should be added to kbd_timeout(),
but that is in commit e73ca934bbc464699b4220bf7a5ffe45f6a18cb3,
rather than here.
---
commit 98964c2fc1649a2ad7d2560cdfdf5124046302a0
tree 49ef2577118cabdaa818e703113e45c38cea2ba4
parent f700eee1e2cc78b0e37e1e33ad54f90f83c148c4
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:33:52 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:33:52 +0300
src/terminal/kbd.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index f4eac74..16bbd7f 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -373,6 +373,8 @@ block_itrm(int fd)
ditrm->blocked = 1;
block_stdin();
+ kill_timer(&ditrm->timer);
+ ditrm->in.queue.len = 0;
unhandle_terminal_resize(ditrm->in.ctl);
send_done_sequence(ditrm->out.std, ditrm->altscreen);
tcsetattr(ditrm->in.ctl, TCSANOW, &ditrm->t);
!-------------------------------------------------------------flip-
terminal: Allow other modifiers on control characters.
For example, Ctrl-Alt-A should now work.
---
commit 27c6518ba2b5dd1778b8024e0a70b938a6ed8b54
tree 3cccd7765ef5c43533e6358920593fa76fcf230e
parent 98964c2fc1649a2ad7d2560cdfdf5124046302a0
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:35:57 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:35:57 +0300
src/terminal/kbd.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 16bbd7f..348250c 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -803,7 +803,7 @@ #endif
default:
if (key < ' ') {
key += 'A' - 1;
- modifier = KBD_MOD_CTRL;
+ modifier |= KBD_MOD_CTRL;
}
}
!-------------------------------------------------------------flip-
terminal: In the ESC timeout, don't assume merely ESC was pressed.
If there is e.g. ESC [ in the input buffer, combine that to Alt-[.
Check the first character too; don't blindly assume it is ESC, as
it can be NUL as well.
Also, assert that the itrm has not been blocked when the timeout hits.
This is safe because a previous commit made block_itrm kill the timer.
P.S. This version does not map ASCII_ESC to KBD_ESC as it should.
That is fixed in commit 3bfea0c9e187d464f9112402ae5c68c098d4e6ac.
---
commit e73ca934bbc464699b4220bf7a5ffe45f6a18cb3
tree 4be1d2e2d11d7fd1465c7bf639784647952cd6af
parent 27c6518ba2b5dd1778b8024e0a70b938a6ed8b54
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:46:45 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 00:46:45 +0300
src/terminal/kbd.c | 22 ++++++++++++++++------
1 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 348250c..07ecbeb 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -815,22 +815,32 @@ static void
kbd_timeout(struct itrm *itrm)
{
struct term_event ev;
+ int el;
itrm->timer = TIMER_ID_UNDEF;
+ assertm(itrm->in.queue.len, "timeout on empty queue");
+ assert(!itrm->blocked);
+ if_assert_failed return;
+
if (can_read(itrm->in.std)) {
in_kbd(itrm);
return;
}
- assertm(itrm->in.queue.len, "timeout on empty queue");
- if_assert_failed return;
-
- set_kbd_term_event(&ev, KBD_ESC, KBD_MOD_NONE);
+ if (itrm->in.queue.len >= 2 && itrm->in.queue.data[0] == ASCII_ESC) {
+ /* This is used for ESC [ and ESC O. */
+ set_kbd_event(&ev, itrm->in.queue.data[1], KBD_MOD_ALT);
+ el = 2;
+ } else {
+ set_kbd_event(&ev, itrm->in.queue.data[0], KBD_MOD_NONE);
+ el = 1;
+ }
itrm_queue_event(itrm, (char *) &ev, sizeof(ev));
- if (--itrm->in.queue.len)
- memmove(itrm->in.queue.data, itrm->in.queue.data + 1, itrm->in.queue.len);
+ itrm->in.queue.len -= el;
+ if (itrm->in.queue.len)
+ memmove(itrm->in.queue.data, itrm->in.queue.data + el, itrm->in.queue.len);
while (process_queue(itrm));
}
!-------------------------------------------------------------flip-
terminal: Rewrite process_queue.
The new version makes no attempt to recognize Alt-ESC.
The conversion from ASCII_ESC to KBD_ESC is now in set_kbd_event,
rather than in process_queue.
---
commit 3bfea0c9e187d464f9112402ae5c68c098d4e6ac
tree df9deefe10e47e64a71d5aed062634a3d63f1415
parent e73ca934bbc464699b4220bf7a5ffe45f6a18cb3
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 01:04:33 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 01:04:33 +0300
src/terminal/kbd.c | 91 +++++++++++++++++++++++++++++-----------------------
1 files changed, 50 insertions(+), 41 deletions(-)
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 07ecbeb..65c46b0 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -800,6 +800,10 @@ #endif
key = KBD_ENTER;
break;
+ case ASCII_ESC:
+ key = KBD_ESC;
+ break;
+
default:
if (key < ' ') {
key += 'A' - 1;
@@ -845,8 +849,6 @@ kbd_timeout(struct itrm *itrm)
while (process_queue(itrm));
}
-/* I feeeeeel the neeeed ... to rewrite this ... --pasky */
-/* Just Do it ! --Zas */
/* Parse one event from itrm->in.queue and append to itrm->out.queue.
* Return the number of bytes removed from itrm->in.queue; at least 0.
* If this function leaves the queue not full, it also reenables reading
@@ -858,7 +860,9 @@ process_queue(struct itrm *itrm)
struct term_event ev;
int el = 0;
- if (!itrm->in.queue.len) goto end;
+ if (!itrm->in.queue.len) goto return_without_event;
+ assert(!itrm->blocked);
+ if_assert_failed return 0; /* unlike goto, don't enable reading */
set_kbd_term_event(&ev, KBD_UNDEF, KBD_MOD_NONE);
@@ -880,32 +884,30 @@ #ifdef DEBUG_ITRM_QUEUE
}
#endif /* DEBUG_ITRM_QUEUE */
+ /* el == -1 means itrm->in.queue appears to be the beginning of an
+ * escape sequence but it is not yet complete. Set a timer;
+ * if it times out, then assume it wasn't an escape sequence
+ * after all.
+ * el == 0 means this function has not yet figured out what the data
+ * in itrm->in.queue is, but some possibilities remain.
+ * One of them will be chosen before returning.
+ * el > 0 means some bytes were successfully parsed from the beginning
+ * of itrm->in.queue and should now be removed from there.
+ * However, this does not always imply an event will be queued.
+ */
+
/* ELinks should also recognize U+009B CONTROL SEQUENCE INTRODUCER
* as meaning the same as ESC [, and U+008F SINGLE SHIFT THREE as
* meaning the same as ESC O, but those cannot yet be implemented
* because of bug 777: the UTF-8 decoder is run too late. */
if (itrm->in.queue.data[0] == ASCII_ESC) {
- if (itrm->in.queue.len < 2) goto ret;
- if (itrm->in.queue.data[1] == '[' || itrm->in.queue.data[1] == 'O') {
+ if (itrm->in.queue.len < 2)
+ el = -1;
+ else if (itrm->in.queue.data[1] == '[' || itrm->in.queue.data[1] == 'O')
el = decode_terminal_escape_sequence(itrm, &ev);
-
- if (el == -1) goto ret;
-
- } else {
+ else if (itrm->in.queue.data[1] != ASCII_ESC) {
+ set_kbd_event(&ev, itrm->in.queue.data[1], KBD_MOD_ALT);
el = 2;
-
- if (itrm->in.queue.data[1] == ASCII_ESC) {
- if (itrm->in.queue.len >= 3 &&
- (itrm->in.queue.data[2] == '[' ||
- itrm->in.queue.data[2] == 'O')) {
- el = 1;
- }
-
- set_kbd_event(&ev, KBD_ESC, KBD_MOD_NONE);
-
- } else {
- set_kbd_event(&ev, itrm->in.queue.data[1], KBD_MOD_ALT);
- }
}
} else if (itrm->in.queue.data[0] == 0) {
@@ -913,39 +915,46 @@ #endif /* DEBUG_ITRM_QUEUE */
#include "terminal/key.inc"
};
- if (itrm->in.queue.len < 2) goto ret;
- copy_struct(&ev.info.keyboard, &os2xtd[itrm->in.queue.data[1]]);
- el = 2;
+ if (itrm->in.queue.len < 2)
+ el = -1;
+ else {
+ copy_struct(&ev.info.keyboard, &os2xtd[itrm->in.queue.data[1]]);
+ el = 2;
+ }
- } else {
+ } else { /* The first byte doesn't look like it begins a sequence. */
el = 1;
set_kbd_event(&ev, itrm->in.queue.data[0], 0);
}
- assertm(itrm->in.queue.len >= el, "event queue underflow");
- if_assert_failed { itrm->in.queue.len = el; }
-
- itrm->in.queue.len -= el;
+ if (el == 0) {
+ set_kbd_event(&ev, itrm->in.queue.data[0], KBD_MOD_NONE);
+ el = 1;
+ }
/* The call to decode_terminal_escape_sequence() might have changed the
* keyboard event to a mouse event. */
if (ev.ev == EVENT_MOUSE || ev.info.keyboard.key != KBD_UNDEF)
itrm_queue_event(itrm, (char *) &ev, sizeof(ev));
- if (itrm->in.queue.len)
- memmove(itrm->in.queue.data, itrm->in.queue.data + el, itrm->in.queue.len);
-
-end:
- if (itrm->in.queue.len < ITRM_IN_QUEUE_SIZE)
- handle_itrm_stdin(itrm);
+ return_without_event:
+ if (el == -1) {
+ install_timer(&itrm->timer, ESC_TIMEOUT, (void (*)(void *)) kbd_timeout,
+ itrm);
+ return 0;
+ } else {
+ assertm(itrm->in.queue.len >= el, "event queue underflow");
+ if_assert_failed { itrm->in.queue.len = el; }
- return el;
+ itrm->in.queue.len -= el;
+ if (itrm->in.queue.len)
+ memmove(itrm->in.queue.data, itrm->in.queue.data + el, itrm->in.queue.len);
-ret:
- install_timer(&itrm->timer, ESC_TIMEOUT, (void (*)(void *)) kbd_timeout,
- itrm);
+ if (itrm->in.queue.len < ITRM_IN_QUEUE_SIZE)
+ handle_itrm_stdin(itrm);
- return 0;
+ return el;
+ }
}
!-------------------------------------------------------------flip-
terminal: Decode ESC O entirely separately from ESC [.
decode_terminal_escape_sequence() used to handle both, but
there is now a separate decode_terminal_application_key()
for ESC O. I have not yet edited decode_terminal_escape_sequence();
there may be dead code in it.
---
commit 2f252234ecaffd08efe5ec0e0005c99c5445c87c
tree e1a785c905c5072883b73a022938e4bb710c057f
parent 3bfea0c9e187d464f9112402ae5c68c098d4e6ac
author Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 01:09:52 +0300
committer Kalle Olavi Niemitalo <[EMAIL PROTECTED]> Fri, 28 Jul 2006 01:09:52 +0300
src/terminal/kbd.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 60 insertions(+), 1 deletions(-)
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 65c46b0..66bd2e8 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -775,6 +775,63 @@ #endif /* CONFIG_MOUSE */
return el;
}
+/* Decode an escape sequence that begins with SS3 (SINGLE SHIFT 3).
+ * These are used for application cursor keys and the application keypad.
+ * Return one of:
+ * -1 if the escape sequence is not yet complete; the callers sets a timer.
+ * 0 if the escape sequence should be parsed by some other function.
+ * The length of the escape sequence otherwise.
+ * Returning >0 does not imply this function has altered *ev. */
+static int
+decode_terminal_application_key(struct itrm *itrm, struct term_event *ev)
+{
+ unsigned char c;
+ struct term_event_keyboard kbd = { KBD_UNDEF, KBD_MOD_NONE };
+
+ assert(itrm->in.queue.len >= 2);
+ assert(itrm->in.queue.data[0] == ASCII_ESC);
+ assert(itrm->in.queue.data[1] == 0x4F); /* == 'O', incidentally */
+ if_assert_failed return 0;
+
+ if (itrm->in.queue.len < 3) return -1;
+ /* According to ECMA-35 section 8.4, a single (possibly multibyte)
+ * character follows the SS3. We now assume the code identifies
+ * GL as the single-shift area and the designated set has 94
+ * characters. */
+ c = itrm->in.queue.data[2];
+ if (c < 0x21 || c > 0x7E) return 0;
+
+ /* These are all from xterm-215/ctlseqs.txt. */
+ switch (c) {
+ case ' ': kbd.key = ' '; break;
+ case 'A': kbd.key = KBD_UP; break;
+ case 'B': kbd.key = KBD_DOWN; break;
+ case 'C': kbd.key = KBD_RIGHT; break;
+ case 'D': kbd.key = KBD_LEFT; break;
+ case 'F': kbd.key = KBD_END; break;
+ case 'H': kbd.key = KBD_HOME; break;
+ case 'I': kbd.key = KBD_TAB; break;
+ case 'M': kbd.key = KBD_ENTER; break;
+ /* FIXME: xterm generates ESC O 2 P for Shift-PF1 */
+ case 'P': kbd.key = KBD_F1; break;
+ case 'Q': kbd.key = KBD_F2; break;
+ case 'R': kbd.key = KBD_F3; break;
+ case 'S': kbd.key = KBD_F4; break;
+ case 'X': kbd.key = '='; break;
+
+ case 'j': case 'k': case 'l': case 'm': /* *+,- */
+ case 'n': case 'o': case 'p': case 'q': /* ./01 */
+ case 'r': case 's': case 't': case 'u': /* 2345 */
+ case 'v': case 'w': case 'x': case 'y': /* 6789 */
+ kbd.key = c - 'p' + '0'; break;
+ }
+ if (kbd.key != KBD_UNDEF)
+ copy_struct(&ev->info.keyboard, &kbd);
+
+ return 3; /* even if we didn't recognize it */
+}
+
+
static void
set_kbd_event(struct term_event *ev, int key, int modifier)
{
@@ -903,8 +960,10 @@ #endif /* DEBUG_ITRM_QUEUE */
if (itrm->in.queue.data[0] == ASCII_ESC) {
if (itrm->in.queue.len < 2)
el = -1;
- else if (itrm->in.queue.data[1] == '[' || itrm->in.queue.data[1] == 'O')
+ else if (itrm->in.queue.data[1] == '[')
el = decode_terminal_escape_sequence(itrm, &ev);
+ else if (itrm->in.queue.data[1] == 'O')
+ el = decode_terminal_application_key(itrm, &ev);
else if (itrm->in.queue.data[1] != ASCII_ESC) {
set_kbd_event(&ev, itrm->in.queue.data[1], KBD_MOD_ALT);
el = 2;
pgpaKn2KD0hVM.pgp
Description: PGP signature
_______________________________________________ elinks-dev mailing list [email protected] http://linuxfromscratch.org/mailman/listinfo/elinks-dev
