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