comparison src/msdos.c @ 13179:b0de215331ba

[!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.
author Kim F. Storm <storm@cua.dk>
date Wed, 11 Oct 1995 15:08:15 +0000
parents 169d50e2ee4c
children 712386e1abe0
comparison
equal deleted inserted replaced
13178:74b4edb62cf0 13179:b0de215331ba
16 You should have received a copy of the GNU General Public License 16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to 17 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
24 #include <config.h> 25 #include <config.h>
25 26
43 #include <ctype.h> 44 #include <ctype.h>
44 /* #include <process.h> */ 45 /* #include <process.h> */
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 */ 72
144 0xffb2, /* Keypad 2 */ 73 int have_mouse; /* 0: no, 1: enabled, -1: disabled */
145 0xffb3, /* Keypad 3 */ 74 static int mouse_visible;
146 0xffb4, /* Keypad 4 */ 75
147 0xffb5, /* Keypad 5 */ 76 static int mouse_last_x;
148 0xffb6, /* Keypad 6 */ 77 static int mouse_last_y;
149 0xffb7, /* Keypad 7 */ 78
150 0xffb8, /* Keypad 8 */ 79 static int mouse_button_translate[NUM_MOUSE_BUTTONS];
151 0xffb9, /* Keypad 9 */ 80 static int mouse_button_count;
152 0xffb0, /* Keypad 0 */ 81
153 '-', '=', 82 void
154 0xff08, /* Backspace */ 83 mouse_on ()
155 0xff74, /* (Shift) Tab [Tab doesn't use this table] */ 84 {
156 85 union REGS regs;
157 /* --------------- 10 to 1f --------------- */ 86
158 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 87 if (have_mouse > 0 && !mouse_visible)
159 0xff8d, /* Keypad Enter */ 88 {
160 0, /* Ctrl */ 89 if (termscript)
161 'a', 's', 90 fprintf (termscript, "<M_ON>");
162 91 regs.x.ax = 0x0001;
163 /* --------------- 20 to 2f --------------- */ 92 int86 (0x33, &regs, &regs);
164 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 93 mouse_visible = 1;
165 0, /* Left shift */ 94 }
166 '\\', 'z', 'x', 'c', 'v', 95 }
167 96
168 /* --------------- 30 to 3f --------------- */ 97 void
169 'b', 'n', 'm', ',', '.', 98 mouse_off ()
170 0xffaf, /* Grey / */ 99 {
171 0, /* Right shift */ 100 union REGS regs;
172 0xffaa, /* Grey * */ 101
173 0, /* Alt */ 102 if (have_mouse > 0 && mouse_visible)
174 ' ', 103 {
175 0, /* Caps Lock */ 104 if (termscript)
176 0xffbe, /* F1 */ 105 fprintf (termscript, "<M_OFF>");
177 0xffbf, /* F2 */ 106 regs.x.ax = 0x0002;
178 0xffc0, /* F3 */ 107 int86 (0x33, &regs, &regs);
179 0xffc1, /* F4 */ 108 mouse_visible = 0;
180 0xffc2, /* F5 */ 109 }
181 110 }
182 /* --------------- 40 to 4f --------------- */ 111
183 0xffc3, /* F6 */ 112 void
184 0xffc4, /* F7 */ 113 mouse_moveto (x, y)
185 0xffc5, /* F8 */ 114 int x, y;
186 0xffc6, /* F9 */ 115 {
187 0xffc7, /* F10 */ 116 union REGS regs;
188 0, /* Num Lock */ 117
189 0, /* Scroll Lock */ 118 if (termscript)
190 0xff50, /* Home */ 119 fprintf (termscript, "<M_XY=%dx%d>", x, y);
191 0xff52, /* Up */ 120 regs.x.ax = 0x0004;
192 0xff55, /* Page Up */ 121 mouse_last_x = regs.x.cx = x * 8;
193 0xffad, /* Grey - */ 122 mouse_last_y = regs.x.dx = y * 8;
194 0xff51, /* Left */ 123 int86 (0x33, &regs, &regs);
195 0xffb5, /* Keypad 5 */ 124 }
196 0xff53, /* Right */ 125
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
236 /* --------------- 70 to 7f --------------- */
237 0xffc6, /* (Alt) F9 */
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
247 /* --------------- 80 to 8f --------------- */
248 '9', '0', '-', '=', /* (Alt) */
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
280 /* --------------- a0 to af --------------- */
281 0xff54, /* (Alt) Down */
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
290 /* Get a char from keyboard. Function keys are put into the event queue. */
291 static int 126 static int
292 dos_rawgetc () 127 mouse_pressed (b, xp, yp)
293 { 128 int b, *xp, *yp;
294 struct input_event event; 129 {
295 union REGS regs; 130 union REGS regs;
296 int ctrl_p, alt_p, shift_p; 131
297 132 if (b >= mouse_button_count)
298 /* Calculate modifier bits */ 133 return 0;
299 regs.h.ah = extended_kbd ? 0x12 : 0x02; 134 regs.x.ax = 0x0005;
300 int86 (0x16, &regs, &regs); 135 regs.x.bx = mouse_button_translate[b];
301 ctrl_p = ((regs.h.al & 4) != 0); 136 int86 (0x33, &regs, &regs);
302 shift_p = ((regs.h.al & 3) != 0); 137 if (regs.x.bx)
303 /* Please be very careful here not to break international keyboard support. 138 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
304 When Keyb.Com is loaded, the key marked `Alt Gr' is used for accessing 139 return (regs.x.bx != 0);
305 characters like { and } if their positions are overlaid. */ 140 }
306 alt_p = ((extended_kbd ? (regs.h.ah & 2) : (regs.h.al & 8)) != 0); 141
307 142 static int
308 /* The following condition is equivalent to `kbhit ()', except that 143 mouse_released (b, xp, yp)
309 it uses the bios to do its job. This pleases DESQview/X. */ 144 int b, *xp, *yp;
310 while ((regs.h.ah = extended_kbd ? 0x11 : 0x01), 145 {
311 int86 (0x16, &regs, &regs), 146 union REGS regs;
312 (regs.x.flags & 0x40) == 0) 147
313 { 148 if (b >= mouse_button_count)
314 union REGS regs; 149 return 0;
315 register unsigned char c; 150 regs.x.ax = 0x0006;
316 int sc, code; 151 regs.x.bx = mouse_button_translate[b];
317 152 int86 (0x33, &regs, &regs);
318 regs.h.ah = extended_kbd ? 0x10 : 0x00; 153 if (regs.x.bx)
319 int86 (0x16, &regs, &regs); 154 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
320 c = regs.h.al; 155 return (regs.x.bx != 0);
321 sc = regs.h.ah; 156 }
322 157
323 /* Determine from the scan code if a keypad key was pressed. */ 158 static void
324 if (c >= '0' && c <= '9' && sc > 0xb) 159 mouse_get_xy (int *x, int *y)
325 sc = (c == '0') ? 0xb : (c - '0' + 1), c = 0; 160 {
326 else if (sc == 0x53 && c != 0xe0) 161 union REGS regs;
327 { 162
328 code = 0xffae; /* Keypad decimal point/comma. */ 163 regs.x.ax = 0x0003;
329 goto nonascii; 164 int86 (0x33, &regs, &regs);
330 } 165 *x = regs.x.cx / 8;
331 else if (sc == 0xe0) 166 *y = regs.x.dx / 8;
332 { 167 }
333 switch (c) 168
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
348 if (c == 0
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 {
408 int but, press, x, y, ok;
409
410 /* Check for mouse movement *before* buttons. */
411 mouse_check_moved ();
412
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 }
437
438 return -1;
439 }
440
441 static int prev_get_char = -1;
442
443 /* Return 1 if a key is ready to be read without suspending execution. */
444 dos_keysns ()
445 {
446 if (prev_get_char != -1)
447 return 1;
448 else
449 return ((prev_get_char = dos_rawgetc ()) != -1);
450 }
451
452 /* Read a key. Return -1 if no key is ready. */
453 dos_keyread ()
454 {
455 if (prev_get_char != -1)
456 {
457 int c = prev_get_char;
458 prev_get_char = -1;
459 return c;
460 }
461 else
462 return dos_rawgetc ();
463 }
464
465 /* Hostnames for a pc are not really funny, but they are used in change log
466 so we emulate the best we can. */
467 gethostname (p, size)
468 char *p;
469 int size;
470 {
471 char *q = egetenv ("HOSTNAME");
472
473 if (!q) q = "pc";
474 strcpy (p, q);
475 return 0;
476 }
477
478 /* Destructively turn backslashes into slashes. */
479 void 169 void
480 dostounix_filename (p) 170 mouse_get_pos (f, insist, bar_window, part, x, y, time)
481 register char *p; 171 FRAME_PTR *f;
482 { 172 int insist;
483 while (*p) 173 Lisp_Object *bar_window, *x, *y;
484 { 174 enum scroll_bar_part *part;
485 if (*p == '\\') 175 unsigned long *time;
486 *p = '/'; 176 {
487 p++; 177 int ix, iy;
488 } 178 union REGS regs;
489 } 179
490 180 regs.x.ax = 0x0003;
491 /* Destructively turn slashes into backslashes. */ 181 int86 (0x33, &regs, &regs);
182 *f = selected_frame;
183 *bar_window = Qnil;
184 mouse_get_xy (&ix, &iy);
185 selected_frame->mouse_moved = 0;
186 *x = make_number (ix);
187 *y = make_number (iy);
188 *time = event_timestamp ();
189 }
190
191 static void
192 mouse_check_moved ()
193 {
194 int x, y;
195
196 mouse_get_xy (&x, &y);
197 selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
198 mouse_last_x = x;
199 mouse_last_y = y;
200 }
201
492 void 202 void
493 unixtodos_filename (p) 203 mouse_init ()
494 register char *p;
495 {
496 while (*p)
497 {
498 if (*p == '/')
499 *p = '\\';
500 p++;
501 }
502 }
503
504 /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
505 int
506 getdefdir (drive, dst)
507 int drive;
508 char *dst;
509 { 204 {
510 union REGS regs; 205 union REGS regs;
511 206
512 *dst++ = '/'; 207 if (termscript)
513 regs.h.dl = drive; 208 fprintf (termscript, "<M_INIT>");
514 regs.x.si = (int) dst; 209
515 regs.h.ah = 0x47; 210 regs.x.ax = 0x0021;
516 intdos (&regs, &regs); 211 int86 (0x33, &regs, &regs);
517 return !regs.x.cflag; 212
518 } 213 regs.x.ax = 0x0007;
519 214 regs.x.cx = 0;
520 /* Remove all CR's that are followed by a LF. */ 215 regs.x.dx = 8 * (ScreenCols () - 1);
521 int 216 int86 (0x33, &regs, &regs);
522 crlf_to_lf (n, buf) 217
523 register int n; 218 regs.x.ax = 0x0008;
524 register unsigned char *buf; 219 regs.x.cx = 0;
525 { 220 regs.x.dx = 8 * (ScreenRows () - 1);
526 unsigned char *np = buf; 221 int86 (0x33, &regs, &regs);
527 unsigned char *startp = buf; 222
528 unsigned char *endp = buf + n; 223 mouse_moveto (0, 0);
529 unsigned char c; 224 mouse_visible = 0;
530 225 }
531 if (n == 0) 226
532 return n; 227 /* ------------------------- Screen control ----------------------
533 while (buf < endp - 1) 228 *
534 { 229 */
535 if (*buf == 0x0d) 230
536 { 231 static int internal_terminal = 0;
537 if (*(++buf) != 0x0a) 232
538 *np++ = 0x0d; 233 #ifndef HAVE_X_WINDOWS
539 } 234 extern unsigned char ScreenAttrib;
540 else 235 static int screen_face;
541 *np++ = *buf++; 236 static int highlight;
542 } 237
543 if (buf < endp) 238 static int screen_size_X;
544 *np++ = *buf++; 239 static int screen_size_Y;
545 return np - startp; 240 static int screen_size;
546 } 241
547 242 static int current_pos_X;
548 243 static int current_pos_Y;
549 /* Run command as specified by ARGV in directory DIR. 244 static int new_pos_X;
550 The command is run with input from TEMPIN and output to file TEMPOUT. */ 245 static int new_pos_Y;
551 int 246
552 run_msdos_command (argv, dir, tempin, tempout) 247 static void *startup_screen_buffer;
553 unsigned char **argv; 248 static int startup_screen_size_X;
554 Lisp_Object dir; 249 static int startup_screen_size_Y;
555 int tempin, tempout; 250 static int startup_pos_X;
556 { 251 static int startup_pos_Y;
557 char *saveargv1, *saveargv2, **envv; 252
558 char oldwd[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ 253 static int term_setup_done;
559 int msshell, result = -1; 254
560 int in, out, inbak, outbak, errbak; 255 /* Similar to the_only_frame. */
561 int x, y; 256 struct x_display the_only_x_display;
562 Lisp_Object cmd; 257
563 258 /* This is never dereferenced. */
564 /* Get current directory as MSDOS cwd is not per-process. */ 259 Display *x_current_display;
565 getwd (oldwd); 260
566 261
567 cmd = Ffile_name_nondirectory (build_string (argv[0])); 262 #define SCREEN_SET_CURSOR() \
568 msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells")))) 263 if (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y) \
569 && !strcmp ("-c", argv[1]); 264 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X)
570 if (msshell) 265
571 { 266 static
572 saveargv1 = argv[1]; 267 dos_direct_output (y, x, buf, len)
573 saveargv2 = argv[2]; 268 int y;
574 argv[1] = "/c"; 269 int x;
575 if (argv[2]) 270 char *buf;
576 { 271 int len;
577 char *p = alloca (strlen (argv[2]) + 1); 272 {
578 273 int t = (int) ScreenPrimary + 2 * (x + y * screen_size_X);
579 strcpy (argv[2] = p, saveargv2); 274
580 while (*p && isspace (*p)) 275 while (--len >= 0) {
581 p++; 276 dosmemput (buf++, 1, t);
582 while (*p && !isspace (*p)) 277 t += 2;
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 } 278 }
610 279 }
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
639 dos_ttraw();
640 if (have_mouse > 0) {
641 mouse_init ();
642 mouse_moveto (x, y);
643 }
644
645 done:
646 chdir (oldwd);
647 if (msshell)
648 {
649 argv[1] = saveargv1;
650 argv[2] = saveargv2;
651 }
652 return result;
653 }
654
655
656 croak (badfunc)
657 char *badfunc;
658 {
659 fprintf (stderr, "%s not yet implemented\r\n", badfunc);
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
676 #ifdef chdir
677 #undef chdir
678 #endif 280 #endif
679 281
680 int
681 sys_chdir (path)
682 const char* path;
683 {
684 int len = strlen (path);
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
707 #ifndef HAVE_SELECT
708 #include "sysselect.h"
709
710 /* Only event queue is checked. */
711 int
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
721 FD_ZERO (&orfds);
722 if (rfds)
723 {
724 orfds = *rfds;
725 FD_ZERO (rfds);
726 }
727 if (wfds)
728 FD_ZERO (wfds);
729 if (efds)
730 FD_ZERO (efds);
731
732 if (nfds != 1 || !FD_ISSET (0, &orfds))
733 abort ();
734
735 /* If we are looking only for the terminal, with no timeout,
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
747 while (!detect_input_pending ())
748 {
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 }
764 #endif
765
766 /* The Emacs root directory as determined by init_environment. */
767 static char emacsroot[MAXPATHLEN];
768
769 char *
770 rootrelativepath (rel)
771 char *rel;
772 {
773 static char result[MAXPATHLEN + 10];
774
775 strcpy (result, emacsroot);
776 strcat (result, "/");
777 strcat (result, rel);
778 return result;
779 }
780
781 /* Define a lot of environment variables if not already defined. Don't
782 remove anything unless you know what you're doing -- lots of code will
783 break if one or more of these are missing. */
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
793 /* Find our root from argv[0]. Assuming argv[0] is, say,
794 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
795 root = alloca (MAXPATHLEN + 20);
796 _fixpath (argv[0], root);
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
809 /* We default HOME to our root. */
810 setenv ("HOME", root, 0);
811
812 /* We default EMACSPATH to root + "/bin". */
813 strcpy (root + len, "/bin");
814 setenv ("EMACSPATH", root, 0);
815
816 /* I don't expect anybody to ever use other terminals so the internal
817 terminal is the default. */
818 setenv ("TERM", "internal", 0);
819
820 #ifdef HAVE_X_WINDOWS
821 /* Emacs expects DISPLAY to be set. */
822 setenv ("DISPLAY", "unix:0.0", 0);
823 #endif
824
825 /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
826 downcase it and mirror the backslashes. */
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
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
846 /* In some sense all dos users have root privileges, so... */
847 setenv ("USER", "root", 0);
848 setenv ("NAME", getenv ("USER"), 0);
849
850 /* Time zone determined from country code. To make this possible, the
851 country code may not span more than one time zone. In other words,
852 in the USA, you lose. */
853 switch (dos_country_code)
854 {
855 case 31: /* Belgium */
856 case 32: /* The Netherlands */
857 case 33: /* France */
858 case 34: /* Spain */
859 case 36: /* Hungary */
860 case 38: /* Yugoslavia (or what's left of it?) */
861 case 39: /* Italy */
862 case 41: /* Switzerland */
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 }
889
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;
895 { 288 {
896 asm volatile 289 asm volatile
917 decw %%cx 310 decw %%cx
918 jne visible_bell_2 311 jne 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; 321 {
932 unsigned char *s; 322 /* This creates an xor-mask that will swap the default fore- and
933 unsigned char a; 323 background colors. */
934 { 324 do_visible_bell (((the_only_x_display.foreground_pixel
935 char *t = (char *)ScreenPrimary + 2 * (x + ScreenCols () * y); 325 ^ the_only_x_display.background_pixel)
936 #ifdef DO_TERMSCRIPT 326 * 0x11) & 0x7f);
937 if (termscript) 327 }
938 { 328 #endif
939 fprintf (termscript, "<%d@%dx%d>", c, x, y); 329
940 fwrite (s, sizeof (unsigned char), c, termscript); 330 #ifndef HAVE_X_WINDOWS
941 } 331
942 #endif 332 /*
943 asm volatile 333 * If we write a character in the position where the mouse is,
944 (" movl %1,%%eax 334 * the mouse cursor may need to be refreshed.
945 call dosmemsetup 335 */
946 movl %%eax,%%edi 336
947 movb %0,%%ah 337 static void
948 movl %2,%%ecx 338 mouse_off_maybe ()
949 movl %3,%%esi 339 {
950 output_string1: 340 int x, y;
951 movb (%%esi),%%al 341
952 movw %%ax,%%gs:(%%edi) 342 if (!mouse_visible)
953 addl $2,%%edi 343 return;
954 incl %%esi 344
955 decl %%ecx 345 mouse_get_xy (&x, &y);
956 jne output_string1" 346 if (y != new_pos_Y || x < new_pos_X)
957 : /* no output */ 347 return;
958 : "m" (a), "g" (t), "g" (c), "g" (s)
959 : "%eax", "%ecx", /* "%gs",*/ "%esi", "%edi");
960 }
961
962 static int internal_terminal = 0;
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
1062 esc_count = 0;
1063 return used;
1064 }
1065
1066 int
1067 internal_flush (f)
1068 FILE *f;
1069 {
1070 static int x;
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 348
1083 mouse_off (); 349 mouse_off ();
1084 cp = stdout->_base;
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
1092 if (resume_esc)
1093 {
1094 i = flush_escape (1, cp, count, &x, &y);
1095 if (i < 0)
1096 count = 0;
1097 else
1098 {
1099 resume_esc = 0;
1100 count -= i;
1101 cp += i;
1102 }
1103 }
1104
1105 while (count > 0)
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
1160 IT_ring_bell () 353 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
1178 static void 364 static void
1179 IT_set_face (int face) 365 IT_set_face (int face)
1185 fp = FRAME_MODE_LINE_FACE (foo); 371 fp = FRAME_MODE_LINE_FACE (foo);
1186 else if (face <= 0 || face >= FRAME_N_COMPUTED_FACES (foo)) 372 else if (face <= 0 || face >= FRAME_N_COMPUTED_FACES (foo))
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;
1205 387 unsigned char *buf, *bp;
1206 while (len > 0) 388
389 if (len == 0) return;
390
391 buf = bp = alloca (len * 2);
392
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 */ 405 }
1217 putchar (ch); 406
1218 str++, len--; 407 mouse_off_maybe ();
1219 } 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 ('@'); 467 }
1243 putchar (y); 468
1244 putchar (x); 469 static
1245 }
1246
1247 IT_reassert_line_highlight (new, vpos) 470 IT_reassert_line_highlight (new, vpos)
1248 int new, vpos; 471 int new, vpos;
1249 { 472 {
1250 highlight = new; 473 highlight = new;
1251 IT_set_face (0); /* To possibly clear the highlighting. */ 474 IT_set_face (0); /* To possibly clear the highlighting. */
1263 static 486 static
1264 IT_update_begin () 487 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 */
1271 static void 500 static void
1272 IT_set_menu_bar_lines (window, n) 501 IT_set_menu_bar_lines (window, n)
1286 for (window = w->hchild; !NILP (window); window = w->next) 515 for (window = w->hchild; !NILP (window); window = w->next)
1287 { 516 {
1288 w = XWINDOW (window); 517 w = XWINDOW (window);
1289 IT_set_menu_bar_lines (window, n); 518 IT_set_menu_bar_lines (window, n);
1290 } 519 }
520 }
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 {
1291 } 588 }
1292 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;
1347 recompute_basic_faces (f); 644 recompute_basic_faces (f);
1348 Fredraw_frame (Fselected_frame ()); 645 Fredraw_frame (Fselected_frame ());
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 */
650
1359 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;
1370 #endif 662 #endif
1371 663
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)
685 {
686 the_only_x_display.foreground_pixel = colors[0] & 0x07;
687 the_only_x_display.background_pixel = colors[1] & 0x07;
688 }
689 the_only_x_display.line_height = 1;
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;
710 #endif
711 }
712
713 dos_get_saved_screen (screen, rows, cols)
714 char **screen;
715 int *rows;
716 int *cols;
717 {
718 #ifndef HAVE_X_WINDOWS
719 *screen = startup_screen_buffer;
720 *cols = startup_screen_size_X;
721 *rows = startup_screen_size_Y;
722 return 1;
723 #else
724 return 0;
725 #endif
726 }
727
728
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
743 {
744 char *unshifted;
745 char *shifted;
746 char *alt_gr;
747 };
748
749
750 static struct dos_keyboard_map us_keyboard = {
751 /* 0 1 2 3 4 5 */
752 /* 01234567890123456789012345678901234567890 12345678901234 */
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
780 {
781 int country_code;
782 struct dos_keyboard_map *keyboard_map;
783 } keyboard_layout_list[] = {
784 1, &us_keyboard,
785 33, &fr_keyboard,
786 45, &dk_keyboard
787 };
788
789 static struct dos_keyboard_map *keyboard;
790 static int keyboard_map_all;
791
792 int
793 dos_set_keyboard (code, always)
794 int code;
795 int always;
796 {
797 int i;
798 for (i = 0; i < (sizeof (keyboard_layout_list)/sizeof (struct keyboard_layout_list)); i++)
799 if (code == keyboard_layout_list[i].country_code)
800 {
801 keyboard = keyboard_layout_list[i].keyboard_map;
802 keyboard_map_all = always;
803 dos_keyboard_layout = code;
804 return 1;
805 }
806 return 0;
807 }
808
809 #define Ignore 0x0000
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 };
841
842 static struct
843 {
844 unsigned char char_code; /* normal code */
845 unsigned char keypad_code; /* keypad code */
846 } grey_key_translate_map[] = {
847 '/', 0xaf, /* kp-decimal */
848 '*', 0xaa, /* kp-multiply */
849 '-', 0xad, /* kp-subtract */
850 '+', 0xab, /* kp-add */
851 '\r', 0x8d /* kp-enter */
852 };
853
854 static unsigned short
855 ibmpc_translate_map[] =
856 {
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 */
874
875 /* --------------- 10 to 1f --------------- */
876 Map | 15, /* 'q' */
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' */
892
893 /* --------------- 20 to 2f --------------- */
894 Map | 32, /* 'd' */
895 Map | 33, /* 'f' */
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' */
910
911 /* --------------- 30 to 3f --------------- */
912 Map | 49, /* 'b' */
913 Map | 50, /* 'n' */
914 Map | 51, /* 'm' */
915 Map | 52, /* ',' */
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 */
928
929 /* --------------- 40 to 4f --------------- */
930 FctKey | 0xc3, /* F6 */
931 FctKey | 0xc4, /* F7 */
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 */
946
947 /* --------------- 50 to 5f --------------- */
948 KeyPad | 2, /* Down */
949 KeyPad | 3, /* Page Down */
950 KeyPad | 0, /* Insert */
951 KeyPad | 10, /* Delete */
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 */
964
965 /* --------------- 60 to 6f --------------- */
966 Ctrl | FctKey | 0xc0, /* (Ctrl) F3 */
967 Ctrl | FctKey | 0xc1, /* (Ctrl) F4 */
968 Ctrl | FctKey | 0xc2, /* (Ctrl) F5 */
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 */
982
983 /* --------------- 70 to 7f --------------- */
984 Alt | FctKey | 0xc6, /* (Alt) F9 */
985 Alt | FctKey | 0xc7, /* (Alt) F10 */
986 Ctrl | FctKey | 0x6d, /* (Ctrl) Sys Rq */
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' */
1000
1001 /* --------------- 80 to 8f --------------- */
1002 Alt | Map | 9, /* '9' */
1003 Alt | Map | 10, /* '0' */
1004 Alt | Map | 11, /* '-' */
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 */
1018
1019 /* --------------- 90 to 9f --------------- */
1020 Ctrl | Grey | 3, /* (Ctrl) Grey + */
1021 Ctrl | KeyPad | 2, /* (Ctrl) Down */
1022 Ctrl | KeyPad | 0, /* (Ctrl) Insert */
1023 Ctrl | KeyPad | 10, /* (Ctrl) Delete */
1024 Ctrl | FctKey | 0x09, /* (Ctrl) Tab */
1025 Ctrl | Grey | 0, /* (Ctrl) Grey / */
1026 Ctrl | Grey | 1, /* (Ctrl) Grey * */
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 */
1036
1037 /* --------------- a0 to af --------------- */
1038 Alt | KeyPad | 2, /* (Alt) Down */
1039 Alt | KeyPad | 3, /* (Alt) Page Down */
1040 Alt | KeyPad | 0, /* (Alt) Insert */
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 };
1046
1047 /* These bit-positions corresponds to values returned by BIOS */
1048 #define SHIFT_P 0x0003 /* two bits! */
1049 #define CTRL_P 0x0004
1050 #define ALT_P 0x0008
1051 #define SCRLOCK_P 0x0010
1052 #define NUMLOCK_P 0x0020
1053 #define CAPSLOCK_P 0x0040
1054 #define ALT_GR_P 0x0800
1055 #define SUPER_P 0x4000 /* pseudo */
1056 #define HYPER_P 0x8000 /* pseudo */
1057
1058 static int
1059 dos_get_modifiers (keymask)
1060 int *keymask;
1061 {
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, &regs, &regs);
1069
1070 if (!extended_kbd)
1071 {
1072 mask = regs.h.al & (SHIFT_P | CTRL_P | ALT_P |
1073 SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
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;
1085
1086 if ((regs.h.ah & 8) != 0) /* Right ALT pressed ? */
1386 { 1087 {
1387 the_only_x_display.foreground_pixel = colors[0] & 0x07; 1088 mask |= ALT_GR_P;
1388 the_only_x_display.background_pixel = colors[1] & 0x07; 1089 if (dos_hyper_key == 1)
1090 {
1091 mask |= HYPER_P;
1092 modifiers |= hyper_modifier;
1093 }
1094 else if (dos_super_key == 1)
1095 {
1096 mask |= SUPER_P;
1097 modifiers |= super_modifier;
1098 }
1389 } 1099 }
1390 the_only_x_display.line_height = 1; 1100
1391 the_only_frame.display.x = &the_only_x_display; 1101 if (regs.h.ah & 1) /* Left CTRL pressed
1392 the_only_frame.output_method = output_msdos_raw; 1102 mask |= CTRL_P;
1393 1103
1394 init_frame_faces ((FRAME_PTR) &the_only_frame); 1104 if (regs.h.ah & 4) /* Right CTRL pressed ? */
1395 1105 {
1396 ring_bell_hook = IT_ring_bell; 1106 if (dos_hyper_key == 2)
1397 write_glyphs_hook = IT_write_glyphs; 1107 {
1398 cursor_to_hook = raw_cursor_to_hook = IT_cursor_to; 1108 mask |= HYPER_P;
1399 clear_end_of_line_hook = IT_clear_end_of_line; 1109 modifiers |= hyper_modifier;
1400 change_line_highlight_hook = IT_change_line_highlight; 1110 }
1401 update_begin_hook = IT_update_begin; 1111 else if (dos_super_key == 2)
1402 reassert_line_highlight_hook = IT_reassert_line_highlight; 1112 {
1403 1113 mask |= SUPER_P;
1404 /* These hooks are called by term.c without being checked. */ 1114 modifiers |= super_modifier;
1405 set_terminal_modes_hook 1115 }
1406 = reset_terminal_modes_hook 1116 else
1407 = update_end_hook 1117 mask |= CTRL_P;
1408 = set_terminal_window_hook 1118 }
1409 = (void *)rien_du_tout; 1119 }
1410 } 1120
1411 else 1121 if (mask & SHIFT_P)
1412 the_only_frame.output_method = output_termcap; 1122 modifiers |= shift_modifier;
1123 if (mask & CTRL_P)
1124 modifiers |= ctrl_modifier;
1125 if (mask & ALT_P)
1126 modifiers |= meta_modifier;
1127
1128 if (keymask)
1129 *keymask = mask;
1130 return modifiers;
1131 }
1132
1133 /* Get a char from keyboard. Function keys are put into the event queue. */
1134 static int
1135 dos_rawgetc ()
1136 {
1137 struct input_event event;
1138 union REGS regs;
1139
1140 #ifndef HAVE_X_WINDOWS
1141 SCREEN_SET_CURSOR();
1142 if (!mouse_visible) mouse_on ();
1413 #endif 1143 #endif
1414 } 1144
1415 1145 /* The following condition is equivalent to `kbhit ()', except that
1416 /* When time zones are set from Ms-Dos too may C-libraries are playing 1146 it uses the bios to do its job. This pleases DESQview/X. */
1417 tricks with time values. We solve this by defining our own version 1147 while ((regs.h.ah = extended_kbd ? 0x11 : 0x01),
1418 of `gettimeofday' bypassing GO32. Our version needs to be initialized 1148 int86 (0x16, &regs, &regs),
1419 once and after each call to `tzset' with TZ changed. */ 1149 (regs.x.flags & 0x40) == 0)
1420 1150 {
1421 static int daylight, gmtoffset; 1151 union REGS regs;
1422 1152 register unsigned char c;
1423 int 1153 int sc, code, mask, kp_mode;
1424 gettimeofday (struct timeval *tp, struct timezone *tzp) 1154 int modifiers;
1425 { 1155
1426 if (tp) 1156 regs.h.ah = extended_kbd ? 0x10 : 0x00;
1427 { 1157 int86 (0x16, &regs, &regs);
1428 struct time t; 1158 c = regs.h.al;
1429 struct date d; 1159 sc = regs.h.ah;
1430 struct tm tmrec; 1160
1431 1161 modifiers = dos_get_modifiers( &mask );
1432 gettime (&t); 1162
1433 /* If midnight occurs here, the results can be incorrect. */ 1163 #ifndef HAVE_X_WINDOWS
1434 getdate (&d); 1164 if (!NILP(Vdos_display_scancodes))
1435 tmrec.tm_year = d.da_year - 1900; 1165 {
1436 tmrec.tm_mon = d.da_mon - 1; 1166 char buf[10];
1437 tmrec.tm_mday = d.da_day; 1167 sprintf (buf, "%02x:%02x*%04x",
1438 tmrec.tm_hour = t.ti_hour; 1168 (unsigned) (sc&0xff), (unsigned) c, mask);
1439 tmrec.tm_min = t.ti_min; 1169 dos_direct_output (screen_size_Y - 2, screen_size_X - 12, buf, 10);
1440 tmrec.tm_sec = t.ti_sec; 1170 }
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;
1448 }
1449
1450 void
1451 init_gettimeofday ()
1452 {
1453 time_t ltm, gtm;
1454 struct tm *lstm;
1455 #undef tzset
1456 extern void tzset (void);
1457
1458 tzset ();
1459 daylight = 0;
1460 gmtoffset = 0;
1461 ltm = gtm = time (NULL);
1462 ltm = mktime (lstm = localtime (&ltm));
1463 gtm = mktime (gmtime (&gtm));
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
1473 /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
1474 void
1475 ctrl_break_func (regs)
1476 _go32_dpmi_registers *regs;
1477 {
1478 Vquit_flag = Qt;
1479 }
1480
1481 void
1482 install_ctrl_break_check ()
1483 {
1484 if (!ctrlbreakinstalled)
1485 {
1486 /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
1487 was compiler with Djgpp 1.11 maintenance level 5 or later! */
1488 ctrlbreakinstalled = 1;
1489 ctrl_break_vector.pm_offset = (int) ctrl_break_func;
1490 _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector,
1491 &ctrl_break_regs);
1492 _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector);
1493 }
1494 }
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
1500 static int mouse_button_translate[NUM_MOUSE_BUTTONS];
1501 static int mouse_button_count;
1502
1503 void
1504 mouse_init ()
1505 {
1506 union REGS regs;
1507
1508 regs.x.ax = 0x0007;
1509 regs.x.cx = 0;
1510 regs.x.dx = 8 * (ScreenCols () - 1);
1511 int86 (0x33, &regs, &regs);
1512
1513 regs.x.ax = 0x0008;
1514 regs.x.cx = 0;
1515 regs.x.dx = 8 * (ScreenRows () - 1);
1516 int86 (0x33, &regs, &regs);
1517
1518 mouse_moveto (ScreenCols () - 1, ScreenRows () - 1);
1519 mouse_on ();
1520 }
1521
1522 void
1523 mouse_on ()
1524 {
1525 union REGS regs;
1526
1527 if (have_mouse > 0)
1528 {
1529 regs.x.ax = 0x0001;
1530 int86 (0x33, &regs, &regs);
1531 }
1532 }
1533
1534 void
1535 mouse_off ()
1536 {
1537 union REGS regs;
1538
1539 if (have_mouse > 0)
1540 {
1541 regs.x.ax = 0x0002;
1542 int86 (0x33, &regs, &regs);
1543 }
1544 }
1545
1546 void
1547 mouse_moveto (x, y)
1548 int x, y;
1549 {
1550 union REGS regs;
1551
1552 regs.x.ax = 0x0004;
1553 mouse_last_x = regs.x.cx = x * 8;
1554 mouse_last_y = regs.x.dx = y * 8;
1555 int86 (0x33, &regs, &regs);
1556 }
1557
1558 int
1559 mouse_pressed (b, xp, yp)
1560 int b, *xp, *yp;
1561 {
1562 union REGS regs;
1563
1564 if (b >= mouse_button_count)
1565 return 0;
1566 regs.x.ax = 0x0005;
1567 regs.x.bx = mouse_button_translate[b];
1568 int86 (0x33, &regs, &regs);
1569 if (regs.x.bx)
1570 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
1571 return (regs.x.bx != 0);
1572 }
1573
1574 int
1575 mouse_released (b, xp, yp)
1576 int b, *xp, *yp;
1577 {
1578 union REGS regs;
1579
1580 if (b >= mouse_button_count)
1581 return 0;
1582 regs.x.ax = 0x0006;
1583 regs.x.bx = mouse_button_translate[b];
1584 int86 (0x33, &regs, &regs);
1585 #if 0
1586 if (regs.x.ax & (1 << mouse_button_translate[b]))
1587 regs.x.bx = 0; /* if mouse is still pressed, ignore release */
1588 #endif 1171 #endif
1589 if (regs.x.bx) 1172
1590 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8; 1173 if (sc == 0xe0)
1591 return (regs.x.bx != 0);
1592 }
1593
1594 static void
1595 mouse_get_xy (int *x, int *y)
1596 {
1597 union REGS regs;
1598
1599 regs.x.ax = 0x0003;
1600 int86 (0x33, &regs, &regs);
1601 *x = regs.x.cx / 8;
1602 *y = regs.x.dx / 8;
1603 }
1604
1605 void
1606 mouse_get_pos (f, insist, bar_window, part, x, y, time)
1607 FRAME_PTR *f;
1608 int insist;
1609 Lisp_Object *bar_window, *x, *y;
1610 enum scroll_bar_part *part;
1611 unsigned long *time;
1612 {
1613 int ix, iy;
1614 union REGS regs;
1615
1616 regs.x.ax = 0x0003;
1617 int86 (0x33, &regs, &regs);
1618 *f = selected_frame;
1619 *bar_window = Qnil;
1620 mouse_get_xy (&ix, &iy);
1621 selected_frame->mouse_moved = 0;
1622 *x = make_number (ix);
1623 *y = make_number (iy);
1624 *time = event_timestamp ();
1625 }
1626
1627 void
1628 mouse_check_moved ()
1629 {
1630 int x, y;
1631
1632 mouse_get_xy (&x, &y);
1633 selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
1634 mouse_last_x = x;
1635 mouse_last_y = y;
1636 }
1637
1638 int
1639 mouse_init1 ()
1640 {
1641 union REGS regs;
1642 int present;
1643
1644 #ifdef HAVE_X_WINDOWS
1645 if (!inhibit_window_system)
1646 return 0;
1647 #endif
1648 if (!internal_terminal)
1649 return 0;
1650
1651 regs.x.ax = 0x0021;
1652 int86 (0x33, &regs, &regs);
1653 present = (regs.x.ax & 0xffff) == 0xffff;
1654 if (!present)
1655 {
1656 /* Reportedly, the above doesn't work for some mouse drivers. There
1657 is an additional detection method that should work, but might be
1658 a little slower. Use that as an alternative. */
1659 regs.x.ax = 0x0000;
1660 int86 (0x33, &regs, &regs);
1661 present = (regs.x.ax & 0xffff) == 0xffff;
1662 }
1663
1664 if (present)
1665 {
1666 if (regs.x.bx == 3)
1667 { 1174 {
1668 mouse_button_count = 3; 1175 switch (c)
1669 mouse_button_translate[0] = 0; /* Left */ 1176 {
1670 mouse_button_translate[1] = 2; /* Middle */ 1177 case 10: /* Ctrl Grey Enter */
1671 mouse_button_translate[2] = 1; /* Right */ 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)
1681 } 1200 {
1682 return present; 1201 if (code & Alt)
1683 } 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 }
1345 }
1346
1347 return -1;
1348 }
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
1684 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
1688 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip) 1379 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1764 for (i = 0; i < menu->count; i++) 1455 for (i = 0; i < menu->count; i++)
1765 if (menu->submenu[i]) 1456 if (menu->submenu[i])
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;
1773 } 1464 }
1774 1465
1808 1499
1809 width = menu->width; 1500 width = menu->width;
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);
1821 face = faces[enabled + mousehere * 2]; 1511 face = faces[enabled + mousehere * 2];
1822 p = text; 1512 p = text;
1824 for (j = 0, q = menu->text[i]; *q; j++) 1514 for (j = 0, q = menu->text[i]; *q; j++)
1825 *p++ = FAST_MAKE_GLYPH (*q++, face); 1515 *p++ = FAST_MAKE_GLYPH (*q++, face);
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 }
1525
1526 /* --------------------------- X Menu emulation ---------------------- */
1837 1527
1838 /* Create a brand new menu structure. */ 1528 /* Create a brand new menu structure. */
1839 1529
1840 XMenu * 1530 XMenu *
1841 XMenuCreate (Display *foo1, Window foo2, char *foo3) 1531 XMenuCreate (Display *foo1, Window foo2, char *foo3)
1927 /* Just in case we got here without a mouse present... */ 1617 /* Just in case we got here without a mouse present... */
1928 if (have_mouse <= 0) 1618 if (have_mouse <= 0)
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
1936 (&the_only_frame, 1626 (&the_only_frame,
1937 intern ("msdos-menu-passive-face")), 1627 intern ("msdos-menu-passive-face")),
1949 1639
1950 statecount = 1; 1640 statecount = 1;
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;
1958 state[0].menu = menu->submenu[0]; 1647 state[0].menu = menu->submenu[0];
1959 } 1648 }
1967 1656
1968 mouse_last_x = -1; /* A hack that forces display. */ 1657 mouse_last_x = -1; /* A hack that forces display. */
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 {
1975 selected_frame->mouse_moved = 0; 1665 selected_frame->mouse_moved = 0;
1976 result = XM_IA_SELECT; 1666 result = XM_IA_SELECT;
1996 while (i != statecount - 1) 1686 while (i != statecount - 1)
1997 { 1687 {
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])
2005 { 1694 {
2006 IT_menu_display (state[i].menu, 1695 IT_menu_display (state[i].menu,
2010 state[statecount].menu = state[i].menu->submenu[dy]; 1699 state[statecount].menu = state[i].menu->submenu[dy];
2011 state[statecount].pane = state[i].menu->panenumber[dy]; 1700 state[statecount].pane = state[i].menu->panenumber[dy];
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;
2019 statecount++; 1707 statecount++;
2020 } 1708 }
2033 } 1721 }
2034 } 1722 }
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;
2042 } 1729 }
2043 1730
2070 { 1757 {
2071 return FRAME_HEIGHT (f); 1758 return FRAME_HEIGHT (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 (&regs, &regs);
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 (&ltm));
2450 gtm = mktime (gmtime (&gtm));
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 */