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