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