Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/screen.c @ 761:4532a9fe0e8c
Handle some keyboard escape sequences
Some sequences are not caught by ncurses, so I've made a basic escape
sequences interpreter.
The patch defines a few sequences for xterm and Gnome terminal (ctrl-arrows).
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 19 Mar 2006 12:41:46 +0100 |
parents | 715952c2f37f |
children | 96d46e00524a |
comparison
equal
deleted
inserted
replaced
760:715952c2f37f | 761:4532a9fe0e8c |
---|---|
89 static short int inputline_offset; | 89 static short int inputline_offset; |
90 static int completion_started; | 90 static int completion_started; |
91 static GList *cmdhisto; | 91 static GList *cmdhisto; |
92 static GList *cmdhisto_cur; | 92 static GList *cmdhisto_cur; |
93 static char cmdhisto_backup[INPUTLINE_LENGTH+1]; | 93 static char cmdhisto_backup[INPUTLINE_LENGTH+1]; |
94 | |
95 #define MAX_KEYSEQ_LENGTH 8 | |
96 | |
97 typedef struct { | |
98 char *seqstr; | |
99 guint mkeycode; | |
100 gint value; | |
101 } keyseq; | |
102 | |
103 GSList *keyseqlist; | |
104 static void add_keyseq(char *seqstr, guint mkeycode, gint value); | |
94 | 105 |
95 | 106 |
96 /* Functions */ | 107 /* Functions */ |
97 | 108 |
98 static int scr_WindowWidth(WINDOW * win) | 109 static int scr_WindowWidth(WINDOW * win) |
207 } | 218 } |
208 } | 219 } |
209 | 220 |
210 void scr_InitCurses(void) | 221 void scr_InitCurses(void) |
211 { | 222 { |
223 /* Key sequences initialization */ | |
224 add_keyseq("O5A", MKEY_EQUIV, 521); // Ctrl-Up | |
225 add_keyseq("O5B", MKEY_EQUIV, 514); // Ctrl-Down | |
226 add_keyseq("O5C", MKEY_EQUIV, 518); // Ctrl-Right | |
227 add_keyseq("O5D", MKEY_EQUIV, 516); // Ctrl-Left | |
228 add_keyseq("O6A", MKEY_EQUIV, 520); // Ctrl-Shift-Up | |
229 add_keyseq("O6B", MKEY_EQUIV, 513); // Ctrl-Shift-Down | |
230 add_keyseq("O6C", MKEY_EQUIV, 402); // Ctrl-Shift-Right | |
231 add_keyseq("O6D", MKEY_EQUIV, 393); // Ctrl-Shift-Left | |
232 | |
233 // Xterm | |
234 add_keyseq("[1;5A", MKEY_EQUIV, 521); // Ctrl-Up | |
235 add_keyseq("[1;5B", MKEY_EQUIV, 514); // Ctrl-Down | |
236 add_keyseq("[1;5C", MKEY_EQUIV, 518); // Ctrl-Right | |
237 add_keyseq("[1;5D", MKEY_EQUIV, 516); // Ctrl-Left | |
238 add_keyseq("[1;6A", MKEY_EQUIV, 520); // Ctrl-Shift-Up | |
239 add_keyseq("[1;6B", MKEY_EQUIV, 513); // Ctrl-Shift-Down | |
240 add_keyseq("[1;6C", MKEY_EQUIV, 402); // Ctrl-Shift-Right | |
241 add_keyseq("[1;6D", MKEY_EQUIV, 393); // Ctrl-Shift-Left | |
242 | |
212 initscr(); | 243 initscr(); |
213 raw(); | 244 raw(); |
214 noecho(); | 245 noecho(); |
215 nonl(); | 246 nonl(); |
216 intrflush(stdscr, FALSE); | 247 intrflush(stdscr, FALSE); |
1861 scr_end_current_completion(); | 1892 scr_end_current_completion(); |
1862 check_offset(-1); | 1893 check_offset(-1); |
1863 refresh_inputline(); | 1894 refresh_inputline(); |
1864 } | 1895 } |
1865 | 1896 |
1866 int scr_Getch(void) | 1897 static void add_keyseq(char *seqstr, guint mkeycode, gint value) |
1867 { | 1898 { |
1868 return wgetch(inputWnd); | 1899 keyseq *ks; |
1900 | |
1901 // Let's make sure the length is correct | |
1902 if (strlen(seqstr) > MAX_KEYSEQ_LENGTH) { | |
1903 scr_LogPrint(LPRINT_LOGNORM, "add_keyseq(): key sequence is too long!"); | |
1904 return; | |
1905 } | |
1906 | |
1907 ks = g_new0(keyseq, 1); | |
1908 ks->seqstr = g_strdup(seqstr); | |
1909 ks->mkeycode = mkeycode; | |
1910 ks->value = value; | |
1911 keyseqlist = g_slist_append(keyseqlist, ks); | |
1912 } | |
1913 | |
1914 // match_keyseq(iseq, &ret) | |
1915 // Check if "iseq" is a known key escape sequence. | |
1916 // Return value: | |
1917 // -1 if "seq" matches no known sequence | |
1918 // 0 if "seq" could match 1 or more known sequences | |
1919 // >0 if "seq" matches a key sequence; the mkey code is returned | |
1920 // and *ret is set to the matching keyseq structure. | |
1921 static inline guint match_keyseq(int *iseq, keyseq **ret) | |
1922 { | |
1923 GSList *ksl; | |
1924 keyseq *ksp; | |
1925 char *p, c; | |
1926 int *i; | |
1927 int needmore = FALSE; | |
1928 | |
1929 for (ksl = keyseqlist; ksl; ksl = g_slist_next(ksl)) { | |
1930 ksp = ksl->data; | |
1931 p = ksp->seqstr; | |
1932 i = iseq; | |
1933 while (1) { | |
1934 c = (unsigned char)*i; | |
1935 if (!*p && !c) { // Match | |
1936 (*ret) = ksp; | |
1937 return ksp->mkeycode; | |
1938 } | |
1939 if (!c) { | |
1940 // iseq is too short | |
1941 needmore = TRUE; | |
1942 break; | |
1943 } else if (!*p || c != *p) { | |
1944 // This isn't a match | |
1945 break; | |
1946 } | |
1947 p++; i++; | |
1948 } | |
1949 } | |
1950 | |
1951 if (needmore) | |
1952 return 0; | |
1953 return -1; | |
1954 } | |
1955 | |
1956 void scr_Getch(keycode *kcode) | |
1957 { | |
1958 keyseq *mks; | |
1959 int ks[MAX_KEYSEQ_LENGTH+1]; | |
1960 int i; | |
1961 | |
1962 memset(kcode, 0, sizeof(keycode)); | |
1963 memset(ks, 0, sizeof(ks)); | |
1964 | |
1965 kcode->value = wgetch(inputWnd); | |
1966 if (kcode->value != 27) | |
1967 return; | |
1968 | |
1969 // Check for escape key sequence | |
1970 for (i=0; i < MAX_KEYSEQ_LENGTH; i++) { | |
1971 int match; | |
1972 ks[i] = wgetch(inputWnd); | |
1973 if (ks[i] == ERR) break; | |
1974 match = match_keyseq(ks, &mks); | |
1975 if (match == -1) { | |
1976 // No such key sequence. Let's increment i as it is a valid key. | |
1977 i++; | |
1978 break; | |
1979 } | |
1980 if (match > 0) { | |
1981 // We have a matching sequence | |
1982 kcode->mcode = mks->mkeycode; | |
1983 kcode->value = mks->value; | |
1984 return; | |
1985 } | |
1986 } | |
1987 | |
1988 // No match. Let's return a meta-key. | |
1989 if (i > 0) { | |
1990 kcode->mcode = MKEY_META; | |
1991 kcode->value = ks[0]; | |
1992 } | |
1993 if (i > 1) { | |
1994 // We need to push some keys back to the keyboard buffer | |
1995 while (i-- > 1) | |
1996 ungetch(ks[i]); | |
1997 } | |
1998 return; | |
1869 } | 1999 } |
1870 | 2000 |
1871 // process_key(key) | 2001 // process_key(key) |
1872 // Handle the pressed key, in the command line (bottom). | 2002 // Handle the pressed key, in the command line (bottom). |
1873 int process_key(int key) | 2003 int process_key(keycode kcode) |
1874 { | 2004 { |
1875 if (key == 27) { | 2005 int key = kcode.value; |
1876 key = scr_Getch(); | 2006 |
1877 if (key == -1 || key == 27) { | 2007 switch (kcode.mcode) { |
1878 // This is a "real" escape... | 2008 case 0: |
1879 scr_CheckAutoAway(TRUE); | 2009 break; |
1880 currentWindow = NULL; | 2010 case MKEY_EQUIV: |
1881 chatmode = FALSE; | 2011 key = kcode.value; |
1882 if (current_buddy) | 2012 break; |
1883 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, FALSE); | 2013 case MKEY_META: |
1884 scr_RosterVisibility(1); | 2014 key = ERR; |
1885 scr_UpdateChatStatus(FALSE); | 2015 switch (kcode.value) { |
1886 top_panel(chatPanel); | 2016 case 27: |
1887 top_panel(inputPanel); | 2017 key = 27; |
1888 update_panels(); | 2018 break; |
1889 } else { // Meta | 2019 default: |
1890 switch (key) { | 2020 scr_LogPrint(LPRINT_NORMAL, "Unknown key=M%d", kcode.value); |
1891 default: | 2021 } |
1892 scr_LogPrint(LPRINT_NORMAL, "Unknown key=M%d", key); | 2022 break; |
1893 } | 2023 default: |
1894 } | 2024 scr_LogPrint(LPRINT_NORMAL, "Unknown mkeycode! (%d)", kcode.mcode); |
1895 key = -1; | 2025 key = ERR; |
1896 } | 2026 } |
2027 | |
1897 switch (key) { | 2028 switch (key) { |
1898 case -1: | 2029 case 0: |
2030 case ERR: | |
1899 break; | 2031 break; |
1900 case 8: // Ctrl-h | 2032 case 8: // Ctrl-h |
1901 case 127: // Backspace too | 2033 case 127: // Backspace too |
1902 case KEY_BACKSPACE: | 2034 case KEY_BACKSPACE: |
1903 if (ptr_inputline != (char*)&inputLine) { | 2035 if (ptr_inputline != (char*)&inputLine) { |
2028 scr_Resize(); | 2160 scr_Resize(); |
2029 redrawwin(stdscr); | 2161 redrawwin(stdscr); |
2030 break; | 2162 break; |
2031 case KEY_RESIZE: | 2163 case KEY_RESIZE: |
2032 scr_Resize(); | 2164 scr_Resize(); |
2165 break; | |
2166 case 27: // ESC | |
2167 scr_CheckAutoAway(TRUE); | |
2168 currentWindow = NULL; | |
2169 chatmode = FALSE; | |
2170 if (current_buddy) | |
2171 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, FALSE); | |
2172 scr_RosterVisibility(1); | |
2173 scr_UpdateChatStatus(FALSE); | |
2174 top_panel(chatPanel); | |
2175 top_panel(inputPanel); | |
2176 update_panels(); | |
2033 break; | 2177 break; |
2034 default: | 2178 default: |
2035 if (isprint(key)) { | 2179 if (isprint(key)) { |
2036 char tmpLine[INPUTLINE_LENGTH+1]; | 2180 char tmpLine[INPUTLINE_LENGTH+1]; |
2037 | 2181 |