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