aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2009-01-09 23:57:42 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2009-01-09 23:57:42 +0000
commit3ed5aa3e72bf0e720f1ea35159a1d15b1f02e0ff (patch)
treed6d9dc50461b010cd9da225afacf9d4081d29bc6
parente13445875451d66fcc8b0d8b4995321560d03b80 (diff)
downloadrtmux-3ed5aa3e72bf0e720f1ea35159a1d15b1f02e0ff.tar.gz
rtmux-3ed5aa3e72bf0e720f1ea35159a1d15b1f02e0ff.tar.bz2
rtmux-3ed5aa3e72bf0e720f1ea35159a1d15b1f02e0ff.zip
Build array of codes, stop using ncurses global variables and push ncurses crap into tty-term.c.
-rw-r--r--CHANGES9
-rw-r--r--Makefile4
-rw-r--r--TODO2
-rw-r--r--key-string.c3
-rw-r--r--screen-redraw.c4
-rw-r--r--screen-write.c4
-rw-r--r--tmux.c3
-rw-r--r--tmux.h203
-rw-r--r--tty-keys.c162
-rw-r--r--tty-term.c395
-rw-r--r--tty-write.c14
-rw-r--r--tty.c631
12 files changed, 868 insertions, 566 deletions
diff --git a/CHANGES b/CHANGES
index 9ad3dd95..891e2dcf 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,12 @@
09 January 2009
+* Stop using ncurses variables and instead build a table of the codes we want
+ into an array for each terminal type. This makes the code a little more
+ untidy in places but gets rid of the awful global variables and calling
+ setterm all the time, and shoves all the ncurses-dependent mess into a single
+ file, tty-term.c. It also allows overriding single terminal codes, this is
+ used to fix rxvt on some platforms (where it is missing dch) and in future
+ may allow user customisation a la vim.
* Update key handling code. Simplify, support ctrl properly and add a new
window option (xterm-keys) to output xterm key codes including ctrl and,
if available, alt and shift.
@@ -826,7 +833,7 @@
(including mutt, emacs). No status bar yet and no key remapping or other
customisation.
-$Id: CHANGES,v 1.184 2009-01-09 16:45:58 nicm Exp $
+$Id: CHANGES,v 1.185 2009-01-09 23:57:42 nicm Exp $
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB
diff --git a/Makefile b/Makefile
index 96f9f633..9efda487 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.81 2008-12-15 21:21:56 nicm Exp $
+# $Id: Makefile,v 1.82 2009-01-09 23:57:42 nicm Exp $
.SUFFIXES: .c .o .y .h
.PHONY: clean update-index.html upload-index.html
@@ -37,7 +37,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
cmd-respawn-window.c cmd-source-file.c \
window-scroll.c window-more.c window-copy.c options.c paste.c \
- tty.c tty-keys.c tty-write.c colour.c utf8.c options-cmd.c
+ tty.c tty-term.c tty-keys.c tty-write.c colour.c utf8.c options-cmd.c
CC?= cc
INCDIRS+= -I. -I- -I/usr/local/include
diff --git a/TODO b/TODO
index 53c7c1ed..2e9ae074 100644
--- a/TODO
+++ b/TODO
@@ -59,3 +59,5 @@
- input.c is too complicated. simplify?
- try change from pass-though model to redraw model (use updated screen
data). maybe too slow though?
+- use a better termcap internally instead of screen, perhaps xterm
+- tty.c is a bit ugly
diff --git a/key-string.c b/key-string.c
index 56c69e98..9a15144a 100644
--- a/key-string.c
+++ b/key-string.c
@@ -1,4 +1,4 @@
-/* $Id: key-string.c,v 1.11 2009-01-09 16:45:58 nicm Exp $ */
+/* $Id: key-string.c,v 1.12 2009-01-09 23:57:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -88,7 +88,6 @@ key_string_search_table(const char *string)
int
key_string_lookup_string(const char *string)
{
- u_int i;
int key;
if (string[0] == '\0')
diff --git a/screen-redraw.c b/screen-redraw.c
index 4f6286f5..7b3a8ec0 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -1,4 +1,4 @@
-/* $Id: screen-redraw.c,v 1.14 2008-12-08 16:19:51 nicm Exp $ */
+/* $Id: screen-redraw.c,v 1.15 2009-01-09 23:57:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -52,7 +52,7 @@ screen_redraw_start_session(struct screen_redraw_ctx *ctx, struct session *s)
/* Initialise for redrawing. */
void
screen_redraw_start(struct screen_redraw_ctx *ctx,
- struct screen *s, void (*write)(void *, int, ...), void *data)
+ struct screen *s, void (*write)(void *, enum tty_cmd, ...), void *data)
{
ctx->write = write;
ctx->data = data;
diff --git a/screen-write.c b/screen-write.c
index a84141ec..7c2fda4d 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1,4 +1,4 @@
-/* $Id: screen-write.c,v 1.21 2009-01-08 21:55:12 nicm Exp $ */
+/* $Id: screen-write.c,v 1.22 2009-01-09 23:57:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -52,7 +52,7 @@ screen_write_start_session(struct screen_write_ctx *ctx, struct session *s)
/* Initialise writing. */
void
screen_write_start(struct screen_write_ctx *ctx,
- struct screen *s, void (*write)(void *, int, ...), void *data)
+ struct screen *s, void (*write)(void *, enum tty_cmd, ...), void *data)
{
ctx->write = write;
ctx->data = data;
diff --git a/tmux.c b/tmux.c
index f83fdb2f..ac5a5b89 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id: tmux.c,v 1.85 2009-01-09 16:45:58 nicm Exp $ */
+/* $Id: tmux.c,v 1.86 2009-01-09 23:57:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -52,6 +52,7 @@ struct options global_window_options;
int debug_level;
int be_quiet;
+time_t start_time;
void sighandler(int);
__dead void usage(void);
diff --git a/tmux.h b/tmux.h
index 6be25ab9..fb6f26ee 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.211 2009-01-09 16:45:58 nicm Exp $ */
+/* $Id: tmux.h,v 1.212 2009-01-09 23:57:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,7 +19,7 @@
#ifndef TMUX_H
#define TMUX_H
-#define PROTOCOL_VERSION -3
+#define PROTOCOL_VERSION -4
/* Shut up gcc warnings about empty if bodies. */
#define RB_AUGMENT(x) do {} while (0)
@@ -52,13 +52,12 @@
#include "compat/getopt.h"
#endif
-#include <ncurses.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
-#include <term.h>
+#include <termios.h>
#include "array.h"
@@ -221,33 +220,133 @@ struct buffer {
#define KEYC_KP4_0 (KEYC_OFFSET + 0x10e)
#define KEYC_KP4_2 (KEYC_OFFSET + 0x10f)
-/* Output codes. */
-#define TTY_CURSORUP 0
-#define TTY_CURSORDOWN 1
-#define TTY_CURSORRIGHT 2
-#define TTY_CURSORLEFT 3
-#define TTY_INSERTCHARACTER 4
-#define TTY_DELETECHARACTER 5
-#define TTY_INSERTLINE 6
-#define TTY_DELETELINE 7
-#define TTY_CLEARLINE 8
-#define TTY_CLEARENDOFLINE 9
-#define TTY_CLEARSTARTOFLINE 10
-#define TTY_CURSORMOVE 11
-#define TTY_CURSORMODE 12
-#define TTY_REVERSEINDEX 13
-#define TTY_SCROLLREGION 14
-#define TTY_INSERTMODE 15
-#define TTY_MOUSEMODE 16
-#define TTY_LINEFEED 17
-#define TTY_CARRIAGERETURN 18
-#define TTY_BELL 19
-#define TTY_KCURSORMODE 20
-#define TTY_KKEYPADMODE 21
-#define TTY_CLEARENDOFSCREEN 22
-#define TTY_CLEARSTARTOFSCREEN 23
-#define TTY_CLEARSCREEN 24
-#define TTY_CELL 25
+/* Termcap codes. */
+enum tty_code_code {
+ TTYC_AX = 0,
+ TTYC_ACSC, /* acs_chars, ac */
+ TTYC_BEL, /* bell, bl */
+ TTYC_BLINK, /* enter_blink_mode, mb */
+ TTYC_BOLD, /* enter_bold_mode, md */
+ TTYC_CIVIS, /* cursor_invisible, vi */
+ TTYC_CLEAR, /* clear_screen, cl */
+ TTYC_CNORM, /* cursor_normal, ve */
+ TTYC_COLORS, /* max_colors, Co */
+ TTYC_CR, /* carriage_return, cr */
+ TTYC_CSR, /* change_scroll_region, cs */
+ TTYC_CUB, /* parm_left_cursor, LE */
+ TTYC_CUB1, /* cursor_left, le */
+ TTYC_CUD, /* parm_down_cursor, DO */
+ TTYC_CUD1, /* cursor_down, do */
+ TTYC_CUF, /* parm_right_cursor, RI */
+ TTYC_CUF1, /* cursor_right, nd */
+ TTYC_CUP, /* cursor_address, cm */
+ TTYC_CUU, /* parm_up_cursor, UP */
+ TTYC_CUU1, /* cursor_up, up */
+ TTYC_DCH, /* parm_dch, DC */
+ TTYC_DCH1, /* delete_character, dc */
+ TTYC_DIM, /* enter_dim_mode, mh */
+ TTYC_DL, /* parm_delete_line, DL */
+ TTYC_DL1, /* delete_line, dl */
+ TTYC_ED, /* clr_eos, cd */
+ TTYC_EL, /* clr_eol, ce */
+ TTYC_EL1, /* clr_bol, cb */
+ TTYC_ENACS, /* ena_acs, eA */
+ TTYC_ICH, /* parm_ich, IC */
+ TTYC_ICH1, /* insert_character, ic */
+ TTYC_IL, /* parm_insert_line, IL */
+ TTYC_IL1, /* insert_line, il */
+ TTYC_INVIS, /* enter_secure_mode, mk */
+ TTYC_IS1, /* init_1string, i1 */
+ TTYC_IS2, /* init_2string, i2 */
+ TTYC_IS3, /* init_3string, i3 */
+ TTYC_KCUB1, /* key_left, kl */
+ TTYC_KCUD1, /* key_down, kd */
+ TTYC_KCUF1, /* key_right, kr */
+ TTYC_KCUU1, /* key_up, ku */
+ TTYC_KDCH1, /* key_dc, kD */
+ TTYC_KEND, /* key_end, ke */
+ TTYC_KF1, /* key_f1, k1 */
+ TTYC_KF10, /* key_f10, k; */
+ TTYC_KF11, /* key_f11, F1 */
+ TTYC_KF12, /* key_f12, 21 */
+ TTYC_KF2, /* key_f2, k2 */
+ TTYC_KF3, /* key_f3, k3 */
+ TTYC_KF4, /* key_f4, k4 */
+ TTYC_KF5, /* key_f5, k5 */
+ TTYC_KF6, /* key_f6, k6 */
+ TTYC_KF7, /* key_f7, k7 */
+ TTYC_KF8, /* key_f8, k8 */
+ TTYC_KF9, /* key_f9, k9 */
+ TTYC_KHOME, /* key_home, kh */
+ TTYC_KICH1, /* key_ic, kI */
+ TTYC_KMOUS, /* key_mouse, Km */
+ TTYC_KNP, /* key_npage, kN */
+ TTYC_KPP, /* key_ppage, kP */
+ TTYC_OP, /* orig_pair, op */
+ TTYC_REV, /* enter_reverse_mode, mr */
+ TTYC_RI, /* scroll_reverse, sr */
+ TTYC_RMACS, /* exit_alt_charset_mode */
+ TTYC_RMCUP, /* exit_ca_mode, te */
+ TTYC_RMKX, /* keypad_local, ke */
+ TTYC_SETAB, /* set_a_background, AB */
+ TTYC_SETAF, /* set_a_foreground, AF */
+ TTYC_SGR0, /* exit_attribute_mode, me */
+ TTYC_SMACS, /* enter_alt_charset_mode, as */
+ TTYC_SMCUP, /* enter_ca_mode, ti */
+ TTYC_SMKX, /* keypad_xmit, ks */
+ TTYC_SMSO, /* enter_standout_mode, so */
+ TTYC_SMUL, /* enter_underline_mode, us */
+
+ NTTYCODE
+};
+
+/* Termcap types. */
+enum tty_code_type {
+ TTYCODE_NONE = 0,
+ TTYCODE_STRING,
+ TTYCODE_NUMBER,
+ TTYCODE_FLAG,
+};
+
+/* Termcap code. */
+struct tty_code {
+ enum tty_code_type type;
+ union {
+ char *string;
+ int number;
+ int flag;
+ } value;
+};
+
+/* Output commands. */
+enum tty_cmd {
+ TTY_BELL,
+ TTY_CARRIAGERETURN,
+ TTY_CELL,
+ TTY_CLEARENDOFLINE,
+ TTY_CLEARENDOFSCREEN,
+ TTY_CLEARLINE,
+ TTY_CLEARSCREEN,
+ TTY_CLEARSTARTOFLINE,
+ TTY_CLEARSTARTOFSCREEN,
+ TTY_CURSORDOWN,
+ TTY_CURSORLEFT,
+ TTY_CURSORMODE,
+ TTY_CURSORMOVE,
+ TTY_CURSORRIGHT,
+ TTY_CURSORUP,
+ TTY_DELETECHARACTER,
+ TTY_DELETELINE,
+ TTY_INSERTCHARACTER,
+ TTY_INSERTLINE,
+ TTY_INSERTMODE,
+ TTY_KCURSORMODE,
+ TTY_KKEYPADMODE,
+ TTY_LINEFEED,
+ TTY_MOUSEMODE,
+ TTY_REVERSEINDEX,
+ TTY_SCROLLREGION,
+};
/* Message codes. */
enum hdrtype {
@@ -405,7 +504,7 @@ struct screen {
/* Screen redraw context. */
struct screen_redraw_ctx {
void *data;
- void (*write)(void *, int, ...);
+ void (*write)(void *, enum tty_cmd, ...);
u_int saved_cx;
u_int saved_cy;
@@ -416,7 +515,7 @@ struct screen_redraw_ctx {
/* Screen write context. */
struct screen_write_ctx {
void *data;
- void (*write)(void *, int, ...);
+ void (*write)(void *, enum tty_cmd, ...);
struct screen *s;
};
@@ -557,7 +656,7 @@ ARRAY_DECL(sessions, struct session *);
/* TTY information. */
struct tty_key {
- int code;
+ int key;
char *string;
int flags;
@@ -569,9 +668,10 @@ struct tty_key {
struct tty_term {
char *name;
- TERMINAL *term;
u_int references;
+ struct tty_code codes[NTTYCODE];
+
#define TERM_HASDEFAULTS 0x1
#define TERM_256COLOURS 0x2
int flags;
@@ -824,6 +924,7 @@ extern struct options global_window_options;
extern char *cfg_file;
extern int debug_level;
extern int be_quiet;
+extern time_t start_time;
void logfile(const char *);
void siginit(void);
void sigreset(void);
@@ -854,8 +955,20 @@ void tty_set_title(struct tty *, const char *);
int tty_open(struct tty *, char **);
void tty_close(struct tty *);
void tty_free(struct tty *);
-void tty_write(struct tty *, struct screen *, int, ...);
-void tty_vwrite(struct tty *, struct screen *s, int, va_list);
+void tty_write(struct tty *, struct screen *, enum tty_cmd, ...);
+void tty_vwrite(
+ struct tty *, struct screen *s, enum tty_cmd, va_list);
+
+/* tty-term.c */
+struct tty_term *tty_term_find(char *, int,char **);
+void tty_term_free(struct tty_term *);
+int tty_term_has(struct tty_term *, enum tty_code_code);
+const char *tty_term_string(struct tty_term *, enum tty_code_code);
+const char *tty_term_string1(struct tty_term *, enum tty_code_code, int);
+const char *tty_term_string2(
+ struct tty_term *, enum tty_code_code, int, int);
+int tty_term_number(struct tty_term *, enum tty_code_code);
+int tty_term_flag(struct tty_term *, enum tty_code_code);
/* tty-keys.c */
int tty_keys_cmp(struct tty_key *, struct tty_key *);
@@ -865,12 +978,12 @@ void tty_keys_free(struct tty *);
int tty_keys_next(struct tty *, int *);
/* tty-write.c */
-void tty_write_client(void *, int, ...);
-void tty_vwrite_client(void *, int, va_list);
-void tty_write_window(void *, int, ...);
-void tty_vwrite_window(void *, int, va_list);
-void tty_write_session(void *, int, ...);
-void tty_vwrite_session(void *, int, va_list);
+void tty_write_client(void *, enum tty_cmd, ...);
+void tty_vwrite_client(void *, enum tty_cmd, va_list);
+void tty_write_window(void *, enum tty_cmd, ...);
+void tty_vwrite_window(void *, enum tty_cmd, va_list);
+void tty_write_session(void *, enum tty_cmd, ...);
+void tty_vwrite_session(void *, enum tty_cmd, va_list);
/* options-cmd.c */
void set_option_string(struct cmd_ctx *,
@@ -1135,7 +1248,7 @@ void screen_write_start_client(struct screen_write_ctx *, struct client *);
void screen_write_start_session(
struct screen_write_ctx *, struct session *);
void screen_write_start(struct screen_write_ctx *,
- struct screen *, void (*)(void *, int, ...), void *);
+ struct screen *, void (*)(void *, enum tty_cmd, ...), void *);
void screen_write_stop(struct screen_write_ctx *);
void printflike3 screen_write_puts(
struct screen_write_ctx *, struct grid_cell *, const char *, ...);
@@ -1175,7 +1288,7 @@ void screen_redraw_start_client(struct screen_redraw_ctx *, struct client *);
void screen_redraw_start_session(
struct screen_redraw_ctx *, struct session *);
void screen_redraw_start(struct screen_redraw_ctx *,
- struct screen *, void (*)(void *, int, ...), void *);
+ struct screen *, void (*)(void *, enum tty_cmd, ...), void *);
void screen_redraw_stop(struct screen_redraw_ctx *);
void printflike3 screen_redraw_puts(
struct screen_redraw_ctx *, struct grid_cell *, const char *, ...);
diff --git a/tty-keys.c b/tty-keys.c
index b0d85c6e..00d48579 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -1,4 +1,4 @@
-/* $Id: tty-keys.c,v 1.15 2009-01-09 16:47:06 nicm Exp $ */
+/* $Id: tty-keys.c,v 1.16 2009-01-09 23:57:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,46 +26,47 @@
void tty_keys_add(struct tty *, const char *, int, int);
struct tty_key_ent {
- const char *name;
- int code;
+ enum tty_code_code code;
+ const char *string;
- int flags;
+ int key;
+ int flags;
};
struct tty_key_ent tty_keys[] = {
/* Function keys. */
- { "kf1", KEYC_F1, TTYKEY_MODIFIER },
- { "kf2", KEYC_F2, TTYKEY_MODIFIER },
- { "kf3", KEYC_F3, TTYKEY_MODIFIER },
- { "kf4", KEYC_F4, TTYKEY_MODIFIER },
- { "kf5", KEYC_F5, TTYKEY_MODIFIER },
- { "kf6", KEYC_F6, TTYKEY_MODIFIER },
- { "kf7", KEYC_F7, TTYKEY_MODIFIER },
- { "kf8", KEYC_F8, TTYKEY_MODIFIER },
- { "kf9", KEYC_F9, TTYKEY_MODIFIER },
- { "kf10", KEYC_F10, TTYKEY_MODIFIER },
- { "kf11", KEYC_F11, TTYKEY_MODIFIER },
- { "kf12", KEYC_F12, TTYKEY_MODIFIER },
- { "kich1", KEYC_IC, TTYKEY_MODIFIER },
- { "kdch1", KEYC_DC, TTYKEY_MODIFIER },
- { "khome", KEYC_HOME, TTYKEY_MODIFIER },
- { "kend", KEYC_END, TTYKEY_MODIFIER },
- { "knp", KEYC_NPAGE, TTYKEY_MODIFIER },
- { "kpp", KEYC_PPAGE, TTYKEY_MODIFIER },
-
- /* Arrow keys. */
- { "kcuu1", KEYC_UP, TTYKEY_MODIFIER },
- { "kcud1", KEYC_DOWN, TTYKEY_MODIFIER },
- { "kcub1", KEYC_LEFT, TTYKEY_MODIFIER },
- { "kcuf1", KEYC_RIGHT, TTYKEY_MODIFIER },
- { "\033OA",KEYC_UP, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033OB",KEYC_DOWN, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033OD",KEYC_LEFT, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033OC",KEYC_RIGHT, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033[A",KEYC_UP, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033[B",KEYC_DOWN, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033[D",KEYC_LEFT, TTYKEY_RAW|TTYKEY_MODIFIER },
- { "\033[C",KEYC_RIGHT, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { TTYC_KF1, NULL, KEYC_F1, TTYKEY_MODIFIER },
+ { TTYC_KF2, NULL, KEYC_F2, TTYKEY_MODIFIER },
+ { TTYC_KF3, NULL, KEYC_F3, TTYKEY_MODIFIER },
+ { TTYC_KF4, NULL, KEYC_F4, TTYKEY_MODIFIER },
+ { TTYC_KF5, NULL, KEYC_F5, TTYKEY_MODIFIER },
+ { TTYC_KF6, NULL, KEYC_F6, TTYKEY_MODIFIER },
+ { TTYC_KF7, NULL, KEYC_F7, TTYKEY_MODIFIER },
+ { TTYC_KF8, NULL, KEYC_F8, TTYKEY_MODIFIER },
+ { TTYC_KF9, NULL, KEYC_F9, TTYKEY_MODIFIER },
+ { TTYC_KF10, NULL, KEYC_F10, TTYKEY_MODIFIER },
+ { TTYC_KF11, NULL, KEYC_F11, TTYKEY_MODIFIER },
+ { TTYC_KF12, NULL, KEYC_F12, TTYKEY_MODIFIER },
+ { TTYC_KICH1, NULL, KEYC_IC, TTYKEY_MODIFIER },
+ { TTYC_KDCH1, NULL, KEYC_DC, TTYKEY_MODIFIER },
+ { TTYC_KHOME, NULL, KEYC_HOME, TTYKEY_MODIFIER },
+ { TTYC_KEND, NULL, KEYC_END, TTYKEY_MODIFIER },
+ { TTYC_KNP, NULL, KEYC_NPAGE, TTYKEY_MODIFIER },
+ { TTYC_KPP, NULL, KEYC_PPAGE, TTYKEY_MODIFIER },
+
+ /* Arrow keys. */
+ { TTYC_KCUU1, NULL, KEYC_UP, TTYKEY_MODIFIER },
+ { TTYC_KCUD1, NULL, KEYC_DOWN, TTYKEY_MODIFIER },
+ { TTYC_KCUB1, NULL, KEYC_LEFT, TTYKEY_MODIFIER },
+ { TTYC_KCUF1, NULL, KEYC_RIGHT, TTYKEY_MODIFIER },
+ { 0, "\033OA", KEYC_UP, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033OB", KEYC_DOWN, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033OD", KEYC_LEFT, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033OC", KEYC_RIGHT, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033[A", KEYC_UP, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033[B", KEYC_DOWN, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033[D", KEYC_LEFT, TTYKEY_RAW|TTYKEY_MODIFIER },
+ { 0, "\033[C", KEYC_RIGHT, TTYKEY_RAW|TTYKEY_MODIFIER },
/*
* Numeric keypad. termcap and terminfo are totally confusing for this.
@@ -77,22 +78,22 @@ struct tty_key_ent tty_keys[] = {
* mode. Translation of numbers mode/applications mode is done in
* input-keys.c.
*/
- { "\033Oo", KEYC_KP0_1, TTYKEY_RAW },
- { "\033Oj", KEYC_KP0_2, TTYKEY_RAW },
- { "\033Om", KEYC_KP0_3, TTYKEY_RAW },
- { "\033Ow", KEYC_KP1_0, TTYKEY_RAW },
- { "\033Ox", KEYC_KP1_1, TTYKEY_RAW },
- { "\033Oy", KEYC_KP1_2, TTYKEY_RAW },
- { "\033Ok", KEYC_KP1_3, TTYKEY_RAW },
- { "\033Ot", KEYC_KP2_0, TTYKEY_RAW },
- { "\033Ou", KEYC_KP2_1, TTYKEY_RAW },
- { "\033Ov", KEYC_KP2_2, TTYKEY_RAW },
- { "\033Oq", KEYC_KP3_0, TTYKEY_RAW },
- { "\033Or", KEYC_KP3_1, TTYKEY_RAW },
- { "\033Os", KEYC_KP3_2, TTYKEY_RAW },
- { "\033OM", KEYC_KP3_3, TTYKEY_RAW },
- { "\033Op", KEYC_KP4_0, TTYKEY_RAW },
- { "\033On", KEYC_KP4_2, TTYKEY_RAW },
+ { 0, "\033Oo", KEYC_KP0_1, TTYKEY_RAW },
+ { 0, "\033Oj", KEYC_KP0_2, TTYKEY_RAW },
+ { 0, "\033Om", KEYC_KP0_3, TTYKEY_RAW },
+ { 0, "\033Ow", KEYC_KP1_0, TTYKEY_RAW },
+ { 0, "\033Ox", KEYC_KP1_1, TTYKEY_RAW },
+ { 0, "\033Oy", KEYC_KP1_2, TTYKEY_RAW },
+ { 0, "\033Ok", KEYC_KP1_3, TTYKEY_RAW },
+ { 0, "\033Ot", KEYC_KP2_0, TTYKEY_RAW },
+ { 0, "\033Ou", KEYC_KP2_1, TTYKEY_RAW },
+ { 0, "\033Ov", KEYC_KP2_2, TTYKEY_RAW },
+ { 0, "\033Oq", KEYC_KP3_0, TTYKEY_RAW },
+ { 0, "\033Or", KEYC_KP3_1, TTYKEY_RAW },
+ { 0, "\033Os", KEYC_KP3_2, TTYKEY_RAW },
+ { 0, "\033OM", KEYC_KP3_3, TTYKEY_RAW },
+ { 0, "\033Op", KEYC_KP4_0, TTYKEY_RAW },
+ { 0, "\033On", KEYC_KP4_2, TTYKEY_RAW },
};
RB_GENERATE(tty_keys, tty_key, entry, tty_keys_cmp);
@@ -106,21 +107,20 @@ tty_keys_cmp(struct tty_key *k1, struct tty_key *k2)
}
void
-tty_keys_add(struct tty *tty, const char *s, int code, int flags)
+tty_keys_add(struct tty *tty, const char *s, int key, int flags)
{
struct tty_key *tk;
tk = xmalloc(sizeof *tk);
tk->string = xstrdup(s);
- tk->code = code;
+ tk->key = key;
tk->flags = flags;
if (strlen(tk->string) > tty->ksize)
tty->ksize = strlen(tk->string);
RB_INSERT(tty_keys, &tty->ktree, tk);
- log_debug(
- "new key %x: size now %zu (%s)", code, tty->ksize, tk->string);
+ log_debug("new key %x: size now %zu (%s)", key, tty->ksize, tk->string);
}
void
@@ -138,21 +138,21 @@ tty_keys_init(struct tty *tty)
tke = &tty_keys[i];
if (tke->flags & TTYKEY_RAW)
- s = tke->name;
+ s = tke->string;
else {
- s = tigetstr(tke->name);
- if (s == (char *) -1 || s == (char *) 0)
+ if (!tty_term_has(tty->term, tke->code))
continue;
+ s = tty_term_string(tty->term, tke->code);
if (s[0] != '\033' || s[1] == '\0')
continue;
}
- tty_keys_add(tty, s + 1, tke->code, tke->flags);
+ tty_keys_add(tty, s + 1, tke->key, tke->flags);
if (tke->flags & TTYKEY_MODIFIER) {
if (strlcpy(tmp, s, sizeof tmp) >= sizeof tmp)
continue;
tmp[strlen(tmp) - 1] ^= 0x20;
- tty_keys_add(tty, tmp + 1, KEYC_ADDCTL(tke->code), 0);
+ tty_keys_add(tty, tmp + 1, KEYC_ADDCTL(tke->key), 0);
}
}
}
@@ -201,7 +201,7 @@ tty_keys_find(struct tty *tty, char *buf, size_t len, size_t *size)
}
int
-tty_keys_next(struct tty *tty, int *code)
+tty_keys_next(struct tty *tty, int *key)
{
struct tty_key *tk;
struct timeval tv;
@@ -216,14 +216,14 @@ tty_keys_next(struct tty *tty, int *code)
/* If a normal key, return it. */
if (*buf != '\033') {
- *code = buffer_read8(tty->in);
+ *key = buffer_read8(tty->in);
return (0);
}
/* Look for matching key string and return if found. */
tk = tty_keys_find(tty, buf + 1, len - 1, &size);
if (tk != NULL) {
- *code = tk->code;
+ *key = tk->key;
buffer_remove(tty->in, size + 1);
tty->flags &= ~TTY_ESCAPE;
@@ -239,35 +239,35 @@ tty_keys_next(struct tty *tty, int *code)
tk = tty_keys_find(tty, tmp + 1, len - 3, &size);
if (tk != NULL) {
- *code = tk->code;
+ *key = tk->key;
buffer_remove(tty->in, size + 3);
switch (arg) {
case '8':
- *code = KEYC_ADDSFT(*code);
- *code = KEYC_ADDESC(*code);
- *code = KEYC_ADDCTL(*code);
+ *key = KEYC_ADDSFT(*key);
+ *key = KEYC_ADDESC(*key);
+ *key = KEYC_ADDCTL(*key);
break;
case '7':
- *code = KEYC_ADDESC(*code);
- *code = KEYC_ADDCTL(*code);
+ *key = KEYC_ADDESC(*key);
+ *key = KEYC_ADDCTL(*key);
break;
case '6':
- *code = KEYC_ADDSFT(*code);
- *code = KEYC_ADDCTL(*code);
+ *key = KEYC_ADDSFT(*key);
+ *key = KEYC_ADDCTL(*key);
break;
case '5':
- *code = KEYC_ADDCTL(*code);
+ *key = KEYC_ADDCTL(*key);
break;
case '4':
- *code = KEYC_ADDSFT(*code);
- *code = KEYC_ADDESC(*code);
+ *key = KEYC_ADDSFT(*key);
+ *key = KEYC_ADDESC(*key);
break;
case '3':
- *code = KEYC_ADDESC(*code);
+ *key = KEYC_ADDESC(*key);
break;
case '2':
- *code = KEYC_ADDSFT(*code);
+ *key = KEYC_ADDSFT(*key);
break;
}
@@ -302,26 +302,26 @@ tty_keys_next(struct tty *tty, int *code)
/* If we have no following data, return escape. */
if (len == 0) {
- *code = '\033';
+ *key = '\033';
return (0);
}
/* If a normal key follows, return it. */
if (*buf != '\033') {
- *code = KEYC_ADDESC(buffer_read8(tty->in));
+ *key = KEYC_ADDESC(buffer_read8(tty->in));
return (0);
}
/* Try to look up the key. */
tk = tty_keys_find(tty, buf + 1, len - 1, &size);
if (tk != NULL) {
- *code = KEYC_ADDESC(tk->code);
+ *key = KEYC_ADDESC(tk->key);
buffer_remove(tty->in, size + 1);
return (0);
}
/* If not found, return escape-escape. */
- *code = KEYC_ADDESC('\033');
+ *key = KEYC_ADDESC('\033');
buffer_remove(tty->in, 1);
return (0);
}
diff --git a/tty-term.c b/tty-term.c
new file mode 100644
index 00000000..1aca9bd9
--- /dev/null
+++ b/tty-term.c
@@ -0,0 +1,395 @@
+/* $Id: tty-term.c,v 1.1 2009-01-09 23:57:42 nicm Exp $ */
+
+/*
+ * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <ncurses.h>
+#include <string.h>
+#include <term.h>
+
+#include "tmux.h"
+
+void tty_term_quirks(struct tty_term *);
+char *tty_term_strip(const char *);
+
+SLIST_HEAD(, tty_term) tty_terms = SLIST_HEAD_INITIALIZER(tty_terms);
+
+struct tty_term_code_entry {
+ enum tty_code_code code;
+ enum tty_code_type type;
+ const char *name;
+};
+
+struct tty_term_code_entry tty_term_codes[] = {
+ { TTYC_AX, TTYCODE_FLAG, "AX" },
+ { TTYC_ACSC, TTYCODE_STRING, "acsc" },
+ { TTYC_BEL, TTYCODE_STRING, "bel" },
+ { TTYC_BLINK, TTYCODE_STRING, "blink" },
+ { TTYC_BOLD, TTYCODE_STRING, "bold" },
+ { TTYC_CIVIS, TTYCODE_STRING, "civis" },
+ { TTYC_CLEAR, TTYCODE_STRING, "clear" },
+ { TTYC_CNORM, TTYCODE_STRING, "cnorm" },
+ { TTYC_COLORS, TTYCODE_NUMBER, "colors" },
+ { TTYC_CR, TTYCODE_STRING, "cr" },
+ { TTYC_CSR, TTYCODE_STRING, "csr" },
+ { TTYC_CUB, TTYCODE_STRING, "cub" },
+ { TTYC_CUB1, TTYCODE_STRING, "cub1" },
+ { TTYC_CUD, TTYCODE_STRING, "cud" },
+ { TTYC_CUD1, TTYCODE_STRING, "cud1" },
+ { TTYC_CUF, TTYCODE_STRING, "cuf" },
+ { TTYC_CUF1, TTYCODE_STRING, "cuf1" },
+ { TTYC_CUP, TTYCODE_STRING, "cup" },
+ { TTYC_CUU, TTYCODE_STRING, "cuu" },
+ { TTYC_CUU1, TTYCODE_STRING, "cuu1" },
+ { TTYC_DCH, TTYCODE_STRING, "dch" },
+ { TTYC_DIM, TTYCODE_STRING, "dim" },
+ { TTYC_DL, TTYCODE_STRING, "dl" },
+ { TTYC_DL1, TTYCODE_STRING, "dl1" },
+ { TTYC_ED, TTYCODE_STRING, "ed" },
+ { TTYC_EL, TTYCODE_STRING, "el" },
+ { TTYC_EL1, TTYCODE_STRING, "el1" },
+ { TTYC_ENACS, TTYCODE_STRING, "enacs" },
+ { TTYC_ICH, TTYCODE_STRING, "ich" },
+ { TTYC_ICH1, TTYCODE_STRING, "ich1" },
+ { TTYC_IL, TTYCODE_STRING, "il" },
+ { TTYC_IL1, TTYCODE_STRING, "il1" },
+ { TTYC_INVIS, TTYCODE_STRING, "invis" },
+ { TTYC_IS1, TTYCODE_STRING, "is1" },
+ { TTYC_IS2, TTYCODE_STRING, "is2" },
+ { TTYC_IS3, TTYCODE_STRING, "is3" },
+ { TTYC_KCUB1, TTYCODE_STRING, "kcub1" },
+ { TTYC_KCUD1, TTYCODE_STRING, "kcud1" },
+ { TTYC_KCUF1, TTYCODE_STRING, "kcuf1" },
+ { TTYC_KCUU1, TTYCODE_STRING, "kcuu1" },
+ { TTYC_KDCH1, TTYCODE_STRING, "kdch1" },
+ { TTYC_KEND, TTYCODE_STRING, "kend" },
+ { TTYC_KF1, TTYCODE_STRING, "kf1" },
+ { TTYC_KF10, TTYCODE_STRING, "kf10" },
+ { TTYC_KF11, TTYCODE_STRING, "kf11" },
+ { TTYC_KF12, TTYCODE_STRING, "kf12" },
+ { TTYC_KF2, TTYCODE_STRING, "kf2" },
+ { TTYC_KF3, TTYCODE_STRING, "kf3" },
+ { TTYC_KF4, TTYCODE_STRING, "kf4" },
+ { TTYC_KF5, TTYCODE_STRING, "kf5" },
+ { TTYC_KF6, TTYCODE_STRING, "kf6" },
+ { TTYC_KF7, TTYCODE_STRING, "kf7" },
+ { TTYC_KF8, TTYCODE_STRING, "kf8" },
+ { TTYC_KF9, TTYCODE_STRING, "kf9" },
+ { TTYC_KHOME, TTYCODE_STRING, "khome" },
+ { TTYC_KICH1, TTYCODE_STRING, "kich1" },
+ { TTYC_KMOUS, TTYCODE_STRING, "kmous" },
+ { TTYC_KNP, TTYCODE_STRING, "knp" },
+ { TTYC_KPP, TTYCODE_STRING, "kpp" },
+ { TTYC_OP, TTYCODE_STRING, "op" },
+ { TTYC_REV, TTYCODE_STRING, "rev" },
+ { TTYC_RI, TTYCODE_STRING, "ri" },
+ { TTYC_RMACS, TTYCODE_STRING, "rmacs" },
+ { TTYC_RMCUP, TTYCODE_STRING, "rmcup" },
+ { TTYC_RMKX, TTYCODE_STRING, "rmkx" },
+ { TTYC_SETAB, TTYCODE_STRING, "setab" },
+ { TTYC_SETAF, TTYCODE_STRING, "setaf" },
+ { TTYC_SGR0, TTYCODE_STRING, "sgr0" },
+ { TTYC_SMACS, TTYCODE_STRING, "smacs" },
+ { TTYC_SMCUP, TTYCODE_STRING, "smcup" },
+ { TTYC_SMKX, TTYCODE_STRING, "smkx" },
+ { TTYC_SMSO, TTYCODE_STRING, "smso" },
+ { TTYC_SMUL, TTYCODE_STRING, "smul" },
+};
+
+char *
+tty_term_strip(const char *s)
+{
+ const char *ptr;
+ static char buf[BUFSIZ];
+ size_t len;
+
+ /* Ignore strings with no padding. */
+ if (strchr(s, '$') == NULL)
+ return (xstrdup(s));
+
+ len = 0;
+ for (ptr = s; *ptr != '\0'; ptr++) {
+ if (*ptr == '$' && *(ptr + 1) == '<') {
+ while (*ptr != '\0' && *ptr != '>')
+ ptr++;
+ if (*ptr == '>')
+ ptr++;
+ }
+
+ buf[len++] = *ptr;
+ if (len == (sizeof buf) - 1)
+ break;
+ }
+ buf[len] = '\0';
+
+ return (xstrdup(buf));
+}
+
+void
+tty_term_quirks(struct tty_term *term)
+{
+ if (strcmp(term->name, "rxvt") == 0) {
+ /* rxvt supports dch1 but some termcap files do not have it. */
+ if (!tty_term_has(term, TTYC_DCH1)) {
+ term->codes[TTYC_DCH1].type = TTYCODE_STRING;
+ term->codes[TTYC_DCH1].value.string = xstrdup("\033[P");
+ }
+ }
+}
+
+struct tty_term *
+tty_term_find(char *name, int fd, char **cause)
+{
+ struct tty_term *term;
+ struct tty_term_code_entry *ent;
+ struct tty_code *code;
+ u_int i;
+ int n, error;
+ char *s;
+
+ SLIST_FOREACH(term, &tty_terms, entry) {
+ if (strcmp(term->name, name) == 0) {
+ term->references++;
+ return (term);
+ }
+ }
+
+ log_debug("new term: %s", name);
+ term = xmalloc(sizeof *term);
+ term->name = xstrdup(name);
+ term->references = 1;
+ SLIST_INSERT_HEAD(&tty_terms, term, entry);
+
+ /* Set up ncurses terminal. */
+ if (setupterm(name, fd, &error) != OK) {
+ switch (error) {
+ case 0:
+ xasprintf(cause, "can't use hardcopy terminal");
+ break;
+ case 1:
+ xasprintf(cause, "missing or unsuitable terminal");
+ break;
+ case 2:
+ xasprintf(cause, "can't find terminfo database");
+ break;
+ default:
+ xasprintf(cause, "unknown error");
+ break;
+ }
+ goto error;
+ }
+
+ /* Fill in codes. */
+ memset(&term->codes, 0, sizeof term->codes);
+ for (i = 0; i < nitems(tty_term_codes); i++) {
+ ent = &tty_term_codes[i];
+
+ code = &term->codes[ent->code];
+ code->type = TTYCODE_NONE;
+ switch (ent->type) {
+ case TTYCODE_NONE:
+ break;
+ case TTYCODE_STRING:
+ s = tigetstr(ent->name);
+ if (s == NULL || s == (char *) -1)
+ break;
+ code->type = TTYCODE_STRING;
+ code->value.string = tty_term_strip(s);
+ log_debug(
+ "code %d,%s: (string) %s", ent->code, ent->name, s);
+ break;
+ case TTYCODE_NUMBER:
+ n = tigetnum(ent->name);
+ if (n == -1 || n == -2)
+ break;
+ code->type = TTYCODE_NUMBER;
+ code->value.number = n;
+ log_debug(
+ "code %d,%s: (number) %d", ent->code, ent->name, n);
+ break;
+ case TTYCODE_FLAG:
+ n = tigetflag(ent->name);
+ if (n == -1)
+ break;
+ code->type = TTYCODE_FLAG;
+ code->value.number = n;
+ log_debug(
+ "code %d,%s: (flag) %d", ent->code, ent->name, n);
+ break;
+ }
+ }
+ tty_term_quirks(term);
+
+ /* Delete ncurses data. */
+ del_curterm(cur_term);
+
+ /* These are always required. */
+ if (!tty_term_has(term, TTYC_CLEAR)) {
+ xasprintf(cause, "terminal does not support clear");
+ goto error;
+ }
+ if (!tty_term_has(term, TTYC_CUD)) {
+ xasprintf(cause, "terminal does not support cud");
+ goto error;
+ }
+ if (!tty_term_has(term, TTYC_CR)) {
+ xasprintf(cause, "terminal does not support cr");
+ goto error;
+ }
+ if (!tty_term_has(term, TTYC_RI)) {
+ xasprintf(cause, "terminal does not support ri");
+ goto error;
+ }
+ if (!tty_term_has(term, TTYC_CSR)) {
+ xasprintf(cause, "terminal does not support csr");
+ goto error;
+ }
+ if (!tty_term_has(term, TTYC_CUP)) {
+ xasprintf(cause, "terminal does not support cup");
+ goto error;
+ }
+
+ /* These can be emulated so one of the two is required. */
+ if (!tty_term_has(term, TTYC_CUU1) && !tty_term_has(term, TTYC_CUU)) {
+ xasprintf(cause, "terminal does not support cuu1 or cuu");
+ go