Simplify EMACS_TIME-related code.
[bpt/emacs.git] / src / msdos.c
CommitLineData
d26e478e 1/* MS-DOS specific C utilities. -*- coding: cp850 -*-
95df8112 2
ab422c4d 3Copyright (C) 1993-1997, 1999-2013 Free Software Foundation, Inc.
1b94449f
RS
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
1b94449f 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
1b94449f
RS
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1b94449f 19
9da6e765 20/* Contributed by Morten Welinder */
f32d4091 21/* New display, keyboard, and mouse control by Kim F. Storm */
9da6e765 22
d26e478e
EZ
23/* Note: This file MUST use a unibyte encoding, to both display the
24 keys on the non-US keyboard layout as their respective labels, and
25 provide the correct byte values for the keyboard input to inject
26 into Emacs. See 'struct dos_keyboard_map' below. As long as there
27 are only European keyboard layouts here, we are OK with DOS
28 codepage 850 encoding. */
29
1b94449f
RS
30/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
31
48984716 32#include <config.h>
1b94449f
RS
33
34#ifdef MSDOS
d7306fe6 35#include <setjmp.h>
1b94449f
RS
36#include "lisp.h"
37#include <stdio.h>
06b1ea13 38#include <time.h>
1b94449f
RS
39#include <sys/param.h>
40#include <sys/time.h>
e3ac1281 41/* gettime and settime in dos.h clash with their namesakes from
0d23c240
EZ
42 gnulib, so we move out of our way the prototypes in dos.h. */
43#define gettime dos_h_gettime_
44#define settime dos_h_settime_
1b94449f 45#include <dos.h>
0d23c240
EZ
46#undef gettime
47#undef settime
d21e67b5
RS
48#include <errno.h>
49#include <sys/stat.h> /* for _fixpath */
a7cf9151 50#include <unistd.h> /* for chdir, dup, dup2, etc. */
bf794306 51#include <dir.h> /* for getdisk */
affa509c 52#pragma pack(0) /* dir.h does a pack(4), which isn't GCC's default */
1bd7b2c7 53#include <fcntl.h>
a7cf9151 54#include <io.h> /* for setmode */
fc171623
KH
55#include <dpmi.h> /* for __dpmi_xxx stuff */
56#include <sys/farptr.h> /* for _farsetsel, _farnspokeb */
d21e67b5 57#include <libc/dosio.h> /* for _USE_LFN */
a7cf9151 58#include <conio.h> /* for cputs */
1bd7b2c7 59
1b94449f
RS
60#include "msdos.h"
61#include "systime.h"
3e1944a3 62#include "frame.h"
1b94449f 63#include "termhooks.h"
aa9ce936 64#include "termchar.h"
87485d6f 65#include "dispextern.h"
c77f6f1b 66#include "dosfns.h"
87485d6f 67#include "termopts.h"
83be827a 68#include "character.h"
aa9ce936
EZ
69#include "coding.h"
70#include "disptab.h"
87485d6f 71#include "window.h"
fc171623
KH
72#include "buffer.h"
73#include "commands.h"
41ad069b 74#include "blockinput.h"
97dd288b 75#include "keyboard.h"
6b61353c 76#include "intervals.h"
1b94449f
RS
77#include <go32.h>
78#include <pc.h>
79#include <ctype.h>
80/* #include <process.h> */
891ef8f7
EZ
81/* Damn that local process.h! Instead we can define P_WAIT and
82 spawnve ourselves. */
1b94449f 83#define P_WAIT 1
891ef8f7 84extern int spawnve (int, const char *, char *const [], char *const []);
1b94449f 85
d21e67b5
RS
86#ifndef _USE_LFN
87#define _USE_LFN 0
88#endif
89
b36701cc
RS
90#ifndef _dos_ds
91#define _dos_ds _go32_info_block.selector_for_linear_memory
92#endif
93
8748735b 94#include <signal.h>
417a04bb 95#include "syssignal.h"
8748735b 96
7c106b1e
EZ
97#include "careadlinkat.h"
98#include "allocator.h"
99
1bd7b2c7
RS
100#ifndef SYSTEM_MALLOC
101
102#ifdef GNU_MALLOC
103
104/* If other `malloc' than ours is used, force our `sbrk' behave like
105 Unix programs expect (resize memory blocks to keep them contiguous).
106 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
107 because that's what `gmalloc' expects to get. */
108#include <crt0.h>
109
110#ifdef REL_ALLOC
111int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
112#else /* not REL_ALLOC */
113int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
114#endif /* not REL_ALLOC */
115#endif /* GNU_MALLOC */
116
117#endif /* not SYSTEM_MALLOC */
aee81730 118
0d23c240 119/* Return the current timestamp in milliseconds since midnight. */
aee81730 120static unsigned long
3a8ce822 121event_timestamp (void)
aee81730 122{
0d23c240 123 struct timespec t;
aee81730 124 unsigned long s;
56e19ec4 125
aee81730 126 gettime (&t);
0d23c240
EZ
127 s = t.tv_sec;
128 s %= 86400;
aee81730 129 s *= 1000;
0d23c240 130 s += t.tv_nsec * 1000000;
56e19ec4 131
aee81730
RS
132 return s;
133}
134
f32d4091
KS
135\f
136/* ------------------------ Mouse control ---------------------------
137 *
138 * Coordinates are in screen positions and zero based.
139 * Mouse buttons are numbered from left to right and also zero based.
140 */
1b94449f 141
0c3cfc51
EZ
142/* This used to be in termhooks.h, but mainstream Emacs code no longer
143 uses it, and it was removed... */
144#define NUM_MOUSE_BUTTONS (5)
145
f32d4091
KS
146int have_mouse; /* 0: no, 1: enabled, -1: disabled */
147static int mouse_visible;
1b94449f 148
f32d4091
KS
149static int mouse_last_x;
150static int mouse_last_y;
1b94449f 151
f32d4091
KS
152static int mouse_button_translate[NUM_MOUSE_BUTTONS];
153static int mouse_button_count;
1b94449f 154
f32d4091 155void
3a8ce822 156mouse_on (void)
1b94449f 157{
1b94449f 158 union REGS regs;
1b94449f 159
f32d4091 160 if (have_mouse > 0 && !mouse_visible)
1b94449f 161 {
3e1944a3
EZ
162 struct tty_display_info *tty = CURTTY ();
163
164 if (tty->termscript)
165 fprintf (tty->termscript, "<M_ON>");
f32d4091
KS
166 regs.x.ax = 0x0001;
167 int86 (0x33, &regs, &regs);
168 mouse_visible = 1;
1b94449f 169 }
1b94449f
RS
170}
171
f32d4091 172void
3a8ce822 173mouse_off (void)
1b94449f 174{
f32d4091 175 union REGS regs;
1b94449f 176
f32d4091 177 if (have_mouse > 0 && mouse_visible)
1b94449f 178 {
3e1944a3
EZ
179 struct tty_display_info *tty = CURTTY ();
180
181 if (tty->termscript)
182 fprintf (tty->termscript, "<M_OFF>");
f32d4091
KS
183 regs.x.ax = 0x0002;
184 int86 (0x33, &regs, &regs);
185 mouse_visible = 0;
1b94449f 186 }
1b94449f
RS
187}
188
8f190436
EZ
189static void
190mouse_setup_buttons (int n_buttons)
191{
192 if (n_buttons == 3)
193 {
194 mouse_button_count = 3;
195 mouse_button_translate[0] = 0; /* Left */
196 mouse_button_translate[1] = 2; /* Middle */
197 mouse_button_translate[2] = 1; /* Right */
198 }
199 else /* two, what else? */
200 {
201 mouse_button_count = 2;
202 mouse_button_translate[0] = 0;
203 mouse_button_translate[1] = 1;
204 }
205}
206
207DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons, Smsdos_set_mouse_buttons,
208 1, 1, "NSet number of mouse buttons to: ",
70da46c3
PJ
209 doc: /* Set the number of mouse buttons to use by Emacs.
210This is useful with mice that report the number of buttons inconsistently,
211e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of
212them. This happens with wheeled mice on Windows 9X, for example. */)
5842a27b 213 (Lisp_Object nbuttons)
8f190436 214{
e7522695
EZ
215 int n;
216
b7826503 217 CHECK_NUMBER (nbuttons);
e7522695
EZ
218 n = XINT (nbuttons);
219 if (n < 2 || n > 3)
ebe061ca
KS
220 xsignal2 (Qargs_out_of_range,
221 build_string ("only 2 or 3 mouse buttons are supported"),
222 nbuttons);
e7522695 223 mouse_setup_buttons (n);
8f190436
EZ
224 return Qnil;
225}
226
211c7152
EZ
227static void
228mouse_get_xy (int *x, int *y)
229{
230 union REGS regs;
231
232 regs.x.ax = 0x0003;
233 int86 (0x33, &regs, &regs);
234 *x = regs.x.cx / 8;
235 *y = regs.x.dx / 8;
236}
237
f32d4091 238void
3a8ce822 239mouse_moveto (int x, int y)
1b94449f 240{
f32d4091 241 union REGS regs;
3e1944a3 242 struct tty_display_info *tty = CURTTY ();
1b94449f 243
3e1944a3
EZ
244 if (tty->termscript)
245 fprintf (tty->termscript, "<M_XY=%dx%d>", x, y);
f32d4091
KS
246 regs.x.ax = 0x0004;
247 mouse_last_x = regs.x.cx = x * 8;
248 mouse_last_y = regs.x.dx = y * 8;
249 int86 (0x33, &regs, &regs);
1b94449f
RS
250}
251
f32d4091 252static int
3a8ce822 253mouse_pressed (int b, int *xp, int *yp)
1b94449f 254{
f32d4091 255 union REGS regs;
1b94449f 256
f32d4091
KS
257 if (b >= mouse_button_count)
258 return 0;
259 regs.x.ax = 0x0005;
260 regs.x.bx = mouse_button_translate[b];
261 int86 (0x33, &regs, &regs);
262 if (regs.x.bx)
263 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
264 return (regs.x.bx != 0);
1b94449f
RS
265}
266
f32d4091 267static int
3a8ce822 268mouse_released (int b, int *xp, int *yp)
1b94449f
RS
269{
270 union REGS regs;
271
f32d4091
KS
272 if (b >= mouse_button_count)
273 return 0;
274 regs.x.ax = 0x0006;
275 regs.x.bx = mouse_button_translate[b];
276 int86 (0x33, &regs, &regs);
277 if (regs.x.bx)
278 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
279 return (regs.x.bx != 0);
1b94449f
RS
280}
281
0c7bc1aa 282static int
3a8ce822 283mouse_button_depressed (int b, int *xp, int *yp)
0c7bc1aa
EZ
284{
285 union REGS regs;
286
287 if (b >= mouse_button_count)
288 return 0;
289 regs.x.ax = 0x0003;
290 int86 (0x33, &regs, &regs);
291 if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0)
292 {
293 *xp = regs.x.cx / 8;
294 *yp = regs.x.dx / 8;
295 return 1;
296 }
297 return 0;
298}
299
f32d4091 300void
a10c8269 301mouse_get_pos (struct frame **f, int insist, Lisp_Object *bar_window,
3a8ce822 302 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
9fbd6841 303 Time *time)
f32d4091
KS
304{
305 int ix, iy;
211c7152
EZ
306 Lisp_Object frame, tail;
307
308 /* Clear the mouse-moved flag for every frame on this display. */
309 FOR_EACH_FRAME (tail, frame)
310 XFRAME (frame)->mouse_moved = 0;
f32d4091 311
5e617bc2 312 *f = SELECTED_FRAME ();
f32d4091
KS
313 *bar_window = Qnil;
314 mouse_get_xy (&ix, &iy);
f32d4091 315 *time = event_timestamp ();
211c7152
EZ
316 *x = make_number (mouse_last_x = ix);
317 *y = make_number (mouse_last_y = iy);
f32d4091 318}
1b94449f 319
f32d4091 320static void
3a8ce822 321mouse_check_moved (void)
1b94449f 322{
aee81730 323 int x, y;
1b94449f 324
f32d4091 325 mouse_get_xy (&x, &y);
5e617bc2 326 SELECTED_FRAME ()->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
f32d4091
KS
327 mouse_last_x = x;
328 mouse_last_y = y;
329}
1b94449f 330
97dd288b
EZ
331/* Force the mouse driver to ``forget'' about any button clicks until
332 now. */
333static void
334mouse_clear_clicks (void)
335{
336 int b;
337
338 for (b = 0; b < mouse_button_count; b++)
339 {
340 int dummy_x, dummy_y;
341
342 (void) mouse_pressed (b, &dummy_x, &dummy_y);
343 (void) mouse_released (b, &dummy_x, &dummy_y);
344 }
345}
346
f32d4091 347void
3a8ce822 348mouse_init (void)
f32d4091
KS
349{
350 union REGS regs;
3e1944a3 351 struct tty_display_info *tty = CURTTY ();
647c32eb 352
3e1944a3
EZ
353 if (tty->termscript)
354 fprintf (tty->termscript, "<M_INIT>");
1b94449f 355
f32d4091
KS
356 regs.x.ax = 0x0021;
357 int86 (0x33, &regs, &regs);
091d0bdf 358
0c7bc1aa
EZ
359 /* Reset the mouse last press/release info. It seems that Windows
360 doesn't do that automatically when function 21h is called, which
361 causes Emacs to ``remember'' the click that switched focus to the
362 window just before Emacs was started from that window. */
97dd288b 363 mouse_clear_clicks ();
0c7bc1aa 364
f32d4091
KS
365 regs.x.ax = 0x0007;
366 regs.x.cx = 0;
367 regs.x.dx = 8 * (ScreenCols () - 1);
368 int86 (0x33, &regs, &regs);
1b94449f 369
f32d4091
KS
370 regs.x.ax = 0x0008;
371 regs.x.cx = 0;
372 regs.x.dx = 8 * (ScreenRows () - 1);
373 int86 (0x33, &regs, &regs);
1b94449f 374
f32d4091
KS
375 mouse_moveto (0, 0);
376 mouse_visible = 0;
377}
3eb1dbb6 378\f
f32d4091
KS
379/* ------------------------- Screen control ----------------------
380 *
381 */
aee81730 382
f32d4091 383static int internal_terminal = 0;
aee81730 384
f32d4091
KS
385#ifndef HAVE_X_WINDOWS
386extern unsigned char ScreenAttrib;
387static int screen_face;
aee81730 388
f32d4091
KS
389static int screen_size_X;
390static int screen_size_Y;
391static int screen_size;
1b94449f 392
f32d4091
KS
393static int current_pos_X;
394static int current_pos_Y;
395static int new_pos_X;
396static int new_pos_Y;
1b94449f 397
f32d4091
KS
398static void *startup_screen_buffer;
399static int startup_screen_size_X;
400static int startup_screen_size_Y;
401static int startup_pos_X;
402static int startup_pos_Y;
c9adab25 403static unsigned char startup_screen_attrib;
1b94449f 404
06b1ea13
EZ
405static clock_t startup_time;
406
f32d4091 407static int term_setup_done;
1b94449f 408
8ba01a32
EZ
409static unsigned short outside_cursor;
410
f32d4091 411/* Similar to the_only_frame. */
3e1944a3 412struct tty_display_info the_only_display_info;
1b94449f 413
039274cf
EZ
414/* Support for DOS/V (allows Japanese characters to be displayed on
415 standard, non-Japanese, ATs). Only supported for DJGPP v2 and later. */
416
417/* Holds the address of the text-mode screen buffer. */
418static unsigned long screen_old_address = 0;
419/* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
420static unsigned short screen_virtual_segment = 0;
421static unsigned short screen_virtual_offset = 0;
6b61353c
KH
422extern Lisp_Object Qcursor_type;
423extern Lisp_Object Qbar, Qhbar;
8ba01a32 424
9ccf54e9 425/* The screen colors of the current frame, which serve as the default
deece6f5
EZ
426 colors for newly-created frames. */
427static int initial_screen_colors[2];
428
039274cf
EZ
429/* Update the screen from a part of relocated DOS/V screen buffer which
430 begins at OFFSET and includes COUNT characters. */
431static void
432dosv_refresh_virtual_screen (int offset, int count)
433{
434 __dpmi_regs regs;
435
9ab8560d 436 if (offset < 0 || count < 0) /* paranoia; invalid values crash DOS/V */
40437cf5
EZ
437 return;
438
039274cf
EZ
439 regs.h.ah = 0xff; /* update relocated screen */
440 regs.x.es = screen_virtual_segment;
441 regs.x.di = screen_virtual_offset + offset;
442 regs.x.cx = count;
443 __dpmi_int (0x10, &regs);
444}
039274cf 445
d1d5dc19 446static void
3a8ce822 447dos_direct_output (int y, int x, char *buf, int len)
1b94449f 448{
40437cf5
EZ
449 int t0 = 2 * (x + y * screen_size_X);
450 int t = t0 + (int) ScreenPrimary;
039274cf 451 int l0 = len;
fc171623 452
fc171623
KH
453 /* This is faster. */
454 for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
455 _farnspokeb (t, *buf);
039274cf
EZ
456
457 if (screen_virtual_segment)
458 dosv_refresh_virtual_screen (t0, l0);
f32d4091
KS
459}
460#endif
461
462#ifndef HAVE_X_WINDOWS
463
b36701cc
RS
464static int blink_bit = -1; /* the state of the blink bit at startup */
465
76ac1508
RS
466/* Enable bright background colors. */
467static void
468bright_bg (void)
469{
470 union REGS regs;
471
b36701cc
RS
472 /* Remember the original state of the blink/bright-background bit.
473 It is stored at 0040:0065h in the BIOS data area. */
474 if (blink_bit == -1)
475 blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
476
76ac1508
RS
477 regs.h.bl = 0;
478 regs.x.ax = 0x1003;
479 int86 (0x10, &regs, &regs);
480}
481
b36701cc
RS
482/* Disable bright background colors (and enable blinking) if we found
483 the video system in that state at startup. */
484static void
485maybe_enable_blinking (void)
486{
487 if (blink_bit == 1)
488 {
489 union REGS regs;
490
491 regs.h.bl = 1;
492 regs.x.ax = 0x1003;
493 int86 (0x10, &regs, &regs);
494 }
495}
496
8ba01a32
EZ
497/* Return non-zero if the system has a VGA adapter. */
498static int
499vga_installed (void)
500{
501 union REGS regs;
502
503 regs.x.ax = 0x1a00;
504 int86 (0x10, &regs, &regs);
505 if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
506 return 1;
507 return 0;
508}
509
4a96d4d2
KH
510/* Set the screen dimensions so that it can show no less than
511 ROWS x COLS frame. */
48ffe371 512
4a96d4d2 513void
3a8ce822 514dos_set_window_size (int *rows, int *cols)
4a96d4d2
KH
515{
516 char video_name[30];
4a96d4d2 517 union REGS regs;
56e19ec4
EZ
518 Lisp_Object video_mode;
519 int video_mode_value, have_vga = 0;
4a96d4d2
KH
520 int current_rows = ScreenRows (), current_cols = ScreenCols ();
521
522 if (*rows == current_rows && *cols == current_cols)
523 return;
524
4a96d4d2 525 mouse_off ();
8ba01a32 526 have_vga = vga_installed ();
4a96d4d2 527
48ffe371 528 /* If the user specified a special video mode for these dimensions,
4a96d4d2 529 use that mode. */
15dbb4d6
PE
530 video_mode
531 = Fsymbol_value (Fintern_soft (make_formatted_string
a8290ec3
DA
532 (video_name, "screen-dimensions-%dx%d",
533 *rows, *cols), Qnil));
4a96d4d2
KH
534
535 if (INTEGERP (video_mode)
536 && (video_mode_value = XINT (video_mode)) > 0)
537 {
538 regs.x.ax = video_mode_value;
539 int86 (0x10, &regs, &regs);
48ffe371
RS
540
541 if (have_mouse)
542 {
543 /* Must hardware-reset the mouse, or else it won't update
544 its notion of screen dimensions for some non-standard
545 video modes. This is *painfully* slow... */
546 regs.x.ax = 0;
547 int86 (0x33, &regs, &regs);
548 }
4a96d4d2
KH
549 }
550
551 /* Find one of the dimensions supported by standard EGA/VGA
552 which gives us at least the required dimensions. */
4a96d4d2
KH
553 else
554 {
555 static struct {
56e19ec4 556 int rows, need_vga;
4a96d4d2
KH
557 } std_dimension[] = {
558 {25, 0},
559 {28, 1},
560 {35, 0},
561 {40, 1},
562 {43, 0},
563 {50, 1}
564 };
565 int i = 0;
566
567 while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
568 {
569 if (std_dimension[i].need_vga <= have_vga
570 && std_dimension[i].rows >= *rows)
571 {
572 if (std_dimension[i].rows != current_rows
573 || *cols != current_cols)
48ffe371 574 _set_screen_lines (std_dimension[i].rows);
4a96d4d2
KH
575 break;
576 }
48ffe371 577 i++;
4a96d4d2
KH
578 }
579 }
580
4a96d4d2
KH
581
582 if (have_mouse)
583 {
4a96d4d2
KH
584 mouse_init ();
585 mouse_on ();
586 }
587
588 /* Tell the caller what dimensions have been REALLY set. */
589 *rows = ScreenRows ();
590 *cols = ScreenCols ();
76ac1508 591
bed43f1d
EZ
592 /* Update Emacs' notion of screen dimensions. */
593 screen_size_X = *cols;
594 screen_size_Y = *rows;
595 screen_size = *cols * *rows;
596
41ad069b
EZ
597 /* If the dimensions changed, the mouse highlight info is invalid. */
598 if (current_rows != *rows || current_cols != *cols)
599 {
5e617bc2 600 struct frame *f = SELECTED_FRAME ();
34574c02
EZ
601 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
602 Lisp_Object window = hlinfo->mouse_face_window;
41ad069b 603
d3d50620 604 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
9fed9729 605 reset_mouse_highlight (hlinfo);
41ad069b 606 }
41ad069b 607
76ac1508
RS
608 /* Enable bright background colors. */
609 bright_bg ();
039274cf
EZ
610
611 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
612 be defensive anyway. */
613 if (screen_virtual_segment)
614 dosv_refresh_virtual_screen (0, *cols * *rows);
4a96d4d2
KH
615}
616
48ffe371
RS
617/* If we write a character in the position where the mouse is,
618 the mouse cursor may need to be refreshed. */
09e2ac30
RS
619
620static void
3a8ce822 621mouse_off_maybe (void)
09e2ac30 622{
f32d4091 623 int x, y;
56e19ec4 624
f32d4091
KS
625 if (!mouse_visible)
626 return;
56e19ec4 627
f32d4091
KS
628 mouse_get_xy (&x, &y);
629 if (y != new_pos_Y || x < new_pos_X)
630 return;
56e19ec4 631
f32d4091
KS
632 mouse_off ();
633}
634
8ba01a32
EZ
635#define DEFAULT_CURSOR_START (-1)
636#define DEFAULT_CURSOR_WIDTH (-1)
637#define BOX_CURSOR_WIDTH (-32)
638
639/* Set cursor to begin at scan line START_LINE in the character cell
640 and extend for WIDTH scan lines. Scan lines are counted from top
641 of the character cell, starting from zero. */
642static void
643msdos_set_cursor_shape (struct frame *f, int start_line, int width)
644{
8ba01a32
EZ
645 unsigned desired_cursor;
646 __dpmi_regs regs;
647 int max_line, top_line, bot_line;
3e1944a3 648 struct tty_display_info *tty = FRAME_TTY (f);
8ba01a32
EZ
649
650 /* Avoid the costly BIOS call if F isn't the currently selected
651 frame. Allow for NULL as unconditionally meaning the selected
652 frame. */
5e617bc2 653 if (f && f != SELECTED_FRAME ())
8ba01a32
EZ
654 return;
655
3e1944a3
EZ
656 if (tty->termscript)
657 fprintf (tty->termscript, "\nCURSOR SHAPE=(%d,%d)", start_line, width);
b106731c 658
8ba01a32
EZ
659 /* The character cell size in scan lines is stored at 40:85 in the
660 BIOS data area. */
661 max_line = _farpeekw (_dos_ds, 0x485) - 1;
662 switch (max_line)
663 {
664 default: /* this relies on CGA cursor emulation being ON! */
665 case 7:
666 bot_line = 7;
667 break;
668 case 9:
669 bot_line = 9;
670 break;
671 case 13:
672 bot_line = 12;
673 break;
674 case 15:
675 bot_line = 14;
676 break;
677 }
678
679 if (width < 0)
680 {
681 if (width == BOX_CURSOR_WIDTH)
682 {
683 top_line = 0;
684 bot_line = max_line;
685 }
686 else if (start_line != DEFAULT_CURSOR_START)
687 {
688 top_line = start_line;
689 bot_line = top_line - width - 1;
690 }
691 else if (width != DEFAULT_CURSOR_WIDTH)
692 {
693 top_line = 0;
694 bot_line = -1 - width;
695 }
696 else
697 top_line = bot_line + 1;
698 }
699 else if (width == 0)
700 {
701 /* [31, 0] seems to DTRT for all screen sizes. */
702 top_line = 31;
703 bot_line = 0;
704 }
705 else /* WIDTH is positive */
706 {
707 if (start_line != DEFAULT_CURSOR_START)
708 bot_line = start_line;
709 top_line = bot_line - (width - 1);
710 }
711
712 /* If the current cursor shape is already what they want, we are
713 history here. */
714 desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
715 if (desired_cursor == _farpeekw (_dos_ds, 0x460))
716 return;
717
718 regs.h.ah = 1;
719 regs.x.cx = desired_cursor;
720 __dpmi_int (0x10, &regs);
8ba01a32
EZ
721}
722
723static void
724IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
725{
a0738471 726 if (EQ (cursor_type, Qbar) || EQ (cursor_type, Qhbar))
8ba01a32
EZ
727 {
728 /* Just BAR means the normal EGA/VGA cursor. */
729 msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
730 }
a0738471
EZ
731 else if (CONSP (cursor_type)
732 && (EQ (XCAR (cursor_type), Qbar)
733 || EQ (XCAR (cursor_type), Qhbar)))
8ba01a32
EZ
734 {
735 Lisp_Object bar_parms = XCDR (cursor_type);
736 int width;
737
738 if (INTEGERP (bar_parms))
739 {
740 /* Feature: negative WIDTH means cursor at the top
741 of the character cell, zero means invisible cursor. */
742 width = XINT (bar_parms);
743 msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
744 width);
745 }
746 else if (CONSP (bar_parms)
747 && INTEGERP (XCAR (bar_parms))
748 && INTEGERP (XCDR (bar_parms)))
749 {
750 int start_line = XINT (XCDR (bar_parms));
751
752 width = XINT (XCAR (bar_parms));
753 msdos_set_cursor_shape (f, start_line, width);
754 }
755 }
756 else
b106731c
EZ
757 {
758 /* Treat anything unknown as "box cursor". This includes nil, so
759 that a frame which doesn't specify a cursor type gets a box,
760 which is the default in Emacs. */
761 msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
762 }
8ba01a32
EZ
763}
764
71f65669 765static void
3e1944a3 766IT_ring_bell (struct frame *f)
f32d4091
KS
767{
768 if (visible_bell)
aee81730 769 {
f32d4091
KS
770 mouse_off ();
771 ScreenVisualBell ();
aee81730 772 }
f32d4091 773 else
3635be47
RS
774 {
775 union REGS inregs, outregs;
776 inregs.h.ah = 2;
777 inregs.h.dl = 7;
778 intdos (&inregs, &outregs);
779 }
09e2ac30
RS
780}
781
c77f6f1b
EZ
782/* Given a face id FACE, extract the face parameters to be used for
783 display until the face changes. The face parameters (actually, its
784 color) are used to construct the video attribute byte for each
785 glyph during the construction of the buffer that is then blitted to
786 the video RAM. */
f32d4091
KS
787static void
788IT_set_face (int face)
789{
5e617bc2 790 struct frame *sf = SELECTED_FRAME ();
546701f5
EZ
791 struct face *fp = FACE_FROM_ID (sf, face);
792 struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
793 unsigned long fg, bg, dflt_fg, dflt_bg;
3e1944a3 794 struct tty_display_info *tty = FRAME_TTY (sf);
f32d4091 795
c77f6f1b 796 if (!fp)
e30aee93 797 {
546701f5 798 fp = dfp;
e30aee93
EZ
799 /* The default face for the frame should always be realized and
800 cached. */
801 if (!fp)
1088b922 802 emacs_abort ();
e30aee93 803 }
f32d4091 804 screen_face = face;
c77f6f1b
EZ
805 fg = fp->foreground;
806 bg = fp->background;
546701f5
EZ
807 dflt_fg = dfp->foreground;
808 dflt_bg = dfp->background;
c77f6f1b 809
abcce93a
MB
810 /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_* colors
811 mean use the colors of the default face. Note that we assume all
812 16 colors to be available for the background, since Emacs switches
813 on this mode (and loses the blinking attribute) at startup. */
f9d2fdc4 814 if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731 815 fg = FRAME_FOREGROUND_PIXEL (sf);
f9d2fdc4 816 else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
3b620731
EZ
817 fg = FRAME_BACKGROUND_PIXEL (sf);
818 if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
819 bg = FRAME_BACKGROUND_PIXEL (sf);
f9d2fdc4 820 else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731
EZ
821 bg = FRAME_FOREGROUND_PIXEL (sf);
822
823 /* Make sure highlighted lines really stand out, come what may. */
abcce93a 824 if (fp->tty_reverse_p && (fg == dflt_fg && bg == dflt_bg))
3b620731
EZ
825 {
826 unsigned long tem = fg;
827
828 fg = bg;
829 bg = tem;
830 }
76648534
EZ
831 /* If the user requested inverse video, obey. */
832 if (inverse_video)
833 {
834 unsigned long tem2 = fg;
835
836 fg = bg;
837 bg = tem2;
838 }
3e1944a3 839 if (tty->termscript)
891ef8f7 840 fprintf (tty->termscript, "<FACE %d: %lu/%lu[FG:%lu/BG:%lu]>", face,
abcce93a 841 fp->foreground, fp->background, fg, bg);
c77f6f1b
EZ
842 if (fg >= 0 && fg < 16)
843 {
844 ScreenAttrib &= 0xf0;
845 ScreenAttrib |= fg;
846 }
847 if (bg >= 0 && bg < 16)
848 {
849 ScreenAttrib &= 0x0f;
850 ScreenAttrib |= ((bg & 0x0f) << 4);
851 }
f32d4091
KS
852}
853
aff01dd9
EZ
854/* According to RBIL (INTERRUP.A, V-1000), 160 is the maximum possible
855 width of a DOS display in any known text mode. We multiply by 2 to
7ee6a1d3 856 accommodate the screen attribute byte. */
aff01dd9
EZ
857#define MAX_SCREEN_BUF 160*2
858
3e1944a3
EZ
859extern unsigned char *encode_terminal_code (struct glyph *, int,
860 struct coding_system *);
7ef4b50c 861
71f65669 862static void
3e1944a3 863IT_write_glyphs (struct frame *f, struct glyph *str, int str_len)
f32d4091 864{
aff01dd9 865 unsigned char screen_buf[MAX_SCREEN_BUF], *screen_bp, *bp;
039274cf 866 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936 867 register int sl = str_len;
3e1944a3 868 struct tty_display_info *tty = FRAME_TTY (f);
2d764c78 869 struct frame *sf;
3e1944a3 870 unsigned char *conversion_buffer;
87485d6f 871
3e1944a3
EZ
872 /* If terminal_coding does any conversion, use it, otherwise use
873 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
874 because it always returns 1 if terminal_coding.src_multibyte is 1. */
875 struct coding_system *coding = FRAME_TERMINAL_CODING (f);
876
877 if (!(coding->common_flags & CODING_REQUIRE_ENCODING_MASK))
878 coding = &safe_terminal_coding;
648648a9 879
3b620731 880 if (str_len <= 0) return;
56e19ec4 881
5e617bc2 882 sf = SELECTED_FRAME ();
e30aee93
EZ
883
884 /* Since faces get cached and uncached behind our back, we can't
885 rely on their indices in the cache being consistent across
886 invocations. So always reset the screen face to the default
887 face of the frame, before writing glyphs, and let the glyphs
888 set the right face if it's different from the default. */
889 IT_set_face (DEFAULT_FACE_ID);
56e19ec4 890
aa9ce936
EZ
891 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
892 the tail. */
3e1944a3 893 coding->mode &= ~CODING_MODE_LAST_BLOCK;
aff01dd9 894 screen_bp = &screen_buf[0];
3e1944a3 895 while (sl > 0)
aa9ce936 896 {
3e1944a3 897 int cf;
aff01dd9 898 int n;
aa9ce936 899
aff01dd9
EZ
900 /* If the face of this glyph is different from the current
901 screen face, update the screen attribute byte. */
902 cf = str->face_id;
903 if (cf != screen_face)
904 IT_set_face (cf); /* handles invalid faces gracefully */
905
906 /* Identify a run of glyphs with the same face. */
907 for (n = 1; n < sl; ++n)
908 if (str[n].face_id != cf)
909 break;
910
911 if (n >= sl)
912 /* This is the last glyph. */
913 coding->mode |= CODING_MODE_LAST_BLOCK;
914
915 conversion_buffer = encode_terminal_code (str, n, coding);
916 if (coding->produced > 0)
aa9ce936 917 {
aff01dd9
EZ
918 /* Copy the encoded bytes to the screen buffer. */
919 for (bp = conversion_buffer; coding->produced--; bp++)
aa9ce936 920 {
aff01dd9
EZ
921 /* Paranoia: discard bytes that would overrun the end of
922 the screen buffer. */
923 if (screen_bp - screen_buf <= MAX_SCREEN_BUF - 2)
aa9ce936 924 {
aff01dd9
EZ
925 *screen_bp++ = (unsigned char)*bp;
926 *screen_bp++ = ScreenAttrib;
aa9ce936 927 }
aff01dd9
EZ
928 if (tty->termscript)
929 fputc (*bp, tty->termscript);
aa9ce936
EZ
930 }
931 }
aff01dd9
EZ
932 /* Update STR and its remaining length. */
933 str += n;
934 sl -= n;
aee81730
RS
935 }
936
aff01dd9 937 /* Dump whatever we have in the screen buffer. */
f32d4091 938 mouse_off_maybe ();
aa9ce936 939 dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
039274cf 940 if (screen_virtual_segment)
aa9ce936
EZ
941 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
942 new_pos_X += (screen_bp - screen_buf) / 2;
f32d4091 943}
aee81730 944
41ad069b
EZ
945/************************************************************************
946 Mouse Highlight (and friends..)
947 ************************************************************************/
948
ee8ceff8 949/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
9005a471
EZ
950static Lisp_Object last_mouse_window;
951
41ad069b
EZ
952static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
953
d009ae66
EZ
954int
955popup_activated (void)
41ad069b 956{
d009ae66 957 return mouse_preempted;
41ad069b
EZ
958}
959
d009ae66 960/* Draw TEXT_AREA glyphs between START and END of glyph row ROW on
28118eb6
EZ
961 window W. X is relative to TEXT_AREA in W. HL is a face override
962 for drawing the glyphs. */
d009ae66 963void
28118eb6
EZ
964tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
965 int start_hpos, int end_hpos,
966 enum draw_glyphs_face hl)
41ad069b 967{
41ad069b 968 struct frame *f = XFRAME (WINDOW_FRAME (w));
3e1944a3 969 struct tty_display_info *tty = FRAME_TTY (f);
34574c02 970 Mouse_HLInfo *hlinfo = &tty->mouse_highlight;
41ad069b 971
d009ae66 972 if (hl == DRAW_MOUSE_FACE)
41ad069b 973 {
d009ae66
EZ
974 int vpos = row->y + WINDOW_TOP_EDGE_Y (w);
975 int kstart = start_hpos + WINDOW_LEFT_EDGE_X (w);
976 int nglyphs = end_hpos - start_hpos;
977 int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
978 int start_offset = offset;
41ad069b 979
d009ae66
EZ
980 if (tty->termscript)
981 fprintf (tty->termscript, "\n<MH+ %d-%d:%d>",
982 kstart, kstart + nglyphs - 1, vpos);
56e19ec4 983
d009ae66 984 mouse_off ();
34574c02 985 IT_set_face (hlinfo->mouse_face_face_id);
d009ae66
EZ
986 /* Since we are going to change only the _colors_ of already
987 displayed text, there's no need to go through all the pain of
988 generating and encoding the text from the glyphs. Instead,
989 we simply poke the attribute byte of each affected position
990 in video memory with the colors computed by IT_set_face! */
991 _farsetsel (_dos_ds);
992 while (nglyphs--)
41ad069b 993 {
d009ae66
EZ
994 _farnspokeb (offset, ScreenAttrib);
995 offset += 2;
41ad069b 996 }
d009ae66
EZ
997 if (screen_virtual_segment)
998 dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
999 mouse_on ();
41ad069b 1000 }
d009ae66 1001 else if (hl == DRAW_NORMAL_TEXT)
41ad069b 1002 {
d009ae66
EZ
1003 /* We are removing a previously-drawn mouse highlight. The
1004 safest way to do so is to redraw the glyphs anew, since all
1005 kinds of faces and display tables could have changed behind
1006 our back. */
1007 int nglyphs = end_hpos - start_hpos;
1008 int save_x = new_pos_X, save_y = new_pos_Y;
1009
1010 if (end_hpos >= row->used[TEXT_AREA])
1011 nglyphs = row->used[TEXT_AREA] - start_hpos;
1012
1013 /* IT_write_glyphs writes at cursor position, so we need to
1014 temporarily move cursor coordinates to the beginning of
1015 the highlight region. */
1016 new_pos_X = start_hpos + WINDOW_LEFT_EDGE_X (w);
1017 new_pos_Y = row->y + WINDOW_TOP_EDGE_Y (w);
41ad069b 1018
d009ae66
EZ
1019 if (tty->termscript)
1020 fprintf (tty->termscript, "<MH- %d-%d:%d>",
1021 new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
1022 IT_write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
1023 if (tty->termscript)
1024 fputs ("\n", tty->termscript);
1025 new_pos_X = save_x;
1026 new_pos_Y = save_y;
41ad069b
EZ
1027 }
1028}
1029
71f65669 1030static void
3e1944a3 1031IT_clear_end_of_line (struct frame *f, int first_unused)
f32d4091
KS
1032{
1033 char *spaces, *sp;
56e19ec4 1034 int i, j, offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
3e1944a3 1035 struct tty_display_info *tty = FRAME_TTY (f);
aa9ce936 1036
2d764c78 1037 if (new_pos_X >= first_unused || fatal_error_in_progress)
aa9ce936 1038 return;
f32d4091
KS
1039
1040 IT_set_face (0);
2d764c78 1041 i = (j = first_unused - new_pos_X) * 2;
3e1944a3
EZ
1042 if (tty->termscript)
1043 fprintf (tty->termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
f32d4091 1044 spaces = sp = alloca (i);
56e19ec4 1045
f32d4091 1046 while (--j >= 0)
aee81730 1047 {
f32d4091
KS
1048 *sp++ = ' ';
1049 *sp++ = ScreenAttrib;
aee81730
RS
1050 }
1051
f32d4091 1052 mouse_off_maybe ();
039274cf
EZ
1053 dosmemput (spaces, i, (int)ScreenPrimary + offset);
1054 if (screen_virtual_segment)
1055 dosv_refresh_virtual_screen (offset, i / 2);
2d764c78
EZ
1056
1057 /* clear_end_of_line_raw on term.c leaves the cursor at first_unused.
1058 Let's follow their lead, in case someone relies on this. */
1059 new_pos_X = first_unused;
aee81730
RS
1060}
1061
71f65669 1062static void
3e1944a3 1063IT_clear_screen (struct frame *f)
f32d4091 1064{
3e1944a3
EZ
1065 struct tty_display_info *tty = FRAME_TTY (f);
1066
1067 if (tty->termscript)
1068 fprintf (tty->termscript, "<CLR:SCR>");
deece6f5
EZ
1069 /* We are sometimes called (from clear_garbaged_frames) when a new
1070 frame is being created, but its faces are not yet realized. In
1071 such a case we cannot call IT_set_face, since it will fail to find
1072 any valid faces and will abort. Instead, use the initial screen
1073 colors; that should mimic what a Unix tty does, which simply clears
1074 the screen with whatever default colors are in use. */
1075 if (FACE_FROM_ID (SELECTED_FRAME (), DEFAULT_FACE_ID) == NULL)
1076 ScreenAttrib = (initial_screen_colors[0] << 4) | initial_screen_colors[1];
1077 else
1078 IT_set_face (0);
f32d4091
KS
1079 mouse_off ();
1080 ScreenClear ();
039274cf
EZ
1081 if (screen_virtual_segment)
1082 dosv_refresh_virtual_screen (0, screen_size);
f32d4091
KS
1083 new_pos_X = new_pos_Y = 0;
1084}
1085
71f65669 1086static void
3e1944a3 1087IT_clear_to_end (struct frame *f)
f32d4091 1088{
3e1944a3
EZ
1089 struct tty_display_info *tty = FRAME_TTY (f);
1090
1091 if (tty->termscript)
1092 fprintf (tty->termscript, "<CLR:EOS>");
f32d4091
KS
1093
1094 while (new_pos_Y < screen_size_Y) {
1095 new_pos_X = 0;
3e1944a3 1096 IT_clear_end_of_line (f, screen_size_X);
f32d4091
KS
1097 new_pos_Y++;
1098 }
1099}
1100
71f65669 1101static void
3e1944a3 1102IT_cursor_to (struct frame *f, int y, int x)
f32d4091 1103{
3e1944a3
EZ
1104 struct tty_display_info *tty = FRAME_TTY (f);
1105
1106 if (tty->termscript)
1107 fprintf (tty->termscript, "\n<XY=%dx%d>", x, y);
f32d4091
KS
1108 new_pos_X = x;
1109 new_pos_Y = y;
1110}
1111
fc171623
KH
1112static int cursor_cleared;
1113
d1d5dc19 1114static void
fc171623
KH
1115IT_display_cursor (int on)
1116{
3e1944a3
EZ
1117 struct tty_display_info *tty = CURTTY ();
1118
fc171623
KH
1119 if (on && cursor_cleared)
1120 {
1121 ScreenSetCursor (current_pos_Y, current_pos_X);
1122 cursor_cleared = 0;
b04021eb 1123 if (tty->termscript)
cb4545ad
EZ
1124 fprintf (tty->termscript, "\nCURSOR ON (%dx%d)",
1125 current_pos_Y, current_pos_X);
fc171623
KH
1126 }
1127 else if (!on && !cursor_cleared)
1128 {
1129 ScreenSetCursor (-1, -1);
1130 cursor_cleared = 1;
b04021eb 1131 if (tty->termscript)
cb4545ad
EZ
1132 fprintf (tty->termscript, "\nCURSOR OFF (%dx%d)",
1133 current_pos_Y, current_pos_X);
fc171623
KH
1134 }
1135}
1136
1137/* Emacs calls cursor-movement functions a lot when it updates the
1138 display (probably a legacy of old terminals where you cannot
1139 update a screen line without first moving the cursor there).
1140 However, cursor movement is expensive on MSDOS (it calls a slow
1141 BIOS function and requires 2 mode switches), while actual screen
1142 updates access the video memory directly and don't depend on
1143 cursor position. To avoid slowing down the redisplay, we cheat:
1144 all functions that move the cursor only set internal variables
1145 which record the cursor position, whereas the cursor is only
1146 moved to its final position whenever screen update is complete.
1147
1148 `IT_cmgoto' is called from the keyboard reading loop and when the
1149 frame update is complete. This means that we are ready for user
1150 input, so we update the cursor position to show where the point is,
1151 and also make the mouse pointer visible.
1152
1153 Special treatment is required when the cursor is in the echo area,
1154 to put the cursor at the end of the text displayed there. */
1155
71f65669 1156static void
a10c8269 1157IT_cmgoto (struct frame *f)
fc171623
KH
1158{
1159 /* Only set the cursor to where it should be if the display is
1160 already in sync with the window contents. */
2d764c78 1161 int update_cursor_pos = 1; /* MODIFF == unchanged_modified; */
3e1944a3 1162 struct tty_display_info *tty = FRAME_TTY (f);
2d764c78
EZ
1163
1164 /* FIXME: This needs to be rewritten for the new redisplay, or
1165 removed. */
1166#if 0
06da1de1
EZ
1167 static int previous_pos_X = -1;
1168
2d764c78
EZ
1169 update_cursor_pos = 1; /* temporary!!! */
1170
06da1de1
EZ
1171 /* If the display is in sync, forget any previous knowledge about
1172 cursor position. This is primarily for unexpected events like
1173 C-g in the minibuffer. */
1174 if (update_cursor_pos && previous_pos_X >= 0)
1175 previous_pos_X = -1;
1176 /* If we are in the echo area, put the cursor at the
1177 end of the echo area message. */
fc171623 1178 if (!update_cursor_pos
c655f6fd 1179 && WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f))) <= new_pos_Y)
fc171623 1180 {
06da1de1
EZ
1181 int tem_X = current_pos_X, dummy;
1182
1183 if (echo_area_glyphs)
1184 {
1185 tem_X = echo_area_glyphs_length;
1186 /* Save current cursor position, to be restored after the
1187 echo area message is erased. Only remember one level
1188 of previous cursor position. */
1189 if (previous_pos_X == -1)
1190 ScreenGetCursor (&dummy, &previous_pos_X);
1191 }
1192 else if (previous_pos_X >= 0)
1193 {
1194 /* We wind up here after the echo area message is erased.
1195 Restore the cursor position we remembered above. */
1196 tem_X = previous_pos_X;
1197 previous_pos_X = -1;
1198 }
9a599a60 1199
06da1de1 1200 if (current_pos_X != tem_X)
9a599a60
EZ
1201 {
1202 new_pos_X = tem_X;
1203 update_cursor_pos = 1;
1204 }
fc171623 1205 }
2d764c78 1206#endif
fc171623
KH
1207
1208 if (update_cursor_pos
1209 && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
1210 {
1211 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
3e1944a3
EZ
1212 if (tty->termscript)
1213 fprintf (tty->termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
fc171623
KH
1214 }
1215
1216 /* Maybe cursor is invisible, so make it visible. */
1217 IT_display_cursor (1);
1218
1219 /* Mouse pointer should be always visible if we are waiting for
1220 keyboard input. */
1221 if (!mouse_visible)
1222 mouse_on ();
1223}
1224
71f65669 1225static void
41ad069b 1226IT_update_begin (struct frame *f)
f32d4091 1227{
3e1944a3 1228 struct tty_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
34574c02
EZ
1229 Mouse_HLInfo *hlinfo = &display_info->mouse_highlight;
1230 struct frame *mouse_face_frame = hlinfo->mouse_face_mouse_frame;
41ad069b 1231
7ccd1daf
EZ
1232 if (display_info->termscript)
1233 fprintf (display_info->termscript, "\n\n<UPDATE_BEGIN");
1234
4d7e6e51 1235 block_input ();
41ad069b 1236
b9f80d41 1237 if (f && f == mouse_face_frame)
41ad069b
EZ
1238 {
1239 /* Don't do highlighting for mouse motion during the update. */
34574c02 1240 hlinfo->mouse_face_defer = 1;
41ad069b
EZ
1241
1242 /* If F needs to be redrawn, simply forget about any prior mouse
1243 highlighting. */
1244 if (FRAME_GARBAGED_P (f))
34574c02 1245 hlinfo->mouse_face_window = Qnil;
41ad069b
EZ
1246
1247 /* Can we tell that this update does not affect the window
1248 where the mouse highlight is? If so, no need to turn off.
48c14970
EZ
1249 Likewise, don't do anything if none of the enabled rows
1250 contains glyphs highlighted in mouse face. */
34574c02
EZ
1251 if (!NILP (hlinfo->mouse_face_window)
1252 && WINDOWP (hlinfo->mouse_face_window))
41ad069b 1253 {
34574c02 1254 struct window *w = XWINDOW (hlinfo->mouse_face_window);
41ad069b
EZ
1255 int i;
1256
8ccb9a54
EZ
1257 /* If the mouse highlight is in the window that was deleted
1258 (e.g., if it was popped by completion), clear highlight
1259 unconditionally. */
e74aeda8 1260 if (NILP (w->contents))
34574c02 1261 hlinfo->mouse_face_window = Qnil;
8ccb9a54
EZ
1262 else
1263 {
1264 for (i = 0; i < w->desired_matrix->nrows; ++i)
48c14970
EZ
1265 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
1266 && MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
8ccb9a54
EZ
1267 break;
1268 }
41ad069b 1269
e74aeda8 1270 if (NILP (w->contents) || i < w->desired_matrix->nrows)
34574c02 1271 clear_mouse_face (hlinfo);
41ad069b
EZ
1272 }
1273 }
b9f80d41 1274 else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
9fed9729
DA
1275 /* If the frame with mouse highlight was deleted, invalidate the
1276 highlight info. */
1277 reset_mouse_highlight (hlinfo);
41ad069b 1278
4d7e6e51 1279 unblock_input ();
f32d4091
KS
1280}
1281
71f65669 1282static void
41ad069b 1283IT_update_end (struct frame *f)
f32d4091 1284{
7ccd1daf
EZ
1285 struct tty_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1286
1287 if (dpyinfo->termscript)
1288 fprintf (dpyinfo->termscript, "\n<UPDATE_END\n");
34574c02 1289 dpyinfo->mouse_highlight.mouse_face_defer = 0;
41ad069b
EZ
1290}
1291
1292static void
1293IT_frame_up_to_date (struct frame *f)
1294{
0c3cfc51
EZ
1295 Lisp_Object new_cursor, frame_desired_cursor;
1296 struct window *sw;
41ad069b 1297
5c747675 1298 FRAME_MOUSE_UPDATE (f);
41ad069b 1299
0c3cfc51
EZ
1300 /* Set the cursor type to whatever they wanted. In a minibuffer
1301 window, we want the cursor to appear only if we are reading input
1302 from this window, and we want the cursor to be taken from the
1303 frame parameters. For the selected window, we use either its
1304 buffer-local value or the value from the frame parameters if the
1305 buffer doesn't define its local value for the cursor type. */
e69b0960
DA
1306 sw = XWINDOW (f->selected_window);
1307 frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
0c3cfc51
EZ
1308 if (cursor_in_echo_area
1309 && FRAME_HAS_MINIBUF_P (f)
1310 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
1311 && sw == XWINDOW (echo_area_window))
1312 new_cursor = frame_desired_cursor;
1313 else
1314 {
e74aeda8 1315 struct buffer *b = XBUFFER (sw->contents);
0c3cfc51 1316
4b4deea2 1317 if (EQ (BVAR (b,cursor_type), Qt))
0c3cfc51 1318 new_cursor = frame_desired_cursor;
4b4deea2 1319 else if (NILP (BVAR (b, cursor_type))) /* nil means no cursor */
0c3cfc51
EZ
1320 new_cursor = Fcons (Qbar, make_number (0));
1321 else
4b4deea2 1322 new_cursor = BVAR (b, cursor_type);
0c3cfc51
EZ
1323 }
1324
1325 IT_set_cursor_type (f, new_cursor);
8ba01a32 1326
41ad069b 1327 IT_cmgoto (f); /* position cursor when update is done */
f32d4091 1328}
1b94449f 1329
c77f6f1b
EZ
1330/* Copy LEN glyphs displayed on a single line whose vertical position
1331 is YPOS, beginning at horizontal position XFROM to horizontal
1332 position XTO, by moving blocks in the video memory. Used by
1333 functions that insert and delete glyphs. */
1334static void
1335IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
1336{
1337 /* The offsets of source and destination relative to the
53964682 1338 conventional memory selector. */
c77f6f1b
EZ
1339 int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary;
1340 int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary;
1341
1342 if (from == to || len <= 0)
1343 return;
1344
1345 _farsetsel (_dos_ds);
1346
1347 /* The source and destination might overlap, so we need to move
1348 glyphs non-destructively. */
1349 if (from > to)
1350 {
1351 for ( ; len; from += 2, to += 2, len--)
1352 _farnspokew (to, _farnspeekw (from));
1353 }
1354 else
1355 {
1356 from += (len - 1) * 2;
1357 to += (len - 1) * 2;
1358 for ( ; len; from -= 2, to -= 2, len--)
1359 _farnspokew (to, _farnspeekw (from));
1360 }
1361 if (screen_virtual_segment)
1362 dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X);
1363}
1364
1365/* Insert and delete glyphs. */
aa9ce936 1366static void
3a8ce822 1367IT_insert_glyphs (struct frame *f, struct glyph *start, int len)
aa9ce936 1368{
c77f6f1b
EZ
1369 int shift_by_width = screen_size_X - (new_pos_X + len);
1370
1371 /* Shift right the glyphs from the nominal cursor position to the
1372 end of this line. */
1373 IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
1374
1375 /* Now write the glyphs to be inserted. */
3e1944a3 1376 IT_write_glyphs (f, start, len);
aa9ce936
EZ
1377}
1378
1379static void
3a8ce822 1380IT_delete_glyphs (struct frame *f, int n)
aa9ce936 1381{
1088b922 1382 emacs_abort ();
aa9ce936
EZ
1383}
1384
211c7152 1385/* set-window-configuration on window.c needs this. */
3bb1f22f 1386void
3a8ce822 1387x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
3bb1f22f 1388{
211c7152
EZ
1389 set_menu_bar_lines (f, value, oldval);
1390}
3bb1f22f 1391
984f5aaa 1392/* This was copied from xfaces.c */
3bb1f22f 1393
984f5aaa
EZ
1394extern Lisp_Object Qbackground_color;
1395extern Lisp_Object Qforeground_color;
8ba01a32 1396Lisp_Object Qreverse;
211c7152 1397extern Lisp_Object Qtitle;
3bb1f22f 1398
48ffe371
RS
1399/* IT_set_terminal_modes is called when emacs is started,
1400 resumed, and whenever the screen is redrawn! */
f32d4091 1401
71f65669 1402static void
3e1944a3 1403IT_set_terminal_modes (struct terminal *term)
f32d4091 1404{
3e1944a3
EZ
1405 struct tty_display_info *tty;
1406
1407 /* If called with initial terminal, it's too early to do anything
1408 useful. */
1409 if (term->type == output_initial)
1410 return;
1411
1412 tty = term->display_info.tty;
1413
1414 if (tty->termscript)
1415 fprintf (tty->termscript, "\n<SET_TERM>");
f32d4091
KS
1416
1417 screen_size_X = ScreenCols ();
1418 screen_size_Y = ScreenRows ();
1419 screen_size = screen_size_X * screen_size_Y;
56e19ec4 1420
f32d4091
KS
1421 new_pos_X = new_pos_Y = 0;
1422 current_pos_X = current_pos_Y = -1;
1423
1424 if (term_setup_done)
1425 return;
1426 term_setup_done = 1;
56e19ec4 1427
f32d4091
KS
1428 startup_screen_size_X = screen_size_X;
1429 startup_screen_size_Y = screen_size_Y;
c9adab25 1430 startup_screen_attrib = ScreenAttrib;
f32d4091 1431
039274cf
EZ
1432 /* Is DOS/V (or any other RSIS software which relocates
1433 the screen) installed? */
1434 {
1435 unsigned short es_value;
1436 __dpmi_regs regs;
1437
1438 regs.h.ah = 0xfe; /* get relocated screen address */
1439 if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
1440 regs.x.es = (ScreenPrimary >> 4) & 0xffff;
1441 else if (screen_old_address) /* already switched to Japanese mode once */
1442 regs.x.es = (screen_old_address >> 4) & 0xffff;
1443 else
1444 regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
1445 regs.x.di = 0;
1446 es_value = regs.x.es;
1447 __dpmi_int (0x10, &regs);
1448
d1d5dc19 1449 if (regs.x.es != es_value)
039274cf 1450 {
d1d5dc19
EZ
1451 /* screen_old_address is only set if ScreenPrimary does NOT
1452 already point to the relocated buffer address returned by
1453 the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
1454 ScreenPrimary to that address at startup under DOS/V. */
891ef8f7 1455 if (regs.x.es != ((ScreenPrimary >> 4) & 0xffff))
d1d5dc19 1456 screen_old_address = ScreenPrimary;
039274cf
EZ
1457 screen_virtual_segment = regs.x.es;
1458 screen_virtual_offset = regs.x.di;
1459 ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
1460 }
1461 }
039274cf 1462
f32d4091
KS
1463 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
1464 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
1465
76ac1508 1466 bright_bg ();
f32d4091
KS
1467}
1468
48ffe371
RS
1469/* IT_reset_terminal_modes is called when emacs is
1470 suspended or killed. */
f32d4091 1471
71f65669 1472static void
3e1944a3 1473IT_reset_terminal_modes (struct terminal *term)
f32d4091 1474{
c9adab25
KH
1475 int display_row_start = (int) ScreenPrimary;
1476 int saved_row_len = startup_screen_size_X * 2;
56e19ec4 1477 int update_row_len = ScreenCols () * 2, current_rows = ScreenRows ();
c9adab25
KH
1478 int to_next_row = update_row_len;
1479 unsigned char *saved_row = startup_screen_buffer;
56e19ec4 1480 int cursor_pos_X = ScreenCols () - 1, cursor_pos_Y = ScreenRows () - 1;
3e1944a3 1481 struct tty_display_info *tty = term->display_info.tty;
c9adab25 1482
3e1944a3
EZ
1483 if (tty->termscript)
1484 fprintf (tty->termscript, "\n<RESET_TERM>");
f32d4091 1485
f32d4091
KS
1486 if (!term_setup_done)
1487 return;
56e19ec4 1488
c9adab25 1489 mouse_off ();
b36701cc
RS
1490
1491 /* Leave the video system in the same state as we found it,
1492 as far as the blink/bright-background bit is concerned. */
1493 maybe_enable_blinking ();
06b1ea13 1494
c9adab25
KH
1495 /* We have a situation here.
1496 We cannot just do ScreenUpdate(startup_screen_buffer) because
1497 the luser could have changed screen dimensions inside Emacs
1498 and failed (or didn't want) to restore them before killing
1499 Emacs. ScreenUpdate() uses the *current* screen dimensions and
1500 thus will happily use memory outside what was allocated for
1501 `startup_screen_buffer'.
1502 Thus we only restore as much as the current screen dimensions
1503 can hold, and clear the rest (if the saved screen is smaller than
1504 the current) with the color attribute saved at startup. The cursor
1505 is also restored within the visible dimensions. */
1506
1507 ScreenAttrib = startup_screen_attrib;
c9adab25 1508
06b1ea13
EZ
1509 /* Don't restore the screen if we are exiting less than 2 seconds
1510 after startup: we might be crashing, and the screen might show
1511 some vital clues to what's wrong. */
1512 if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
c9adab25 1513 {
06b1ea13 1514 ScreenClear ();
039274cf 1515 if (screen_virtual_segment)
06b1ea13
EZ
1516 dosv_refresh_virtual_screen (0, screen_size);
1517
1518 if (update_row_len > saved_row_len)
1519 update_row_len = saved_row_len;
1520 if (current_rows > startup_screen_size_Y)
1521 current_rows = startup_screen_size_Y;
1522
3e1944a3
EZ
1523 if (tty->termscript)
1524 fprintf (tty->termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
06b1ea13
EZ
1525 update_row_len / 2, current_rows);
1526
1527 while (current_rows--)
1528 {
1529 dosmemput (saved_row, update_row_len, display_row_start);
1530 if (screen_virtual_segment)
1531 dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
1532 update_row_len / 2);
1533 saved_row += saved_row_len;
1534 display_row_start += to_next_row;
1535 }
c9adab25
KH
1536 }
1537 if (startup_pos_X < cursor_pos_X)
1538 cursor_pos_X = startup_pos_X;
1539 if (startup_pos_Y < cursor_pos_Y)
1540 cursor_pos_Y = startup_pos_Y;
1541
1542 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
1543 xfree (startup_screen_buffer);
3e1944a3 1544 startup_screen_buffer = NULL;
f32d4091
KS
1545
1546 term_setup_done = 0;
1547}
1548
71f65669 1549static void
3e1944a3 1550IT_set_terminal_window (struct frame *f, int foo)
f32d4091
KS
1551{
1552}
1553
20db1522 1554/* Remember the screen colors of the current frame, to serve as the
2d764c78 1555 default colors for newly-created frames. */
2d764c78
EZ
1556DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
1557 Smsdos_remember_default_colors, 1, 1, 0,
70da46c3 1558 doc: /* Remember the screen colors of the current frame. */)
5842a27b 1559 (Lisp_Object frame)
2d764c78 1560{
2d764c78
EZ
1561 struct frame *f;
1562
b7826503 1563 CHECK_FRAME (frame);
f12dae2f 1564 f = XFRAME (frame);
2d764c78 1565
ff12cd1d
EZ
1566 /* This function is called after applying default-frame-alist to the
1567 initial frame. At that time, if reverse-colors option was
1568 specified in default-frame-alist, it was already applied, and
f12dae2f
EZ
1569 frame colors are reversed. */
1570 initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f);
1571 initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f);
891ef8f7
EZ
1572
1573 return Qnil;
2d764c78
EZ
1574}
1575
f32d4091 1576void
3a8ce822 1577IT_set_frame_parameters (struct frame *f, Lisp_Object alist)
f32d4091
KS
1578{
1579 Lisp_Object tail;
56e19ec4 1580 int i, j, length = XINT (Flength (alist));
db722735 1581 Lisp_Object *parms
663e2b3f 1582 = (Lisp_Object *) alloca (length * word_size);
db722735 1583 Lisp_Object *values
663e2b3f 1584 = (Lisp_Object *) alloca (length * word_size);
2d764c78 1585 /* Do we have to reverse the foreground and background colors? */
e69b0960 1586 int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
2d764c78 1587 int redraw = 0, fg_set = 0, bg_set = 0;
56e19ec4 1588 unsigned long orig_fg, orig_bg;
3e1944a3 1589 struct tty_display_info *tty = FRAME_TTY (f);
2d764c78
EZ
1590
1591 /* If we are creating a new frame, begin with the original screen colors
1592 used for the initial frame. */
76ea4cc9 1593 if (!f->default_face_done_p
2d764c78
EZ
1594 && initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
1595 {
1596 FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
1597 FRAME_BACKGROUND_PIXEL (f) = initial_screen_colors[1];
f12dae2f 1598 init_frame_faces (f);
76ea4cc9 1599 f->default_face_done_p = 1;
2d764c78 1600 }
76ea4cc9
EZ
1601 orig_fg = reverse ? FRAME_BACKGROUND_PIXEL (f) : FRAME_FOREGROUND_PIXEL (f);
1602 orig_bg = reverse ? FRAME_FOREGROUND_PIXEL (f) : FRAME_BACKGROUND_PIXEL (f);
db722735
RS
1603
1604 /* Extract parm names and values into those vectors. */
1605 i = 0;
7d7bbefd 1606 for (tail = alist; CONSP (tail); tail = XCDR (tail))
f32d4091 1607 {
34348bd4 1608 Lisp_Object elt = XCAR (tail);
db722735 1609 parms[i] = Fcar (elt);
b7826503 1610 CHECK_SYMBOL (parms[i]);
db722735
RS
1611 values[i] = Fcdr (elt);
1612 i++;
1613 }
1614
2d764c78 1615 j = i;
db722735 1616
2d764c78
EZ
1617 for (i = 0; i < j; i++)
1618 {
1e21fe48
EZ
1619 Lisp_Object prop, val;
1620
1621 prop = parms[i];
1622 val = values[i];
2d764c78 1623
8ba01a32 1624 if (EQ (prop, Qreverse))
2d764c78
EZ
1625 reverse = EQ (val, Qt);
1626 }
546701f5 1627
76ea4cc9 1628 if (tty->termscript && reverse)
3e1944a3 1629 fprintf (tty->termscript, "<INVERSE-VIDEO>\n");
2d764c78
EZ
1630
1631 /* Now process the alist elements in reverse of specified order. */
db722735
RS
1632 for (i--; i >= 0; i--)
1633 {
76ea4cc9 1634 Lisp_Object prop, val;
1e21fe48
EZ
1635
1636 prop = parms[i];
1637 val = values[i];
f32d4091 1638
4e825084 1639 if (EQ (prop, Qforeground_color))
f32d4091 1640 {
76ea4cc9 1641 unsigned long new_color = load_color (f, NULL, val, reverse
2d764c78
EZ
1642 ? LFACE_BACKGROUND_INDEX
1643 : LFACE_FOREGROUND_INDEX);
3b620731
EZ
1644 if (new_color != FACE_TTY_DEFAULT_COLOR
1645 && new_color != FACE_TTY_DEFAULT_FG_COLOR
1646 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 1647 {
76ea4cc9
EZ
1648 if (!reverse)
1649 {
1650 FRAME_FOREGROUND_PIXEL (f) = new_color;
1651 /* Make sure the foreground of the default face for
1652 this frame is changed as well. */
1653 update_face_from_frame_parameter (f, Qforeground_color, val);
1654 fg_set = 1;
1655 if (tty->termscript)
1656 fprintf (tty->termscript, "<FGCOLOR %lu>\n", new_color);
1657 }
1658 else
1659 {
1660 FRAME_BACKGROUND_PIXEL (f) = new_color;
1661 update_face_from_frame_parameter (f, Qbackground_color, val);
1662 bg_set = 1;
1663 if (tty->termscript)
1664 fprintf (tty->termscript, "<BGCOLOR %lu>\n", new_color);
1665 }
f32d4091
KS
1666 redraw = 1;
1667 }
1668 }
4e825084 1669 else if (EQ (prop, Qbackground_color))
f32d4091 1670 {
76ea4cc9 1671 unsigned long new_color = load_color (f, NULL, val, reverse
2d764c78
EZ
1672 ? LFACE_FOREGROUND_INDEX
1673 : LFACE_BACKGROUND_INDEX);
3b620731
EZ
1674 if (new_color != FACE_TTY_DEFAULT_COLOR
1675 && new_color != FACE_TTY_DEFAULT_FG_COLOR
1676 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 1677 {
76ea4cc9
EZ
1678 if (!reverse)
1679 {
1680 FRAME_BACKGROUND_PIXEL (f) = new_color;
1681 /* Make sure the background of the default face for
1682 this frame is changed as well. */
1683 bg_set = 1;
1684 update_face_from_frame_parameter (f, Qbackground_color, val);
1685 if (tty->termscript)
1686 fprintf (tty->termscript, "<BGCOLOR %lu>\n", new_color);
1687 }
1688 else
1689 {
1690 FRAME_FOREGROUND_PIXEL (f) = new_color;
1691 fg_set = 1;
1692 update_face_from_frame_parameter (f, Qforeground_color, val);
1693 if (tty->termscript)
1694 fprintf (tty->termscript, "<FGCOLOR %lu>\n", new_color);
1695 }
f32d4091
KS
1696 redraw = 1;
1697 }
1698 }
211c7152
EZ
1699 else if (EQ (prop, Qtitle))
1700 {
1701 x_set_title (f, val);
3e1944a3
EZ
1702 if (tty->termscript)
1703 fprintf (tty->termscript, "<TITLE: %s>\n", SDATA (val));
211c7152 1704 }
8ba01a32
EZ
1705 else if (EQ (prop, Qcursor_type))
1706 {
1707 IT_set_cursor_type (f, val);
3e1944a3
EZ
1708 if (tty->termscript)
1709 fprintf (tty->termscript, "<CTYPE: %s>\n",
891ef8f7
EZ
1710 EQ (val, Qbar)
1711 || EQ (val, Qhbar)
1712 || (CONSP (val) && (EQ (XCAR (val), Qbar)
1713 || EQ (XCAR (val), Qhbar)))
8ba01a32
EZ
1714 ? "bar" : "box");
1715 }
3e1944a3
EZ
1716 else if (EQ (prop, Qtty_type))
1717 {
1718 internal_terminal_init ();
1719 if (tty->termscript)
1720 fprintf (tty->termscript, "<TERM_INIT done, TTY_TYPE: %.*s>\n",
1721 SBYTES (val), SDATA (val));
1722 }
db722735 1723 store_frame_param (f, prop, val);
2d764c78 1724 }
db722735 1725
2d764c78
EZ
1726 /* If they specified "reverse", but not the colors, we need to swap
1727 the current frame colors. */
76ea4cc9 1728 if (reverse)
2d764c78
EZ
1729 {
1730 if (!fg_set)
1731 {
76ea4cc9
EZ
1732 FRAME_FOREGROUND_PIXEL (f) = orig_bg;
1733 update_face_from_frame_parameter (f, Qforeground_color,
1734 tty_color_name (f, orig_bg));
2d764c78
EZ
1735 redraw = 1;
1736 }
1737 if (!bg_set)
1738 {
76ea4cc9
EZ
1739 FRAME_BACKGROUND_PIXEL (f) = orig_fg;
1740 update_face_from_frame_parameter (f, Qbackground_color,
1741 tty_color_name (f, orig_fg));
2d764c78
EZ
1742 redraw = 1;
1743 }
f32d4091
KS
1744 }
1745
1746 if (redraw)
1747 {
2d764c78 1748 face_change_count++; /* forces xdisp.c to recompute basic faces */
5e617bc2 1749 if (f == SELECTED_FRAME ())
3bb1f22f 1750 redraw_frame (f);
f32d4091
KS
1751 }
1752}
1753
a10c8269 1754extern void init_frame_faces (struct frame *);
a7cf9151 1755
f32d4091
KS
1756#endif /* !HAVE_X_WINDOWS */
1757
1758
48ffe371
RS
1759/* Do we need the internal terminal? */
1760
f32d4091 1761void
3a8ce822 1762internal_terminal_init (void)
f32d4091 1763{
2306a735 1764 static int init_needed = 1;
56e19ec4 1765 char *term = getenv ("TERM"), *colors;
5e617bc2 1766 struct frame *sf = SELECTED_FRAME ();
3e1944a3 1767 struct tty_display_info *tty;
f32d4091
KS
1768
1769#ifdef HAVE_X_WINDOWS
1770 if (!inhibit_window_system)
1771 return;
1772#endif
1773
3e1944a3
EZ
1774 /* If this is the initial terminal, we are done here. */
1775 if (sf->output_method == output_initial)
1776 return;
1777
f32d4091
KS
1778 internal_terminal
1779 = (!noninteractive) && term && !strcmp (term, "internal");
1780
f32d4091
KS
1781#ifndef HAVE_X_WINDOWS
1782 if (!internal_terminal || inhibit_window_system)
1783 {
2d764c78 1784 sf->output_method = output_termcap;
f32d4091
KS
1785 return;
1786 }
1787
3e1944a3 1788 tty = FRAME_TTY (sf);
15dbb4d6 1789 kset_window_system (current_kboard, Qpc);
f12dae2f 1790 sf->output_method = output_msdos_raw;
2306a735 1791 if (init_needed)
3e1944a3 1792 {
2306a735
EZ
1793 if (!tty->termscript && getenv ("EMACSTEST"))
1794 tty->termscript = fopen (getenv ("EMACSTEST"), "wt");
1795 if (tty->termscript)
1796 {
1797 time_t now = time (NULL);
1798 struct tm *tnow = localtime (&now);
1799 char tbuf[100];
3e1944a3 1800
2306a735
EZ
1801 strftime (tbuf, sizeof (tbuf) - 1, "%a %b %e %Y %H:%M:%S %Z", tnow);
1802 fprintf (tty->termscript, "\nEmacs session started at %s\n", tbuf);
1803 fprintf (tty->termscript, "=====================\n\n");
1804 }
3e1944a3 1805
2306a735 1806 Vinitial_window_system = Qpc;
23415acf 1807 Vwindow_system_version = make_number (24); /* RE Emacs version */
2306a735 1808 tty->terminal->type = output_msdos_raw;
039274cf 1809
2306a735
EZ
1810 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM
1811 address. */
1812 screen_old_address = 0;
039274cf 1813
2306a735
EZ
1814 /* Forget the stale screen colors as well. */
1815 initial_screen_colors[0] = initial_screen_colors[1] = -1;
2d764c78 1816
2306a735
EZ
1817 FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = 7; /* White */
1818 FRAME_FOREGROUND_PIXEL (SELECTED_FRAME ()) = 0; /* Black */
1819 bright_bg ();
1820 colors = getenv ("EMACSCOLORS");
1821 if (colors && strlen (colors) >= 2)
1822 {
1823 /* The colors use 4 bits each (we enable bright background). */
1824 if (isdigit (colors[0]))
1825 colors[0] -= '0';
1826 else if (isxdigit (colors[0]))
1827 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1828 if (colors[0] >= 0 && colors[0] < 16)
1829 FRAME_FOREGROUND_PIXEL (SELECTED_FRAME ()) = colors[0];
1830 if (isdigit (colors[1]))
1831 colors[1] -= '0';
1832 else if (isxdigit (colors[1]))
1833 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
1834 if (colors[1] >= 0 && colors[1] < 16)
1835 FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = colors[1];
1836 }
9fed9729
DA
1837
1838 reset_mouse_highlight (&the_only_display_info.mouse_highlight);
2306a735
EZ
1839
1840 if (have_mouse) /* detected in dos_ttraw, which see */
1841 {
1842 have_mouse = 1; /* enable mouse */
1843 mouse_visible = 0;
1844 mouse_setup_buttons (mouse_button_count);
1845 tty->terminal->mouse_position_hook = &mouse_get_pos;
1846 mouse_init ();
1847 }
f32d4091 1848
2306a735
EZ
1849 if (tty->termscript && screen_size)
1850 fprintf (tty->termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
1851 screen_size_X, screen_size_Y);
f32d4091 1852
f12dae2f 1853 init_frame_faces (sf);
2306a735
EZ
1854 init_needed = 0;
1855 }
f32d4091
KS
1856#endif
1857}
1858
3e1944a3
EZ
1859void
1860initialize_msdos_display (struct terminal *term)
1861{
1862 term->rif = 0; /* we don't support window-based display */
1863 term->cursor_to_hook = term->raw_cursor_to_hook = IT_cursor_to;
1864 term->clear_to_end_hook = IT_clear_to_end;
1865 term->clear_frame_hook = IT_clear_screen;
1866 term->clear_end_of_line_hook = IT_clear_end_of_line;
1867 term->ins_del_lines_hook = 0;
1868 term->insert_glyphs_hook = IT_insert_glyphs;
1869 term->write_glyphs_hook = IT_write_glyphs;
1870 term->delete_glyphs_hook = IT_delete_glyphs;
1871 term->ring_bell_hook = IT_ring_bell;
1872 term->reset_terminal_modes_hook = IT_reset_terminal_modes;
1873 term->set_terminal_modes_hook = IT_set_terminal_modes;
1874 term->set_terminal_window_hook = IT_set_terminal_window;
1875 term->update_begin_hook = IT_update_begin;
1876 term->update_end_hook = IT_update_end;
1877 term->frame_up_to_date_hook = IT_frame_up_to_date;
1878 term->mouse_position_hook = 0; /* set later by dos_ttraw */
1879 term->frame_rehighlight_hook = 0;
1880 term->frame_raise_lower_hook = 0;
1881 term->set_vertical_scroll_bar_hook = 0;
1882 term->condemn_scroll_bars_hook = 0;
1883 term->redeem_scroll_bar_hook = 0;
1884 term->judge_scroll_bars_hook = 0;
1885 term->read_socket_hook = &tty_read_avail_input; /* from keyboard.c */
1886}
1887
3a8ce822
EZ
1888int
1889dos_get_saved_screen (char **screen, int *rows, int *cols)
f32d4091
KS
1890{
1891#ifndef HAVE_X_WINDOWS
1892 *screen = startup_screen_buffer;
1893 *cols = startup_screen_size_X;
1894 *rows = startup_screen_size_Y;
039274cf 1895 return *screen != (char *)0;
f32d4091
KS
1896#else
1897 return 0;
56e19ec4 1898#endif
f32d4091 1899}
3bb1f22f
RS
1900
1901#ifndef HAVE_X_WINDOWS
1902
1903/* We are not X, but we can emulate it well enough for our needs... */
1904void
73931ad1 1905check_window_system (void)
3bb1f22f 1906{
5e617bc2 1907 if (! FRAME_MSDOS_P (SELECTED_FRAME ()))
2d764c78 1908 error ("Not running under a window system");
3bb1f22f
RS
1909}
1910
1911#endif
1912
5063b150 1913\f
f32d4091
KS
1914/* ----------------------- Keyboard control ----------------------
1915 *
1916 * Keymaps reflect the following keyboard layout:
1917 *
1918 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
1919 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
1920 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
1921 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
1922 * SPACE
1923 */
1924
d1d5dc19
EZ
1925#define Ignore 0x0000
1926#define Normal 0x0000 /* normal key - alt changes scan-code */
1927#define FctKey 0x1000 /* func key if c == 0, else c */
1928#define Special 0x2000 /* func key even if c != 0 */
1929#define ModFct 0x3000 /* special if mod-keys, else 'c' */
1930#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
1931#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
1932#define Grey 0x6000 /* Grey keypad key */
1933
1934#define Alt 0x0100 /* alt scan-code */
1935#define Ctrl 0x0200 /* ctrl scan-code */
1936#define Shift 0x0400 /* shift scan-code */
1937
db9cd97a 1938static int extended_kbd; /* 101 (102) keyboard present. */
f32d4091 1939
d1d5dc19
EZ
1940struct kbd_translate {
1941 unsigned char sc;
1942 unsigned char ch;
1943 unsigned short code;
1944};
1945
f32d4091
KS
1946struct dos_keyboard_map
1947{
1948 char *unshifted;
1949 char *shifted;
1950 char *alt_gr;
d1d5dc19 1951 struct kbd_translate *translate_table;
f32d4091
KS
1952};
1953
1954
1955static struct dos_keyboard_map us_keyboard = {
1956/* 0 1 2 3 4 5 */
d26e478e
EZ
1957/* 01234567890123456789012345678901234567890 123 45678901234 */
1958 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ \\zxcvbnm,./ ",
f32d4091 1959/* 0123456789012345678901234567890123456789 012345678901234 */
d26e478e 1960 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| |ZXCVBNM<>? ",
d1d5dc19
EZ
1961 0, /* no Alt-Gr key */
1962 0 /* no translate table */
f32d4091
KS
1963};
1964
1965static struct dos_keyboard_map fr_keyboard = {
1966/* 0 1 2 3 4 5 */
1967/* 012 3456789012345678901234567890123456789012345678901234 */
d26e478e 1968