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