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