Mercurial > mplayer.hg
annotate osdep/getch2.c @ 33071:f4895241bdd5
Conform message determination
Determine message number right after parameter is read and check
for error immediately. Use similar char array for parameter input
and use read in variables for debug output.
author | ib |
---|---|
date | Wed, 30 Mar 2011 13:46:03 +0000 |
parents | 32725ca88fed |
children | 3ee9fd074b8c |
rev | line source |
---|---|
28744 | 1 /* |
2 * GyS-TermIO v2.0 (for GySmail v3) | |
3 * a very small replacement of ncurses library | |
4 * | |
5 * copyright (C) 1999 A'rpi/ESP-team | |
6 * | |
7 * This file is part of MPlayer. | |
8 * | |
9 * MPlayer is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * MPlayer is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU General Public License along | |
20 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
22 */ | |
1 | 23 |
16985 | 24 #include "config.h" |
1 | 25 |
27359
d788e177a35e
Rename some preprocessor directives from CONFIG_* to HAVE_* where appropriate;
diego
parents:
27341
diff
changeset
|
26 //#define HAVE_TERMCAP |
12122 | 27 #if !defined(__OS2__) && !defined(__MORPHOS__) |
27341
e7c989f7a7c9
Start unifying names of internal preprocessor directives.
diego
parents:
24515
diff
changeset
|
28 #define CONFIG_IOCTL |
5300 | 29 #endif |
1 | 30 |
31 #define MAX_KEYS 64 | |
32 #define BUF_LEN 256 | |
33 | |
34 #include <stdio.h> | |
35 #include <stdlib.h> | |
36 #include <string.h> | |
37 #include <sys/time.h> | |
38 #include <sys/types.h> | |
27341
e7c989f7a7c9
Start unifying names of internal preprocessor directives.
diego
parents:
24515
diff
changeset
|
39 #ifdef CONFIG_IOCTL |
1 | 40 #include <sys/ioctl.h> |
41 #endif | |
3281
310c0b9bea21
detect termios.h if no sys/termios.h (qnx getch2 support working)
alex
parents:
3014
diff
changeset
|
42 |
3009 | 43 #ifdef HAVE_TERMIOS |
3281
310c0b9bea21
detect termios.h if no sys/termios.h (qnx getch2 support working)
alex
parents:
3014
diff
changeset
|
44 #ifdef HAVE_TERMIOS_H |
310c0b9bea21
detect termios.h if no sys/termios.h (qnx getch2 support working)
alex
parents:
3014
diff
changeset
|
45 #include <termios.h> |
310c0b9bea21
detect termios.h if no sys/termios.h (qnx getch2 support working)
alex
parents:
3014
diff
changeset
|
46 #endif |
3282 | 47 #ifdef HAVE_SYS_TERMIOS_H |
1 | 48 #include <sys/termios.h> |
3009 | 49 #endif |
3281
310c0b9bea21
detect termios.h if no sys/termios.h (qnx getch2 support working)
alex
parents:
3014
diff
changeset
|
50 #endif |
310c0b9bea21
detect termios.h if no sys/termios.h (qnx getch2 support working)
alex
parents:
3014
diff
changeset
|
51 |
27393 | 52 #if defined(HAVE_LANGINFO) && defined(CONFIG_ICONV) |
22442
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
53 #include <locale.h> |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
54 #include <langinfo.h> |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
55 #endif |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
56 |
1 | 57 #include <unistd.h> |
58 | |
24129 | 59 #include "mp_fifo.h" |
1 | 60 #include "keycodes.h" |
30554 | 61 #include "getch2.h" |
1 | 62 |
3009 | 63 #ifdef HAVE_TERMIOS |
1 | 64 static struct termios tio_orig; |
3009 | 65 #endif |
1 | 66 static int getch2_len=0; |
67 static char getch2_buf[BUF_LEN]; | |
68 | |
69 int screen_width=80; | |
70 int screen_height=24; | |
17258
3d02f6e2a432
change erase to end of line, fall back to old behavior if no termcap found
ods15
parents:
17240
diff
changeset
|
71 char * erase_to_end_of_line = NULL; |
1 | 72 |
73 typedef struct { | |
74 int len; | |
75 int code; | |
76 char chars[8]; | |
77 } keycode_st; | |
78 static keycode_st getch2_keys[MAX_KEYS]; | |
79 static int getch2_key_db=0; | |
80 | |
27359
d788e177a35e
Rename some preprocessor directives from CONFIG_* to HAVE_* where appropriate;
diego
parents:
27341
diff
changeset
|
81 #ifdef HAVE_TERMCAP |
1 | 82 |
83 #if 0 | |
84 #include <termcap.h> | |
85 #else | |
28051 | 86 int tgetent(char *BUFFER, char *TERMTYPE); |
87 int tgetnum(char *NAME); | |
88 int tgetflag(char *NAME); | |
89 char *tgetstr(char *NAME, char **AREA); | |
1 | 90 #endif |
91 | |
92 static char term_buffer[4096]; | |
93 static char term_buffer2[4096]; | |
94 static char *term_p=term_buffer2; | |
95 | |
96 static void termcap_add(char *id,int code){ | |
97 char *p=tgetstr(id,&term_p); | |
98 if(!p) return; | |
99 if(getch2_key_db>=MAX_KEYS) return; | |
100 getch2_keys[getch2_key_db].len=strlen(p); | |
101 strncpy(getch2_keys[getch2_key_db].chars,p,8); | |
102 getch2_keys[getch2_key_db].code=code; | |
103 ++getch2_key_db; | |
104 /* printf("%s=%s\n",id,p); */ | |
105 } | |
106 | |
107 static int success=0; | |
108 | |
109 int load_termcap(char *termtype){ | |
110 if(!termtype) termtype=getenv("TERM"); | |
8889
18427eee9205
The attached little patch fixes a core dump on termcap systems when
arpi
parents:
8016
diff
changeset
|
111 if(!termtype) termtype="unknown"; |
1 | 112 success=tgetent(term_buffer, termtype); |
113 if(success<0){ printf("Could not access the 'termcap' data base.\n"); return 0; } | |
114 if(success==0){ printf("Terminal type `%s' is not defined.\n", termtype);return 0;} | |
115 | |
116 screen_width=tgetnum("co"); | |
117 screen_height=tgetnum("li"); | |
118 if(screen_width<1 || screen_width>255) screen_width=80; | |
119 if(screen_height<1 || screen_height>255) screen_height=24; | |
17258
3d02f6e2a432
change erase to end of line, fall back to old behavior if no termcap found
ods15
parents:
17240
diff
changeset
|
120 erase_to_end_of_line= tgetstr("cd",&term_p); |
1 | 121 |
122 termcap_add("kP",KEY_PGUP); | |
123 termcap_add("kN",KEY_PGDWN); | |
124 termcap_add("kh",KEY_HOME); | |
125 termcap_add("kH",KEY_END); | |
126 termcap_add("kI",KEY_INS); | |
127 termcap_add("kD",KEY_DEL); | |
128 termcap_add("kb",KEY_BS); | |
129 termcap_add("kl",KEY_LEFT); | |
130 termcap_add("kd",KEY_DOWN); | |
131 termcap_add("ku",KEY_UP); | |
132 termcap_add("kr",KEY_RIGHT); | |
133 termcap_add("k0",KEY_F+0); | |
134 termcap_add("k1",KEY_F+1); | |
135 termcap_add("k2",KEY_F+2); | |
136 termcap_add("k3",KEY_F+3); | |
137 termcap_add("k4",KEY_F+4); | |
138 termcap_add("k5",KEY_F+5); | |
139 termcap_add("k6",KEY_F+6); | |
140 termcap_add("k7",KEY_F+7); | |
141 termcap_add("k8",KEY_F+8); | |
142 termcap_add("k9",KEY_F+9); | |
143 termcap_add("k;",KEY_F+10); | |
144 return getch2_key_db; | |
145 } | |
146 | |
147 #endif | |
148 | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17264
diff
changeset
|
149 void get_screen_size(void){ |
27341
e7c989f7a7c9
Start unifying names of internal preprocessor directives.
diego
parents:
24515
diff
changeset
|
150 #ifdef CONFIG_IOCTL |
1 | 151 struct winsize ws; |
152 if (ioctl(0, TIOCGWINSZ, &ws) < 0 || !ws.ws_row || !ws.ws_col) return; | |
153 /* printf("Using IOCTL\n"); */ | |
154 screen_width=ws.ws_col; | |
155 screen_height=ws.ws_row; | |
156 #endif | |
157 } | |
158 | |
24129 | 159 void getch2(void) |
160 { | |
24130 | 161 int retval = read(0, &getch2_buf[getch2_len], BUF_LEN-getch2_len); |
24129 | 162 if (retval < 1) |
24130 | 163 return; |
164 getch2_len += retval; | |
1 | 165 |
24129 | 166 while (getch2_len > 0 && (getch2_len > 1 || getch2_buf[0] != 27)) { |
24130 | 167 int i, len, code; |
168 | |
169 /* First find in the TERMCAP database: */ | |
170 for (i = 0; i < getch2_key_db; i++) { | |
171 if ((len = getch2_keys[i].len) <= getch2_len) | |
172 if(memcmp(getch2_keys[i].chars, getch2_buf, len) == 0) { | |
173 code = getch2_keys[i].code; | |
174 goto found; | |
175 } | |
1 | 176 } |
24130 | 177 /* We always match some keypress here, with length 1 if nothing else. |
178 * Since some of the cases explicitly test remaining buffer length | |
179 * having a keycode only partially read in the buffer could incorrectly | |
180 * use the first byte as an independent character. | |
181 * However the buffer is big enough that this shouldn't happen too | |
182 * easily, and it's been this way for years without many complaints. | |
183 * I see no simple fix as there's no easy test which would tell | |
184 * whether a string must be part of a longer keycode. */ | |
185 len = 1; | |
186 code = getch2_buf[0]; | |
187 /* Check the well-known codes... */ | |
188 if (code != 27) { | |
189 if (code == 'A'-64) code = KEY_HOME; | |
190 else if (code == 'E'-64) code = KEY_END; | |
191 else if (code == 'D'-64) code = KEY_DEL; | |
192 else if (code == 'H'-64) code = KEY_BS; | |
193 else if (code == 'U'-64) code = KEY_PGUP; | |
194 else if (code == 'V'-64) code = KEY_PGDWN; | |
195 else if (code == 8 || code==127) code = KEY_BS; | |
196 else if (code == 10 || code==13) { | |
197 if (getch2_len > 1) { | |
198 int c = getch2_buf[1]; | |
199 if ((c == 10 || c == 13) && (c != code)) | |
200 len = 2; | |
201 } | |
202 code = KEY_ENTER; | |
203 } | |
1 | 204 } |
24130 | 205 else if (getch2_len > 1) { |
206 int c = getch2_buf[1]; | |
207 if (c == 27) { | |
208 code = KEY_ESC; | |
209 len = 2; | |
210 goto found; | |
211 } | |
212 if (c >= '0' && c <= '9') { | |
213 code = c-'0'+KEY_F; | |
214 len = 2; | |
215 goto found; | |
216 } | |
217 if (getch2_len >= 4 && c == '[' && getch2_buf[2] == '[') { | |
218 int c = getch2_buf[3]; | |
219 if (c >= 'A' && c < 'A'+12) { | |
220 code = KEY_F+1 + c-'A'; | |
221 len = 4; | |
222 goto found; | |
223 } | |
224 } | |
24515 | 225 if ((c == '[' || c == 'O') && getch2_len >= 3) { |
24130 | 226 int c = getch2_buf[2]; |
227 const short ctable[] = { | |
228 KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT, 0, | |
229 KEY_END, KEY_PGDWN, KEY_HOME, KEY_PGUP, 0, 0, KEY_INS, 0, 0, 0, | |
230 KEY_F+1, KEY_F+2, KEY_F+3, KEY_F+4}; | |
231 if (c >= 'A' && c <= 'S') | |
232 if (ctable[c - 'A']) { | |
233 code = ctable[c - 'A']; | |
234 len = 3; | |
235 goto found; | |
236 } | |
237 } | |
238 if (getch2_len >= 4 && c == '[' && getch2_buf[3] == '~') { | |
239 int c = getch2_buf[2]; | |
240 const int ctable[8] = {KEY_HOME, KEY_INS, KEY_DEL, KEY_END, KEY_PGUP, KEY_PGDWN, KEY_HOME, KEY_END}; | |
241 if (c >= '1' && c <= '8') { | |
242 code = ctable[c - '1']; | |
243 len = 4; | |
244 goto found; | |
245 } | |
246 } | |
247 if (getch2_len >= 5 && c == '[' && getch2_buf[4] == '~') { | |
248 int i = getch2_buf[2] - '0'; | |
249 int j = getch2_buf[3] - '0'; | |
250 if (i >= 0 && i <= 9 && j >= 0 && j <= 9) { | |
251 const short ftable[20] = { | |
252 11,12,13,14,15, 17,18,19,20,21, | |
253 23,24,25,26,28, 29,31,32,33,34 }; | |
254 int a = i*10 + j; | |
255 for (i = 0; i < 20; i++) | |
256 if (ftable[i] == a) { | |
257 code = KEY_F+1 + i; | |
258 len = 5; | |
259 goto found; | |
260 } | |
261 } | |
262 } | |
1 | 263 } |
24130 | 264 found: |
265 getch2_len -= len; | |
266 for (i = 0; i < getch2_len; i++) | |
267 getch2_buf[i] = getch2_buf[len+i]; | |
268 mplayer_put_key(code); | |
24129 | 269 } |
1 | 270 } |
271 | |
1632 | 272 static int getch2_status=0; |
273 | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17264
diff
changeset
|
274 void getch2_enable(void){ |
3009 | 275 #ifdef HAVE_TERMIOS |
1 | 276 struct termios tio_new; |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
958
diff
changeset
|
277 tcgetattr(0,&tio_orig); |
1 | 278 tio_new=tio_orig; |
279 tio_new.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */ | |
280 tio_new.c_cc[VMIN] = 1; | |
281 tio_new.c_cc[VTIME] = 0; | |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
958
diff
changeset
|
282 tcsetattr(0,TCSANOW,&tio_new); |
3009 | 283 #endif |
1632 | 284 getch2_status=1; |
1 | 285 } |
286 | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
17264
diff
changeset
|
287 void getch2_disable(void){ |
1632 | 288 if(!getch2_status) return; // already disabled / never enabled |
3009 | 289 #ifdef HAVE_TERMIOS |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
958
diff
changeset
|
290 tcsetattr(0,TCSANOW,&tio_orig); |
3009 | 291 #endif |
1632 | 292 getch2_status=0; |
1 | 293 } |
294 | |
27393 | 295 #ifdef CONFIG_ICONV |
22886 | 296 char* get_term_charset(void) |
22442
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
297 { |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
298 char* charset = NULL; |
27359
d788e177a35e
Rename some preprocessor directives from CONFIG_* to HAVE_* where appropriate;
diego
parents:
27341
diff
changeset
|
299 #ifdef HAVE_LANGINFO |
22442
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
300 setlocale(LC_CTYPE, ""); |
29290
ef46d5a66bb2
Use a malloced string for the get_term_charset return value.
reimar
parents:
28744
diff
changeset
|
301 charset = strdup(nl_langinfo(CODESET)); |
22442
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
302 setlocale(LC_CTYPE, "C"); |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
303 #endif |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
304 return charset; |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
305 } |
56a0b0f8a66e
Add code to detect and convert to console codepage on Windows.
reimar
parents:
21589
diff
changeset
|
306 #endif |