diff options
| author | Kim F. Storm | 1995-10-11 15:08:15 +0000 |
|---|---|---|
| committer | Kim F. Storm | 1995-10-11 15:08:15 +0000 |
| commit | f32d40914e7908e043320e7b61dc4f0c9694b113 (patch) | |
| tree | 8aaf58f9fd4b466c295d9a58f93493fa5a29fee4 /src | |
| parent | 8a7b1700250a55f5dfba553cfbb60f29bed66818 (diff) | |
| download | emacs-f32d40914e7908e043320e7b61dc4f0c9694b113.tar.gz emacs-f32d40914e7908e043320e7b61dc4f0c9694b113.zip | |
[!HAVE_X_WINDOWS]:
Reworked display code to perform immediate screen output.
Added menu-bar clock.
Reworked keyboard code to support international keyboards.
Improved keypad handling (see dos-keypad-mode).
Properly distinguish between C-end and C-kp-1 etc.
Corrected M-return & M-kp-enter.
Added support for hyper and super keys.
Reworked mouse code to avoid mouse flicker.
Saves and restores DOS-screen prior to emacs startup.
(sys_select): Would abort if rfds = NULL.
(dos_direct_output): New function.
(dos_dump_scancodes): New variable.
Diffstat (limited to 'src')
| -rw-r--r-- | src/msdos.c | 2993 |
1 files changed, 1698 insertions, 1295 deletions
diff --git a/src/msdos.c b/src/msdos.c index a72e59a315a..cf064306cec 100644 --- a/src/msdos.c +++ b/src/msdos.c | |||
| @@ -18,6 +18,7 @@ along with GNU Emacs; see the file COPYING. If not, write to | |||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
| 19 | 19 | ||
| 20 | /* Contributed by Morten Welinder */ | 20 | /* Contributed by Morten Welinder */ |
| 21 | /* New display, keyboard, and mouse control by Kim F. Storm */ | ||
| 21 | 22 | ||
| 22 | /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */ | 23 | /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */ |
| 23 | 24 | ||
| @@ -45,850 +46,242 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 45 | /* Damn that local process.h! Instead we can define P_WAIT ourselves. */ | 46 | /* Damn that local process.h! Instead we can define P_WAIT ourselves. */ |
| 46 | #define P_WAIT 1 | 47 | #define P_WAIT 1 |
| 47 | 48 | ||
| 48 | static int break_stat; /* BREAK check mode status. */ | ||
| 49 | static int stdin_stat; /* stdin IOCTL status. */ | ||
| 50 | static int extended_kbd; /* 101 (102) keyboard present. */ | ||
| 51 | |||
| 52 | int have_mouse; /* Mouse present? */ | ||
| 53 | static int mouse_last_x; | ||
| 54 | static int mouse_last_y; | ||
| 55 | |||
| 56 | #define DO_TERMSCRIPT /* define if you want open-termscript to work on msdos */ | ||
| 57 | |||
| 58 | /* Standard putchar may call _flsbuf which doesn't go through | ||
| 59 | fflush's overlayed internal_flush routine. */ | ||
| 60 | #undef putchar | ||
| 61 | #define putchar(x) \ | ||
| 62 | (--(stdout)->_cnt>=0? \ | ||
| 63 | ((int)((unsigned char)((*(stdout)->_ptr++=(unsigned)(x))))): \ | ||
| 64 | (internal_flush (stdout), --(stdout)->_cnt, *(stdout)->_ptr++=(unsigned)(x))) | ||
| 65 | |||
| 66 | static void | ||
| 67 | mouse_get_xy (int *x, int *y); | ||
| 68 | |||
| 69 | /* Turn off Dos' Ctrl-C checking and inhibit interpretation of control chars | ||
| 70 | by Dos. Determine the keyboard type. */ | ||
| 71 | int | ||
| 72 | dos_ttraw () | ||
| 73 | { | ||
| 74 | union REGS inregs, outregs; | ||
| 75 | static int only_once = 1; | ||
| 76 | |||
| 77 | if (only_once) { | ||
| 78 | inregs.h.ah = 0xc0; | ||
| 79 | int86 (0x15, &inregs, &outregs); | ||
| 80 | extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0); | ||
| 81 | } | ||
| 82 | |||
| 83 | break_stat = getcbrk (); | ||
| 84 | setcbrk (0); | ||
| 85 | install_ctrl_break_check (); | ||
| 86 | |||
| 87 | if (only_once) | ||
| 88 | have_mouse = mouse_init1 (); | ||
| 89 | |||
| 90 | inregs.x.ax = 0x4400; /* Get IOCTL status. */ | ||
| 91 | inregs.x.bx = 0x00; /* 0 = stdin. */ | ||
| 92 | intdos (&inregs, &outregs); | ||
| 93 | stdin_stat = outregs.h.dl; | ||
| 94 | |||
| 95 | only_once = 0; | ||
| 96 | |||
| 97 | inregs.x.dx = stdin_stat | 0x0020; /* raw mode */ | ||
| 98 | inregs.x.ax = 0x4401; /* Set IOCTL status */ | ||
| 99 | intdos (&inregs, &outregs); | ||
| 100 | return !outregs.x.cflag; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* Restore status of standard input and Ctrl-C checking. */ | ||
| 104 | int | ||
| 105 | dos_ttcooked () | ||
| 106 | { | ||
| 107 | union REGS inregs, outregs; | ||
| 108 | |||
| 109 | setcbrk (break_stat); | ||
| 110 | mouse_off (); | ||
| 111 | |||
| 112 | inregs.x.ax = 0x4401; /* Set IOCTL status. */ | ||
| 113 | inregs.x.bx = 0x00; /* 0 = stdin. */ | ||
| 114 | inregs.x.dx = stdin_stat; | ||
| 115 | intdos (&inregs, &outregs); | ||
| 116 | return !outregs.x.cflag; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* generate a reliable event timestamp, KFS 1995-07-06 */ | ||
| 120 | 49 | ||
| 121 | static unsigned long | 50 | static unsigned long |
| 122 | event_timestamp () | 51 | event_timestamp () |
| 123 | { | 52 | { |
| 124 | struct time t; | 53 | struct time t; |
| 125 | unsigned long s; | 54 | unsigned long s; |
| 126 | 55 | ||
| 127 | gettime (&t); | 56 | gettime (&t); |
| 128 | s = t.ti_min; | 57 | s = t.ti_min; |
| 129 | s *= 60; | 58 | s *= 60; |
| 130 | s += t.ti_sec; | 59 | s += t.ti_sec; |
| 131 | s *= 1000; | 60 | s *= 1000; |
| 132 | s += t.ti_hund * 10; | 61 | s += t.ti_hund * 10; |
| 133 | 62 | ||
| 134 | return s; | 63 | return s; |
| 135 | } | 64 | } |
| 136 | 65 | ||
| 137 | static unsigned short | 66 | |
| 138 | ibmpc_translate_map[] = | 67 | /* ------------------------ Mouse control --------------------------- |
| 139 | { | 68 | * |
| 140 | /* --------------- 00 to 0f --------------- */ | 69 | * Coordinates are in screen positions and zero based. |
| 141 | 0, /* Ctrl Break */ | 70 | * Mouse buttons are numbered from left to right and also zero based. |
| 142 | 0xff1b, /* Escape */ | 71 | */ |
| 143 | 0xffb1, /* Keypad 1 */ | ||
| 144 | 0xffb2, /* Keypad 2 */ | ||
| 145 | 0xffb3, /* Keypad 3 */ | ||
| 146 | 0xffb4, /* Keypad 4 */ | ||
| 147 | 0xffb5, /* Keypad 5 */ | ||
| 148 | 0xffb6, /* Keypad 6 */ | ||
| 149 | 0xffb7, /* Keypad 7 */ | ||
| 150 | 0xffb8, /* Keypad 8 */ | ||
| 151 | 0xffb9, /* Keypad 9 */ | ||
| 152 | 0xffb0, /* Keypad 0 */ | ||
| 153 | '-', '=', | ||
| 154 | 0xff08, /* Backspace */ | ||
| 155 | 0xff74, /* (Shift) Tab [Tab doesn't use this table] */ | ||
| 156 | |||
| 157 | /* --------------- 10 to 1f --------------- */ | ||
| 158 | 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', | ||
| 159 | 0xff8d, /* Keypad Enter */ | ||
| 160 | 0, /* Ctrl */ | ||
| 161 | 'a', 's', | ||
| 162 | |||
| 163 | /* --------------- 20 to 2f --------------- */ | ||
| 164 | 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', | ||
| 165 | 0, /* Left shift */ | ||
| 166 | '\\', 'z', 'x', 'c', 'v', | ||
| 167 | |||
| 168 | /* --------------- 30 to 3f --------------- */ | ||
| 169 | 'b', 'n', 'm', ',', '.', | ||
| 170 | 0xffaf, /* Grey / */ | ||
| 171 | 0, /* Right shift */ | ||
| 172 | 0xffaa, /* Grey * */ | ||
| 173 | 0, /* Alt */ | ||
| 174 | ' ', | ||
| 175 | 0, /* Caps Lock */ | ||
| 176 | 0xffbe, /* F1 */ | ||
| 177 | 0xffbf, /* F2 */ | ||
| 178 | 0xffc0, /* F3 */ | ||
| 179 | 0xffc1, /* F4 */ | ||
| 180 | 0xffc2, /* F5 */ | ||
| 181 | |||
| 182 | /* --------------- 40 to 4f --------------- */ | ||
| 183 | 0xffc3, /* F6 */ | ||
| 184 | 0xffc4, /* F7 */ | ||
| 185 | 0xffc5, /* F8 */ | ||
| 186 | 0xffc6, /* F9 */ | ||
| 187 | 0xffc7, /* F10 */ | ||
| 188 | 0, /* Num Lock */ | ||
| 189 | 0, /* Scroll Lock */ | ||
| 190 | 0xff50, /* Home */ | ||
| 191 | 0xff52, /* Up */ | ||
| 192 | 0xff55, /* Page Up */ | ||
| 193 | 0xffad, /* Grey - */ | ||
| 194 | 0xff51, /* Left */ | ||
| 195 | 0xffb5, /* Keypad 5 */ | ||
| 196 | 0xff53, /* Right */ | ||
| 197 | 0xffab, /* Grey + */ | ||
| 198 | 0xff57, /* End */ | ||
| 199 | |||
| 200 | /* --------------- 50 to 5f --------------- */ | ||
| 201 | 0xff54, /* Down */ | ||
| 202 | 0xff56, /* Page Down */ | ||
| 203 | 0xff63, /* Insert */ | ||
| 204 | 0xffff, /* Delete */ | ||
| 205 | 0xffbe, /* (Shift) F1 */ | ||
| 206 | 0xffbf, /* (Shift) F2 */ | ||
| 207 | 0xffc0, /* (Shift) F3 */ | ||
| 208 | 0xffc1, /* (Shift) F4 */ | ||
| 209 | 0xffc2, /* (Shift) F5 */ | ||
| 210 | 0xffc3, /* (Shift) F6 */ | ||
| 211 | 0xffc4, /* (Shift) F7 */ | ||
| 212 | 0xffc5, /* (Shift) F8 */ | ||
| 213 | 0xffc6, /* (Shift) F9 */ | ||
| 214 | 0xffc7, /* (Shift) F10 */ | ||
| 215 | 0xffbe, /* (Ctrl) F1 */ | ||
| 216 | 0xffbf, /* (Ctrl) F2 */ | ||
| 217 | |||
| 218 | /* --------------- 60 to 6f --------------- */ | ||
| 219 | 0xffc0, /* (Ctrl) F3 */ | ||
| 220 | 0xffc1, /* (Ctrl) F4 */ | ||
| 221 | 0xffc2, /* (Ctrl) F5 */ | ||
| 222 | 0xffc3, /* (Ctrl) F6 */ | ||
| 223 | 0xffc4, /* (Ctrl) F7 */ | ||
| 224 | 0xffc5, /* (Ctrl) F8 */ | ||
| 225 | 0xffc6, /* (Ctrl) F9 */ | ||
| 226 | 0xffc7, /* (Ctrl) F10 */ | ||
| 227 | 0xffbe, /* (Alt) F1 */ | ||
| 228 | 0xffbf, /* (Alt) F2 */ | ||
| 229 | 0xffc0, /* (Alt) F3 */ | ||
| 230 | 0xffc1, /* (Alt) F4 */ | ||
| 231 | 0xffc2, /* (Alt) F5 */ | ||
| 232 | 0xffc3, /* (Alt) F6 */ | ||
| 233 | 0xffc4, /* (Alt) F7 */ | ||
| 234 | 0xffc5, /* (Alt) F8 */ | ||
| 235 | 72 | ||
| 236 | /* --------------- 70 to 7f --------------- */ | 73 | int have_mouse; /* 0: no, 1: enabled, -1: disabled */ |
| 237 | 0xffc6, /* (Alt) F9 */ | 74 | static int mouse_visible; |
| 238 | 0xffc7, /* (Alt) F10 */ | ||
| 239 | 0xff6d, /* (Ctrl) Sys Rq */ | ||
| 240 | 0xff51, /* (Ctrl) Left */ | ||
| 241 | 0xff53, /* (Ctrl) Right */ | ||
| 242 | 0xff57, /* (Ctrl) End */ | ||
| 243 | 0xff56, /* (Ctrl) Page Down */ | ||
| 244 | 0xff50, /* (Ctrl) Home */ | ||
| 245 | '1', '2', '3', '4', '5', '6', '7', '8', /* (Alt) */ | ||
| 246 | 75 | ||
| 247 | /* --------------- 80 to 8f --------------- */ | 76 | static int mouse_last_x; |
| 248 | '9', '0', '-', '=', /* (Alt) */ | 77 | static int mouse_last_y; |
| 249 | 0xff55, /* (Ctrl) Page Up */ | ||
| 250 | 0xffc8, /* F11 */ | ||
| 251 | 0xffc9, /* F12 */ | ||
| 252 | 0xffc8, /* (Shift) F11 */ | ||
| 253 | 0xffc9, /* (Shift) F12 */ | ||
| 254 | 0xffc8, /* (Ctrl) F11 */ | ||
| 255 | 0xffc9, /* (Ctrl) F12 */ | ||
| 256 | 0xffc8, /* (Alt) F11 */ | ||
| 257 | 0xffc9, /* (Alt) F12 */ | ||
| 258 | 0xff52, /* (Ctrl) Up */ | ||
| 259 | 0xffae, /* (Ctrl) Grey - */ | ||
| 260 | 0xffb5, /* (Ctrl) Keypad 5 */ | ||
| 261 | |||
| 262 | /* --------------- 90 to 9f --------------- */ | ||
| 263 | 0xffab, /* (Ctrl) Grey + */ | ||
| 264 | 0xff54, /* (Ctrl) Down */ | ||
| 265 | 0xff63, /* (Ctrl) Insert */ | ||
| 266 | 0xffff, /* (Ctrl) Delete */ | ||
| 267 | 0xff09, /* (Ctrl) Tab */ | ||
| 268 | 0xffaf, /* (Ctrl) Grey / */ | ||
| 269 | 0xffaa, /* (Ctrl) Grey * */ | ||
| 270 | 0xff50, /* (Alt) Home */ | ||
| 271 | 0xff52, /* (Alt) Up */ | ||
| 272 | 0xff55, /* (Alt) Page Up */ | ||
| 273 | 0, /* NO KEY */ | ||
| 274 | 0xff51, /* (Alt) Left */ | ||
| 275 | 0, /* NO KEY */ | ||
| 276 | 0xff53, /* (Alt) Right */ | ||
| 277 | 0, /* NO KEY */ | ||
| 278 | 0xff57, /* (Alt) End */ | ||
| 279 | 78 | ||
| 280 | /* --------------- a0 to af --------------- */ | 79 | static int mouse_button_translate[NUM_MOUSE_BUTTONS]; |
| 281 | 0xff54, /* (Alt) Down */ | 80 | static int mouse_button_count; |
| 282 | 0xff56, /* (Alt) Page Down */ | ||
| 283 | 0xff63, /* (Alt) Insert */ | ||
| 284 | 0xffff, /* (Alt) Delete */ | ||
| 285 | 0xffaf, /* (Alt) Grey / */ | ||
| 286 | 0xff09, /* (Alt) Tab */ | ||
| 287 | 0xff0d /* (Alt) Enter */ | ||
| 288 | }; | ||
| 289 | 81 | ||
| 290 | /* Get a char from keyboard. Function keys are put into the event queue. */ | 82 | void |
| 291 | static int | 83 | mouse_on () |
| 292 | dos_rawgetc () | ||
| 293 | { | 84 | { |
| 294 | struct input_event event; | ||
| 295 | union REGS regs; | 85 | union REGS regs; |
| 296 | int ctrl_p, alt_p, shift_p; | ||
| 297 | |||
| 298 | /* Calculate modifier bits */ | ||
| 299 | regs.h.ah = extended_kbd ? 0x12 : 0x02; | ||
| 300 | int86 (0x16, ®s, ®s); | ||
| 301 | ctrl_p = ((regs.h.al & 4) != 0); | ||
| 302 | shift_p = ((regs.h.al & 3) != 0); | ||
| 303 | /* Please be very careful here not to break international keyboard support. | ||
| 304 | When Keyb.Com is loaded, the key marked `Alt Gr' is used for accessing | ||
| 305 | characters like { and } if their positions are overlaid. */ | ||
| 306 | alt_p = ((extended_kbd ? (regs.h.ah & 2) : (regs.h.al & 8)) != 0); | ||
| 307 | |||
| 308 | /* The following condition is equivalent to `kbhit ()', except that | ||
| 309 | it uses the bios to do its job. This pleases DESQview/X. */ | ||
| 310 | while ((regs.h.ah = extended_kbd ? 0x11 : 0x01), | ||
| 311 | int86 (0x16, ®s, ®s), | ||
| 312 | (regs.x.flags & 0x40) == 0) | ||
| 313 | { | ||
| 314 | union REGS regs; | ||
| 315 | register unsigned char c; | ||
| 316 | int sc, code; | ||
| 317 | |||
| 318 | regs.h.ah = extended_kbd ? 0x10 : 0x00; | ||
| 319 | int86 (0x16, ®s, ®s); | ||
| 320 | c = regs.h.al; | ||
| 321 | sc = regs.h.ah; | ||
| 322 | |||
| 323 | /* Determine from the scan code if a keypad key was pressed. */ | ||
| 324 | if (c >= '0' && c <= '9' && sc > 0xb) | ||
| 325 | sc = (c == '0') ? 0xb : (c - '0' + 1), c = 0; | ||
| 326 | else if (sc == 0x53 && c != 0xe0) | ||
| 327 | { | ||
| 328 | code = 0xffae; /* Keypad decimal point/comma. */ | ||
| 329 | goto nonascii; | ||
| 330 | } | ||
| 331 | else if (sc == 0xe0) | ||
| 332 | { | ||
| 333 | switch (c) | ||
| 334 | { | ||
| 335 | case 10: /* Ctrl Enter */ | ||
| 336 | case 13: | ||
| 337 | sc = 0x1c; | ||
| 338 | break; | ||
| 339 | case '/': | ||
| 340 | sc = 0x35; | ||
| 341 | break; | ||
| 342 | default: | ||
| 343 | sc = 0; | ||
| 344 | }; | ||
| 345 | c = 0; | ||
| 346 | } | ||
| 347 | 86 | ||
| 348 | if (c == 0 | 87 | if (have_mouse > 0 && !mouse_visible) |
| 349 | || c == ' ' | ||
| 350 | || alt_p | ||
| 351 | || (ctrl_p && shift_p) | ||
| 352 | || (c == 0xe0 && sc != 0) /* Pseudo-key */ | ||
| 353 | || sc == 0x37 /* Grey * */ | ||
| 354 | || sc == 0x4a /* Grey - */ | ||
| 355 | || sc == 0x4e /* Grey + */ | ||
| 356 | || sc == 0x0e) /* Back space *key*, not Ctrl-h */ | ||
| 357 | { | ||
| 358 | if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short))) | ||
| 359 | code = 0; | ||
| 360 | else | ||
| 361 | code = ibmpc_translate_map[sc]; | ||
| 362 | if (code != 0) | ||
| 363 | { | ||
| 364 | if (code >= 0x100) | ||
| 365 | { | ||
| 366 | nonascii: | ||
| 367 | event.kind = non_ascii_keystroke; | ||
| 368 | event.code = (code & 0xff) + 0xff00; | ||
| 369 | } | ||
| 370 | else | ||
| 371 | { | ||
| 372 | /* Don't return S- if we don't have to. `shifted' is | ||
| 373 | supposed to be the shifted versions of the characters | ||
| 374 | in `unshifted'. Unfortunately, this is only true for | ||
| 375 | US keyboard layout. If anyone knows how to do this | ||
| 376 | right, please tell us. */ | ||
| 377 | static char *unshifted | ||
| 378 | = "abcdefghijklmnopqrstuvwxyz,./=;[\\]'-`0123456789"; | ||
| 379 | static char *shifted | ||
| 380 | = "ABCDEFGHIJKLMNOPQRSTUVWXYZ<>?+:{|}\"_~)!@#$%^&*("; | ||
| 381 | char *pos; | ||
| 382 | |||
| 383 | if (shift_p && (pos = strchr (unshifted, code))) | ||
| 384 | { | ||
| 385 | c = shifted[pos - unshifted]; | ||
| 386 | shift_p = 0; | ||
| 387 | } | ||
| 388 | else | ||
| 389 | if (c == 0) c = code; | ||
| 390 | event.kind = ascii_keystroke; | ||
| 391 | event.code = c; | ||
| 392 | } | ||
| 393 | event.modifiers | ||
| 394 | = (shift_p ? shift_modifier : 0) | ||
| 395 | + (ctrl_p ? ctrl_modifier : 0) | ||
| 396 | + (alt_p ? meta_modifier : 0); | ||
| 397 | /* EMACS == Enter Meta Alt Control Shift */ | ||
| 398 | XSETFRAME (event.frame_or_window, selected_frame); | ||
| 399 | event.timestamp = event_timestamp (); | ||
| 400 | kbd_buffer_store_event (&event); | ||
| 401 | } | ||
| 402 | } else | ||
| 403 | return c; | ||
| 404 | } | ||
| 405 | |||
| 406 | if (have_mouse > 0) | ||
| 407 | { | 88 | { |
| 408 | int but, press, x, y, ok; | 89 | if (termscript) |
| 409 | 90 | fprintf (termscript, "<M_ON>"); | |
| 410 | /* Check for mouse movement *before* buttons. */ | 91 | regs.x.ax = 0x0001; |
| 411 | mouse_check_moved (); | 92 | int86 (0x33, ®s, ®s); |
| 412 | 93 | mouse_visible = 1; | |
| 413 | for (but = 0; but < NUM_MOUSE_BUTTONS; but++) | ||
| 414 | for (press = 0; press < 2; press++) | ||
| 415 | { | ||
| 416 | if (press) | ||
| 417 | ok = mouse_pressed (but, &x, &y); | ||
| 418 | else | ||
| 419 | ok = mouse_released (but, &x, &y); | ||
| 420 | if (ok) | ||
| 421 | { | ||
| 422 | event.kind = mouse_click; | ||
| 423 | event.code = but; | ||
| 424 | event.modifiers | ||
| 425 | = (shift_p ? shift_modifier : 0) | ||
| 426 | + (ctrl_p ? ctrl_modifier : 0) | ||
| 427 | + (alt_p ? meta_modifier : 0) | ||
| 428 | + (press ? down_modifier : up_modifier); | ||
| 429 | event.x = x; | ||
| 430 | event.y = y; | ||
| 431 | XSETFRAME (event.frame_or_window, selected_frame); | ||
| 432 | event.timestamp = event_timestamp (); | ||
| 433 | kbd_buffer_store_event (&event); | ||
| 434 | } | ||
| 435 | } | ||
| 436 | } | 94 | } |
| 437 | |||
| 438 | return -1; | ||
| 439 | } | 95 | } |
| 440 | 96 | ||
| 441 | static int prev_get_char = -1; | 97 | void |
| 442 | 98 | mouse_off () | |
| 443 | /* Return 1 if a key is ready to be read without suspending execution. */ | ||
| 444 | dos_keysns () | ||
| 445 | { | 99 | { |
| 446 | if (prev_get_char != -1) | 100 | union REGS regs; |
| 447 | return 1; | ||
| 448 | else | ||
| 449 | return ((prev_get_char = dos_rawgetc ()) != -1); | ||
| 450 | } | ||
| 451 | 101 | ||
| 452 | /* Read a key. Return -1 if no key is ready. */ | 102 | if (have_mouse > 0 && mouse_visible) |
| 453 | dos_keyread () | ||
| 454 | { | ||
| 455 | if (prev_get_char != -1) | ||
| 456 | { | 103 | { |
| 457 | int c = prev_get_char; | 104 | if (termscript) |
| 458 | prev_get_char = -1; | 105 | fprintf (termscript, "<M_OFF>"); |
| 459 | return c; | 106 | regs.x.ax = 0x0002; |
| 107 | int86 (0x33, ®s, ®s); | ||
| 108 | mouse_visible = 0; | ||
| 460 | } | 109 | } |
| 461 | else | ||
| 462 | return dos_rawgetc (); | ||
| 463 | } | 110 | } |
| 464 | 111 | ||
| 465 | /* Hostnames for a pc are not really funny, but they are used in change log | 112 | void |
| 466 | so we emulate the best we can. */ | 113 | mouse_moveto (x, y) |
| 467 | gethostname (p, size) | 114 | int x, y; |
| 468 | char *p; | ||
| 469 | int size; | ||
| 470 | { | 115 | { |
| 471 | char *q = egetenv ("HOSTNAME"); | 116 | union REGS regs; |
| 472 | 117 | ||
| 473 | if (!q) q = "pc"; | 118 | if (termscript) |
| 474 | strcpy (p, q); | 119 | fprintf (termscript, "<M_XY=%dx%d>", x, y); |
| 475 | return 0; | 120 | regs.x.ax = 0x0004; |
| 121 | mouse_last_x = regs.x.cx = x * 8; | ||
| 122 | mouse_last_y = regs.x.dx = y * 8; | ||
| 123 | int86 (0x33, ®s, ®s); | ||
| 476 | } | 124 | } |
| 477 | 125 | ||
| 478 | /* Destructively turn backslashes into slashes. */ | 126 | static int |
| 479 | void | 127 | mouse_pressed (b, xp, yp) |
| 480 | dostounix_filename (p) | 128 | int b, *xp, *yp; |
| 481 | register char *p; | ||
| 482 | { | 129 | { |
| 483 | while (*p) | 130 | union REGS regs; |
| 484 | { | ||
| 485 | if (*p == '\\') | ||
| 486 | *p = '/'; | ||
| 487 | p++; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | 131 | ||
| 491 | /* Destructively turn slashes into backslashes. */ | 132 | if (b >= mouse_button_count) |
| 492 | void | 133 | return 0; |
| 493 | unixtodos_filename (p) | 134 | regs.x.ax = 0x0005; |
| 494 | register char *p; | 135 | regs.x.bx = mouse_button_translate[b]; |
| 495 | { | 136 | int86 (0x33, ®s, ®s); |
| 496 | while (*p) | 137 | if (regs.x.bx) |
| 497 | { | 138 | *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; |
| 498 | if (*p == '/') | 139 | return (regs.x.bx != 0); |
| 499 | *p = '\\'; | ||
| 500 | p++; | ||
| 501 | } | ||
| 502 | } | 140 | } |
| 503 | 141 | ||
| 504 | /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */ | 142 | static int |
| 505 | int | 143 | mouse_released (b, xp, yp) |
| 506 | getdefdir (drive, dst) | 144 | int b, *xp, *yp; |
| 507 | int drive; | ||
| 508 | char *dst; | ||
| 509 | { | 145 | { |
| 510 | union REGS regs; | 146 | union REGS regs; |
| 511 | 147 | ||
| 512 | *dst++ = '/'; | 148 | if (b >= mouse_button_count) |
| 513 | regs.h.dl = drive; | 149 | return 0; |
| 514 | regs.x.si = (int) dst; | 150 | regs.x.ax = 0x0006; |
| 515 | regs.h.ah = 0x47; | 151 | regs.x.bx = mouse_button_translate[b]; |
| 516 | intdos (®s, ®s); | 152 | int86 (0x33, ®s, ®s); |
| 517 | return !regs.x.cflag; | 153 | if (regs.x.bx) |
| 154 | *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; | ||
| 155 | return (regs.x.bx != 0); | ||
| 518 | } | 156 | } |
| 519 | 157 | ||
| 520 | /* Remove all CR's that are followed by a LF. */ | 158 | static void |
| 521 | int | 159 | mouse_get_xy (int *x, int *y) |
| 522 | crlf_to_lf (n, buf) | ||
| 523 | register int n; | ||
| 524 | register unsigned char *buf; | ||
| 525 | { | 160 | { |
| 526 | unsigned char *np = buf; | 161 | union REGS regs; |
| 527 | unsigned char *startp = buf; | ||
| 528 | unsigned char *endp = buf + n; | ||
| 529 | unsigned char c; | ||
| 530 | 162 | ||
| 531 | if (n == 0) | 163 | regs.x.ax = 0x0003; |
| 532 | return n; | 164 | int86 (0x33, ®s, ®s); |
| 533 | while (buf < endp - 1) | 165 | *x = regs.x.cx / 8; |
| 534 | { | 166 | *y = regs.x.dx / 8; |
| 535 | if (*buf == 0x0d) | ||
| 536 | { | ||
| 537 | if (*(++buf) != 0x0a) | ||
| 538 | *np++ = 0x0d; | ||
| 539 | } | ||
| 540 | else | ||
| 541 | *np++ = *buf++; | ||
| 542 | } | ||
| 543 | if (buf < endp) | ||
| 544 | *np++ = *buf++; | ||
| 545 | return np - startp; | ||
| 546 | } | 167 | } |
| 547 | 168 | ||
| 548 | 169 | void | |
| 549 | /* Run command as specified by ARGV in directory DIR. | 170 | mouse_get_pos (f, insist, bar_window, part, x, y, time) |
| 550 | The command is run with input from TEMPIN and output to file TEMPOUT. */ | 171 | FRAME_PTR *f; |
| 551 | int | 172 | int insist; |
| 552 | run_msdos_command (argv, dir, tempin, tempout) | 173 | Lisp_Object *bar_window, *x, *y; |
| 553 | unsigned char **argv; | 174 | enum scroll_bar_part *part; |
| 554 | Lisp_Object dir; | 175 | unsigned long *time; |
| 555 | int tempin, tempout; | ||
| 556 | { | 176 | { |
| 557 | char *saveargv1, *saveargv2, **envv; | 177 | int ix, iy; |
| 558 | char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ | 178 | union REGS regs; |
| 559 | int msshell, result = -1; | ||
| 560 | int in, out, inbak, outbak, errbak; | ||
| 561 | int x, y; | ||
| 562 | Lisp_Object cmd; | ||
| 563 | |||
| 564 | /* Get current directory as MSDOS cwd is not per-process. */ | ||
| 565 | getwd (oldwd); | ||
| 566 | |||
| 567 | cmd = Ffile_name_nondirectory (build_string (argv[0])); | ||
| 568 | msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells")))) | ||
| 569 | && !strcmp ("-c", argv[1]); | ||
| 570 | if (msshell) | ||
| 571 | { | ||
| 572 | saveargv1 = argv[1]; | ||
| 573 | saveargv2 = argv[2]; | ||
| 574 | argv[1] = "/c"; | ||
| 575 | if (argv[2]) | ||
| 576 | { | ||
| 577 | char *p = alloca (strlen (argv[2]) + 1); | ||
| 578 | |||
| 579 | strcpy (argv[2] = p, saveargv2); | ||
| 580 | while (*p && isspace (*p)) | ||
| 581 | p++; | ||
| 582 | while (*p && !isspace (*p)) | ||
| 583 | if (*p == '/') | ||
| 584 | *p++ = '\\'; | ||
| 585 | else | ||
| 586 | p++; | ||
| 587 | } | ||
| 588 | } | ||
| 589 | |||
| 590 | /* Build the environment array. */ | ||
| 591 | { | ||
| 592 | extern Lisp_Object Vprocess_environment; | ||
| 593 | Lisp_Object tmp, lst; | ||
| 594 | int i, len; | ||
| 595 | |||
| 596 | lst = Vprocess_environment; | ||
| 597 | len = XFASTINT (Flength (lst)); | ||
| 598 | |||
| 599 | envv = alloca ((len + 1) * sizeof (char *)); | ||
| 600 | for (i = 0; i < len; i++) | ||
| 601 | { | ||
| 602 | tmp = Fcar (lst); | ||
| 603 | lst = Fcdr (lst); | ||
| 604 | CHECK_STRING (tmp, 0); | ||
| 605 | envv[i] = alloca (XSTRING (tmp)->size + 1); | ||
| 606 | strcpy (envv[i], XSTRING (tmp)->data); | ||
| 607 | } | ||
| 608 | envv[len] = (char *) 0; | ||
| 609 | } | ||
| 610 | |||
| 611 | if (STRINGP (dir)) | ||
| 612 | chdir (XSTRING (dir)->data); | ||
| 613 | inbak = dup (0); | ||
| 614 | outbak = dup (1); | ||
| 615 | errbak = dup (2); | ||
| 616 | if (inbak < 0 || outbak < 0 || errbak < 0) | ||
| 617 | goto done; /* Allocation might fail due to lack of descriptors. */ | ||
| 618 | |||
| 619 | if (have_mouse > 0) | ||
| 620 | { | ||
| 621 | mouse_get_xy (&x, &y); | ||
| 622 | mouse_off (); | ||
| 623 | } | ||
| 624 | dos_ttcooked(); /* do it here while 0 = stdin */ | ||
| 625 | |||
| 626 | dup2 (tempin, 0); | ||
| 627 | dup2 (tempout, 1); | ||
| 628 | dup2 (tempout, 2); | ||
| 629 | |||
| 630 | result = spawnve (P_WAIT, argv[0], argv, envv); | ||
| 631 | |||
| 632 | dup2 (inbak, 0); | ||
| 633 | dup2 (outbak, 1); | ||
| 634 | dup2 (errbak, 2); | ||
| 635 | close (inbak); | ||
| 636 | close (outbak); | ||
| 637 | close (errbak); | ||
| 638 | 179 | ||
| 639 | dos_ttraw(); | 180 | regs.x.ax = 0x0003; |
| 640 | if (have_mouse > 0) { | 181 | int86 (0x33, ®s, ®s); |
| 641 | mouse_init (); | 182 | *f = selected_frame; |
| 642 | mouse_moveto (x, y); | 183 | *bar_window = Qnil; |
| 643 | } | 184 | mouse_get_xy (&ix, &iy); |
| 644 | 185 | selected_frame->mouse_moved = 0; | |
| 645 | done: | 186 | *x = make_number (ix); |
| 646 | chdir (oldwd); | 187 | *y = make_number (iy); |
| 647 | if (msshell) | 188 | *time = event_timestamp (); |
| 648 | { | ||
| 649 | argv[1] = saveargv1; | ||
| 650 | argv[2] = saveargv2; | ||
| 651 | } | ||
| 652 | return result; | ||
| 653 | } | 189 | } |
| 654 | 190 | ||
| 655 | 191 | static void | |
| 656 | croak (badfunc) | 192 | mouse_check_moved () |
| 657 | char *badfunc; | ||
| 658 | { | 193 | { |
| 659 | fprintf (stderr, "%s not yet implemented\r\n", badfunc); | 194 | int x, y; |
| 660 | reset_sys_modes (); | ||
| 661 | exit (1); | ||
| 662 | } | ||
| 663 | |||
| 664 | /* A list of unimplemented functions that we silently ignore. */ | ||
| 665 | unsigned alarm (s) unsigned s; {} | ||
| 666 | fork () { return 0; } | ||
| 667 | int kill (x, y) int x, y; { return -1; } | ||
| 668 | nice (p) int p; {} | ||
| 669 | void volatile pause () {} | ||
| 670 | request_sigio () {} | ||
| 671 | setpgrp () {return 0; } | ||
| 672 | setpriority (x,y,z) int x,y,z; { return 0; } | ||
| 673 | sigsetmask (x) int x; { return 0; } | ||
| 674 | unrequest_sigio () {} | ||
| 675 | 195 | ||
| 676 | #ifdef chdir | 196 | mouse_get_xy (&x, &y); |
| 677 | #undef chdir | 197 | selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y); |
| 678 | #endif | 198 | mouse_last_x = x; |
| 199 | mouse_last_y = y; | ||
| 200 | } | ||
| 679 | 201 | ||
| 680 | int | 202 | void |
| 681 | sys_chdir (path) | 203 | mouse_init () |
| 682 | const char* path; | ||
| 683 | { | 204 | { |
| 684 | int len = strlen (path); | 205 | union REGS regs; |
| 685 | char *tmp = (char *)path; | ||
| 686 | /* Gotta do this extern here due to the corresponding #define: */ | ||
| 687 | extern int chdir (); | ||
| 688 | |||
| 689 | if (*tmp && tmp[1] == ':') | ||
| 690 | { | ||
| 691 | if (getdisk () != tolower (tmp[0]) - 'a') | ||
| 692 | setdisk (tolower (tmp[0]) - 'a'); | ||
| 693 | tmp += 2; /* strip drive: KFS 1995-07-06 */ | ||
| 694 | len -= 2; | ||
| 695 | } | ||
| 696 | |||
| 697 | if (len > 1 && (tmp[len - 1] == '/')) | ||
| 698 | { | ||
| 699 | char *tmp1 = (char *) alloca (len + 1); | ||
| 700 | strcpy (tmp1, tmp); | ||
| 701 | tmp1[len - 1] = 0; | ||
| 702 | tmp = tmp1; | ||
| 703 | } | ||
| 704 | return chdir (tmp); | ||
| 705 | } | ||
| 706 | 206 | ||
| 707 | #ifndef HAVE_SELECT | 207 | if (termscript) |
| 708 | #include "sysselect.h" | 208 | fprintf (termscript, "<M_INIT>"); |
| 709 | 209 | ||
| 710 | /* Only event queue is checked. */ | 210 | regs.x.ax = 0x0021; |
| 711 | int | 211 | int86 (0x33, ®s, ®s); |
| 712 | sys_select (nfds, rfds, wfds, efds, timeout) | ||
| 713 | int nfds; | ||
| 714 | SELECT_TYPE *rfds, *wfds, *efds; | ||
| 715 | EMACS_TIME *timeout; | ||
| 716 | { | ||
| 717 | SELECT_TYPE orfds; | ||
| 718 | long timeoutval, clnow, cllast; | ||
| 719 | struct time t; | ||
| 720 | 212 | ||
| 721 | FD_ZERO (&orfds); | 213 | regs.x.ax = 0x0007; |
| 722 | if (rfds) | 214 | regs.x.cx = 0; |
| 723 | { | 215 | regs.x.dx = 8 * (ScreenCols () - 1); |
| 724 | orfds = *rfds; | 216 | int86 (0x33, ®s, ®s); |
| 725 | FD_ZERO (rfds); | ||
| 726 | } | ||
| 727 | if (wfds) | ||
| 728 | FD_ZERO (wfds); | ||
| 729 | if (efds) | ||
| 730 | FD_ZERO (efds); | ||
| 731 | 217 | ||
| 732 | if (nfds != 1 || !FD_ISSET (0, &orfds)) | 218 | regs.x.ax = 0x0008; |
| 733 | abort (); | 219 | regs.x.cx = 0; |
| 734 | 220 | regs.x.dx = 8 * (ScreenRows () - 1); | |
| 735 | /* If we are looking only for the terminal, with no timeout, | 221 | int86 (0x33, ®s, ®s); |
| 736 | just read it and wait -- that's more efficient. */ | ||
| 737 | if (!timeout) | ||
| 738 | { | ||
| 739 | while (! detect_input_pending ()); | ||
| 740 | } | ||
| 741 | else | ||
| 742 | { | ||
| 743 | timeoutval = EMACS_SECS (*timeout) * 100 + EMACS_USECS (*timeout) / 10000; | ||
| 744 | gettime (&t); | ||
| 745 | cllast = t.ti_sec * 100 + t.ti_hund; | ||
| 746 | 222 | ||
| 747 | while (!detect_input_pending ()) | 223 | mouse_moveto (0, 0); |
| 748 | { | 224 | mouse_visible = 0; |
| 749 | gettime (&t); | ||
| 750 | clnow = t.ti_sec * 100 + t.ti_hund; | ||
| 751 | if (clnow < cllast) /* time wrap */ | ||
| 752 | timeoutval -= clnow + 6000 - cllast; | ||
| 753 | else | ||
| 754 | timeoutval -= clnow - cllast; | ||
| 755 | if (timeoutval <= 0) /* Stop on timer being cleared */ | ||
| 756 | return 0; | ||
| 757 | cllast = clnow; | ||
| 758 | } | ||
| 759 | } | ||
| 760 | |||
| 761 | FD_SET (0, rfds); | ||
| 762 | return 1; | ||
| 763 | } | 225 | } |
| 764 | #endif | ||
| 765 | 226 | ||
| 766 | /* The Emacs root directory as determined by init_environment. */ | 227 | /* ------------------------- Screen control ---------------------- |
| 767 | static char emacsroot[MAXPATHLEN]; | 228 | * |
| 229 | */ | ||
| 768 | 230 | ||
| 769 | char * | 231 | static int internal_terminal = 0; |
| 770 | rootrelativepath (rel) | ||
| 771 | char *rel; | ||
| 772 | { | ||
| 773 | static char result[MAXPATHLEN + 10]; | ||
| 774 | 232 | ||
| 775 | strcpy (result, emacsroot); | 233 | #ifndef HAVE_X_WINDOWS |
| 776 | strcat (result, "/"); | 234 | extern unsigned char ScreenAttrib; |
| 777 | strcat (result, rel); | 235 | static int screen_face; |
| 778 | return result; | 236 | static int highlight; |
| 779 | } | ||
| 780 | 237 | ||
| 781 | /* Define a lot of environment variables if not already defined. Don't | 238 | static int screen_size_X; |
| 782 | remove anything unless you know what you're doing -- lots of code will | 239 | static int screen_size_Y; |
| 783 | break if one or more of these are missing. */ | 240 | static int screen_size; |
| 784 | void | ||
| 785 | init_environment (argc, argv, skip_args) | ||
| 786 | int argc; | ||
| 787 | char **argv; | ||
| 788 | int skip_args; | ||
| 789 | { | ||
| 790 | char *s, *t, *root; | ||
| 791 | int len; | ||
| 792 | 241 | ||
| 793 | /* Find our root from argv[0]. Assuming argv[0] is, say, | 242 | static int current_pos_X; |
| 794 | "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */ | 243 | static int current_pos_Y; |
| 795 | root = alloca (MAXPATHLEN + 20); | 244 | static int new_pos_X; |
| 796 | _fixpath (argv[0], root); | 245 | static int new_pos_Y; |
| 797 | strlwr (root); | ||
| 798 | len = strlen (root); | ||
| 799 | while (len > 0 && root[len] != '/' && root[len] != ':') | ||
| 800 | len--; | ||
| 801 | root[len] = '\0'; | ||
| 802 | if (len > 4 && strcmp (root + len - 4, "/bin") == 0) | ||
| 803 | root[len - 4] = '\0'; | ||
| 804 | else | ||
| 805 | strcpy (root, "c:/emacs"); /* Only under debuggers, I think. */ | ||
| 806 | len = strlen (root); | ||
| 807 | strcpy (emacsroot, root); | ||
| 808 | 246 | ||
| 809 | /* We default HOME to our root. */ | 247 | static void *startup_screen_buffer; |
| 810 | setenv ("HOME", root, 0); | 248 | static int startup_screen_size_X; |
| 811 | 249 | static int startup_screen_size_Y; | |
| 812 | /* We default EMACSPATH to root + "/bin". */ | 250 | static int startup_pos_X; |
| 813 | strcpy (root + len, "/bin"); | 251 | static int startup_pos_Y; |
| 814 | setenv ("EMACSPATH", root, 0); | ||
| 815 | 252 | ||
| 816 | /* I don't expect anybody to ever use other terminals so the internal | 253 | static int term_setup_done; |
| 817 | terminal is the default. */ | ||
| 818 | setenv ("TERM", "internal", 0); | ||
| 819 | 254 | ||
| 820 | #ifdef HAVE_X_WINDOWS | 255 | /* Similar to the_only_frame. */ |
| 821 | /* Emacs expects DISPLAY to be set. */ | 256 | struct x_display the_only_x_display; |
| 822 | setenv ("DISPLAY", "unix:0.0", 0); | ||
| 823 | #endif | ||
| 824 | 257 | ||
| 825 | /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must | 258 | /* This is never dereferenced. */ |
| 826 | downcase it and mirror the backslashes. */ | 259 | Display *x_current_display; |
| 827 | s = getenv ("COMSPEC"); | ||
| 828 | if (!s) s = "c:/command.com"; | ||
| 829 | t = alloca (strlen (s) + 1); | ||
| 830 | strcpy (t, s); | ||
| 831 | strlwr (t); | ||
| 832 | dostounix_filename (t); | ||
| 833 | setenv ("SHELL", t, 0); | ||
| 834 | 260 | ||
| 835 | /* PATH is also downcased and backslashes mirrored. */ | ||
| 836 | s = getenv ("PATH"); | ||
| 837 | if (!s) s = ""; | ||
| 838 | t = alloca (strlen (s) + 3); | ||
| 839 | /* Current directory is always considered part of MsDos's path but it is | ||
| 840 | not normally mentioned. Now it is. */ | ||
| 841 | strcat (strcpy (t, ".;"), s); | ||
| 842 | strlwr (t); | ||
| 843 | dostounix_filename (t); /* Not a single file name, but this should work. */ | ||
| 844 | setenv ("PATH", t, 1); | ||
| 845 | 261 | ||
| 846 | /* In some sense all dos users have root privileges, so... */ | 262 | #define SCREEN_SET_CURSOR() \ |
| 847 | setenv ("USER", "root", 0); | 263 | if (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y) \ |
| 848 | setenv ("NAME", getenv ("USER"), 0); | 264 | ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X) |
| 849 | 265 | ||
| 850 | /* Time zone determined from country code. To make this possible, the | 266 | static |
| 851 | country code may not span more than one time zone. In other words, | 267 | dos_direct_output (y, x, buf, len) |
| 852 | in the USA, you lose. */ | 268 | int y; |
| 853 | switch (dos_country_code) | 269 | int x; |
| 854 | { | 270 | char *buf; |
| 855 | case 31: /* Belgium */ | 271 | int len; |
| 856 | case 32: /* The Netherlands */ | 272 | { |
| 857 | case 33: /* France */ | 273 | int t = (int) ScreenPrimary + 2 * (x + y * screen_size_X); |
| 858 | case 34: /* Spain */ | 274 | |
| 859 | case 36: /* Hungary */ | 275 | while (--len >= 0) { |
| 860 | case 38: /* Yugoslavia (or what's left of it?) */ | 276 | dosmemput (buf++, 1, t); |
| 861 | case 39: /* Italy */ | 277 | t += 2; |
| 862 | case 41: /* Switzerland */ | 278 | } |
| 863 | case 42: /* Tjekia */ | ||
| 864 | case 45: /* Denmark */ | ||
| 865 | case 46: /* Sweden */ | ||
| 866 | case 47: /* Norway */ | ||
| 867 | case 48: /* Poland */ | ||
| 868 | case 49: /* Germany */ | ||
| 869 | /* Daylight saving from last Sunday in March to last Sunday in | ||
| 870 | September, both at 2AM. */ | ||
| 871 | setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0); | ||
| 872 | break; | ||
| 873 | case 44: /* United Kingdom */ | ||
| 874 | case 351: /* Portugal */ | ||
| 875 | case 354: /* Iceland */ | ||
| 876 | setenv ("TZ", "GMT+00", 0); | ||
| 877 | break; | ||
| 878 | case 81: /* Japan */ | ||
| 879 | case 82: /* Korea */ | ||
| 880 | setenv ("TZ", "???-09", 0); | ||
| 881 | break; | ||
| 882 | case 90: /* Turkey */ | ||
| 883 | case 358: /* Finland */ | ||
| 884 | case 972: /* Israel */ | ||
| 885 | setenv ("TZ", "EET-02", 0); | ||
| 886 | break; | ||
| 887 | } | ||
| 888 | } | 279 | } |
| 280 | #endif | ||
| 889 | 281 | ||
| 890 | /* Flash the screen as a substitute for BEEPs. */ | 282 | /* Flash the screen as a substitute for BEEPs. */ |
| 891 | 283 | ||
| 284 | #if (__DJGPP__ < 2) | ||
| 892 | static void | 285 | static void |
| 893 | do_visible_bell (xorattr) | 286 | do_visible_bell (xorattr) |
| 894 | unsigned char xorattr; | 287 | unsigned char xorattr; |
| @@ -919,241 +312,41 @@ visible_bell_2: | |||
| 919 | jmp visible_bell_0 | 312 | jmp visible_bell_0 |
| 920 | visible_bell_3:" | 313 | visible_bell_3:" |
| 921 | : /* no output */ | 314 | : /* no output */ |
| 922 | : "m" (xorattr), "g" (ScreenCols () * ScreenRows ()) | 315 | : "m" (xorattr), "g" (screen_size) |
| 923 | : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx"); | 316 | : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx"); |
| 924 | } | 317 | } |
| 925 | 318 | ||
| 926 | /* At screen position (X,Y), output C characters from string S with | ||
| 927 | attribute A. Do it fast! */ | ||
| 928 | |||
| 929 | static void | 319 | static void |
| 930 | output_string (x, y, s, c, a) | 320 | ScreenVisualBell (void) |
| 931 | int x, y, c; | ||
| 932 | unsigned char *s; | ||
| 933 | unsigned char a; | ||
| 934 | { | 321 | { |
| 935 | char *t = (char *)ScreenPrimary + 2 * (x + ScreenCols () * y); | 322 | /* This creates an xor-mask that will swap the default fore- and |
| 936 | #ifdef DO_TERMSCRIPT | 323 | background colors. */ |
| 937 | if (termscript) | 324 | do_visible_bell (((the_only_x_display.foreground_pixel |
| 938 | { | 325 | ^ the_only_x_display.background_pixel) |
| 939 | fprintf (termscript, "<%d@%dx%d>", c, x, y); | 326 | * 0x11) & 0x7f); |
| 940 | fwrite (s, sizeof (unsigned char), c, termscript); | ||
| 941 | } | ||
| 942 | #endif | ||
| 943 | asm volatile | ||
| 944 | (" movl %1,%%eax | ||
| 945 | call dosmemsetup | ||
| 946 | movl %%eax,%%edi | ||
| 947 | movb %0,%%ah | ||
| 948 | movl %2,%%ecx | ||
| 949 | movl %3,%%esi | ||
| 950 | output_string1: | ||
| 951 | movb (%%esi),%%al | ||
| 952 | movw %%ax,%%gs:(%%edi) | ||
| 953 | addl $2,%%edi | ||
| 954 | incl %%esi | ||
| 955 | decl %%ecx | ||
| 956 | jne output_string1" | ||
| 957 | : /* no output */ | ||
| 958 | : "m" (a), "g" (t), "g" (c), "g" (s) | ||
| 959 | : "%eax", "%ecx", /* "%gs",*/ "%esi", "%edi"); | ||
| 960 | } | 327 | } |
| 328 | #endif | ||
| 961 | 329 | ||
| 962 | static int internal_terminal = 0; | 330 | #ifndef HAVE_X_WINDOWS |
| 963 | static int highlight; | ||
| 964 | |||
| 965 | #undef fflush | ||
| 966 | |||
| 967 | static int /* number of characters used by escape; -1 if incomplete */ | ||
| 968 | flush_escape (resume, cp, count, xp, yp) | ||
| 969 | int resume; | ||
| 970 | unsigned char *cp; | ||
| 971 | int count; | ||
| 972 | int *xp; | ||
| 973 | int *yp; | ||
| 974 | { | ||
| 975 | static char spaces[] = " "; | ||
| 976 | static unsigned char esc_cmd[8]; | ||
| 977 | static int esc_count = 0; | ||
| 978 | int esc_needed; | ||
| 979 | int i, j, used = 0; | ||
| 980 | |||
| 981 | if (!resume) | ||
| 982 | { | ||
| 983 | esc_cmd[0] = '\e'; | ||
| 984 | esc_count = 1; | ||
| 985 | used++; | ||
| 986 | } | ||
| 987 | |||
| 988 | while (esc_count < 2) | ||
| 989 | { | ||
| 990 | if (used == count) | ||
| 991 | return -1; | ||
| 992 | esc_cmd[esc_count++] = *cp++; | ||
| 993 | used++; | ||
| 994 | } | ||
| 995 | |||
| 996 | switch (esc_cmd[1]) | ||
| 997 | { | ||
| 998 | case '@': | ||
| 999 | esc_needed = 4; | ||
| 1000 | break; | ||
| 1001 | case 'A': | ||
| 1002 | case 'B': | ||
| 1003 | case 'X': | ||
| 1004 | esc_needed = 3; | ||
| 1005 | break; | ||
| 1006 | default: | ||
| 1007 | esc_needed = 2; | ||
| 1008 | break; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | while (esc_count < esc_needed) | ||
| 1012 | { | ||
| 1013 | if (used == count) | ||
| 1014 | return -1; | ||
| 1015 | esc_cmd[esc_count++] = *cp++; | ||
| 1016 | used++; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | switch (esc_cmd[1]) | ||
| 1020 | { | ||
| 1021 | case '@': | ||
| 1022 | *yp = esc_cmd[2]; | ||
| 1023 | *xp = esc_cmd[3]; | ||
| 1024 | break; | ||
| 1025 | case 'A': | ||
| 1026 | ScreenAttrib = esc_cmd[2]; | ||
| 1027 | break; | ||
| 1028 | case 'B': | ||
| 1029 | do_visible_bell (esc_cmd[2]); | ||
| 1030 | break; | ||
| 1031 | case 'C': | ||
| 1032 | ScreenClear (); | ||
| 1033 | *xp = *yp = 0; | ||
| 1034 | break; | ||
| 1035 | case 'E': | ||
| 1036 | i = ScreenCols () - *xp; | ||
| 1037 | j = *xp; | ||
| 1038 | while (i >= sizeof spaces) | ||
| 1039 | { | ||
| 1040 | output_string (j, *yp, spaces, sizeof spaces, ScreenAttrib); | ||
| 1041 | j += sizeof spaces; | ||
| 1042 | i -= sizeof spaces; | ||
| 1043 | } | ||
| 1044 | if (i > 0) | ||
| 1045 | output_string (j, *yp, spaces, i, ScreenAttrib); | ||
| 1046 | break; | ||
| 1047 | case 'R': | ||
| 1048 | ++*xp; | ||
| 1049 | break; | ||
| 1050 | case 'U': | ||
| 1051 | --*yp; | ||
| 1052 | break; | ||
| 1053 | case 'X': | ||
| 1054 | ScreenAttrib ^= esc_cmd[2]; | ||
| 1055 | break; | ||
| 1056 | case '\e': | ||
| 1057 | output_string (*xp, *yp, &esc_cmd[1], 1, ScreenAttrib); | ||
| 1058 | ++*xp; | ||
| 1059 | break; | ||
| 1060 | } | ||
| 1061 | 331 | ||
| 1062 | esc_count = 0; | 332 | /* |
| 1063 | return used; | 333 | * If we write a character in the position where the mouse is, |
| 1064 | } | 334 | * the mouse cursor may need to be refreshed. |
| 335 | */ | ||
| 1065 | 336 | ||
| 1066 | int | 337 | static void |
| 1067 | internal_flush (f) | 338 | mouse_off_maybe () |
| 1068 | FILE *f; | ||
| 1069 | { | 339 | { |
| 1070 | static int x; | 340 | int x, y; |
| 1071 | static int y; | ||
| 1072 | static int resume_esc = 0; | ||
| 1073 | unsigned char *cp, *cp0; | ||
| 1074 | int count, i; | ||
| 1075 | |||
| 1076 | if (!internal_terminal || f != stdout) | ||
| 1077 | { | ||
| 1078 | /* This is a call to the original fflush. */ | ||
| 1079 | fflush (f); | ||
| 1080 | return; | ||
| 1081 | } | ||
| 1082 | 341 | ||
| 1083 | mouse_off (); | 342 | if (!mouse_visible) |
| 1084 | cp = stdout->_base; | 343 | return; |
| 1085 | count = stdout->_ptr - stdout->_base; | ||
| 1086 | |||
| 1087 | #ifdef DO_TERMSCRIPT | ||
| 1088 | if (termscript) | ||
| 1089 | fprintf (termscript, "\n<FLUSH%s %d>\n", resume_esc ? " RESUME" : "", count); | ||
| 1090 | #endif | ||
| 1091 | 344 | ||
| 1092 | if (resume_esc) | 345 | mouse_get_xy (&x, &y); |
| 1093 | { | 346 | if (y != new_pos_Y || x < new_pos_X) |
| 1094 | i = flush_escape (1, cp, count, &x, &y); | 347 | return; |
| 1095 | if (i < 0) | ||
| 1096 | count = 0; | ||
| 1097 | else | ||
| 1098 | { | ||
| 1099 | resume_esc = 0; | ||
| 1100 | count -= i; | ||
| 1101 | cp += i; | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | 348 | ||
| 1105 | while (count > 0) | 349 | mouse_off (); |
| 1106 | { | ||
| 1107 | switch (*cp++) | ||
| 1108 | { | ||
| 1109 | case 27: | ||
| 1110 | i = flush_escape (0, cp, count, &x, &y); | ||
| 1111 | if (i < 0) | ||
| 1112 | { | ||
| 1113 | resume_esc = 1; | ||
| 1114 | count = 0; | ||
| 1115 | } | ||
| 1116 | else | ||
| 1117 | { | ||
| 1118 | count -= i; | ||
| 1119 | cp += i - 1; | ||
| 1120 | } | ||
| 1121 | break; | ||
| 1122 | case 7: | ||
| 1123 | write (1, "\007", 1); | ||
| 1124 | count--; | ||
| 1125 | break; | ||
| 1126 | case 8: | ||
| 1127 | x--; | ||
| 1128 | count--; | ||
| 1129 | break; | ||
| 1130 | case 13: | ||
| 1131 | x = 0; | ||
| 1132 | count--; | ||
| 1133 | break; | ||
| 1134 | case 10: | ||
| 1135 | y++; | ||
| 1136 | count--; | ||
| 1137 | break; | ||
| 1138 | default: | ||
| 1139 | cp0 = cp - 1; | ||
| 1140 | count--; | ||
| 1141 | while (count > 0 && *cp >= ' ') | ||
| 1142 | cp++, count--; | ||
| 1143 | output_string (x, y, cp0, cp - cp0, ScreenAttrib); | ||
| 1144 | x += (cp - cp0); | ||
| 1145 | } | ||
| 1146 | } | ||
| 1147 | fpurge (stdout); | ||
| 1148 | ScreenSetCursor (y, x); | ||
| 1149 | mouse_on (); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | #ifndef HAVE_X_WINDOWS | ||
| 1153 | static void | ||
| 1154 | rien_du_tout () | ||
| 1155 | { | ||
| 1156 | /* Rien du tout, cela va sans dire! */ | ||
| 1157 | } | 350 | } |
| 1158 | 351 | ||
| 1159 | static | 352 | static |
| @@ -1161,17 +354,10 @@ IT_ring_bell () | |||
| 1161 | { | 354 | { |
| 1162 | if (visible_bell) | 355 | if (visible_bell) |
| 1163 | { | 356 | { |
| 1164 | /* This creates an xor-mask that will swap the default fore- and | ||
| 1165 | background colors. */ | ||
| 1166 | mouse_off (); | 357 | mouse_off (); |
| 1167 | do_visible_bell (((the_only_x_display.foreground_pixel | 358 | ScreenVisualBell (); |
| 1168 | ^ the_only_x_display.background_pixel) | ||
| 1169 | * 0x11) & 0x7f); | ||
| 1170 | mouse_on (); | ||
| 1171 | } | 359 | } |
| 1172 | else | 360 | else |
| 1173 | /* Write it directly to ms-dos -- don't let it go through our terminal | ||
| 1174 | emulator. This way the mouse cursor won't blink. */ | ||
| 1175 | write (1, "\007", 1); | 361 | write (1, "\007", 1); |
| 1176 | } | 362 | } |
| 1177 | 363 | ||
| @@ -1187,63 +373,100 @@ IT_set_face (int face) | |||
| 1187 | fp = FRAME_DEFAULT_FACE (foo); | 373 | fp = FRAME_DEFAULT_FACE (foo); |
| 1188 | else | 374 | else |
| 1189 | fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]); | 375 | fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]); |
| 1190 | #ifdef DO_TERMSCRIPT | ||
| 1191 | if (termscript) | 376 | if (termscript) |
| 1192 | fprintf (termscript, "<FACE:%d:%d>", FACE_FOREGROUND (fp), FACE_BACKGROUND (fp)); | 377 | fprintf (termscript, "<FACE:%d:%d>", FACE_FOREGROUND (fp), FACE_BACKGROUND (fp)); |
| 1193 | #endif | 378 | screen_face = face; |
| 1194 | putchar ('\e'); | 379 | ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp); |
| 1195 | putchar ('A'); | ||
| 1196 | putchar ((FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp)); | ||
| 1197 | } | 380 | } |
| 1198 | 381 | ||
| 1199 | static | 382 | static |
| 1200 | IT_write_glyphs (GLYPH *str, int len) | 383 | IT_write_glyphs (GLYPH *str, int len) |
| 1201 | { | 384 | { |
| 1202 | int face = -1; | ||
| 1203 | int newface; | 385 | int newface; |
| 1204 | int ch; | 386 | int ch, l = len; |
| 387 | unsigned char *buf, *bp; | ||
| 388 | |||
| 389 | if (len == 0) return; | ||
| 390 | |||
| 391 | buf = bp = alloca (len * 2); | ||
| 1205 | 392 | ||
| 1206 | while (len > 0) | 393 | while (--l >= 0) |
| 1207 | { | 394 | { |
| 1208 | newface = FAST_GLYPH_FACE (*str); | 395 | newface = FAST_GLYPH_FACE (*str); |
| 1209 | if (newface != face) | 396 | if (newface != screen_face) |
| 1210 | IT_set_face ((face = newface)); | 397 | IT_set_face (newface); |
| 1211 | ch = FAST_GLYPH_CHAR (*str); | 398 | ch = FAST_GLYPH_CHAR (*str); |
| 1212 | #ifdef DO_TERMSCRIPT | 399 | *bp++ = (unsigned char)ch; |
| 400 | *bp++ = ScreenAttrib; | ||
| 401 | |||
| 1213 | if (termscript) | 402 | if (termscript) |
| 1214 | fputc (ch, termscript); | 403 | fputc (ch, termscript); |
| 1215 | #endif | 404 | str++; |
| 1216 | if (ch == '\e') putchar (ch); /* allow esc to be printed */ | ||
| 1217 | putchar (ch); | ||
| 1218 | str++, len--; | ||
| 1219 | } | 405 | } |
| 406 | |||
| 407 | mouse_off_maybe (); | ||
| 408 | dosmemput (buf, 2 * len, | ||
| 409 | (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y)); | ||
| 410 | new_pos_X += len; | ||
| 1220 | } | 411 | } |
| 1221 | 412 | ||
| 1222 | static | 413 | static |
| 1223 | IT_clear_end_of_line (first_unused) | 414 | IT_clear_end_of_line (first_unused) |
| 1224 | { | 415 | { |
| 416 | char *spaces, *sp; | ||
| 417 | int i, j; | ||
| 418 | |||
| 1225 | IT_set_face (0); | 419 | IT_set_face (0); |
| 1226 | #ifdef DO_TERMSCRIPT | ||
| 1227 | if (termscript) | 420 | if (termscript) |
| 1228 | fprintf (termscript, "<CLR:EOL>"); | 421 | fprintf (termscript, "<CLR:EOL>"); |
| 1229 | #endif | 422 | i = (j = screen_size_X - new_pos_X) * 2; |
| 1230 | putchar ('\e'); | 423 | spaces = sp = alloca (i); |
| 1231 | putchar ('E'); | 424 | |
| 425 | while (--j >= 0) | ||
| 426 | { | ||
| 427 | *sp++ = ' '; | ||
| 428 | *sp++ = ScreenAttrib; | ||
| 429 | } | ||
| 430 | |||
| 431 | mouse_off_maybe (); | ||
| 432 | dosmemput (spaces, i, | ||
| 433 | (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y)); | ||
| 434 | } | ||
| 435 | |||
| 436 | static | ||
| 437 | IT_clear_screen (void) | ||
| 438 | { | ||
| 439 | if (termscript) | ||
| 440 | fprintf (termscript, "<CLR:SCR>"); | ||
| 441 | IT_set_face (0); | ||
| 442 | mouse_off (); | ||
| 443 | ScreenClear (); | ||
| 444 | new_pos_X = new_pos_Y = 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | static | ||
| 448 | IT_clear_to_end (void) | ||
| 449 | { | ||
| 450 | if (termscript) | ||
| 451 | fprintf (termscript, "<CLR:EOS>"); | ||
| 452 | |||
| 453 | while (new_pos_Y < screen_size_Y) { | ||
| 454 | new_pos_X = 0; | ||
| 455 | IT_clear_end_of_line (0); | ||
| 456 | new_pos_Y++; | ||
| 457 | } | ||
| 1232 | } | 458 | } |
| 1233 | 459 | ||
| 1234 | static | 460 | static |
| 1235 | IT_cursor_to (int y, int x) | 461 | IT_cursor_to (int y, int x) |
| 1236 | { | 462 | { |
| 1237 | #ifdef DO_TERMSCRIPT | ||
| 1238 | if (termscript) | 463 | if (termscript) |
| 1239 | fprintf (termscript, "\n<XY=%dx%d>", x, y); | 464 | fprintf (termscript, "\n<XY=%dx%d>", x, y); |
| 1240 | #endif | 465 | new_pos_X = x; |
| 1241 | putchar ('\e'); | 466 | new_pos_Y = y; |
| 1242 | putchar ('@'); | ||
| 1243 | putchar (y); | ||
| 1244 | putchar (x); | ||
| 1245 | } | 467 | } |
| 1246 | 468 | ||
| 469 | static | ||
| 1247 | IT_reassert_line_highlight (new, vpos) | 470 | IT_reassert_line_highlight (new, vpos) |
| 1248 | int new, vpos; | 471 | int new, vpos; |
| 1249 | { | 472 | { |
| @@ -1265,6 +488,12 @@ IT_update_begin () | |||
| 1265 | { | 488 | { |
| 1266 | highlight = 0; | 489 | highlight = 0; |
| 1267 | IT_set_face (0); /* To possibly clear the highlighting. */ | 490 | IT_set_face (0); /* To possibly clear the highlighting. */ |
| 491 | screen_face = -1; | ||
| 492 | } | ||
| 493 | |||
| 494 | static | ||
| 495 | IT_update_end () | ||
| 496 | { | ||
| 1268 | } | 497 | } |
| 1269 | 498 | ||
| 1270 | /* This was more or less copied from xterm.c */ | 499 | /* This was more or less copied from xterm.c */ |
| @@ -1290,6 +519,74 @@ IT_set_menu_bar_lines (window, n) | |||
| 1290 | } | 519 | } |
| 1291 | } | 520 | } |
| 1292 | 521 | ||
| 522 | /* | ||
| 523 | * IT_set_terminal_modes is called when emacs is started, | ||
| 524 | * resumed, and whenever the screen is redrawn! | ||
| 525 | */ | ||
| 526 | |||
| 527 | static | ||
| 528 | IT_set_terminal_modes (void) | ||
| 529 | { | ||
| 530 | char *colors; | ||
| 531 | FRAME_PTR f; | ||
| 532 | struct face *fp; | ||
| 533 | |||
| 534 | if (termscript) | ||
| 535 | fprintf (termscript, "\n<SET_TERM>"); | ||
| 536 | highlight = 0; | ||
| 537 | |||
| 538 | screen_size_X = ScreenCols (); | ||
| 539 | screen_size_Y = ScreenRows (); | ||
| 540 | screen_size = screen_size_X * screen_size_Y; | ||
| 541 | |||
| 542 | new_pos_X = new_pos_Y = 0; | ||
| 543 | current_pos_X = current_pos_Y = -1; | ||
| 544 | |||
| 545 | if (term_setup_done) | ||
| 546 | return; | ||
| 547 | term_setup_done = 1; | ||
| 548 | |||
| 549 | startup_screen_size_X = screen_size_X; | ||
| 550 | startup_screen_size_Y = screen_size_Y; | ||
| 551 | |||
| 552 | ScreenGetCursor (&startup_pos_Y, &startup_pos_X); | ||
| 553 | ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2)); | ||
| 554 | |||
| 555 | if (termscript) | ||
| 556 | fprintf (termscript, "<SCREEN SAVED>\n"); | ||
| 557 | } | ||
| 558 | |||
| 559 | /* | ||
| 560 | * IT_reset_terminal_modes is called when emacs is | ||
| 561 | * suspended or killed. | ||
| 562 | */ | ||
| 563 | |||
| 564 | static | ||
| 565 | IT_reset_terminal_modes (void) | ||
| 566 | { | ||
| 567 | if (termscript) | ||
| 568 | fprintf(termscript, "\n<RESET_TERM>"); | ||
| 569 | |||
| 570 | highlight = 0; | ||
| 571 | |||
| 572 | if (!term_setup_done) | ||
| 573 | return; | ||
| 574 | |||
| 575 | ScreenUpdate (startup_screen_buffer); | ||
| 576 | ScreenSetCursor (startup_pos_Y, startup_pos_X); | ||
| 577 | xfree (startup_screen_buffer); | ||
| 578 | |||
| 579 | if (termscript) | ||
| 580 | fprintf (termscript, "<SCREEN RESTORED>\n"); | ||
| 581 | |||
| 582 | term_setup_done = 0; | ||
| 583 | } | ||
| 584 | |||
| 585 | static | ||
| 586 | IT_set_terminal_window (void) | ||
| 587 | { | ||
| 588 | } | ||
| 589 | |||
| 1293 | void | 590 | void |
| 1294 | IT_set_frame_parameters (frame, alist) | 591 | IT_set_frame_parameters (frame, alist) |
| 1295 | FRAME_PTR frame; | 592 | FRAME_PTR frame; |
| @@ -1349,21 +646,16 @@ IT_set_frame_parameters (frame, alist) | |||
| 1349 | } | 646 | } |
| 1350 | } | 647 | } |
| 1351 | 648 | ||
| 1352 | /* Similar to the_only_frame. */ | ||
| 1353 | struct x_display the_only_x_display; | ||
| 1354 | |||
| 1355 | /* This is never dereferenced. */ | ||
| 1356 | Display *x_current_display; | ||
| 1357 | |||
| 1358 | #endif /* !HAVE_X_WINDOWS */ | 649 | #endif /* !HAVE_X_WINDOWS */ |
| 1359 | 650 | ||
| 651 | |||
| 1360 | /* Do we need the internal terminal? */ | 652 | /* Do we need the internal terminal? */ |
| 1361 | void | 653 | void |
| 1362 | internal_terminal_init () | 654 | internal_terminal_init () |
| 1363 | { | 655 | { |
| 1364 | char *term = getenv ("TERM"); | 656 | char *term = getenv ("TERM"); |
| 1365 | char *colors; | 657 | char *colors; |
| 1366 | 658 | ||
| 1367 | #ifdef HAVE_X_WINDOWS | 659 | #ifdef HAVE_X_WINDOWS |
| 1368 | if (!inhibit_window_system) | 660 | if (!inhibit_window_system) |
| 1369 | return; | 661 | return; |
| @@ -1372,316 +664,715 @@ internal_terminal_init () | |||
| 1372 | internal_terminal | 664 | internal_terminal |
| 1373 | = (!noninteractive) && term && !strcmp (term, "internal"); | 665 | = (!noninteractive) && term && !strcmp (term, "internal"); |
| 1374 | 666 | ||
| 667 | if (getenv ("EMACSTEST")) | ||
| 668 | termscript = fopen(getenv ("EMACSTEST"), "wt"); | ||
| 669 | |||
| 1375 | #ifndef HAVE_X_WINDOWS | 670 | #ifndef HAVE_X_WINDOWS |
| 1376 | if (internal_terminal && !inhibit_window_system) | 671 | if (!internal_terminal || inhibit_window_system) |
| 1377 | { | 672 | { |
| 1378 | Vwindow_system = intern ("pc"); | 673 | the_only_frame.output_method = output_termcap; |
| 1379 | Vwindow_system_version = make_number (1); | 674 | return; |
| 675 | } | ||
| 676 | |||
| 677 | Vwindow_system = intern ("pc"); | ||
| 678 | Vwindow_system_version = make_number (1); | ||
| 1380 | 679 | ||
| 1381 | bzero (&the_only_x_display, sizeof the_only_x_display); | 680 | bzero (&the_only_x_display, sizeof the_only_x_display); |
| 1382 | the_only_x_display.background_pixel = 7; /* White */ | 681 | the_only_x_display.background_pixel = 7; /* White */ |
| 1383 | the_only_x_display.foreground_pixel = 0; /* Black */ | 682 | the_only_x_display.foreground_pixel = 0; /* Black */ |
| 1384 | colors = getenv ("EMACSCOLORS"); | 683 | colors = getenv("EMACSCOLORS"); |
| 1385 | if (colors && strlen (colors) >=2) | 684 | if (colors && strlen (colors) >= 2) |
| 1386 | { | 685 | { |
| 1387 | the_only_x_display.foreground_pixel = colors[0] & 0x07; | 686 | the_only_x_display.foreground_pixel = colors[0] & 0x07; |
| 1388 | the_only_x_display.background_pixel = colors[1] & 0x07; | 687 | the_only_x_display.background_pixel = colors[1] & 0x07; |
| 1389 | } | ||
| 1390 | the_only_x_display.line_height = 1; | ||
| 1391 | the_only_frame.display.x = &the_only_x_display; | ||
| 1392 | the_only_frame.output_method = output_msdos_raw; | ||
| 1393 | |||
| 1394 | init_frame_faces ((FRAME_PTR) &the_only_frame); | ||
| 1395 | |||
| 1396 | ring_bell_hook = IT_ring_bell; | ||
| 1397 | write_glyphs_hook = IT_write_glyphs; | ||
| 1398 | cursor_to_hook = raw_cursor_to_hook = IT_cursor_to; | ||
| 1399 | clear_end_of_line_hook = IT_clear_end_of_line; | ||
| 1400 | change_line_highlight_hook = IT_change_line_highlight; | ||
| 1401 | update_begin_hook = IT_update_begin; | ||
| 1402 | reassert_line_highlight_hook = IT_reassert_line_highlight; | ||
| 1403 | |||
| 1404 | /* These hooks are called by term.c without being checked. */ | ||
| 1405 | set_terminal_modes_hook | ||
| 1406 | = reset_terminal_modes_hook | ||
| 1407 | = update_end_hook | ||
| 1408 | = set_terminal_window_hook | ||
| 1409 | = (void *)rien_du_tout; | ||
| 1410 | } | 688 | } |
| 1411 | else | 689 | the_only_x_display.line_height = 1; |
| 1412 | the_only_frame.output_method = output_termcap; | 690 | the_only_frame.display.x = &the_only_x_display; |
| 691 | the_only_frame.output_method = output_msdos_raw; | ||
| 692 | |||
| 693 | init_frame_faces ((FRAME_PTR) &the_only_frame); | ||
| 694 | |||
| 695 | ring_bell_hook = IT_ring_bell; | ||
| 696 | write_glyphs_hook = IT_write_glyphs; | ||
| 697 | cursor_to_hook = raw_cursor_to_hook = IT_cursor_to; | ||
| 698 | clear_to_end_hook = IT_clear_to_end; | ||
| 699 | clear_end_of_line_hook = IT_clear_end_of_line; | ||
| 700 | clear_frame_hook = IT_clear_screen; | ||
| 701 | change_line_highlight_hook = IT_change_line_highlight; | ||
| 702 | update_begin_hook = IT_update_begin; | ||
| 703 | update_end_hook = IT_update_end; | ||
| 704 | reassert_line_highlight_hook = IT_reassert_line_highlight; | ||
| 705 | |||
| 706 | /* These hooks are called by term.c without being checked. */ | ||
| 707 | set_terminal_modes_hook = IT_set_terminal_modes; | ||
| 708 | reset_terminal_modes_hook = IT_reset_terminal_modes; | ||
| 709 | set_terminal_window_hook = IT_set_terminal_window; | ||
| 1413 | #endif | 710 | #endif |
| 1414 | } | 711 | } |
| 1415 | |||
| 1416 | /* When time zones are set from Ms-Dos too may C-libraries are playing | ||
| 1417 | tricks with time values. We solve this by defining our own version | ||
| 1418 | of `gettimeofday' bypassing GO32. Our version needs to be initialized | ||
| 1419 | once and after each call to `tzset' with TZ changed. */ | ||
| 1420 | |||
| 1421 | static int daylight, gmtoffset; | ||
| 1422 | 712 | ||
| 1423 | int | 713 | dos_get_saved_screen (screen, rows, cols) |
| 1424 | gettimeofday (struct timeval *tp, struct timezone *tzp) | 714 | char **screen; |
| 715 | int *rows; | ||
| 716 | int *cols; | ||
| 1425 | { | 717 | { |
| 1426 | if (tp) | 718 | #ifndef HAVE_X_WINDOWS |
| 1427 | { | 719 | *screen = startup_screen_buffer; |
| 1428 | struct time t; | 720 | *cols = startup_screen_size_X; |
| 1429 | struct date d; | 721 | *rows = startup_screen_size_Y; |
| 1430 | struct tm tmrec; | 722 | return 1; |
| 1431 | 723 | #else | |
| 1432 | gettime (&t); | ||
| 1433 | /* If midnight occurs here, the results can be incorrect. */ | ||
| 1434 | getdate (&d); | ||
| 1435 | tmrec.tm_year = d.da_year - 1900; | ||
| 1436 | tmrec.tm_mon = d.da_mon - 1; | ||
| 1437 | tmrec.tm_mday = d.da_day; | ||
| 1438 | tmrec.tm_hour = t.ti_hour; | ||
| 1439 | tmrec.tm_min = t.ti_min; | ||
| 1440 | tmrec.tm_sec = t.ti_sec; | ||
| 1441 | tmrec.tm_gmtoff = gmtoffset; | ||
| 1442 | tmrec.tm_isdst = daylight; | ||
| 1443 | tp->tv_sec = mktime (&tmrec); | ||
| 1444 | tp->tv_usec = t.ti_hund * (1000000 / 100); | ||
| 1445 | } | ||
| 1446 | /* Ignore tzp; it's obsolescent. */ | ||
| 1447 | return 0; | 724 | return 0; |
| 725 | #endif | ||
| 1448 | } | 726 | } |
| 1449 | 727 | ||
| 1450 | void | 728 | |
| 1451 | init_gettimeofday () | 729 | /* ----------------------- Keyboard control ---------------------- |
| 730 | * | ||
| 731 | * Keymaps reflect the following keyboard layout: | ||
| 732 | * | ||
| 733 | * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS | ||
| 734 | * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41) | ||
| 735 | * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET | ||
| 736 | * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT | ||
| 737 | * SPACE | ||
| 738 | */ | ||
| 739 | |||
| 740 | static int extended_kbd; /* 101 (102) keyboard present. */ | ||
| 741 | |||
| 742 | struct dos_keyboard_map | ||
| 1452 | { | 743 | { |
| 1453 | time_t ltm, gtm; | 744 | char *unshifted; |
| 1454 | struct tm *lstm; | 745 | char *shifted; |
| 1455 | #undef tzset | 746 | char *alt_gr; |
| 1456 | extern void tzset (void); | 747 | }; |
| 1457 | 748 | ||
| 1458 | tzset (); | ||
| 1459 | daylight = 0; | ||
| 1460 | gmtoffset = 0; | ||
| 1461 | ltm = gtm = time (NULL); | ||
| 1462 | ltm = mktime (lstm = localtime (<m)); | ||
| 1463 | gtm = mktime (gmtime (>m)); | ||
| 1464 | daylight = lstm->tm_isdst; | ||
| 1465 | gmtoffset = (int)(gtm - ltm) / 60; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | /* These must be global. */ | ||
| 1469 | static _go32_dpmi_seginfo ctrl_break_vector; | ||
| 1470 | static _go32_dpmi_registers ctrl_break_regs; | ||
| 1471 | static int ctrlbreakinstalled = 0; | ||
| 1472 | 749 | ||
| 1473 | /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */ | 750 | static struct dos_keyboard_map us_keyboard = { |
| 1474 | void | 751 | /* 0 1 2 3 4 5 */ |
| 1475 | ctrl_break_func (regs) | 752 | /* 01234567890123456789012345678901234567890 12345678901234 */ |
| 1476 | _go32_dpmi_registers *regs; | 753 | "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ", |
| 754 | /* 0123456789012345678901234567890123456789 012345678901234 */ | ||
| 755 | "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ", | ||
| 756 | 0 /* no Alt-Gr key */ | ||
| 757 | }; | ||
| 758 | |||
| 759 | static struct dos_keyboard_map fr_keyboard = { | ||
| 760 | /* 0 1 2 3 4 5 */ | ||
| 761 | /* 012 3456789012345678901234567890123456789012345678901234 */ | ||
| 762 | "ý&‚\",(-Š_€…)= azertyuiop^$ qsdfghjklm—* wxcvbnm;:! ", | ||
| 763 | /* 0123456789012345678901234567890123456789012345678901234 */ | ||
| 764 | " 1234567890ø+ AZERTYUIOPùœ QSDFGHJKLM%æ WXCVBN?./õ ", | ||
| 765 | /* 01234567 89012345678901234567890123456789012345678901234 */ | ||
| 766 | " ~#{[|`\\^@]} Ï " | ||
| 767 | }; | ||
| 768 | |||
| 769 | static struct dos_keyboard_map dk_keyboard = { | ||
| 770 | /* 0 1 2 3 4 5 */ | ||
| 771 | /* 0123456789012345678901234567890123456789012345678901234 */ | ||
| 772 | "«1234567890+| qwertyuiop†~ asdfghjkl‘›' zxcvbnm,.- ", | ||
| 773 | /* 01 23456789012345678901234567890123456789012345678901234 */ | ||
| 774 | "õ!\"#$%&/()=?` QWERTYUIOP^ ASDFGHJKL’* ZXCVBNM;:_ ", | ||
| 775 | /* 0123456789012345678901234567890123456789012345678901234 */ | ||
| 776 | " @œ$ {[]} | " | ||
| 777 | }; | ||
| 778 | |||
| 779 | static struct keyboard_layout_list | ||
| 1477 | { | 780 | { |
| 1478 | Vquit_flag = Qt; | 781 | int country_code; |
| 1479 | } | 782 | struct dos_keyboard_map *keyboard_map; |
| 783 | } keyboard_layout_list[] = { | ||
| 784 | 1, &us_keyboard, | ||
| 785 | 33, &fr_keyboard, | ||
| 786 | 45, &dk_keyboard | ||
| 787 | }; | ||
| 1480 | 788 | ||
| 1481 | void | 789 | static struct dos_keyboard_map *keyboard; |
| 1482 | install_ctrl_break_check () | 790 | static int keyboard_map_all; |
| 791 | |||
| 792 | int | ||
| 793 | dos_set_keyboard (code, always) | ||
| 794 | int code; | ||
| 795 | int always; | ||
| 1483 | { | 796 | { |
| 1484 | if (!ctrlbreakinstalled) | 797 | int i; |
| 1485 | { | 798 | for (i = 0; i < (sizeof (keyboard_layout_list)/sizeof (struct keyboard_layout_list)); i++) |
| 1486 | /* Don't press Ctrl-Break if you don't have either DPMI or Emacs | 799 | if (code == keyboard_layout_list[i].country_code) |
| 1487 | was compiler with Djgpp 1.11 maintenance level 5 or later! */ | 800 | { |
| 1488 | ctrlbreakinstalled = 1; | 801 | keyboard = keyboard_layout_list[i].keyboard_map; |
| 1489 | ctrl_break_vector.pm_offset = (int) ctrl_break_func; | 802 | keyboard_map_all = always; |
| 1490 | _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector, | 803 | dos_keyboard_layout = code; |
| 1491 | &ctrl_break_regs); | 804 | return 1; |
| 1492 | _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector); | 805 | } |
| 1493 | } | 806 | return 0; |
| 1494 | } | 807 | } |
| 1495 | |||
| 1496 | /* Mouse routines follow. Coordinates are in screen positions and zero | ||
| 1497 | based. Mouse buttons are numbered from left to right and also zero | ||
| 1498 | based. */ | ||
| 1499 | 808 | ||
| 1500 | static int mouse_button_translate[NUM_MOUSE_BUTTONS]; | 809 | #define Ignore 0x0000 |
| 1501 | static int mouse_button_count; | 810 | #define Normal 0x0000 /* normal key - alt changes scan-code */ |
| 811 | #define FctKey 0x1000 /* func key if c == 0, else c */ | ||
| 812 | #define Special 0x2000 /* func key even if c != 0 */ | ||
| 813 | #define ModFct 0x3000 /* special if mod-keys, else 'c' */ | ||
| 814 | #define Map 0x4000 /* alt scan-code, map to unshift/shift key */ | ||
| 815 | #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */ | ||
| 816 | #define Grey 0x6000 /* Grey keypad key */ | ||
| 817 | |||
| 818 | #define Alt 0x0100 /* alt scan-code */ | ||
| 819 | #define Ctrl 0x0200 /* ctrl scan-code */ | ||
| 820 | #define Shift 0x0400 /* shift scan-code */ | ||
| 821 | |||
| 822 | static struct | ||
| 823 | { | ||
| 824 | unsigned char char_code; /* normal code */ | ||
| 825 | unsigned char meta_code; /* M- code */ | ||
| 826 | unsigned char keypad_code; /* keypad code */ | ||
| 827 | unsigned char editkey_code; /* edit key */ | ||
| 828 | } keypad_translate_map[] = { | ||
| 829 | '0', '0', 0xb0, /* kp-0 */ 0x63, /* insert */ | ||
| 830 | '1', '1', 0xb1, /* kp-1 */ 0x57, /* end */ | ||
| 831 | '2', '2', 0xb2, /* kp-2 */ 0x54, /* down */ | ||
| 832 | '3', '3', 0xb3, /* kp-3 */ 0x56, /* next */ | ||
| 833 | '4', '4', 0xb4, /* kp-4 */ 0x51, /* left */ | ||
| 834 | '5', '5', 0xb5, /* kp-5 */ 0xb5, /* kp-5 */ | ||
| 835 | '6', '6', 0xb6, /* kp-6 */ 0x53, /* right */ | ||
| 836 | '7', '7', 0xb7, /* kp-7 */ 0x50, /* home */ | ||
| 837 | '8', '8', 0xb8, /* kp-8 */ 0x52, /* up */ | ||
| 838 | '9', '9', 0xb9, /* kp-9 */ 0x55, /* prior */ | ||
| 839 | '.', '-', 0xae, /* kp-decimal */ 0xff /* delete */ | ||
| 840 | }; | ||
| 1502 | 841 | ||
| 1503 | void | 842 | static struct |
| 1504 | mouse_init () | ||
| 1505 | { | 843 | { |
| 1506 | union REGS regs; | 844 | unsigned char char_code; /* normal code */ |
| 1507 | 845 | unsigned char keypad_code; /* keypad code */ | |
| 1508 | regs.x.ax = 0x0007; | 846 | } grey_key_translate_map[] = { |
| 1509 | regs.x.cx = 0; | 847 | '/', 0xaf, /* kp-decimal */ |
| 1510 | regs.x.dx = 8 * (ScreenCols () - 1); | 848 | '*', 0xaa, /* kp-multiply */ |
| 1511 | int86 (0x33, ®s, ®s); | 849 | '-', 0xad, /* kp-subtract */ |
| 850 | '+', 0xab, /* kp-add */ | ||
| 851 | '\r', 0x8d /* kp-enter */ | ||
| 852 | }; | ||
| 1512 | 853 | ||
| 1513 | regs.x.ax = 0x0008; | 854 | static unsigned short |
| 1514 | regs.x.cx = 0; | 855 | ibmpc_translate_map[] = |
| 1515 | regs.x.dx = 8 * (ScreenRows () - 1); | 856 | { |
| 1516 | int86 (0x33, ®s, ®s); | 857 | /* --------------- 00 to 0f --------------- */ |
| 858 | Normal | 0xff, /* Ctrl Break + Alt-NNN */ | ||
| 859 | Alt | ModFct | 0x1b, /* Escape */ | ||
| 860 | Normal | 1, /* '1' */ | ||
| 861 | Normal | 2, /* '2' */ | ||
| 862 | Normal | 3, /* '3' */ | ||
| 863 | Normal | 4, /* '4' */ | ||
| 864 | Normal | 5, /* '5' */ | ||
| 865 | Normal | 6, /* '6' */ | ||
| 866 | Normal | 7, /* '7' */ | ||
| 867 | Normal | 8, /* '8' */ | ||
| 868 | Normal | 9, /* '9' */ | ||
| 869 | Normal | 10, /* '0' */ | ||
| 870 | Normal | 11, /* '-' */ | ||
| 871 | Normal | 12, /* '=' */ | ||
| 872 | Special | 0x08, /* Backspace */ | ||
| 873 | ModFct | 0x74, /* Tab/Backtab */ | ||
| 1517 | 874 | ||
| 1518 | mouse_moveto (ScreenCols () - 1, ScreenRows () - 1); | 875 | /* --------------- 10 to 1f --------------- */ |
| 1519 | mouse_on (); | 876 | Map | 15, /* 'q' */ |
| 1520 | } | 877 | Map | 16, /* 'w' */ |
| 878 | Map | 17, /* 'e' */ | ||
| 879 | Map | 18, /* 'r' */ | ||
| 880 | Map | 19, /* 't' */ | ||
| 881 | Map | 20, /* 'y' */ | ||
| 882 | Map | 21, /* 'u' */ | ||
| 883 | Map | 22, /* 'i' */ | ||
| 884 | Map | 23, /* 'o' */ | ||
| 885 | Map | 24, /* 'p' */ | ||
| 886 | Map | 25, /* '[' */ | ||
| 887 | Map | 26, /* ']' */ | ||
| 888 | ModFct | 0x0d, /* Return */ | ||
| 889 | Ignore, /* Ctrl */ | ||
| 890 | Map | 30, /* 'a' */ | ||
| 891 | Map | 31, /* 's' */ | ||
| 1521 | 892 | ||
| 1522 | void | 893 | /* --------------- 20 to 2f --------------- */ |
| 1523 | mouse_on () | 894 | Map | 32, /* 'd' */ |
| 1524 | { | 895 | Map | 33, /* 'f' */ |
| 1525 | union REGS regs; | 896 | Map | 34, /* 'g' */ |
| 897 | Map | 35, /* 'h' */ | ||
| 898 | Map | 36, /* 'j' */ | ||
| 899 | Map | 37, /* 'k' */ | ||
| 900 | Map | 38, /* 'l' */ | ||
| 901 | Map | 39, /* ';' */ | ||
| 902 | Map | 40, /* '\'' */ | ||
| 903 | Map | 0, /* '`' */ | ||
| 904 | Ignore, /* Left shift */ | ||
| 905 | Map | 41, /* '\\' */ | ||
| 906 | Map | 45, /* 'z' */ | ||
| 907 | Map | 46, /* 'x' */ | ||
| 908 | Map | 47, /* 'c' */ | ||
| 909 | Map | 48, /* 'v' */ | ||
| 1526 | 910 | ||
| 1527 | if (have_mouse > 0) | 911 | /* --------------- 30 to 3f --------------- */ |
| 1528 | { | 912 | Map | 49, /* 'b' */ |
| 1529 | regs.x.ax = 0x0001; | 913 | Map | 50, /* 'n' */ |
| 1530 | int86 (0x33, ®s, ®s); | 914 | Map | 51, /* 'm' */ |
| 1531 | } | 915 | Map | 52, /* ',' */ |
| 1532 | } | 916 | Map | 53, /* '.' */ |
| 917 | Map | 54, /* '/' */ | ||
| 918 | Ignore, /* Right shift */ | ||
| 919 | Grey | 1, /* Grey * */ | ||
| 920 | Ignore, /* Alt */ | ||
| 921 | Normal | ' ', /* ' ' */ | ||
| 922 | Ignore, /* Caps Lock */ | ||
| 923 | FctKey | 0xbe, /* F1 */ | ||
| 924 | FctKey | 0xbf, /* F2 */ | ||
| 925 | FctKey | 0xc0, /* F3 */ | ||
| 926 | FctKey | 0xc1, /* F4 */ | ||
| 927 | FctKey | 0xc2, /* F5 */ | ||
| 1533 | 928 | ||
| 1534 | void | 929 | /* --------------- 40 to 4f --------------- */ |
| 1535 | mouse_off () | 930 | FctKey | 0xc3, /* F6 */ |
| 1536 | { | 931 | FctKey | 0xc4, /* F7 */ |
| 1537 | union REGS regs; | 932 | FctKey | 0xc5, /* F8 */ |
| 933 | FctKey | 0xc6, /* F9 */ | ||
| 934 | FctKey | 0xc7, /* F10 */ | ||
| 935 | Ignore, /* Num Lock */ | ||
| 936 | Ignore, /* Scroll Lock */ | ||
| 937 | KeyPad | 7, /* Home */ | ||
| 938 | KeyPad | 8, /* Up */ | ||
| 939 | KeyPad | 9, /* Page Up */ | ||
| 940 | Grey | 2, /* Grey - */ | ||
| 941 | KeyPad | 4, /* Left */ | ||
| 942 | KeyPad | 5, /* Keypad 5 */ | ||
| 943 | KeyPad | 6, /* Right */ | ||
| 944 | Grey | 3, /* Grey + */ | ||
| 945 | KeyPad | 1, /* End */ | ||
| 1538 | 946 | ||
| 1539 | if (have_mouse > 0) | 947 | /* --------------- 50 to 5f --------------- */ |
| 1540 | { | 948 | KeyPad | 2, /* Down */ |
| 1541 | regs.x.ax = 0x0002; | 949 | KeyPad | 3, /* Page Down */ |
| 1542 | int86 (0x33, ®s, ®s); | 950 | KeyPad | 0, /* Insert */ |
| 1543 | } | 951 | KeyPad | 10, /* Delete */ |
| 1544 | } | 952 | Shift | FctKey | 0xbe, /* (Shift) F1 */ |
| 953 | Shift | FctKey | 0xbf, /* (Shift) F2 */ | ||
| 954 | Shift | FctKey | 0xc0, /* (Shift) F3 */ | ||
| 955 | Shift | FctKey | 0xc1, /* (Shift) F4 */ | ||
| 956 | Shift | FctKey | 0xc2, /* (Shift) F5 */ | ||
| 957 | Shift | FctKey | 0xc3, /* (Shift) F6 */ | ||
| 958 | Shift | FctKey | 0xc4, /* (Shift) F7 */ | ||
| 959 | Shift | FctKey | 0xc5, /* (Shift) F8 */ | ||
| 960 | Shift | FctKey | 0xc6, /* (Shift) F9 */ | ||
| 961 | Shift | FctKey | 0xc7, /* (Shift) F10 */ | ||
| 962 | Ctrl | FctKey | 0xbe, /* (Ctrl) F1 */ | ||
| 963 | Ctrl | FctKey | 0xbf, /* (Ctrl) F2 */ | ||
| 1545 | 964 | ||
| 1546 | void | 965 | /* --------------- 60 to 6f --------------- */ |
| 1547 | mouse_moveto (x, y) | 966 | Ctrl | FctKey | 0xc0, /* (Ctrl) F3 */ |
| 1548 | int x, y; | 967 | Ctrl | FctKey | 0xc1, /* (Ctrl) F4 */ |
| 1549 | { | 968 | Ctrl | FctKey | 0xc2, /* (Ctrl) F5 */ |
| 1550 | union REGS regs; | 969 | Ctrl | FctKey | 0xc3, /* (Ctrl) F6 */ |
| 970 | Ctrl | FctKey | 0xc4, /* (Ctrl) F7 */ | ||
| 971 | Ctrl | FctKey | 0xc5, /* (Ctrl) F8 */ | ||
| 972 | Ctrl | FctKey | 0xc6, /* (Ctrl) F9 */ | ||
| 973 | Ctrl | FctKey | 0xc7, /* (Ctrl) F10 */ | ||
| 974 | Alt | FctKey | 0xbe, /* (Alt) F1 */ | ||
| 975 | Alt | FctKey | 0xbf, /* (Alt) F2 */ | ||
| 976 | Alt | FctKey | 0xc0, /* (Alt) F3 */ | ||
| 977 | Alt | FctKey | 0xc1, /* (Alt) F4 */ | ||
| 978 | Alt | FctKey | 0xc2, /* (Alt) F5 */ | ||
| 979 | Alt | FctKey | 0xc3, /* (Alt) F6 */ | ||
| 980 | Alt | FctKey | 0xc4, /* (Alt) F7 */ | ||
| 981 | Alt | FctKey | 0xc5, /* (Alt) F8 */ | ||
| 1551 | 982 | ||
| 1552 | regs.x.ax = 0x0004; | 983 | /* --------------- 70 to 7f --------------- */ |
| 1553 | mouse_last_x = regs.x.cx = x * 8; | 984 | Alt | FctKey | 0xc6, /* (Alt) F9 */ |
| 1554 | mouse_last_y = regs.x.dx = y * 8; | 985 | Alt | FctKey | 0xc7, /* (Alt) F10 */ |
| 1555 | int86 (0x33, ®s, ®s); | 986 | Ctrl | FctKey | 0x6d, /* (Ctrl) Sys Rq */ |
| 1556 | } | 987 | Ctrl | KeyPad | 4, /* (Ctrl) Left */ |
| 988 | Ctrl | KeyPad | 6, /* (Ctrl) Right */ | ||
| 989 | Ctrl | KeyPad | 1, /* (Ctrl) End */ | ||
| 990 | Ctrl | KeyPad | 3, /* (Ctrl) Page Down */ | ||
| 991 | Ctrl | KeyPad | 7, /* (Ctrl) Home */ | ||
| 992 | Alt | Map | 1, /* '1' */ | ||
| 993 | Alt | Map | 2, /* '2' */ | ||
| 994 | Alt | Map | 3, /* '3' */ | ||
| 995 | Alt | Map | 4, /* '4' */ | ||
| 996 | Alt | Map | 5, /* '5' */ | ||
| 997 | Alt | Map | 6, /* '6' */ | ||
| 998 | Alt | Map | 7, /* '7' */ | ||
| 999 | Alt | Map | 8, /* '8' */ | ||
| 1557 | 1000 | ||
| 1558 | int | 1001 | /* --------------- 80 to 8f --------------- */ |
| 1559 | mouse_pressed (b, xp, yp) | 1002 | Alt | Map | 9, /* '9' */ |
| 1560 | int b, *xp, *yp; | 1003 | Alt | Map | 10, /* '0' */ |
| 1561 | { | 1004 | Alt | Map | 11, /* '-' */ |
| 1562 | union REGS regs; | 1005 | Alt | Map | 12, /* '=' */ |
| 1006 | Ctrl | KeyPad | 9, /* (Ctrl) Page Up */ | ||
| 1007 | FctKey | 0xc8, /* F11 */ | ||
| 1008 | FctKey | 0xc9, /* F12 */ | ||
| 1009 | Shift | FctKey | 0xc8, /* (Shift) F11 */ | ||
| 1010 | Shift | FctKey | 0xc9, /* (Shift) F12 */ | ||
| 1011 | Ctrl | FctKey | 0xc8, /* (Ctrl) F11 */ | ||
| 1012 | Ctrl | FctKey | 0xc9, /* (Ctrl) F12 */ | ||
| 1013 | Alt | FctKey | 0xc8, /* (Alt) F11 */ | ||
| 1014 | Alt | FctKey | 0xc9, /* (Alt) F12 */ | ||
| 1015 | Ctrl | KeyPad | 8, /* (Ctrl) Up */ | ||
| 1016 | Ctrl | Grey | 2, /* (Ctrl) Grey - */ | ||
| 1017 | Ctrl | KeyPad | 5, /* (Ctrl) Keypad 5 */ | ||
| 1563 | 1018 | ||
| 1564 | if (b >= mouse_button_count) | 1019 | /* --------------- 90 to 9f --------------- */ |
| 1565 | return 0; | 1020 | Ctrl | Grey | 3, /* (Ctrl) Grey + */ |
| 1566 | regs.x.ax = 0x0005; | 1021 | Ctrl | KeyPad | 2, /* (Ctrl) Down */ |
| 1567 | regs.x.bx = mouse_button_translate[b]; | 1022 | Ctrl | KeyPad | 0, /* (Ctrl) Insert */ |
| 1568 | int86 (0x33, ®s, ®s); | 1023 | Ctrl | KeyPad | 10, /* (Ctrl) Delete */ |
| 1569 | if (regs.x.bx) | 1024 | Ctrl | FctKey | 0x09, /* (Ctrl) Tab */ |
| 1570 | *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; | 1025 | Ctrl | Grey | 0, /* (Ctrl) Grey / */ |
| 1571 | return (regs.x.bx != 0); | 1026 | Ctrl | Grey | 1, /* (Ctrl) Grey * */ |
| 1572 | } | 1027 | Alt | FctKey | 0x50, /* (Alt) Home */ |
| 1028 | Alt | FctKey | 0x52, /* (Alt) Up */ | ||
| 1029 | Alt | FctKey | 0x55, /* (Alt) Page Up */ | ||
| 1030 | Ignore, /* NO KEY */ | ||
| 1031 | Alt | FctKey | 0x51, /* (Alt) Left */ | ||
| 1032 | Ignore, /* NO KEY */ | ||
| 1033 | Alt | FctKey | 0x53, /* (Alt) Right */ | ||
| 1034 | Ignore, /* NO KEY */ | ||
| 1035 | Alt | FctKey | 0x57, /* (Alt) End */ | ||
| 1573 | 1036 | ||
| 1574 | int | 1037 | /* --------------- a0 to af --------------- */ |
| 1575 | mouse_released (b, xp, yp) | 1038 | Alt | KeyPad | 2, /* (Alt) Down */ |
| 1576 | int b, *xp, *yp; | 1039 | Alt | KeyPad | 3, /* (Alt) Page Down */ |
| 1577 | { | 1040 | Alt | KeyPad | 0, /* (Alt) Insert */ |
| 1578 | union REGS regs; | 1041 | Alt | KeyPad | 10, /* (Alt) Delete */ |
| 1042 | Alt | Grey | 0, /* (Alt) Grey / */ | ||
| 1043 | Alt | FctKey | 0x09, /* (Alt) Tab */ | ||
| 1044 | Alt | Grey | 4 /* (Alt) Keypad Enter */ | ||
| 1045 | }; | ||
| 1579 | 1046 | ||
| 1580 | if (b >= mouse_button_count) | 1047 | /* These bit-positions corresponds to values returned by BIOS */ |
| 1581 | return 0; | 1048 | #define SHIFT_P 0x0003 /* two bits! */ |
| 1582 | regs.x.ax = 0x0006; | 1049 | #define CTRL_P 0x0004 |
| 1583 | regs.x.bx = mouse_button_translate[b]; | 1050 | #define ALT_P 0x0008 |
| 1584 | int86 (0x33, ®s, ®s); | 1051 | #define SCRLOCK_P 0x0010 |
| 1585 | #if 0 | 1052 | #define NUMLOCK_P 0x0020 |
| 1586 | if (regs.x.ax & (1 << mouse_button_translate[b])) | 1053 | #define CAPSLOCK_P 0x0040 |
| 1587 | regs.x.bx = 0; /* if mouse is still pressed, ignore release */ | 1054 | #define ALT_GR_P 0x0800 |
| 1588 | #endif | 1055 | #define SUPER_P 0x4000 /* pseudo */ |
| 1589 | if (regs.x.bx) | 1056 | #define HYPER_P 0x8000 /* pseudo */ |
| 1590 | *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; | ||
| 1591 | return (regs.x.bx != 0); | ||
| 1592 | } | ||
| 1593 | 1057 | ||
| 1594 | static void | 1058 | static int |
| 1595 | mouse_get_xy (int *x, int *y) | 1059 | dos_get_modifiers (keymask) |
| 1060 | int *keymask; | ||
| 1596 | { | 1061 | { |
| 1597 | union REGS regs; | 1062 | union REGS regs; |
| 1063 | int mask; | ||
| 1064 | int modifiers = 0; | ||
| 1065 | |||
| 1066 | /* Calculate modifier bits */ | ||
| 1067 | regs.h.ah = extended_kbd ? 0x12 : 0x02; | ||
| 1068 | int86 (0x16, ®s, ®s); | ||
| 1598 | 1069 | ||
| 1599 | regs.x.ax = 0x0003; | 1070 | if (!extended_kbd) |
| 1600 | int86 (0x33, ®s, ®s); | 1071 | { |
| 1601 | *x = regs.x.cx / 8; | 1072 | mask = regs.h.al & (SHIFT_P | CTRL_P | ALT_P | |
| 1602 | *y = regs.x.dx / 8; | 1073 | SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P); |
| 1603 | } | 1074 | } |
| 1075 | else | ||
| 1076 | { | ||
| 1077 | mask = regs.h.al & (SHIFT_P | | ||
| 1078 | SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P); | ||
| 1079 | |||
| 1080 | /* Do not break international keyboard support. */ | ||
| 1081 | /* When Keyb.Com is loaded, the right Alt key is */ | ||
| 1082 | /* used for accessing characters like { and } */ | ||
| 1083 | if (regs.h.ah & 2) /* Left ALT pressed ? */ | ||
| 1084 | mask |= ALT_P; | ||
| 1604 | 1085 | ||
| 1605 | void | 1086 | if ((regs.h.ah & 8) != 0) /* Right ALT pressed ? */ |
| 1606 | mouse_get_pos (f, insist, bar_window, part, x, y, time) | 1087 | { |
| 1607 | FRAME_PTR *f; | 1088 | mask |= ALT_GR_P; |
| 1608 | int insist; | 1089 | if (dos_hyper_key == 1) |
| 1609 | Lisp_Object *bar_window, *x, *y; | 1090 | { |
| 1610 | enum scroll_bar_part *part; | 1091 | mask |= HYPER_P; |
| 1611 | unsigned long *time; | 1092 | modifiers |= hyper_modifier; |
| 1612 | { | 1093 | } |
| 1613 | int ix, iy; | 1094 | else if (dos_super_key == 1) |
| 1614 | union REGS regs; | 1095 | { |
| 1096 | mask |= SUPER_P; | ||
| 1097 | modifiers |= super_modifier; | ||
| 1098 | } | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | if (regs.h.ah & 1) /* Left CTRL pressed | ||
| 1102 | mask |= CTRL_P; | ||
| 1615 | 1103 | ||
| 1616 | regs.x.ax = 0x0003; | 1104 | if (regs.h.ah & 4) /* Right CTRL pressed ? */ |
| 1617 | int86 (0x33, ®s, ®s); | 1105 | { |
| 1618 | *f = selected_frame; | 1106 | if (dos_hyper_key == 2) |
| 1619 | *bar_window = Qnil; | 1107 | { |
| 1620 | mouse_get_xy (&ix, &iy); | 1108 | mask |= HYPER_P; |
| 1621 | selected_frame->mouse_moved = 0; | 1109 | modifiers |= hyper_modifier; |
| 1622 | *x = make_number (ix); | 1110 | } |
| 1623 | *y = make_number (iy); | 1111 | else if (dos_super_key == 2) |
| 1624 | *time = event_timestamp (); | 1112 | { |
| 1625 | } | 1113 | mask |= SUPER_P; |
| 1114 | modifiers |= super_modifier; | ||
| 1115 | } | ||
| 1116 | else | ||
| 1117 | mask |= CTRL_P; | ||
| 1118 | } | ||
| 1119 | } | ||
| 1626 | 1120 | ||
| 1627 | void | 1121 | if (mask & SHIFT_P) |
| 1628 | mouse_check_moved () | 1122 | modifiers |= shift_modifier; |
| 1629 | { | 1123 | if (mask & CTRL_P) |
| 1630 | int x, y; | 1124 | modifiers |= ctrl_modifier; |
| 1125 | if (mask & ALT_P) | ||
| 1126 | modifiers |= meta_modifier; | ||
| 1631 | 1127 | ||
| 1632 | mouse_get_xy (&x, &y); | 1128 | if (keymask) |
| 1633 | selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y); | 1129 | *keymask = mask; |
| 1634 | mouse_last_x = x; | 1130 | return modifiers; |
| 1635 | mouse_last_y = y; | ||
| 1636 | } | 1131 | } |
| 1637 | 1132 | ||
| 1638 | int | 1133 | /* Get a char from keyboard. Function keys are put into the event queue. */ |
| 1639 | mouse_init1 () | 1134 | static int |
| 1135 | dos_rawgetc () | ||
| 1640 | { | 1136 | { |
| 1137 | struct input_event event; | ||
| 1641 | union REGS regs; | 1138 | union REGS regs; |
| 1642 | int present; | 1139 | |
| 1643 | 1140 | #ifndef HAVE_X_WINDOWS | |
| 1644 | #ifdef HAVE_X_WINDOWS | 1141 | SCREEN_SET_CURSOR(); |
| 1645 | if (!inhibit_window_system) | 1142 | if (!mouse_visible) mouse_on (); |
| 1646 | return 0; | ||
| 1647 | #endif | 1143 | #endif |
| 1648 | if (!internal_terminal) | 1144 | |
| 1649 | return 0; | 1145 | /* The following condition is equivalent to `kbhit ()', except that |
| 1650 | 1146 | it uses the bios to do its job. This pleases DESQview/X. */ | |
| 1651 | regs.x.ax = 0x0021; | 1147 | while ((regs.h.ah = extended_kbd ? 0x11 : 0x01), |
| 1652 | int86 (0x33, ®s, ®s); | 1148 | int86 (0x16, ®s, ®s), |
| 1653 | present = (regs.x.ax & 0xffff) == 0xffff; | 1149 | (regs.x.flags & 0x40) == 0) |
| 1654 | if (!present) | ||
| 1655 | { | 1150 | { |
| 1656 | /* Reportedly, the above doesn't work for some mouse drivers. There | 1151 | union REGS regs; |
| 1657 | is an additional detection method that should work, but might be | 1152 | register unsigned char c; |
| 1658 | a little slower. Use that as an alternative. */ | 1153 | int sc, code, mask, kp_mode; |
| 1659 | regs.x.ax = 0x0000; | 1154 | int modifiers; |
| 1660 | int86 (0x33, ®s, ®s); | ||
| 1661 | present = (regs.x.ax & 0xffff) == 0xffff; | ||
| 1662 | } | ||
| 1663 | 1155 | ||
| 1664 | if (present) | 1156 | regs.h.ah = extended_kbd ? 0x10 : 0x00; |
| 1665 | { | 1157 | int86 (0x16, ®s, ®s); |
| 1666 | if (regs.x.bx == 3) | 1158 | c = regs.h.al; |
| 1159 | sc = regs.h.ah; | ||
| 1160 | |||
| 1161 | modifiers = dos_get_modifiers( &mask ); | ||
| 1162 | |||
| 1163 | #ifndef HAVE_X_WINDOWS | ||
| 1164 | if (!NILP(Vdos_display_scancodes)) | ||
| 1667 | { | 1165 | { |
| 1668 | mouse_button_count = 3; | 1166 | char buf[10]; |
| 1669 | mouse_button_translate[0] = 0; /* Left */ | 1167 | sprintf (buf, "%02x:%02x*%04x", |
| 1670 | mouse_button_translate[1] = 2; /* Middle */ | 1168 | (unsigned) (sc&0xff), (unsigned) c, mask); |
| 1671 | mouse_button_translate[2] = 1; /* Right */ | 1169 | dos_direct_output (screen_size_Y - 2, screen_size_X - 12, buf, 10); |
| 1170 | } | ||
| 1171 | #endif | ||
| 1172 | |||
| 1173 | if (sc == 0xe0) | ||
| 1174 | { | ||
| 1175 | switch (c) | ||
| 1176 | { | ||
| 1177 | case 10: /* Ctrl Grey Enter */ | ||
| 1178 | code = Ctrl | Grey | 4; | ||
| 1179 | break; | ||
| 1180 | case 13: /* Grey Enter */ | ||
| 1181 | code = Grey | 4; | ||
| 1182 | break; | ||
| 1183 | case '/': /* Grey / */ | ||
| 1184 | code = Grey | 0; | ||
| 1185 | break; | ||
| 1186 | default: | ||
| 1187 | continue; | ||
| 1188 | }; | ||
| 1189 | c = 0; | ||
| 1672 | } | 1190 | } |
| 1673 | else | 1191 | else |
| 1674 | { | 1192 | { |
| 1675 | mouse_button_count = 2; | 1193 | if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short))) |
| 1676 | mouse_button_translate[0] = 0; | 1194 | continue; |
| 1677 | mouse_button_translate[1] = 1; | 1195 | if ((code = ibmpc_translate_map[sc]) == Ignore) |
| 1196 | continue; | ||
| 1678 | } | 1197 | } |
| 1679 | mouse_position_hook = &mouse_get_pos; | 1198 | |
| 1680 | mouse_init (); | 1199 | if (c == 0) |
| 1200 | { | ||
| 1201 | if (code & Alt) | ||
| 1202 | modifiers |= meta_modifier; | ||
| 1203 | if (code & Ctrl) | ||
| 1204 | modifiers |= ctrl_modifier; | ||
| 1205 | if (code & Shift) | ||
| 1206 | modifiers |= shift_modifier; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | switch (code & 0xf000) | ||
| 1210 | { | ||
| 1211 | case ModFct: | ||
| 1212 | if (c && !(mask & (SHIFT_P | ALT_P | CTRL_P | HYPER_P | SUPER_P))) | ||
| 1213 | return c; | ||
| 1214 | c = 0; /* Special */ | ||
| 1215 | |||
| 1216 | case FctKey: | ||
| 1217 | if (c != 0) | ||
| 1218 | return c; | ||
| 1219 | |||
| 1220 | case Special: | ||
| 1221 | code |= 0xff00; | ||
| 1222 | break; | ||
| 1223 | |||
| 1224 | case Normal: | ||
| 1225 | if (sc == 0) | ||
| 1226 | { | ||
| 1227 | if (c == 0) /* ctrl-break */ | ||
| 1228 | continue; | ||
| 1229 | return c; /* ALT-nnn */ | ||
| 1230 | } | ||
| 1231 | if (!keyboard_map_all) | ||
| 1232 | { | ||
| 1233 | if (c != ' ') | ||
| 1234 | return c; | ||
| 1235 | code = c; | ||
| 1236 | break; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | case Map: | ||
| 1240 | if (c && !(mask & ALT_P) && !((mask & SHIFT_P) && (mask & CTRL_P))) | ||
| 1241 | if (!keyboard_map_all) | ||
| 1242 | return c; | ||
| 1243 | |||
| 1244 | code &= 0xff; | ||
| 1245 | if (mask & ALT_P && code <= 10 && code > 0 && dos_keypad_mode & 0x200) | ||
| 1246 | mask |= SHIFT_P; /* ALT-1 => M-! etc. */ | ||
| 1247 | |||
| 1248 | if (mask & SHIFT_P) | ||
| 1249 | { | ||
| 1250 | code = keyboard->shifted[ code ]; | ||
| 1251 | mask -= SHIFT_P; | ||
| 1252 | modifiers &= ~shift_modifier; | ||
| 1253 | } | ||
| 1254 | else | ||
| 1255 | if ((mask & ALT_GR_P) && keyboard->alt_gr && keyboard->alt_gr[ code ] != ' ') | ||
| 1256 | code = keyboard->alt_gr[ code ]; | ||
| 1257 | else | ||
| 1258 | code = keyboard->unshifted[ code ]; | ||
| 1259 | break; | ||
| 1260 | |||
| 1261 | case KeyPad: | ||
| 1262 | code &= 0xff; | ||
| 1263 | if (c == 0xe0) /* edit key */ | ||
| 1264 | kp_mode = 3; | ||
| 1265 | else | ||
| 1266 | if ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P) /* numlock on */ | ||
| 1267 | kp_mode = dos_keypad_mode & 0x03; | ||
| 1268 | else | ||
| 1269 | kp_mode = (dos_keypad_mode >> 4) & 0x03; | ||
| 1270 | |||
| 1271 | switch (kp_mode) | ||
| 1272 | { | ||
| 1273 | case 0: | ||
| 1274 | if (code == 10 && dos_decimal_point) | ||
| 1275 | return dos_decimal_point; | ||
| 1276 | return keypad_translate_map[ code ].char_code; | ||
| 1277 | |||
| 1278 | case 1: | ||
| 1279 | code = 0xff00 | keypad_translate_map[ code ].keypad_code; | ||
| 1280 | break; | ||
| 1281 | |||
| 1282 | case 2: | ||
| 1283 | code = keypad_translate_map[ code ].meta_code; | ||
| 1284 | modifiers = meta_modifier; | ||
| 1285 | break; | ||
| 1286 | |||
| 1287 | case 3: | ||
| 1288 | code = 0xff00 | keypad_translate_map[ code ].editkey_code; | ||
| 1289 | break; | ||
| 1290 | } | ||
| 1291 | break; | ||
| 1292 | |||
| 1293 | case Grey: | ||
| 1294 | code &= 0xff; | ||
| 1295 | kp_mode = ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P) ? 0x04 : 0x40; | ||
| 1296 | if (dos_keypad_mode & kp_mode) | ||
| 1297 | code = 0xff00 | grey_key_translate_map[ code ].keypad_code; | ||
| 1298 | else | ||
| 1299 | code = grey_key_translate_map[ code ].char_code; | ||
| 1300 | break; | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | make_event: | ||
| 1304 | if (code == 0) | ||
| 1305 | continue; | ||
| 1306 | |||
| 1307 | if (code >= 0x100) | ||
| 1308 | event.kind = non_ascii_keystroke; | ||
| 1309 | else | ||
| 1310 | event.kind = ascii_keystroke; | ||
| 1311 | event.code = code; | ||
| 1312 | event.modifiers = modifiers; | ||
| 1313 | XSETFRAME (event.frame_or_window, selected_frame); | ||
| 1314 | event.timestamp = event_timestamp (); | ||
| 1315 | kbd_buffer_store_event (&event); | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | if (have_mouse > 0) | ||
| 1319 | { | ||
| 1320 | int but, press, x, y, ok; | ||
| 1321 | |||
| 1322 | /* Check for mouse movement *before* buttons. */ | ||
| 1323 | mouse_check_moved (); | ||
| 1324 | |||
| 1325 | for (but = 0; but < NUM_MOUSE_BUTTONS; but++) | ||
| 1326 | for (press = 0; press < 2; press++) | ||
| 1327 | { | ||
| 1328 | if (press) | ||
| 1329 | ok = mouse_pressed (but, &x, &y); | ||
| 1330 | else | ||
| 1331 | ok = mouse_released (but, &x, &y); | ||
| 1332 | if (ok) | ||
| 1333 | { | ||
| 1334 | event.kind = mouse_click; | ||
| 1335 | event.code = but; | ||
| 1336 | event.modifiers = dos_get_modifiers (0) | ||
| 1337 | | (press ? down_modifier : up_modifier); | ||
| 1338 | event.x = x; | ||
| 1339 | event.y = y; | ||
| 1340 | XSETFRAME (event.frame_or_window, selected_frame); | ||
| 1341 | event.timestamp = event_timestamp (); | ||
| 1342 | kbd_buffer_store_event (&event); | ||
| 1343 | } | ||
| 1344 | } | ||
| 1681 | } | 1345 | } |
| 1682 | return present; | 1346 | |
| 1347 | return -1; | ||
| 1683 | } | 1348 | } |
| 1684 | 1349 | ||
| 1350 | static int prev_get_char = -1; | ||
| 1351 | |||
| 1352 | /* Return 1 if a key is ready to be read without suspending execution. */ | ||
| 1353 | dos_keysns () | ||
| 1354 | { | ||
| 1355 | if (prev_get_char != -1) | ||
| 1356 | return 1; | ||
| 1357 | else | ||
| 1358 | return ((prev_get_char = dos_rawgetc ()) != -1); | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | /* Read a key. Return -1 if no key is ready. */ | ||
| 1362 | dos_keyread () | ||
| 1363 | { | ||
| 1364 | if (prev_get_char != -1) | ||
| 1365 | { | ||
| 1366 | int c = prev_get_char; | ||
| 1367 | prev_get_char = -1; | ||
| 1368 | return c; | ||
| 1369 | } | ||
| 1370 | else | ||
| 1371 | return dos_rawgetc (); | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | |||
| 1375 | |||
| 1685 | #ifndef HAVE_X_WINDOWS | 1376 | #ifndef HAVE_X_WINDOWS |
| 1686 | /* See xterm.c for more info. */ | 1377 | /* See xterm.c for more info. */ |
| 1687 | void | 1378 | void |
| @@ -1766,7 +1457,7 @@ IT_menu_search_pane (XMenu *menu, int pane) | |||
| 1766 | { | 1457 | { |
| 1767 | if (pane == menu->panenumber[i]) | 1458 | if (pane == menu->panenumber[i]) |
| 1768 | return menu->submenu[i]; | 1459 | return menu->submenu[i]; |
| 1769 | else if ((try = IT_menu_search_pane (menu->submenu[i], pane))) | 1460 | if ((try = IT_menu_search_pane (menu->submenu[i], pane))) |
| 1770 | return try; | 1461 | return try; |
| 1771 | } | 1462 | } |
| 1772 | return (XMenu *) 0; | 1463 | return (XMenu *) 0; |
| @@ -1810,11 +1501,10 @@ IT_menu_display (XMenu *menu, int y, int x, int *faces) | |||
| 1810 | text = (GLYPH *) xmalloc ((width + 2) * sizeof (GLYPH)); | 1501 | text = (GLYPH *) xmalloc ((width + 2) * sizeof (GLYPH)); |
| 1811 | ScreenGetCursor (&row, &col); | 1502 | ScreenGetCursor (&row, &col); |
| 1812 | mouse_get_xy (&mx, &my); | 1503 | mouse_get_xy (&mx, &my); |
| 1813 | mouse_off (); | 1504 | IT_update_begin (); |
| 1814 | (*update_begin_hook) (); | ||
| 1815 | for (i = 0; i < menu->count; i++) | 1505 | for (i = 0; i < menu->count; i++) |
| 1816 | { | 1506 | { |
| 1817 | (*cursor_to_hook) (y + i, x); | 1507 | IT_cursor_to (y + i, x); |
| 1818 | enabled | 1508 | enabled |
| 1819 | = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]); | 1509 | = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]); |
| 1820 | mousehere = (y + i == my && x <= mx && mx < x + width + 2); | 1510 | mousehere = (y + i == my && x <= mx && mx < x + width + 2); |
| @@ -1826,15 +1516,15 @@ IT_menu_display (XMenu *menu, int y, int x, int *faces) | |||
| 1826 | for (; j < width; j++) | 1516 | for (; j < width; j++) |
| 1827 | *p++ = FAST_MAKE_GLYPH (' ', face); | 1517 | *p++ = FAST_MAKE_GLYPH (' ', face); |
| 1828 | *p++ = FAST_MAKE_GLYPH (menu->submenu[i] ? 16 : ' ', face); | 1518 | *p++ = FAST_MAKE_GLYPH (menu->submenu[i] ? 16 : ' ', face); |
| 1829 | (*write_glyphs_hook) (text, width + 2); | 1519 | IT_write_glyphs (text, width + 2); |
| 1830 | } | 1520 | } |
| 1831 | internal_flush (stdout); | 1521 | IT_update_end (); |
| 1832 | (*update_end_hook) (); | 1522 | IT_cursor_to (row, col); |
| 1833 | mouse_on (); | ||
| 1834 | ScreenSetCursor (row, col); | ||
| 1835 | xfree (text); | 1523 | xfree (text); |
| 1836 | } | 1524 | } |
| 1837 | 1525 | ||
| 1526 | /* --------------------------- X Menu emulation ---------------------- */ | ||
| 1527 | |||
| 1838 | /* Create a brand new menu structure. */ | 1528 | /* Create a brand new menu structure. */ |
| 1839 | 1529 | ||
| 1840 | XMenu * | 1530 | XMenu * |
| @@ -1929,7 +1619,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 1929 | return XM_IA_SELECT; | 1619 | return XM_IA_SELECT; |
| 1930 | 1620 | ||
| 1931 | state = alloca (menu->panecount * sizeof (struct IT_menu_state)); | 1621 | state = alloca (menu->panecount * sizeof (struct IT_menu_state)); |
| 1932 | screensize = ScreenRows () * ScreenCols () * 2; | 1622 | screensize = screen_size * 2; |
| 1933 | faces[0] | 1623 | faces[0] |
| 1934 | = compute_glyph_face (&the_only_frame, | 1624 | = compute_glyph_face (&the_only_frame, |
| 1935 | face_name_id_number | 1625 | face_name_id_number |
| @@ -1951,7 +1641,6 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 1951 | state[0].menu = menu; | 1641 | state[0].menu = menu; |
| 1952 | mouse_off (); | 1642 | mouse_off (); |
| 1953 | ScreenRetrieve (state[0].screen_behind = xmalloc (screensize)); | 1643 | ScreenRetrieve (state[0].screen_behind = xmalloc (screensize)); |
| 1954 | mouse_on (); | ||
| 1955 | if ((onepane = menu->count == 1 && menu->submenu[0])) | 1644 | if ((onepane = menu->count == 1 && menu->submenu[0])) |
| 1956 | { | 1645 | { |
| 1957 | menu->width = menu->submenu[0]->width; | 1646 | menu->width = menu->submenu[0]->width; |
| @@ -1969,6 +1658,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 1969 | leave = 0; | 1658 | leave = 0; |
| 1970 | while (!leave) | 1659 | while (!leave) |
| 1971 | { | 1660 | { |
| 1661 | if (!mouse_visible) mouse_on (); | ||
| 1972 | mouse_check_moved (); | 1662 | mouse_check_moved (); |
| 1973 | if (selected_frame->mouse_moved) | 1663 | if (selected_frame->mouse_moved) |
| 1974 | { | 1664 | { |
| @@ -1998,7 +1688,6 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 1998 | statecount--; | 1688 | statecount--; |
| 1999 | mouse_off (); | 1689 | mouse_off (); |
| 2000 | ScreenUpdate (state[statecount].screen_behind); | 1690 | ScreenUpdate (state[statecount].screen_behind); |
| 2001 | mouse_on (); | ||
| 2002 | xfree (state[statecount].screen_behind); | 1691 | xfree (state[statecount].screen_behind); |
| 2003 | } | 1692 | } |
| 2004 | if (i == statecount - 1 && state[i].menu->submenu[dy]) | 1693 | if (i == statecount - 1 && state[i].menu->submenu[dy]) |
| @@ -2012,7 +1701,6 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 2012 | mouse_off (); | 1701 | mouse_off (); |
| 2013 | ScreenRetrieve (state[statecount].screen_behind | 1702 | ScreenRetrieve (state[statecount].screen_behind |
| 2014 | = xmalloc (screensize)); | 1703 | = xmalloc (screensize)); |
| 2015 | mouse_on (); | ||
| 2016 | state[statecount].x | 1704 | state[statecount].x |
| 2017 | = state[i].x + state[i].menu->width + 2; | 1705 | = state[i].x + state[i].menu->width + 2; |
| 2018 | state[statecount].y = y; | 1706 | state[statecount].y = y; |
| @@ -2035,7 +1723,6 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 2035 | 1723 | ||
| 2036 | mouse_off (); | 1724 | mouse_off (); |
| 2037 | ScreenUpdate (state[0].screen_behind); | 1725 | ScreenUpdate (state[0].screen_behind); |
| 2038 | mouse_on (); | ||
| 2039 | while (statecount--) | 1726 | while (statecount--) |
| 2040 | xfree (state[statecount].screen_behind); | 1727 | xfree (state[statecount].screen_behind); |
| 2041 | return result; | 1728 | return result; |
| @@ -2072,4 +1759,720 @@ x_pixel_height (struct frame *f) | |||
| 2072 | } | 1759 | } |
| 2073 | #endif /* !HAVE_X_WINDOWS */ | 1760 | #endif /* !HAVE_X_WINDOWS */ |
| 2074 | 1761 | ||
| 1762 | |||
| 1763 | /* ----------------------- DOS / UNIX conversion --------------------- */ | ||
| 1764 | |||
| 1765 | /* Destructively turn backslashes into slashes. */ | ||
| 1766 | |||
| 1767 | void | ||
| 1768 | dostounix_filename (p) | ||
| 1769 | register char *p; | ||
| 1770 | { | ||
| 1771 | while (*p) | ||
| 1772 | { | ||
| 1773 | if (*p == '\\') | ||
| 1774 | *p = '/'; | ||
| 1775 | p++; | ||
| 1776 | } | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | /* Destructively turn slashes into backslashes. */ | ||
| 1780 | |||
| 1781 | void | ||
| 1782 | unixtodos_filename (p) | ||
| 1783 | register char *p; | ||
| 1784 | { | ||
| 1785 | while (*p) | ||
| 1786 | { | ||
| 1787 | if (*p == '/') | ||
| 1788 | *p = '\\'; | ||
| 1789 | p++; | ||
| 1790 | } | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */ | ||
| 1794 | |||
| 1795 | int | ||
| 1796 | getdefdir (drive, dst) | ||
| 1797 | int drive; | ||
| 1798 | char *dst; | ||
| 1799 | { | ||
| 1800 | union REGS regs; | ||
| 1801 | |||
| 1802 | *dst++ = '/'; | ||
| 1803 | regs.h.dl = drive; | ||
| 1804 | regs.x.si = (int) dst; | ||
| 1805 | regs.h.ah = 0x47; | ||
| 1806 | intdos (®s, ®s); | ||
| 1807 | return !regs.x.cflag; | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | /* Remove all CR's that are followed by a LF. */ | ||
| 1811 | |||
| 1812 | int | ||
| 1813 | crlf_to_lf (n, buf) | ||
| 1814 | register int n; | ||
| 1815 | register unsigned char *buf; | ||
| 1816 | { | ||
| 1817 | unsigned char *np = buf; | ||
| 1818 | unsigned char *startp = buf; | ||
| 1819 | unsigned char *endp = buf + n; | ||
| 1820 | unsigned char c; | ||
| 1821 | |||
| 1822 | if (n == 0) | ||
| 1823 | return n; | ||
| 1824 | while (buf < endp - 1) | ||
| 1825 | { | ||
| 1826 | if (*buf == 0x0d) | ||
| 1827 | { | ||
| 1828 | if (*(++buf) != 0x0a) | ||
| 1829 | *np++ = 0x0d; | ||
| 1830 | } | ||
| 1831 | else | ||
| 1832 | *np++ = *buf++; | ||
| 1833 | } | ||
| 1834 | if (buf < endp) | ||
| 1835 | *np++ = *buf++; | ||
| 1836 | return np - startp; | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | /* The Emacs root directory as determined by init_environment. */ | ||
| 1840 | |||
| 1841 | static char emacsroot[MAXPATHLEN]; | ||
| 1842 | |||
| 1843 | char * | ||
| 1844 | rootrelativepath (rel) | ||
| 1845 | char *rel; | ||
| 1846 | { | ||
| 1847 | static char result[MAXPATHLEN + 10]; | ||
| 1848 | |||
| 1849 | strcpy (result, emacsroot); | ||
| 1850 | strcat (result, "/"); | ||
| 1851 | strcat (result, rel); | ||
| 1852 | return result; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | /* Define a lot of environment variables if not already defined. Don't | ||
| 1856 | remove anything unless you know what you're doing -- lots of code will | ||
| 1857 | break if one or more of these are missing. */ | ||
| 1858 | |||
| 1859 | void | ||
| 1860 | init_environment (argc, argv, skip_args) | ||
| 1861 | int argc; | ||
| 1862 | char **argv; | ||
| 1863 | int skip_args; | ||
| 1864 | { | ||
| 1865 | char *s, *t, *root; | ||
| 1866 | int len; | ||
| 1867 | |||
| 1868 | /* Find our root from argv[0]. Assuming argv[0] is, say, | ||
| 1869 | "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */ | ||
| 1870 | root = alloca (MAXPATHLEN + 20); | ||
| 1871 | _fixpath (argv[0], root); | ||
| 1872 | strlwr (root); | ||
| 1873 | len = strlen (root); | ||
| 1874 | while (len > 0 && root[len] != '/' && root[len] != ':') | ||
| 1875 | len--; | ||
| 1876 | root[len] = '\0'; | ||
| 1877 | if (len > 4 && strcmp (root + len - 4, "/bin") == 0) | ||
| 1878 | root[len - 4] = '\0'; | ||
| 1879 | else | ||
| 1880 | strcpy (root, "c:/emacs"); /* Only under debuggers, I think. */ | ||
| 1881 | len = strlen (root); | ||
| 1882 | strcpy (emacsroot, root); | ||
| 1883 | |||
| 1884 | /* We default HOME to our root. */ | ||
| 1885 | setenv ("HOME", root, 0); | ||
| 1886 | |||
| 1887 | /* We default EMACSPATH to root + "/bin". */ | ||
| 1888 | strcpy (root + len, "/bin"); | ||
| 1889 | setenv ("EMACSPATH", root, 0); | ||
| 1890 | |||
| 1891 | /* I don't expect anybody to ever use other terminals so the internal | ||
| 1892 | terminal is the default. */ | ||
| 1893 | setenv ("TERM", "internal", 0); | ||
| 1894 | |||
| 1895 | #ifdef HAVE_X_WINDOWS | ||
| 1896 | /* Emacs expects DISPLAY to be set. */ | ||
| 1897 | setenv ("DISPLAY", "unix:0.0", 0); | ||
| 1898 | #endif | ||
| 1899 | |||
| 1900 | /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must | ||
| 1901 | downcase it and mirror the backslashes. */ | ||
| 1902 | s = getenv ("COMSPEC"); | ||
| 1903 | if (!s) s = "c:/command.com"; | ||
| 1904 | t = alloca (strlen (s) + 1); | ||
| 1905 | strcpy (t, s); | ||
| 1906 | strlwr (t); | ||
| 1907 | dostounix_filename (t); | ||
| 1908 | setenv ("SHELL", t, 0); | ||
| 1909 | |||
| 1910 | /* PATH is also downcased and backslashes mirrored. */ | ||
| 1911 | s = getenv ("PATH"); | ||
| 1912 | if (!s) s = ""; | ||
| 1913 | t = alloca (strlen (s) + 3); | ||
| 1914 | /* Current directory is always considered part of MsDos's path but it is | ||
| 1915 | not normally mentioned. Now it is. */ | ||
| 1916 | strcat (strcpy (t, ".;"), s); | ||
| 1917 | strlwr (t); | ||
| 1918 | dostounix_filename (t); /* Not a single file name, but this should work. */ | ||
| 1919 | setenv ("PATH", t, 1); | ||
| 1920 | |||
| 1921 | /* In some sense all dos users have root privileges, so... */ | ||
| 1922 | setenv ("USER", "root", 0); | ||
| 1923 | setenv ("NAME", getenv ("USER"), 0); | ||
| 1924 | |||
| 1925 | /* Time zone determined from country code. To make this possible, the | ||
| 1926 | country code may not span more than one time zone. In other words, | ||
| 1927 | in the USA, you lose. */ | ||
| 1928 | if (!getenv("TZ")) | ||
| 1929 | switch (dos_country_code) | ||
| 1930 | { | ||
| 1931 | case 31: /* Belgium */ | ||
| 1932 | case 32: /* The Netherlands */ | ||
| 1933 | case 33: /* France */ | ||
| 1934 | case 34: /* Spain */ | ||
| 1935 | case 36: /* Hungary */ | ||
| 1936 | case 38: /* Yugoslavia (or what's left of it?) */ | ||
| 1937 | case 39: /* Italy */ | ||
| 1938 | case 41: /* Switzerland */ | ||
| 1939 | case 42: /* Tjekia */ | ||
| 1940 | case 45: /* Denmark */ | ||
| 1941 | case 46: /* Sweden */ | ||
| 1942 | case 47: /* Norway */ | ||
| 1943 | case 48: /* Poland */ | ||
| 1944 | case 49: /* Germany */ | ||
| 1945 | /* Daylight saving from last Sunday in March to last Sunday in | ||
| 1946 | September, both at 2AM. */ | ||
| 1947 | setenv ("TZ", "MET" /* "-01METDST-02,M3.5.0/02:00,M9.5.0/02:00" */, 0); | ||
| 1948 | break; | ||
| 1949 | case 44: /* United Kingdom */ | ||
| 1950 | case 351: /* Portugal */ | ||
| 1951 | case 354: /* Iceland */ | ||
| 1952 | setenv ("TZ", "GMT" /* "+00" */, 0); | ||
| 1953 | break; | ||
| 1954 | case 81: /* Japan */ | ||
| 1955 | case 82: /* Korea */ | ||
| 1956 | setenv ("TZ", "JST" /* "-09" */, 0); | ||
| 1957 | break; | ||
| 1958 | case 90: /* Turkey */ | ||
| 1959 | case 358: /* Finland */ | ||
| 1960 | case 972: /* Israel */ | ||
| 1961 | setenv ("TZ", "EET" /* "-02" */, 0); | ||
| 1962 | break; | ||
| 1963 | } | ||
| 1964 | } | ||
| 1965 | |||
| 1966 | |||
| 1967 | |||
| 1968 | static int break_stat; /* BREAK check mode status. */ | ||
| 1969 | static int stdin_stat; /* stdin IOCTL status. */ | ||
| 1970 | |||
| 1971 | /* These must be global. */ | ||
| 1972 | static _go32_dpmi_seginfo ctrl_break_vector; | ||
| 1973 | static _go32_dpmi_registers ctrl_break_regs; | ||
| 1974 | static int ctrlbreakinstalled = 0; | ||
| 1975 | |||
| 1976 | /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */ | ||
| 1977 | |||
| 1978 | void | ||
| 1979 | ctrl_break_func (regs) | ||
| 1980 | _go32_dpmi_registers *regs; | ||
| 1981 | { | ||
| 1982 | Vquit_flag = Qt; | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | void | ||
| 1986 | install_ctrl_break_check () | ||
| 1987 | { | ||
| 1988 | if (!ctrlbreakinstalled) | ||
| 1989 | { | ||
| 1990 | /* Don't press Ctrl-Break if you don't have either DPMI or Emacs | ||
| 1991 | was compiler with Djgpp 1.11 maintenance level 5 or later! */ | ||
| 1992 | ctrlbreakinstalled = 1; | ||
| 1993 | ctrl_break_vector.pm_offset = (int) ctrl_break_func; | ||
| 1994 | _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector, | ||
| 1995 | &ctrl_break_regs); | ||
| 1996 | _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector); | ||
| 1997 | } | ||
| 1998 | } | ||
| 1999 | |||
| 2000 | /* | ||
| 2001 | * Turn off Dos' Ctrl-C checking and inhibit interpretation of | ||
| 2002 | * control chars by Dos. | ||
| 2003 | * Determine the keyboard type. | ||
| 2004 | */ | ||
| 2005 | |||
| 2006 | int | ||
| 2007 | dos_ttraw () | ||
| 2008 | { | ||
| 2009 | union REGS inregs, outregs; | ||
| 2010 | static int first_time = 1; | ||
| 2011 | |||
| 2012 | break_stat = getcbrk (); | ||
| 2013 | setcbrk (0); | ||
| 2014 | install_ctrl_break_check (); | ||
| 2015 | |||
| 2016 | if (first_time) | ||
| 2017 | { | ||
| 2018 | inregs.h.ah = 0xc0; | ||
| 2019 | int86 (0x15, &inregs, &outregs); | ||
| 2020 | extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0); | ||
| 2021 | |||
| 2022 | have_mouse = 0; | ||
| 2023 | |||
| 2024 | if (internal_terminal | ||
| 2025 | #ifdef HAVE_X_WINDOWS | ||
| 2026 | && inhibit_window_system | ||
| 2027 | #endif | ||
| 2028 | ) | ||
| 2029 | { | ||
| 2030 | inregs.x.ax = 0x0021; | ||
| 2031 | int86 (0x33, &inregs, &outregs); | ||
| 2032 | have_mouse = (outregs.x.ax & 0xffff) == 0xffff; | ||
| 2033 | if (!have_mouse) | ||
| 2034 | { | ||
| 2035 | /* Reportedly, the above doesn't work for some mouse drivers. There | ||
| 2036 | is an additional detection method that should work, but might be | ||
| 2037 | a little slower. Use that as an alternative. */ | ||
| 2038 | inregs.x.ax = 0x0000; | ||
| 2039 | int86 (0x33, &inregs, &outregs); | ||
| 2040 | have_mouse = (outregs.x.ax & 0xffff) == 0xffff; | ||
| 2041 | } | ||
| 2042 | |||
| 2043 | if (have_mouse) | ||
| 2044 | { | ||
| 2045 | have_mouse = 1; /* enable mouse */ | ||
| 2046 | mouse_visible = 0; | ||
| 2047 | |||
| 2048 | if (outregs.x.bx == 3) | ||
| 2049 | { | ||
| 2050 | mouse_button_count = 3; | ||
| 2051 | mouse_button_translate[0] = 0; /* Left */ | ||
| 2052 | mouse_button_translate[1] = 2; /* Middle */ | ||
| 2053 | mouse_button_translate[2] = 1; /* Right */ | ||
| 2054 | } | ||
| 2055 | else | ||
| 2056 | { | ||
| 2057 | mouse_button_count = 2; | ||
| 2058 | mouse_button_translate[0] = 0; | ||
| 2059 | mouse_button_translate[1] = 1; | ||
| 2060 | } | ||
| 2061 | mouse_position_hook = &mouse_get_pos; | ||
| 2062 | mouse_init (); | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | first_time = 0; | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | inregs.x.ax = 0x4400; /* Get IOCTL status. */ | ||
| 2070 | inregs.x.bx = 0x00; /* 0 = stdin. */ | ||
| 2071 | intdos (&inregs, &outregs); | ||
| 2072 | stdin_stat = outregs.h.dl; | ||
| 2073 | |||
| 2074 | inregs.x.dx = stdin_stat | 0x0020; /* raw mode */ | ||
| 2075 | inregs.x.ax = 0x4401; /* Set IOCTL status */ | ||
| 2076 | intdos (&inregs, &outregs); | ||
| 2077 | return !outregs.x.cflag; | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | /* Restore status of standard input and Ctrl-C checking. */ | ||
| 2081 | int | ||
| 2082 | dos_ttcooked () | ||
| 2083 | { | ||
| 2084 | union REGS inregs, outregs; | ||
| 2085 | |||
| 2086 | setcbrk (break_stat); | ||
| 2087 | mouse_off (); | ||
| 2088 | |||
| 2089 | inregs.x.ax = 0x4401; /* Set IOCTL status. */ | ||
| 2090 | inregs.x.bx = 0x00; /* 0 = stdin. */ | ||
| 2091 | inregs.x.dx = stdin_stat; | ||
| 2092 | intdos (&inregs, &outregs); | ||
| 2093 | return !outregs.x.cflag; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | |||
| 2097 | /* Run command as specified by ARGV in directory DIR. | ||
| 2098 | The command is run with input from TEMPIN and output to file TEMPOUT. */ | ||
| 2099 | int | ||
| 2100 | run_msdos_command (argv, dir, tempin, tempout) | ||
| 2101 | unsigned char **argv; | ||
| 2102 | Lisp_Object dir; | ||
| 2103 | int tempin, tempout; | ||
| 2104 | { | ||
| 2105 | char *saveargv1, *saveargv2, **envv; | ||
| 2106 | char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ | ||
| 2107 | int msshell, result = -1; | ||
| 2108 | int in, out, inbak, outbak, errbak; | ||
| 2109 | int x, y; | ||
| 2110 | Lisp_Object cmd; | ||
| 2111 | |||
| 2112 | /* Get current directory as MSDOS cwd is not per-process. */ | ||
| 2113 | getwd (oldwd); | ||
| 2114 | |||
| 2115 | cmd = Ffile_name_nondirectory (build_string (argv[0])); | ||
| 2116 | msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells")))) | ||
| 2117 | && !strcmp ("-c", argv[1]); | ||
| 2118 | if (msshell) | ||
| 2119 | { | ||
| 2120 | saveargv1 = argv[1]; | ||
| 2121 | saveargv2 = argv[2]; | ||
| 2122 | argv[1] = "/c"; | ||
| 2123 | if (argv[2]) | ||
| 2124 | { | ||
| 2125 | char *p = alloca (strlen (argv[2]) + 1); | ||
| 2126 | |||
| 2127 | strcpy (argv[2] = p, saveargv2); | ||
| 2128 | while (*p && isspace (*p)) | ||
| 2129 | p++; | ||
| 2130 | while (*p && !isspace (*p)) | ||
| 2131 | if (*p == '/') | ||
| 2132 | *p++ = '\\'; | ||
| 2133 | else | ||
| 2134 | p++; | ||
| 2135 | } | ||
| 2136 | } | ||
| 2137 | |||
| 2138 | /* Build the environment array. */ | ||
| 2139 | { | ||
| 2140 | extern Lisp_Object Vprocess_environment; | ||
| 2141 | Lisp_Object tmp, lst; | ||
| 2142 | int i, len; | ||
| 2143 | |||
| 2144 | lst = Vprocess_environment; | ||
| 2145 | len = XFASTINT (Flength (lst)); | ||
| 2146 | |||
| 2147 | envv = alloca ((len + 1) * sizeof (char *)); | ||
| 2148 | for (i = 0; i < len; i++) | ||
| 2149 | { | ||
| 2150 | tmp = Fcar (lst); | ||
| 2151 | lst = Fcdr (lst); | ||
| 2152 | CHECK_STRING (tmp, 0); | ||
| 2153 | envv[i] = alloca (XSTRING (tmp)->size + 1); | ||
| 2154 | strcpy (envv[i], XSTRING (tmp)->data); | ||
| 2155 | } | ||
| 2156 | envv[len] = (char *) 0; | ||
| 2157 | } | ||
| 2158 | |||
| 2159 | if (STRINGP (dir)) | ||
| 2160 | chdir (XSTRING (dir)->data); | ||
| 2161 | inbak = dup (0); | ||
| 2162 | outbak = dup (1); | ||
| 2163 | errbak = dup (2); | ||
| 2164 | if (inbak < 0 || outbak < 0 || errbak < 0) | ||
| 2165 | goto done; /* Allocation might fail due to lack of descriptors. */ | ||
| 2166 | |||
| 2167 | if (have_mouse > 0) | ||
| 2168 | mouse_get_xy (&x, &y); | ||
| 2169 | |||
| 2170 | dos_ttcooked (); /* do it here while 0 = stdin */ | ||
| 2171 | |||
| 2172 | dup2 (tempin, 0); | ||
| 2173 | dup2 (tempout, 1); | ||
| 2174 | dup2 (tempout, 2); | ||
| 2175 | |||
| 2176 | result = spawnve (P_WAIT, argv[0], argv, envv); | ||
| 2177 | |||
| 2178 | dup2 (inbak, 0); | ||
| 2179 | dup2 (outbak, 1); | ||
| 2180 | dup2 (errbak, 2); | ||
| 2181 | close (inbak); | ||
| 2182 | close (outbak); | ||
| 2183 | close (errbak); | ||
| 2184 | |||
| 2185 | dos_ttraw(); | ||
| 2186 | if (have_mouse > 0) | ||
| 2187 | { | ||
| 2188 | mouse_init (); | ||
| 2189 | mouse_moveto (x, y); | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | done: | ||
| 2193 | chdir (oldwd); | ||
| 2194 | if (msshell) | ||
| 2195 | { | ||
| 2196 | argv[1] = saveargv1; | ||
| 2197 | argv[2] = saveargv2; | ||
| 2198 | } | ||
| 2199 | return result; | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | croak (badfunc) | ||
| 2203 | char *badfunc; | ||
| 2204 | { | ||
| 2205 | fprintf (stderr, "%s not yet implemented\r\n", badfunc); | ||
| 2206 | reset_sys_modes (); | ||
| 2207 | exit (1); | ||
| 2208 | } | ||
| 2209 | |||
| 2210 | |||
| 2211 | /* ------------------------- Compatibility functions ------------------- | ||
| 2212 | * gethostname | ||
| 2213 | * gettimeofday | ||
| 2214 | */ | ||
| 2215 | |||
| 2216 | /* | ||
| 2217 | * Hostnames for a pc are not really funny, | ||
| 2218 | * but they are used in change log so we emulate the best we can. | ||
| 2219 | */ | ||
| 2220 | |||
| 2221 | gethostname (p, size) | ||
| 2222 | char *p; | ||
| 2223 | int size; | ||
| 2224 | { | ||
| 2225 | char *q = egetenv ("HOSTNAME"); | ||
| 2226 | |||
| 2227 | if (!q) q = "pc"; | ||
| 2228 | strcpy (p, q); | ||
| 2229 | return 0; | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | /* When time zones are set from Ms-Dos too may C-libraries are playing | ||
| 2233 | tricks with time values. We solve this by defining our own version | ||
| 2234 | of `gettimeofday' bypassing GO32. Our version needs to be initialized | ||
| 2235 | once and after each call to `tzset' with TZ changed. That is | ||
| 2236 | accomplished by aliasing tzset to init_gettimeofday. */ | ||
| 2237 | |||
| 2238 | static struct tm time_rec; | ||
| 2239 | |||
| 2240 | int | ||
| 2241 | gettimeofday (struct timeval *tp, struct timezone *tzp) | ||
| 2242 | { | ||
| 2243 | if (tp) | ||
| 2244 | { | ||
| 2245 | struct time t; | ||
| 2246 | struct tm tm; | ||
| 2247 | |||
| 2248 | gettime (&t); | ||
| 2249 | if (t.ti_hour < time_rec.tm_hour) /* midnight wrap */ | ||
| 2250 | { | ||
| 2251 | struct date d; | ||
| 2252 | getdate (&d); | ||
| 2253 | time_rec.tm_year = d.da_year - 1900; | ||
| 2254 | time_rec.tm_mon = d.da_mon - 1; | ||
| 2255 | time_rec.tm_mday = d.da_day; | ||
| 2256 | } | ||
| 2257 | |||
| 2258 | time_rec.tm_hour = t.ti_hour; | ||
| 2259 | time_rec.tm_min = t.ti_min; | ||
| 2260 | time_rec.tm_sec = t.ti_sec; | ||
| 2261 | |||
| 2262 | tm = time_rec; | ||
| 2263 | tm.tm_gmtoff = dos_timezone_offset; | ||
| 2264 | |||
| 2265 | tp->tv_sec = mktime (&tm); /* may modify tm */ | ||
| 2266 | tp->tv_usec = t.ti_hund * (1000000 / 100); | ||
| 2267 | } | ||
| 2268 | /* Ignore tzp; it's obsolescent. */ | ||
| 2269 | return 0; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | |||
| 2273 | /* | ||
| 2274 | * A list of unimplemented functions that we silently ignore. | ||
| 2275 | */ | ||
| 2276 | |||
| 2277 | unsigned alarm (s) unsigned s; {} | ||
| 2278 | fork () { return 0; } | ||
| 2279 | int kill (x, y) int x, y; { return -1; } | ||
| 2280 | nice (p) int p; {} | ||
| 2281 | void volatile pause () {} | ||
| 2282 | request_sigio () {} | ||
| 2283 | setpgrp () {return 0; } | ||
| 2284 | setpriority (x,y,z) int x,y,z; { return 0; } | ||
| 2285 | sigsetmask (x) int x; { return 0; } | ||
| 2286 | unrequest_sigio () {} | ||
| 2287 | |||
| 2288 | int run_dos_timer_hooks = 0; | ||
| 2289 | |||
| 2290 | #ifndef HAVE_SELECT | ||
| 2291 | #include "sysselect.h" | ||
| 2292 | |||
| 2293 | static int last_ti_sec = -1; | ||
| 2294 | |||
| 2295 | static void | ||
| 2296 | check_timer (t) | ||
| 2297 | struct time *t; | ||
| 2298 | { | ||
| 2299 | gettime (t); | ||
| 2300 | |||
| 2301 | if (t->ti_sec == last_ti_sec) | ||
| 2302 | return; | ||
| 2303 | last_ti_sec = t->ti_sec; | ||
| 2304 | |||
| 2305 | if (!NILP (Vdos_menubar_clock)) | ||
| 2306 | { | ||
| 2307 | char clock_str[16]; | ||
| 2308 | int len; | ||
| 2309 | int min = t->ti_min; | ||
| 2310 | int hour = t->ti_hour; | ||
| 2311 | |||
| 2312 | if (dos_timezone_offset) | ||
| 2313 | { | ||
| 2314 | int tz = dos_timezone_offset; | ||
| 2315 | min -= tz % 60; | ||
| 2316 | if (min < 0) | ||
| 2317 | min += 60, hour--; | ||
| 2318 | else | ||
| 2319 | if (min >= 60) | ||
| 2320 | min -= 60, hour++; | ||
| 2321 | |||
| 2322 | if ((hour -= (tz / 60)) < 0) | ||
| 2323 | hour += 24; | ||
| 2324 | else | ||
| 2325 | hour %= 24; | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | if ((dos_country_info[0x11] & 0x01) == 0) /* 12 hour clock */ | ||
| 2329 | { | ||
| 2330 | hour %= 12; | ||
| 2331 | if (hour == 0) hour = 12; | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | len = sprintf (clock_str, "%2d.%02d.%02d", hour, min, t->ti_sec); | ||
| 2335 | dos_direct_output (0, screen_size_X - len - 1, clock_str, len); | ||
| 2336 | } | ||
| 2337 | |||
| 2338 | if (!NILP (Vdos_timer_hooks)) | ||
| 2339 | run_dos_timer_hooks++; | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | /* Only event queue is checked. */ | ||
| 2343 | int | ||
| 2344 | sys_select (nfds, rfds, wfds, efds, timeout) | ||
| 2345 | int nfds; | ||
| 2346 | SELECT_TYPE *rfds, *wfds, *efds; | ||
| 2347 | EMACS_TIME *timeout; | ||
| 2348 | { | ||
| 2349 | int check_input; | ||
| 2350 | long timeoutval, clnow, cllast; | ||
| 2351 | struct time t; | ||
| 2352 | |||
| 2353 | check_input = 0; | ||
| 2354 | if (rfds) | ||
| 2355 | { | ||
| 2356 | check_input = FD_ISSET (0, rfds); | ||
| 2357 | FD_ZERO (rfds); | ||
| 2358 | } | ||
| 2359 | if (wfds) | ||
| 2360 | FD_ZERO (wfds); | ||
| 2361 | if (efds) | ||
| 2362 | FD_ZERO (efds); | ||
| 2363 | |||
| 2364 | if (nfds != 1) | ||
| 2365 | abort (); | ||
| 2366 | |||
| 2367 | /* If we are looking only for the terminal, with no timeout, | ||
| 2368 | just read it and wait -- that's more efficient. */ | ||
| 2369 | if (!timeout) | ||
| 2370 | { | ||
| 2371 | while (! detect_input_pending ()) | ||
| 2372 | check_timer (&t); | ||
| 2373 | } | ||
| 2374 | else | ||
| 2375 | { | ||
| 2376 | timeoutval = EMACS_SECS (*timeout) * 100 + EMACS_USECS (*timeout) / 10000; | ||
| 2377 | check_timer (&t); | ||
| 2378 | cllast = t.ti_sec * 100 + t.ti_hund; | ||
| 2379 | |||
| 2380 | while (!check_input || !detect_input_pending ()) | ||
| 2381 | { | ||
| 2382 | check_timer (&t); | ||
| 2383 | clnow = t.ti_sec * 100 + t.ti_hund; | ||
| 2384 | if (clnow < cllast) /* time wrap */ | ||
| 2385 | timeoutval -= clnow + 6000 - cllast; | ||
| 2386 | else | ||
| 2387 | timeoutval -= clnow - cllast; | ||
| 2388 | if (timeoutval <= 0) /* Stop on timer being cleared */ | ||
| 2389 | return 0; | ||
| 2390 | cllast = clnow; | ||
| 2391 | } | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | FD_SET (0, rfds); | ||
| 2395 | return 1; | ||
| 2396 | } | ||
| 2397 | #endif | ||
| 2398 | |||
| 2399 | /* | ||
| 2400 | * Define overlayed functions: | ||
| 2401 | * | ||
| 2402 | * chdir -> sys_chdir | ||
| 2403 | * tzset -> init_gettimeofday | ||
| 2404 | * abort -> dos_abort | ||
| 2405 | */ | ||
| 2406 | |||
| 2407 | #ifdef chdir | ||
| 2408 | #undef chdir | ||
| 2409 | extern int chdir (); | ||
| 2410 | |||
| 2411 | int | ||
| 2412 | sys_chdir (path) | ||
| 2413 | const char* path; | ||
| 2414 | { | ||
| 2415 | int len = strlen (path); | ||
| 2416 | char *tmp = (char *)path; | ||
| 2417 | |||
| 2418 | if (*tmp && tmp[1] == ':') | ||
| 2419 | { | ||
| 2420 | if (getdisk () != tolower (tmp[0]) - 'a') | ||
| 2421 | setdisk (tolower (tmp[0]) - 'a'); | ||
| 2422 | tmp += 2; /* strip drive: KFS 1995-07-06 */ | ||
| 2423 | len -= 2; | ||
| 2424 | } | ||
| 2425 | |||
| 2426 | if (len > 1 && (tmp[len - 1] == '/')) | ||
| 2427 | { | ||
| 2428 | char *tmp1 = (char *) alloca (len + 1); | ||
| 2429 | strcpy (tmp1, tmp); | ||
| 2430 | tmp1[len - 1] = 0; | ||
| 2431 | tmp = tmp1; | ||
| 2432 | } | ||
| 2433 | return chdir (tmp); | ||
| 2434 | } | ||
| 2435 | #endif | ||
| 2436 | |||
| 2437 | #ifdef tzset | ||
| 2438 | #undef tzset | ||
| 2439 | extern void tzset (void); | ||
| 2440 | |||
| 2441 | void | ||
| 2442 | init_gettimeofday () | ||
| 2443 | { | ||
| 2444 | time_t ltm, gtm; | ||
| 2445 | struct tm *lstm; | ||
| 2446 | |||
| 2447 | tzset (); | ||
| 2448 | ltm = gtm = time (NULL); | ||
| 2449 | ltm = mktime (lstm = localtime (<m)); | ||
| 2450 | gtm = mktime (gmtime (>m)); | ||
| 2451 | time_rec.tm_hour = 99; /* force gettimeofday to get date */ | ||
| 2452 | time_rec.tm_isdst = lstm->tm_isdst; | ||
| 2453 | dos_timezone_offset = time_rec.tm_gmtoff = (int)(gtm - ltm) / 60; | ||
| 2454 | } | ||
| 2455 | #endif | ||
| 2456 | |||
| 2457 | #ifdef abort | ||
| 2458 | #undef abort | ||
| 2459 | void | ||
| 2460 | dos_abort (file, line) | ||
| 2461 | char *file; | ||
| 2462 | int line; | ||
| 2463 | { | ||
| 2464 | char buffer1[200], buffer2[400]; | ||
| 2465 | int i, j; | ||
| 2466 | |||
| 2467 | sprintf (buffer1, "<EMACS FATAL ERROR IN %s LINE %d>", file, line); | ||
| 2468 | for (i = j = 0; buffer1[i]; i++) { | ||
| 2469 | buffer2[j++] = buffer1[i]; | ||
| 2470 | buffer2[j++] = 0x70; | ||
| 2471 | } | ||
| 2472 | dosmemput (buffer2, j, (int)ScreenPrimary); | ||
| 2473 | ScreenSetCursor (2, 0); | ||
| 2474 | abort (); | ||
| 2475 | } | ||
| 2476 | #endif | ||
| 2477 | |||
| 2075 | #endif /* MSDOS */ | 2478 | #endif /* MSDOS */ |