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