(IT_menu_display): Display control characters as ^X.
[bpt/emacs.git] / src / msdos.c
CommitLineData
9da6e765 1/* MS-DOS specific C utilities.
48ffe371 2 Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
1b94449f
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
edfc0d45 8the Free Software Foundation; either version 2, or (at your option)
1b94449f
RS
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
1b94449f 20
9da6e765 21/* Contributed by Morten Welinder */
f32d4091 22/* New display, keyboard, and mouse control by Kim F. Storm */
9da6e765 23
1b94449f
RS
24/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
25
48984716 26#include <config.h>
1b94449f
RS
27
28#ifdef MSDOS
29#include "lisp.h"
30#include <stdio.h>
31#include <stdlib.h>
32#include <sys/param.h>
33#include <sys/time.h>
34#include <dos.h>
d21e67b5
RS
35#include <errno.h>
36#include <sys/stat.h> /* for _fixpath */
1bd7b2c7
RS
37#if __DJGPP__ >= 2
38#include <fcntl.h>
d21e67b5 39#include <libc/dosio.h> /* for _USE_LFN */
1bd7b2c7
RS
40#endif
41
1b94449f
RS
42#include "dosfns.h"
43#include "msdos.h"
44#include "systime.h"
45#include "termhooks.h"
87485d6f
MW
46#include "dispextern.h"
47#include "termopts.h"
1b94449f 48#include "frame.h"
87485d6f 49#include "window.h"
1b94449f
RS
50#include <go32.h>
51#include <pc.h>
52#include <ctype.h>
53/* #include <process.h> */
54/* Damn that local process.h! Instead we can define P_WAIT ourselves. */
55#define P_WAIT 1
56
d21e67b5
RS
57#ifndef _USE_LFN
58#define _USE_LFN 0
59#endif
60
1bd7b2c7
RS
61#if __DJGPP__ > 1
62
8748735b
RS
63#include <signal.h>
64
1bd7b2c7
RS
65#ifndef SYSTEM_MALLOC
66
67#ifdef GNU_MALLOC
68
69/* If other `malloc' than ours is used, force our `sbrk' behave like
70 Unix programs expect (resize memory blocks to keep them contiguous).
71 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
72 because that's what `gmalloc' expects to get. */
73#include <crt0.h>
74
75#ifdef REL_ALLOC
76int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
77#else /* not REL_ALLOC */
78int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
79#endif /* not REL_ALLOC */
80#endif /* GNU_MALLOC */
81
82#endif /* not SYSTEM_MALLOC */
83#endif /* __DJGPP__ > 1 */
aee81730
RS
84
85static unsigned long
86event_timestamp ()
87{
88 struct time t;
89 unsigned long s;
f32d4091 90
aee81730
RS
91 gettime (&t);
92 s = t.ti_min;
93 s *= 60;
94 s += t.ti_sec;
95 s *= 1000;
96 s += t.ti_hund * 10;
f32d4091 97
aee81730
RS
98 return s;
99}
100
f32d4091
KS
101\f
102/* ------------------------ Mouse control ---------------------------
103 *
104 * Coordinates are in screen positions and zero based.
105 * Mouse buttons are numbered from left to right and also zero based.
106 */
1b94449f 107
f32d4091
KS
108int have_mouse; /* 0: no, 1: enabled, -1: disabled */
109static int mouse_visible;
1b94449f 110
f32d4091
KS
111static int mouse_last_x;
112static int mouse_last_y;
1b94449f 113
f32d4091
KS
114static int mouse_button_translate[NUM_MOUSE_BUTTONS];
115static int mouse_button_count;
1b94449f 116
f32d4091
KS
117void
118mouse_on ()
1b94449f 119{
1b94449f 120 union REGS regs;
1b94449f 121
f32d4091 122 if (have_mouse > 0 && !mouse_visible)
1b94449f 123 {
f32d4091
KS
124 if (termscript)
125 fprintf (termscript, "<M_ON>");
126 regs.x.ax = 0x0001;
127 int86 (0x33, &regs, &regs);
128 mouse_visible = 1;
1b94449f 129 }
1b94449f
RS
130}
131
f32d4091
KS
132void
133mouse_off ()
1b94449f 134{
f32d4091 135 union REGS regs;
1b94449f 136
f32d4091 137 if (have_mouse > 0 && mouse_visible)
1b94449f 138 {
f32d4091
KS
139 if (termscript)
140 fprintf (termscript, "<M_OFF>");
141 regs.x.ax = 0x0002;
142 int86 (0x33, &regs, &regs);
143 mouse_visible = 0;
1b94449f 144 }
1b94449f
RS
145}
146
f32d4091
KS
147void
148mouse_moveto (x, y)
149 int x, y;
1b94449f 150{
f32d4091 151 union REGS regs;
1b94449f 152
f32d4091
KS
153 if (termscript)
154 fprintf (termscript, "<M_XY=%dx%d>", x, y);
155 regs.x.ax = 0x0004;
156 mouse_last_x = regs.x.cx = x * 8;
157 mouse_last_y = regs.x.dx = y * 8;
158 int86 (0x33, &regs, &regs);
1b94449f
RS
159}
160
f32d4091
KS
161static int
162mouse_pressed (b, xp, yp)
163 int b, *xp, *yp;
1b94449f 164{
f32d4091 165 union REGS regs;
1b94449f 166
f32d4091
KS
167 if (b >= mouse_button_count)
168 return 0;
169 regs.x.ax = 0x0005;
170 regs.x.bx = mouse_button_translate[b];
171 int86 (0x33, &regs, &regs);
172 if (regs.x.bx)
173 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
174 return (regs.x.bx != 0);
1b94449f
RS
175}
176
f32d4091
KS
177static int
178mouse_released (b, xp, yp)
179 int b, *xp, *yp;
1b94449f
RS
180{
181 union REGS regs;
182
f32d4091
KS
183 if (b >= mouse_button_count)
184 return 0;
185 regs.x.ax = 0x0006;
186 regs.x.bx = mouse_button_translate[b];
187 int86 (0x33, &regs, &regs);
188 if (regs.x.bx)
189 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
190 return (regs.x.bx != 0);
1b94449f
RS
191}
192
f32d4091
KS
193static void
194mouse_get_xy (int *x, int *y)
1b94449f 195{
f32d4091 196 union REGS regs;
1b94449f 197
f32d4091
KS
198 regs.x.ax = 0x0003;
199 int86 (0x33, &regs, &regs);
200 *x = regs.x.cx / 8;
201 *y = regs.x.dx / 8;
1b94449f
RS
202}
203
f32d4091
KS
204void
205mouse_get_pos (f, insist, bar_window, part, x, y, time)
206 FRAME_PTR *f;
207 int insist;
208 Lisp_Object *bar_window, *x, *y;
209 enum scroll_bar_part *part;
210 unsigned long *time;
211{
212 int ix, iy;
213 union REGS regs;
214
215 regs.x.ax = 0x0003;
216 int86 (0x33, &regs, &regs);
217 *f = selected_frame;
218 *bar_window = Qnil;
219 mouse_get_xy (&ix, &iy);
220 selected_frame->mouse_moved = 0;
221 *x = make_number (ix);
222 *y = make_number (iy);
223 *time = event_timestamp ();
224}
1b94449f 225
f32d4091
KS
226static void
227mouse_check_moved ()
1b94449f 228{
aee81730 229 int x, y;
1b94449f 230
f32d4091
KS
231 mouse_get_xy (&x, &y);
232 selected_frame->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
233 mouse_last_x = x;
234 mouse_last_y = y;
235}
1b94449f 236
f32d4091
KS
237void
238mouse_init ()
239{
240 union REGS regs;
647c32eb 241
f32d4091
KS
242 if (termscript)
243 fprintf (termscript, "<M_INIT>");
1b94449f 244
f32d4091
KS
245 regs.x.ax = 0x0021;
246 int86 (0x33, &regs, &regs);
091d0bdf 247
f32d4091
KS
248 regs.x.ax = 0x0007;
249 regs.x.cx = 0;
250 regs.x.dx = 8 * (ScreenCols () - 1);
251 int86 (0x33, &regs, &regs);
1b94449f 252
f32d4091
KS
253 regs.x.ax = 0x0008;
254 regs.x.cx = 0;
255 regs.x.dx = 8 * (ScreenRows () - 1);
256 int86 (0x33, &regs, &regs);
1b94449f 257
f32d4091
KS
258 mouse_moveto (0, 0);
259 mouse_visible = 0;
260}
3eb1dbb6 261\f
f32d4091
KS
262/* ------------------------- Screen control ----------------------
263 *
264 */
aee81730 265
f32d4091 266static int internal_terminal = 0;
aee81730 267
f32d4091
KS
268#ifndef HAVE_X_WINDOWS
269extern unsigned char ScreenAttrib;
270static int screen_face;
271static int highlight;
aee81730 272
f32d4091
KS
273static int screen_size_X;
274static int screen_size_Y;
275static int screen_size;
1b94449f 276
f32d4091
KS
277static int current_pos_X;
278static int current_pos_Y;
279static int new_pos_X;
280static int new_pos_Y;
1b94449f 281
f32d4091
KS
282static void *startup_screen_buffer;
283static int startup_screen_size_X;
284static int startup_screen_size_Y;
285static int startup_pos_X;
286static int startup_pos_Y;
c9adab25 287static unsigned char startup_screen_attrib;
1b94449f 288
f32d4091 289static int term_setup_done;
1b94449f 290
f32d4091 291/* Similar to the_only_frame. */
f6816f88 292struct x_output the_only_x_display;
1b94449f 293
f32d4091
KS
294/* This is never dereferenced. */
295Display *x_current_display;
1b94449f 296
1b94449f 297
f32d4091
KS
298#define SCREEN_SET_CURSOR() \
299 if (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y) \
300 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X)
aee81730 301
f32d4091
KS
302static
303dos_direct_output (y, x, buf, len)
304 int y;
305 int x;
306 char *buf;
307 int len;
1b94449f 308{
f32d4091 309 int t = (int) ScreenPrimary + 2 * (x + y * screen_size_X);
aee81730 310
f32d4091
KS
311 while (--len >= 0) {
312 dosmemput (buf++, 1, t);
313 t += 2;
314 }
1b94449f 315}
aee81730 316#endif
1b94449f 317
1b94449f
RS
318/* Flash the screen as a substitute for BEEPs. */
319
f32d4091 320#if (__DJGPP__ < 2)
49a09c76 321static void
fcea9cd4 322do_visible_bell (xorattr)
1b94449f
RS
323 unsigned char xorattr;
324{
49a09c76 325 asm volatile
ca986694 326 (" movb $1,%%dl
1b94449f 327visible_bell_0:
ca986694 328 movl _ScreenPrimary,%%eax
49a09c76 329 call dosmemsetup
ca986694
RS
330 movl %%eax,%%ebx
331 movl %1,%%ecx
332 movb %0,%%al
333 incl %%ebx
1b94449f 334visible_bell_1:
ca986694
RS
335 xorb %%al,%%gs:(%%ebx)
336 addl $2,%%ebx
337 decl %%ecx
49a09c76 338 jne visible_bell_1
ca986694 339 decb %%dl
49a09c76 340 jne visible_bell_3
1b94449f 341visible_bell_2:
ca986694
RS
342 movzwl %%ax,%%eax
343 movzwl %%ax,%%eax
344 movzwl %%ax,%%eax
345 movzwl %%ax,%%eax
346 decw %%cx
49a09c76
RS
347 jne visible_bell_2
348 jmp visible_bell_0
ca986694
RS
349visible_bell_3:"
350 : /* no output */
f32d4091 351 : "m" (xorattr), "g" (screen_size)
ca986694 352 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
1b94449f
RS
353}
354
f32d4091
KS
355static void
356ScreenVisualBell (void)
357{
358 /* This creates an xor-mask that will swap the default fore- and
359 background colors. */
360 do_visible_bell (((the_only_x_display.foreground_pixel
361 ^ the_only_x_display.background_pixel)
362 * 0x11) & 0x7f);
363}
364#endif
365
366#ifndef HAVE_X_WINDOWS
367
76ac1508
RS
368/* Enable bright background colors. */
369static void
370bright_bg (void)
371{
372 union REGS regs;
373
374 regs.h.bl = 0;
375 regs.x.ax = 0x1003;
376 int86 (0x10, &regs, &regs);
377}
378
4a96d4d2
KH
379/* Set the screen dimensions so that it can show no less than
380 ROWS x COLS frame. */
48ffe371 381
4a96d4d2
KH
382void
383dos_set_window_size (rows, cols)
384 int *rows, *cols;
385{
386 char video_name[30];
387 Lisp_Object video_mode;
388 int video_mode_value;
389 int have_vga = 0;
390 union REGS regs;
391 int current_rows = ScreenRows (), current_cols = ScreenCols ();
392
393 if (*rows == current_rows && *cols == current_cols)
394 return;
395
396 /* Do we have a VGA? */
397 regs.x.ax = 0x1a00;
398 int86 (0x10, &regs, &regs);
399 if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
400 have_vga = 1;
401
402 mouse_off ();
403
48ffe371 404 /* If the user specified a special video mode for these dimensions,
4a96d4d2
KH
405 use that mode. */
406 sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols);
407 video_mode = XSYMBOL (Fintern_soft (build_string (video_name),
408 Qnil))-> value;
409
410 if (INTEGERP (video_mode)
411 && (video_mode_value = XINT (video_mode)) > 0)
412 {
413 regs.x.ax = video_mode_value;
414 int86 (0x10, &regs, &regs);
48ffe371
RS
415
416 if (have_mouse)
417 {
418 /* Must hardware-reset the mouse, or else it won't update
419 its notion of screen dimensions for some non-standard
420 video modes. This is *painfully* slow... */
421 regs.x.ax = 0;
422 int86 (0x33, &regs, &regs);
423 }
4a96d4d2
KH
424 }
425
426 /* Find one of the dimensions supported by standard EGA/VGA
427 which gives us at least the required dimensions. */
428
429#if __DJGPP__ > 1
430
431 else
432 {
433 static struct {
434 int rows;
435 int need_vga;
436 } std_dimension[] = {
437 {25, 0},
438 {28, 1},
439 {35, 0},
440 {40, 1},
441 {43, 0},
442 {50, 1}
443 };
444 int i = 0;
445
446 while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
447 {
448 if (std_dimension[i].need_vga <= have_vga
449 && std_dimension[i].rows >= *rows)
450 {
451 if (std_dimension[i].rows != current_rows
452 || *cols != current_cols)
48ffe371 453 _set_screen_lines (std_dimension[i].rows);
4a96d4d2
KH
454 break;
455 }
48ffe371 456 i++;
4a96d4d2
KH
457 }
458 }
459
460#else /* not __DJGPP__ > 1 */
461
462 else if (*rows <= 25)
463 {
464 if (current_rows != 25 || current_cols != 80)
465 {
466 regs.x.ax = 3;
467 int86 (0x10, &regs, &regs);
468 regs.x.ax = 0x1101;
469 regs.h.bl = 0;
470 int86 (0x10, &regs, &regs);
471 regs.x.ax = 0x1200;
472 regs.h.bl = 32;
473 int86 (0x10, &regs, &regs);
474 regs.x.ax = 3;
475 int86 (0x10, &regs, &regs);
476 }
477 }
478 else if (*rows <= 50)
479 if (have_vga && (current_rows != 50 || current_cols != 80)
480 || *rows <= 43 && (current_rows != 43 || current_cols != 80))
481 {
482 regs.x.ax = 3;
483 int86 (0x10, &regs, &regs);
484 regs.x.ax = 0x1112;
485 regs.h.bl = 0;
486 int86 (0x10, &regs, &regs);
487 regs.x.ax = 0x1200;
488 regs.h.bl = 32;
489 int86 (0x10, &regs, &regs);
490 regs.x.ax = 0x0100;
491 regs.x.cx = 7;
492 int86 (0x10, &regs, &regs);
493 }
494#endif /* not __DJGPP__ > 1 */
495
496 if (have_mouse)
497 {
4a96d4d2
KH
498 mouse_init ();
499 mouse_on ();
500 }
501
502 /* Tell the caller what dimensions have been REALLY set. */
503 *rows = ScreenRows ();
504 *cols = ScreenCols ();
76ac1508
RS
505
506 /* Enable bright background colors. */
507 bright_bg ();
4a96d4d2
KH
508}
509
48ffe371
RS
510/* If we write a character in the position where the mouse is,
511 the mouse cursor may need to be refreshed. */
09e2ac30
RS
512
513static void
f32d4091 514mouse_off_maybe ()
09e2ac30 515{
f32d4091
KS
516 int x, y;
517
518 if (!mouse_visible)
519 return;
520
521 mouse_get_xy (&x, &y);
522 if (y != new_pos_Y || x < new_pos_X)
523 return;
524
525 mouse_off ();
526}
527
528static
529IT_ring_bell ()
530{
531 if (visible_bell)
aee81730 532 {
f32d4091
KS
533 mouse_off ();
534 ScreenVisualBell ();
aee81730 535 }
f32d4091 536 else
3635be47
RS
537 {
538 union REGS inregs, outregs;
539 inregs.h.ah = 2;
540 inregs.h.dl = 7;
541 intdos (&inregs, &outregs);
542 }
09e2ac30
RS
543}
544
f32d4091
KS
545static void
546IT_set_face (int face)
547{
548 struct face *fp;
549 extern struct face *intern_face (/* FRAME_PTR, struct face * */);
550
551 if (face == 1 || (face == 0 && highlight))
552 fp = FRAME_MODE_LINE_FACE (foo);
553 else if (face <= 0 || face >= FRAME_N_COMPUTED_FACES (foo))
554 fp = FRAME_DEFAULT_FACE (foo);
555 else
556 fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]);
557 if (termscript)
558 fprintf (termscript, "<FACE:%d:%d>", FACE_FOREGROUND (fp), FACE_BACKGROUND (fp));
559 screen_face = face;
560 ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
561}
562
563static
564IT_write_glyphs (GLYPH *str, int len)
565{
566 int newface;
567 int ch, l = len;
568 unsigned char *buf, *bp;
87485d6f 569
f32d4091 570 if (len == 0) return;
aee81730 571
f32d4091 572 buf = bp = alloca (len * 2);
aee81730 573
f32d4091 574 while (--l >= 0)
aee81730 575 {
f32d4091
KS
576 newface = FAST_GLYPH_FACE (*str);
577 if (newface != screen_face)
578 IT_set_face (newface);
579 ch = FAST_GLYPH_CHAR (*str);
580 *bp++ = (unsigned char)ch;
581 *bp++ = ScreenAttrib;
582
583 if (termscript)
584 fputc (ch, termscript);
585 str++;
aee81730
RS
586 }
587
f32d4091
KS
588 mouse_off_maybe ();
589 dosmemput (buf, 2 * len,
590 (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y));
591 new_pos_X += len;
592}
aee81730 593
f32d4091
KS
594static
595IT_clear_end_of_line (first_unused)
596{
597 char *spaces, *sp;
598 int i, j;
599
600 IT_set_face (0);
601 if (termscript)
602 fprintf (termscript, "<CLR:EOL>");
603 i = (j = screen_size_X - new_pos_X) * 2;
604 spaces = sp = alloca (i);
aee81730 605
f32d4091 606 while (--j >= 0)
aee81730 607 {
f32d4091
KS
608 *sp++ = ' ';
609 *sp++ = ScreenAttrib;
aee81730
RS
610 }
611
f32d4091
KS
612 mouse_off_maybe ();
613 dosmemput (spaces, i,
614 (int)ScreenPrimary + 2 * (new_pos_X + screen_size_X * new_pos_Y));
aee81730
RS
615}
616
f32d4091
KS
617static
618IT_clear_screen (void)
619{
620 if (termscript)
621 fprintf (termscript, "<CLR:SCR>");
622 IT_set_face (0);
623 mouse_off ();
624 ScreenClear ();
625 new_pos_X = new_pos_Y = 0;
626}
627
628static
629IT_clear_to_end (void)
630{
631 if (termscript)
632 fprintf (termscript, "<CLR:EOS>");
633
634 while (new_pos_Y < screen_size_Y) {
635 new_pos_X = 0;
636 IT_clear_end_of_line (0);
637 new_pos_Y++;
638 }
639}
640
641static
642IT_cursor_to (int y, int x)
643{
644 if (termscript)
645 fprintf (termscript, "\n<XY=%dx%d>", x, y);
646 new_pos_X = x;
647 new_pos_Y = y;
648}
649
650static
651IT_reassert_line_highlight (new, vpos)
652 int new, vpos;
653{
654 highlight = new;
655 IT_set_face (0); /* To possibly clear the highlighting. */
656}
657
658static
659IT_change_line_highlight (new_highlight, vpos, first_unused_hpos)
1b94449f 660{
f32d4091
KS
661 highlight = new_highlight;
662 IT_set_face (0); /* To possibly clear the highlighting. */
663 IT_cursor_to (vpos, 0);
664 IT_clear_end_of_line (first_unused_hpos);
665}
666
667static
668IT_update_begin ()
669{
670 highlight = 0;
671 IT_set_face (0); /* To possibly clear the highlighting. */
672 screen_face = -1;
673}
674
675static
676IT_update_end ()
677{
678}
1b94449f 679
3bb1f22f
RS
680/* This was more or less copied from xterm.c
681
682 Nowadays, the corresponding function under X is `x_set_menu_bar_lines_1'
683 on xfns.c */
48ffe371 684
f32d4091
KS
685static void
686IT_set_menu_bar_lines (window, n)
48ffe371
RS
687 Lisp_Object window;
688 int n;
f32d4091
KS
689{
690 struct window *w = XWINDOW (window);
691
9a166e40 692 XSETFASTINT (w->last_modified, 0);
f32d4091
KS
693 XSETFASTINT (w->top, XFASTINT (w->top) + n);
694 XSETFASTINT (w->height, XFASTINT (w->height) - n);
695
696 /* Handle just the top child in a vertical split. */
697 if (!NILP (w->vchild))
698 IT_set_menu_bar_lines (w->vchild, n);
699
700 /* Adjust all children in a horizontal split. */
701 for (window = w->hchild; !NILP (window); window = w->next)
1b94449f 702 {
f32d4091
KS
703 w = XWINDOW (window);
704 IT_set_menu_bar_lines (window, n);
aee81730 705 }
f32d4091
KS
706}
707
3bb1f22f
RS
708/* This was copied from xfns.c */
709
710void
711x_set_menu_bar_lines (f, value, oldval)
712 struct frame *f;
713 Lisp_Object value, oldval;
714{
715 int nlines;
716 int olines = FRAME_MENU_BAR_LINES (f);
717
718 /* Right now, menu bars don't work properly in minibuf-only frames;
719 most of the commands try to apply themselves to the minibuffer
720 frame itslef, and get an error because you can't switch buffers
721 in or split the minibuffer window. */
722 if (FRAME_MINIBUF_ONLY_P (f))
723 return;
724
725 if (INTEGERP (value))
726 nlines = XINT (value);
727 else
728 nlines = 0;
729
730 FRAME_MENU_BAR_LINES (f) = nlines;
731 IT_set_menu_bar_lines (f->root_window, nlines - olines);
732}
733
48ffe371
RS
734/* IT_set_terminal_modes is called when emacs is started,
735 resumed, and whenever the screen is redrawn! */
f32d4091
KS
736
737static
738IT_set_terminal_modes (void)
739{
740 char *colors;
741 FRAME_PTR f;
742 struct face *fp;
aee81730 743
aee81730 744 if (termscript)
f32d4091
KS
745 fprintf (termscript, "\n<SET_TERM>");
746 highlight = 0;
747
748 screen_size_X = ScreenCols ();
749 screen_size_Y = ScreenRows ();
750 screen_size = screen_size_X * screen_size_Y;
aee81730 751
f32d4091
KS
752 new_pos_X = new_pos_Y = 0;
753 current_pos_X = current_pos_Y = -1;
754
755 if (term_setup_done)
756 return;
757 term_setup_done = 1;
aee81730 758
f32d4091
KS
759 startup_screen_size_X = screen_size_X;
760 startup_screen_size_Y = screen_size_Y;
c9adab25 761 startup_screen_attrib = ScreenAttrib;
f32d4091
KS
762
763 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
764 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
765
766 if (termscript)
c9adab25
KH
767 fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
768 screen_size_X, screen_size_Y);
76ac1508
RS
769
770 bright_bg ();
f32d4091
KS
771}
772
48ffe371
RS
773/* IT_reset_terminal_modes is called when emacs is
774 suspended or killed. */
f32d4091
KS
775
776static
777IT_reset_terminal_modes (void)
778{
c9adab25
KH
779 int display_row_start = (int) ScreenPrimary;
780 int saved_row_len = startup_screen_size_X * 2;
781 int update_row_len = ScreenCols () * 2;
782 int current_rows = ScreenRows ();
783 int to_next_row = update_row_len;
784 unsigned char *saved_row = startup_screen_buffer;
785 int cursor_pos_X = ScreenCols () - 1;
786 int cursor_pos_Y = ScreenRows () - 1;
787
f32d4091 788 if (termscript)
5063b150 789 fprintf (termscript, "\n<RESET_TERM>");
f32d4091
KS
790
791 highlight = 0;
792
793 if (!term_setup_done)
794 return;
795
c9adab25
KH
796 mouse_off ();
797
798 /* We have a situation here.
799 We cannot just do ScreenUpdate(startup_screen_buffer) because
800 the luser could have changed screen dimensions inside Emacs
801 and failed (or didn't want) to restore them before killing
802 Emacs. ScreenUpdate() uses the *current* screen dimensions and
803 thus will happily use memory outside what was allocated for
804 `startup_screen_buffer'.
805 Thus we only restore as much as the current screen dimensions
806 can hold, and clear the rest (if the saved screen is smaller than
807 the current) with the color attribute saved at startup. The cursor
808 is also restored within the visible dimensions. */
809
810 ScreenAttrib = startup_screen_attrib;
811 ScreenClear ();
812
813 if (update_row_len > saved_row_len)
814 update_row_len = saved_row_len;
815 if (current_rows > startup_screen_size_Y)
816 current_rows = startup_screen_size_Y;
f32d4091
KS
817
818 if (termscript)
c9adab25
KH
819 fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
820 update_row_len / 2, current_rows);
821
822 while (current_rows--)
823 {
824 dosmemput (saved_row, update_row_len, display_row_start);
825 saved_row += saved_row_len;
826 display_row_start += to_next_row;
827 }
828 if (startup_pos_X < cursor_pos_X)
829 cursor_pos_X = startup_pos_X;
830 if (startup_pos_Y < cursor_pos_Y)
831 cursor_pos_Y = startup_pos_Y;
832
833 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
834 xfree (startup_screen_buffer);
f32d4091
KS
835
836 term_setup_done = 0;
837}
838
839static
840IT_set_terminal_window (void)
841{
842}
843
844void
3bb1f22f
RS
845IT_set_frame_parameters (f, alist)
846 FRAME_PTR f;
f32d4091
KS
847 Lisp_Object alist;
848{
849 Lisp_Object tail;
850 int redraw;
851 extern unsigned long load_color ();
f32d4091
KS
852
853 redraw = 0;
854 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
855 {
856 Lisp_Object elt, prop, val;
857
858 elt = Fcar (tail);
859 prop = Fcar (elt);
860 val = Fcdr (elt);
861 CHECK_SYMBOL (prop, 1);
862
863 if (EQ (prop, intern ("foreground-color")))
864 {
865 unsigned long new_color = load_color (f, val);
866 if (new_color != ~0)
867 {
868 FRAME_FOREGROUND_PIXEL (f) = new_color;
869 redraw = 1;
76ac1508
RS
870 if (termscript)
871 fprintf (termscript, "<FGCOLOR %d>\n", new_color);
f32d4091
KS
872 }
873 }
874 else if (EQ (prop, intern ("background-color")))
875 {
876 unsigned long new_color = load_color (f, val);
877 if (new_color != ~0)
878 {
76ac1508 879 FRAME_BACKGROUND_PIXEL (f) = new_color;
f32d4091 880 redraw = 1;
76ac1508
RS
881 if (termscript)
882 fprintf (termscript, "<BGCOLOR %d>\n", new_color);
f32d4091
KS
883 }
884 }
885 else if (EQ (prop, intern ("menu-bar-lines")))
3bb1f22f 886 x_set_menu_bar_lines (f, val, 0);
f32d4091
KS
887 }
888
889 if (redraw)
890 {
891 recompute_basic_faces (f);
3bb1f22f
RS
892 if (f == selected_frame)
893 redraw_frame (f);
f32d4091
KS
894 }
895}
896
897#endif /* !HAVE_X_WINDOWS */
898
899
48ffe371
RS
900/* Do we need the internal terminal? */
901
f32d4091
KS
902void
903internal_terminal_init ()
904{
905 char *term = getenv ("TERM");
906 char *colors;
907
908#ifdef HAVE_X_WINDOWS
909 if (!inhibit_window_system)
910 return;
911#endif
912
913 internal_terminal
914 = (!noninteractive) && term && !strcmp (term, "internal");
915
916 if (getenv ("EMACSTEST"))
5063b150 917 termscript = fopen (getenv ("EMACSTEST"), "wt");
f32d4091
KS
918
919#ifndef HAVE_X_WINDOWS
920 if (!internal_terminal || inhibit_window_system)
921 {
3bb1f22f 922 selected_frame->output_method = output_termcap;
f32d4091
KS
923 return;
924 }
925
926 Vwindow_system = intern ("pc");
927 Vwindow_system_version = make_number (1);
928
929 bzero (&the_only_x_display, sizeof the_only_x_display);
930 the_only_x_display.background_pixel = 7; /* White */
931 the_only_x_display.foreground_pixel = 0; /* Black */
76ac1508 932 bright_bg ();
5063b150 933 colors = getenv ("EMACSCOLORS");
f32d4091
KS
934 if (colors && strlen (colors) >= 2)
935 {
76ac1508
RS
936 /* The colors use 4 bits each (we enable bright background). */
937 if (isdigit (colors[0]))
938 colors[0] -= '0';
939 else if (isxdigit (colors[0]))
940 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1bd7b2c7
RS
941 if (colors[0] >= 0 && colors[0] < 16)
942 the_only_x_display.foreground_pixel = colors[0];
76ac1508
RS
943 if (isdigit (colors[1]))
944 colors[1] -= '0';
945 else if (isxdigit (colors[1]))
946 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
947 if (colors[1] >= 0 && colors[1] < 16)
1bd7b2c7 948 the_only_x_display.background_pixel = colors[1];
f32d4091
KS
949 }
950 the_only_x_display.line_height = 1;
64ec6a02 951 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
f32d4091 952
3bb1f22f 953 init_frame_faces (selected_frame);
f32d4091
KS
954
955 ring_bell_hook = IT_ring_bell;
956 write_glyphs_hook = IT_write_glyphs;
957 cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
958 clear_to_end_hook = IT_clear_to_end;
959 clear_end_of_line_hook = IT_clear_end_of_line;
960 clear_frame_hook = IT_clear_screen;
961 change_line_highlight_hook = IT_change_line_highlight;
962 update_begin_hook = IT_update_begin;
963 update_end_hook = IT_update_end;
964 reassert_line_highlight_hook = IT_reassert_line_highlight;
965
966 /* These hooks are called by term.c without being checked. */
967 set_terminal_modes_hook = IT_set_terminal_modes;
968 reset_terminal_modes_hook = IT_reset_terminal_modes;
969 set_terminal_window_hook = IT_set_terminal_window;
970#endif
971}
972
973dos_get_saved_screen (screen, rows, cols)
974 char **screen;
975 int *rows;
976 int *cols;
977{
978#ifndef HAVE_X_WINDOWS
979 *screen = startup_screen_buffer;
980 *cols = startup_screen_size_X;
981 *rows = startup_screen_size_Y;
982 return 1;
983#else
984 return 0;
985#endif
986}
3bb1f22f
RS
987
988#ifndef HAVE_X_WINDOWS
989
990/* We are not X, but we can emulate it well enough for our needs... */
991void
992check_x (void)
993{
994 if (! FRAME_MSDOS_P (selected_frame))
995 error ("Not running under a windows system");
996}
997
998#endif
999
5063b150 1000\f
f32d4091
KS
1001/* ----------------------- Keyboard control ----------------------
1002 *
1003 * Keymaps reflect the following keyboard layout:
1004 *
1005 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
1006 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
1007 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
1008 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
1009 * SPACE
1010 */
1011
1012static int extended_kbd; /* 101 (102) keyboard present. */
1013
1014struct dos_keyboard_map
1015{
1016 char *unshifted;
1017 char *shifted;
1018 char *alt_gr;
1019};
1020
1021
1022static struct dos_keyboard_map us_keyboard = {
1023/* 0 1 2 3 4 5 */
1024/* 01234567890123456789012345678901234567890 12345678901234 */
1025 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
1026/* 0123456789012345678901234567890123456789 012345678901234 */
1027 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
1028 0 /* no Alt-Gr key */
1029};
1030
1031static struct dos_keyboard_map fr_keyboard = {
1032/* 0 1 2 3 4 5 */
1033/* 012 3456789012345678901234567890123456789012345678901234 */
1034