(rmail-summary-expunge)
[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
bed43f1d
EZ
673 /* Update Emacs' notion of screen dimensions. */
674 screen_size_X = *cols;
675 screen_size_Y = *rows;
676 screen_size = *cols * *rows;
677
41ad069b
EZ
678#if __DJGPP__ > 1
679 /* If the dimensions changed, the mouse highlight info is invalid. */
680 if (current_rows != *rows || current_cols != *cols)
681 {
682 struct frame *f = SELECTED_FRAME();
683 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
684 Lisp_Object window = dpyinfo->mouse_face_window;
685
686 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
687 {
688 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
689 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
690 dpyinfo->mouse_face_window = Qnil;
691 }
692 }
693#endif
694
76ac1508
RS
695 /* Enable bright background colors. */
696 bright_bg ();
039274cf
EZ
697
698 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
699 be defensive anyway. */
700 if (screen_virtual_segment)
701 dosv_refresh_virtual_screen (0, *cols * *rows);
4a96d4d2
KH
702}
703
48ffe371
RS
704/* If we write a character in the position where the mouse is,
705 the mouse cursor may need to be refreshed. */
09e2ac30
RS
706
707static void
f32d4091 708mouse_off_maybe ()
09e2ac30 709{
f32d4091
KS
710 int x, y;
711
712 if (!mouse_visible)
713 return;
714
715 mouse_get_xy (&x, &y);
716 if (y != new_pos_Y || x < new_pos_X)
717 return;
718
719 mouse_off ();
720}
721
8ba01a32
EZ
722#define DEFAULT_CURSOR_START (-1)
723#define DEFAULT_CURSOR_WIDTH (-1)
724#define BOX_CURSOR_WIDTH (-32)
725
726/* Set cursor to begin at scan line START_LINE in the character cell
727 and extend for WIDTH scan lines. Scan lines are counted from top
728 of the character cell, starting from zero. */
729static void
730msdos_set_cursor_shape (struct frame *f, int start_line, int width)
731{
732#if __DJGPP__ > 1
733 unsigned desired_cursor;
734 __dpmi_regs regs;
735 int max_line, top_line, bot_line;
736
737 /* Avoid the costly BIOS call if F isn't the currently selected
738 frame. Allow for NULL as unconditionally meaning the selected
739 frame. */
740 if (f && f != SELECTED_FRAME())
741 return;
742
743 /* The character cell size in scan lines is stored at 40:85 in the
744 BIOS data area. */
745 max_line = _farpeekw (_dos_ds, 0x485) - 1;
746 switch (max_line)
747 {
748 default: /* this relies on CGA cursor emulation being ON! */
749 case 7:
750 bot_line = 7;
751 break;
752 case 9:
753 bot_line = 9;
754 break;
755 case 13:
756 bot_line = 12;
757 break;
758 case 15:
759 bot_line = 14;
760 break;
761 }
762
763 if (width < 0)
764 {
765 if (width == BOX_CURSOR_WIDTH)
766 {
767 top_line = 0;
768 bot_line = max_line;
769 }
770 else if (start_line != DEFAULT_CURSOR_START)
771 {
772 top_line = start_line;
773 bot_line = top_line - width - 1;
774 }
775 else if (width != DEFAULT_CURSOR_WIDTH)
776 {
777 top_line = 0;
778 bot_line = -1 - width;
779 }
780 else
781 top_line = bot_line + 1;
782 }
783 else if (width == 0)
784 {
785 /* [31, 0] seems to DTRT for all screen sizes. */
786 top_line = 31;
787 bot_line = 0;
788 }
789 else /* WIDTH is positive */
790 {
791 if (start_line != DEFAULT_CURSOR_START)
792 bot_line = start_line;
793 top_line = bot_line - (width - 1);
794 }
795
796 /* If the current cursor shape is already what they want, we are
797 history here. */
798 desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
799 if (desired_cursor == _farpeekw (_dos_ds, 0x460))
800 return;
801
802 regs.h.ah = 1;
803 regs.x.cx = desired_cursor;
804 __dpmi_int (0x10, &regs);
805#endif /* __DJGPP__ > 1 */
806}
807
808static void
809IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
810{
811 if (EQ (cursor_type, Qbar))
812 {
813 /* Just BAR means the normal EGA/VGA cursor. */
814 msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
815 }
816 else if (CONSP (cursor_type) && EQ (XCAR (cursor_type), Qbar))
817 {
818 Lisp_Object bar_parms = XCDR (cursor_type);
819 int width;
820
821 if (INTEGERP (bar_parms))
822 {
823 /* Feature: negative WIDTH means cursor at the top
824 of the character cell, zero means invisible cursor. */
825 width = XINT (bar_parms);
826 msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
827 width);
828 }
829 else if (CONSP (bar_parms)
830 && INTEGERP (XCAR (bar_parms))
831 && INTEGERP (XCDR (bar_parms)))
832 {
833 int start_line = XINT (XCDR (bar_parms));
834
835 width = XINT (XCAR (bar_parms));
836 msdos_set_cursor_shape (f, start_line, width);
837 }
838 }
839 else
840 /* Treat anything unknown as "box cursor". This includes nil, so
841 that a frame which doesn't specify a cursor type gets a box,
842 which is the default in Emacs. */
843 msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
844}
845
71f65669
EZ
846static void
847IT_ring_bell (void)
f32d4091
KS
848{
849 if (visible_bell)
aee81730 850 {
f32d4091
KS
851 mouse_off ();
852 ScreenVisualBell ();
aee81730 853 }
f32d4091 854 else
3635be47
RS
855 {
856 union REGS inregs, outregs;
857 inregs.h.ah = 2;
858 inregs.h.dl = 7;
859 intdos (&inregs, &outregs);
860 }
09e2ac30
RS
861}
862
c77f6f1b
EZ
863/* Given a face id FACE, extract the face parameters to be used for
864 display until the face changes. The face parameters (actually, its
865 color) are used to construct the video attribute byte for each
866 glyph during the construction of the buffer that is then blitted to
867 the video RAM. */
f32d4091
KS
868static void
869IT_set_face (int face)
870{
2d764c78 871 struct frame *sf = SELECTED_FRAME();
546701f5
EZ
872 struct face *fp = FACE_FROM_ID (sf, face);
873 struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
874 unsigned long fg, bg, dflt_fg, dflt_bg;
f32d4091 875
c77f6f1b 876 if (!fp)
e30aee93 877 {
546701f5 878 fp = dfp;
e30aee93
EZ
879 /* The default face for the frame should always be realized and
880 cached. */
881 if (!fp)
882 abort ();
883 }
f32d4091 884 screen_face = face;
c77f6f1b
EZ
885 fg = fp->foreground;
886 bg = fp->background;
546701f5
EZ
887 dflt_fg = dfp->foreground;
888 dflt_bg = dfp->background;
c77f6f1b 889
3b620731
EZ
890 /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_*
891 colors mean use the colors of the default face, except that if
892 highlight is on, invert the foreground and the background. Note
893 that we assume all 16 colors to be available for the background,
894 since Emacs switches on this mode (and loses the blinking
895 attribute) at startup. */
f9d2fdc4 896 if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731 897 fg = FRAME_FOREGROUND_PIXEL (sf);
f9d2fdc4 898 else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
3b620731
EZ
899 fg = FRAME_BACKGROUND_PIXEL (sf);
900 if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
901 bg = FRAME_BACKGROUND_PIXEL (sf);
f9d2fdc4 902 else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731
EZ
903 bg = FRAME_FOREGROUND_PIXEL (sf);
904
905 /* Make sure highlighted lines really stand out, come what may. */
906 if ((highlight || fp->tty_reverse_p)
546701f5 907 && (fg == dflt_fg && bg == dflt_bg))
3b620731
EZ
908 {
909 unsigned long tem = fg;
910
911 fg = bg;
912 bg = tem;
913 }
c77f6f1b 914 if (termscript)
3b620731
EZ
915 fprintf (termscript, "<FACE %d%s: %d/%d[FG:%d/BG:%d]>", face,
916 highlight ? "H" : "", fp->foreground, fp->background, fg, bg);
c77f6f1b
EZ
917 if (fg >= 0 && fg < 16)
918 {
919 ScreenAttrib &= 0xf0;
920 ScreenAttrib |= fg;
921 }
922 if (bg >= 0 && bg < 16)
923 {
924 ScreenAttrib &= 0x0f;
925 ScreenAttrib |= ((bg & 0x0f) << 4);
926 }
f32d4091
KS
927}
928
aa9ce936
EZ
929Lisp_Object Vdos_unsupported_char_glyph;
930
71f65669 931static void
c77f6f1b 932IT_write_glyphs (struct glyph *str, int str_len)
f32d4091 933{
aa9ce936
EZ
934 unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
935 int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
936 unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
039274cf 937 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
938 register int sl = str_len;
939 register int tlen = GLYPH_TABLE_LENGTH;
940 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
941
e023fb27
EZ
942 /* If terminal_coding does any conversion, use it, otherwise use
943 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
944 because it always returns 1 if terminal_coding.src_multibyte is 1. */
945 struct coding_system *coding =
946 (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
947 ? &terminal_coding
948 : &safe_terminal_coding);
2d764c78 949 struct frame *sf;
87485d6f 950
52d38ab2
EZ
951 /* Do we need to consider conversion of unibyte characters to
952 multibyte? */
953 int convert_unibyte_characters
e16bf494
AI
954 = (NILP (current_buffer->enable_multibyte_characters)
955 && unibyte_display_via_language_environment);
52d38ab2 956
648648a9
KH
957 unsigned char conversion_buffer[256];
958 int conversion_buffer_size = sizeof conversion_buffer;
959
3b620731 960 if (str_len <= 0) return;
aee81730 961
aa9ce936
EZ
962 screen_buf = screen_bp = alloca (str_len * 2);
963 screen_buf_end = screen_buf + str_len * 2;
2d764c78 964 sf = SELECTED_FRAME();
e30aee93
EZ
965
966 /* Since faces get cached and uncached behind our back, we can't
967 rely on their indices in the cache being consistent across
968 invocations. So always reset the screen face to the default
969 face of the frame, before writing glyphs, and let the glyphs
970 set the right face if it's different from the default. */
971 IT_set_face (DEFAULT_FACE_ID);
aee81730 972
aa9ce936
EZ
973 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
974 the tail. */
975 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
976 while (sl)
977 {
c77f6f1b 978 int cf, chlen, enclen;
3b620731 979 unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
c77f6f1b 980 unsigned ch;
aa9ce936
EZ
981
982 /* Glyphs with GLYPH_MASK_PADDING bit set are actually there
983 only for the redisplay code to know how many columns does
984 this character occupy on the screen. Skip padding glyphs. */
c77f6f1b 985 if (CHAR_GLYPH_PADDING_P (*str))
aa9ce936
EZ
986 {
987 str++;
988 sl--;
989 }
990 else
991 {
04ee4f45
EZ
992 register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str);
993 int glyph_not_in_table = 0;
994
995 if (g < 0 || g >= tlen)
996 {
997 /* This glyph doesn't have an entry in Vglyph_table. */
998 ch = str->u.ch;
999 glyph_not_in_table = 1;
1000 }
1001 else
1002 {
1003 /* This glyph has an entry in Vglyph_table, so process
1004 any aliases before testing for simpleness. */
1005 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
1006 ch = FAST_GLYPH_CHAR (g);
1007 }
1008
aa9ce936 1009 /* Convert the character code to multibyte, if they
04ee4f45
EZ
1010 requested display via language environment. We only want
1011 to convert unibyte characters to multibyte in unibyte
1012 buffers! Otherwise, the 8-bit value in CH came from the
1013 display table set up to display foreign characters. */
52d38ab2 1014 if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters
f0dd4c35
EZ
1015 && (ch >= 0240
1016 || (ch >= 0200 && !NILP (Vnonascii_translation_table))))
aa9ce936
EZ
1017 ch = unibyte_char_to_multibyte (ch);
1018
1019 /* Invalid characters are displayed with a special glyph. */
04ee4f45 1020 if (! CHAR_VALID_P (ch, 0))
aa9ce936
EZ
1021 {
1022 g = !NILP (Vdos_unsupported_char_glyph)
1023 ? Vdos_unsupported_char_glyph
2d764c78 1024 : MAKE_GLYPH (sf, '\177', GLYPH_FACE (sf, g));
aa9ce936
EZ
1025 ch = FAST_GLYPH_CHAR (g);
1026 }
aa9ce936
EZ
1027
1028 /* If the face of this glyph is different from the current
1029 screen face, update the screen attribute byte. */
1030 cf = FAST_GLYPH_FACE (g);
1031 if (cf != screen_face)
1032 IT_set_face (cf); /* handles invalid faces gracefully */
1033
04ee4f45 1034 if (glyph_not_in_table || GLYPH_SIMPLE_P (tbase, tlen, g))
3b620731
EZ
1035 {
1036 /* We generate the multi-byte form of CH in WORKBUF. */
1037 chlen = CHAR_STRING (ch, workbuf);
1038 buf = workbuf;
1039 }
aa9ce936
EZ
1040 else
1041 {
1042 /* We have a string in Vglyph_table. */
1043 chlen = GLYPH_LENGTH (tbase, g);
1044 buf = GLYPH_STRING (tbase, g);
1045 }
1046
c77f6f1b 1047 /* If the character is not multibyte, don't bother converting it. */
aa9ce936
EZ
1048 if (chlen == 1)
1049 {
1050 *conversion_buffer = (unsigned char)ch;
1051 chlen = 0;
1052 enclen = 1;
1053 }
1054 else
1055 {
55a17202 1056 coding->src_multibyte = 1;
aa9ce936
EZ
1057 encode_coding (coding, buf, conversion_buffer, chlen,
1058 conversion_buffer_size);
1059 chlen -= coding->consumed;
1060 enclen = coding->produced;
1061
1062 /* Replace glyph codes that cannot be converted by
1063 terminal_coding with Vdos_unsupported_char_glyph. */
1064 if (*conversion_buffer == '?')
1065 {
5e30eaa2 1066 unsigned char *cbp = conversion_buffer;
aa9ce936
EZ
1067
1068 while (cbp < conversion_buffer + enclen && *cbp == '?')
1069 *cbp++ = unsupported_char;
1070 if (unsupported_face != screen_face)
1071 IT_set_face (unsupported_face);
1072 }
1073 }
1074
1075 if (enclen + chlen > screen_buf_end - screen_bp)
1076 {
1077 /* The allocated buffer for screen writes is too small.
1078 Flush it and loop again without incrementing STR, so
1079 that the next loop will begin with the same glyph. */
1080 int nbytes = screen_bp - screen_buf;
1081
1082 mouse_off_maybe ();
1083 dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset);
1084 if (screen_virtual_segment)
1085 dosv_refresh_virtual_screen (offset, nbytes / 2);
1086 new_pos_X += nbytes / 2;
1087 offset += nbytes;
1088
1089 /* Prepare to reuse the same buffer again. */
1090 screen_bp = screen_buf;
1091 }
1092 else
1093 {
1094 /* There's enough place in the allocated buffer to add
1095 the encoding of this glyph. */
1096
1097 /* First, copy the encoded bytes. */
1098 for (bp = conversion_buffer; enclen--; bp++)
1099 {
1100 *screen_bp++ = (unsigned char)*bp;
1101 *screen_bp++ = ScreenAttrib;
1102 if (termscript)
1103 fputc (*bp, termscript);
1104 }
1105
1106 /* Now copy the bytes not consumed by the encoding. */
1107 if (chlen > 0)
1108 {
1109 buf += coding->consumed;
1110 while (chlen--)
1111 {
1112 if (termscript)
1113 fputc (*buf, termscript);
1114 *screen_bp++ = (unsigned char)*buf++;
1115 *screen_bp++ = ScreenAttrib;
1116 }
1117 }
1118
1119 /* Update STR and its remaining length. */
1120 str++;
1121 sl--;
1122 }
1123 }
aee81730
RS
1124 }
1125
aa9ce936 1126 /* Dump whatever is left in the screen buffer. */
f32d4091 1127 mouse_off_maybe ();
aa9ce936 1128 dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
039274cf 1129 if (screen_virtual_segment)
aa9ce936
EZ
1130 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
1131 new_pos_X += (screen_bp - screen_buf) / 2;
1132
1133 /* We may have to output some codes to terminate the writing. */
1134 if (CODING_REQUIRE_FLUSHING (coding))
1135 {
1136 coding->mode |= CODING_MODE_LAST_BLOCK;
1137 encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
1138 if (coding->produced > 0)
1139 {
241424da 1140 screen_buf = alloca (coding->produced * 2);
aa9ce936
EZ
1141 for (screen_bp = screen_buf, bp = conversion_buffer;
1142 coding->produced--; bp++)
1143 {
1144 *screen_bp++ = (unsigned char)*bp;
1145 *screen_bp++ = ScreenAttrib;
1146 if (termscript)
1147 fputc (*bp, termscript);
1148 }
1149 offset += screen_bp - screen_buf;
1150 mouse_off_maybe ();
1151 dosmemput (screen_buf, screen_bp - screen_buf,
1152 (int)ScreenPrimary + offset);
1153 if (screen_virtual_segment)
1154 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
1155 new_pos_X += (screen_bp - screen_buf) / 2;
1156 }
1157 }
f32d4091 1158}
aee81730 1159
41ad069b
EZ
1160/************************************************************************
1161 Mouse Highlight (and friends..)
1162 ************************************************************************/
1163
1164/* This is used for debugging, to turn off note_mouse_highlight. */
1165int disable_mouse_highlight;
1166
48c14970
EZ
1167/* If non-nil, dos_rawgetc generates an event to display that string.
1168 (The display is done in keyboard.c:read_char, by calling
1169 show_help_echo.) */
41ad069b
EZ
1170static Lisp_Object help_echo;
1171static Lisp_Object previous_help_echo; /* a helper temporary variable */
1172
48c14970
EZ
1173/* These record the window, the object and the position where the help
1174 echo string was generated. */
1175static Lisp_Object help_echo_window;
1176static Lisp_Object help_echo_object;
1177static int help_echo_pos;
1178
41ad069b
EZ
1179static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
1180
1181/* Set the mouse pointer shape according to whether it is in the
1182 area where the mouse highlight is in effect. */
1183static void
1184IT_set_mouse_pointer (int mode)
1185{
1186 /* A no-op for now. DOS text-mode mouse pointer doesn't offer too
1187 many possibilities to change its shape, and the available
1188 functionality pretty much sucks (e.g., almost every reasonable
1189 shape will conceal the character it is on). Since the color of
1190 the pointer changes in the highlighted area, it is not clear to
1191 me whether anything else is required, anyway. */
1192}
1193
1194/* Display the active region described by mouse_face_*
1195 in its mouse-face if HL > 0, in its normal face if HL = 0. */
1196static void
1197show_mouse_face (struct display_info *dpyinfo, int hl)
1198{
1199 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
1200 struct frame *f = XFRAME (WINDOW_FRAME (w));
1201 int i;
1202 struct face *fp;
1203
1204
1205 /* If window is in the process of being destroyed, don't bother
1206 doing anything. */
1207 if (w->current_matrix == NULL)
1208 goto set_cursor_shape;
1209
1210 /* Recognize when we are called to operate on rows that don't exist
1211 anymore. This can happen when a window is split. */
1212 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
1213 goto set_cursor_shape;
1214
1215 /* There's no sense to do anything if the mouse face isn't realized. */
1216 if (hl > 0)
1217 {
1218 fp = FACE_FROM_ID (SELECTED_FRAME(), dpyinfo->mouse_face_face_id);
1219 if (!fp)
1220 goto set_cursor_shape;
1221 }
1222
1223 /* Note that mouse_face_beg_row etc. are window relative. */
1224 for (i = dpyinfo->mouse_face_beg_row;
1225 i <= dpyinfo->mouse_face_end_row;
1226 i++)
1227 {
1228 int start_hpos, end_hpos;
1229 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
1230
1231 /* Don't do anything if row doesn't have valid contents. */
1232 if (!row->enabled_p)
1233 continue;
1234
1235 /* For all but the first row, the highlight starts at column 0. */
1236 if (i == dpyinfo->mouse_face_beg_row)
1237 start_hpos = dpyinfo->mouse_face_beg_col;
1238 else
1239 start_hpos = 0;
1240
1241 if (i == dpyinfo->mouse_face_end_row)
1242 end_hpos = dpyinfo->mouse_face_end_col;
1243 else
1244 end_hpos = row->used[TEXT_AREA];
1245
1246 if (end_hpos <= start_hpos)
1247 continue;
48c14970
EZ
1248 /* Record that some glyphs of this row are displayed in
1249 mouse-face. */
1250 row->mouse_face_p = hl > 0;
41ad069b
EZ
1251 if (hl > 0)
1252 {
1253 int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1254 int kstart = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1255 int nglyphs = end_hpos - start_hpos;
1256 int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
1257 int start_offset = offset;
1258
1259 if (termscript)
1260 fprintf (termscript, "\n<MH+ %d-%d:%d>",
1261 kstart, kstart + nglyphs - 1, vpos);
1262
1263 mouse_off ();
1264 IT_set_face (dpyinfo->mouse_face_face_id);
1265 /* Since we are going to change only the _colors_ of the
1266 displayed text, there's no need to go through all the
1267 pain of generating and encoding the text from the glyphs.
1268 Instead, we simply poke the attribute byte of each
1269 affected position in video memory with the colors
1270 computed by IT_set_face! */
1271 _farsetsel (_dos_ds);
1272 while (nglyphs--)
1273 {
1274 _farnspokeb (offset, ScreenAttrib);
1275 offset += 2;
1276 }
1277 if (screen_virtual_segment)
1278 dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
1279 mouse_on ();
1280 }
1281 else
1282 {
1283 /* We are removing a previously-drawn mouse highlight. The
1284 safest way to do so is to redraw the glyphs anew, since
1285 all kinds of faces and display tables could have changed
1286 behind our back. */
1287 int nglyphs = end_hpos - start_hpos;
1288 int save_x = new_pos_X, save_y = new_pos_Y;
1289
1290 if (end_hpos >= row->used[TEXT_AREA])
1291 nglyphs = row->used[TEXT_AREA] - start_hpos;
1292
1293 /* IT_write_glyphs writes at cursor position, so we need to
1294 temporarily move cursor coordinates to the beginning of
1295 the highlight region. */
1296 new_pos_X = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1297 new_pos_Y = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1298
1299 if (termscript)
1300 fprintf (termscript, "<MH- %d-%d:%d>",
1301 new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
1302 IT_write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
1303 if (termscript)
1304 fputs ("\n", termscript);
1305 new_pos_X = save_x;
1306 new_pos_Y = save_y;
1307 }
1308 }
1309
1310 set_cursor_shape:
1311
1312 /* Change the mouse pointer shape. */
1313 IT_set_mouse_pointer (hl);
1314}
1315
1316/* Clear out the mouse-highlighted active region.
1317 Redraw it un-highlighted first. */
1318static void
1319clear_mouse_face (struct display_info *dpyinfo)
1320{
1321 if (! NILP (dpyinfo->mouse_face_window))
1322 show_mouse_face (dpyinfo, 0);
1323
1324 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1325 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1326 dpyinfo->mouse_face_window = Qnil;
1327}
1328
1329/* Find the glyph matrix position of buffer position POS in window W.
1330 *HPOS and *VPOS are set to the positions found. W's current glyphs
1331 must be up to date. If POS is above window start return (0, 0).
1332 If POS is after end of W, return end of last line in W. */
1333static int
1334fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
1335{
1336 int i;
1337 int lastcol;
1338 int maybe_next_line_p = 0;
1339 int line_start_position;
1340 int yb = window_text_bottom_y (w);
1341 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
1342 struct glyph_row *best_row = row;
1343
1344 while (row->y < yb)
1345 {
1346 if (row->used[TEXT_AREA])
1347 line_start_position = row->glyphs[TEXT_AREA]->charpos;
1348 else
1349 line_start_position = 0;
1350
1351 if (line_start_position > pos)
1352 break;
1353 /* If the position sought is the end of the buffer,
1354 don't include the blank lines at the bottom of the window. */
1355 else if (line_start_position == pos
1356 && pos == BUF_ZV (XBUFFER (w->buffer)))
1357 {
1358 maybe_next_line_p = 1;
1359 break;
1360 }
1361 else if (line_start_position > 0)
1362 best_row = row;
1363
1364 ++row;
1365 }
1366
1367 /* Find the right column within BEST_ROW. */
1368 lastcol = 0;
1369 row = best_row;
1370 for (i = 0; i < row->used[TEXT_AREA]; i++)
1371 {
1372 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
1373 int charpos;
1374
1375 charpos = glyph->charpos;
1376 if (charpos == pos)
1377 {
1378 *hpos = i;
1379 *vpos = row->y;
1380 return 1;
1381 }
1382 else if (charpos > pos)
1383 break;
1384 else if (charpos > 0)
1385 lastcol = i;
1386 }
1387
1388 /* If we're looking for the end of the buffer,
1389 and we didn't find it in the line we scanned,
1390 use the start of the following line. */
1391 if (maybe_next_line_p)
1392 {
1393 ++row;
1394 lastcol = 0;
1395 }
1396
1397 *vpos = row->y;
1398 *hpos = lastcol + 1;
1399 return 0;
1400}
1401
1402/* Take proper action when mouse has moved to the mode or top line of
1403 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
1404 mode line. X is relative to the start of the text display area of
1405 W, so the width of bitmap areas and scroll bars must be subtracted
1406 to get a position relative to the start of the mode line. */
1407static void
1408IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
1409{
1410 struct frame *f = XFRAME (w->frame);
1411 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1412 struct glyph_row *row;
1413
1414 if (mode_line_p)
1415 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1416 else
1417 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1418
1419 if (row->enabled_p)
1420 {
1421 extern Lisp_Object Qhelp_echo;
1422 struct glyph *glyph, *end;
1423 Lisp_Object help, map;
1424
1425 /* Find the glyph under X. */
1426 glyph = row->glyphs[TEXT_AREA]
1427 + x - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
1428 end = glyph + row->used[TEXT_AREA];
1429 if (glyph < end
1430 && STRINGP (glyph->object)
1431 && XSTRING (glyph->object)->intervals
1432 && glyph->charpos >= 0
1433 && glyph->charpos < XSTRING (glyph->object)->size)
1434 {
1435 /* If we're on a string with `help-echo' text property,
1436 arrange for the help to be displayed. This is done by
1437 setting the global variable help_echo to the help string. */
1438 help = Fget_text_property (make_number (glyph->charpos),
1439 Qhelp_echo, glyph->object);
b7e80413 1440 if (!NILP (help))
48c14970
EZ
1441 {
1442 help_echo = help;
1443 XSETWINDOW (help_echo_window, w);
1444 help_echo_object = glyph->object;
1445 help_echo_pos = glyph->charpos;
1446 }
41ad069b
EZ
1447 }
1448 }
1449}
1450
1451/* Take proper action when the mouse has moved to position X, Y on
1452 frame F as regards highlighting characters that have mouse-face
1453 properties. Also de-highlighting chars where the mouse was before.
1454 X and Y can be negative or out of range. */
1455static void
1456IT_note_mouse_highlight (struct frame *f, int x, int y)
1457{
1458 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1459 int portion;
1460 Lisp_Object window;
1461 struct window *w;
1462
1463 /* When a menu is active, don't highlight because this looks odd. */
1464 if (mouse_preempted)
1465 return;
1466
515d0d0e
EZ
1467 if (disable_mouse_highlight
1468 || !f->glyphs_initialized_p)
41ad069b
EZ
1469 return;
1470
1471 dpyinfo->mouse_face_mouse_x = x;
1472 dpyinfo->mouse_face_mouse_y = y;
1473 dpyinfo->mouse_face_mouse_frame = f;
1474
1475 if (dpyinfo->mouse_face_defer)
1476 return;
1477
1478 if (gc_in_progress)
1479 {
1480 dpyinfo->mouse_face_deferred_gc = 1;
1481 return;
1482 }
1483
1484 /* Which window is that in? */
1485 window = window_from_coordinates (f, x, y, &portion, 0);
1486
1487 /* If we were displaying active text in another window, clear that. */
1488 if (! EQ (window, dpyinfo->mouse_face_window))
1489 clear_mouse_face (dpyinfo);
1490
1491 /* Not on a window -> return. */
1492 if (!WINDOWP (window))
1493 return;
1494
1495 /* Convert to window-relative coordinates. */
1496 w = XWINDOW (window);
1497 x -= WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1498 y -= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1499
1500 if (portion == 1 || portion == 3)
1501 {
1502 /* Mouse is on the mode or top line. */
1503 IT_note_mode_line_highlight (w, x, portion == 1);
1504 return;
1505 }
1506 else
1507 IT_set_mouse_pointer (0);
1508
1509 /* Are we in a window whose display is up to date?
1510 And verify the buffer's text has not changed. */
1511 if (/* Within text portion of the window. */
1512 portion == 0
1513 && EQ (w->window_end_valid, w->buffer)
1514 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
1515 && (XFASTINT (w->last_overlay_modified)
1516 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
1517 {
1518 int pos, i, area;
1519 struct glyph_row *row;
1520 struct glyph *glyph;
1521
1522 /* Find the glyph under X/Y. */
1523 glyph = NULL;
1524 if (y < w->current_matrix->nrows)
1525 {
1526 row = MATRIX_ROW (w->current_matrix, y);
1527 if (row->enabled_p
1528 && row->displays_text_p
1529 && x < window_box_width (w, TEXT_AREA))
1530 {
1531 glyph = row->glyphs[TEXT_AREA];
1532 if (x >= row->used[TEXT_AREA])
1533 glyph = NULL;
1534 else
1535 {
1536 glyph += x;
1537 if (!BUFFERP (glyph->object))
1538 glyph = NULL;
1539 }
1540 }
1541 }
1542
1543 /* Clear mouse face if X/Y not over text. */
1544 if (glyph == NULL)
1545 {
1546 clear_mouse_face (dpyinfo);
1547 return;
1548 }
1549
1550 if (!BUFFERP (glyph->object))
1551 abort ();
1552 pos = glyph->charpos;
1553
1554 /* Check for mouse-face and help-echo. */
1555 {
1556 extern Lisp_Object Qmouse_face;
1557 Lisp_Object mouse_face, overlay, position;
1558 Lisp_Object *overlay_vec;
1559 int len, noverlays;
1560 struct buffer *obuf;
1561 int obegv, ozv;
1562
1563 /* If we get an out-of-range value, return now; avoid an error. */
1564 if (pos > BUF_Z (XBUFFER (w->buffer)))
1565 return;
1566
1567 /* Make the window's buffer temporarily current for
1568 overlays_at and compute_char_face. */
1569 obuf = current_buffer;
1570 current_buffer = XBUFFER (w->buffer);
1571 obegv = BEGV;
1572 ozv = ZV;
1573 BEGV = BEG;
1574 ZV = Z;
1575
1576 /* Is this char mouse-active or does it have help-echo? */
1577 XSETINT (position, pos);
1578
1579 /* Put all the overlays we want in a vector in overlay_vec.
1580 Store the length in len. If there are more than 10, make
1581 enough space for all, and try again. */
1582 len = 10;
1583 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
99cd7364 1584 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
41ad069b
EZ
1585 if (noverlays > len)
1586 {
1587 len = noverlays;
1588 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
99cd7364
EZ
1589 noverlays = overlays_at (pos,
1590 0, &overlay_vec, &len, NULL, NULL, 0);
41ad069b
EZ
1591 }
1592
f0a4139c 1593 /* Sort overlays into increasing priority order. */
41ad069b
EZ
1594 noverlays = sort_overlays (overlay_vec, noverlays, w);
1595
1596 /* Check mouse-face highlighting. */
1597 if (! (EQ (window, dpyinfo->mouse_face_window)
1598 && y >= dpyinfo->mouse_face_beg_row
1599 && y <= dpyinfo->mouse_face_end_row
1600 && (y > dpyinfo->mouse_face_beg_row
1601 || x >= dpyinfo->mouse_face_beg_col)
1602 && (y < dpyinfo->mouse_face_end_row
1603 || x < dpyinfo->mouse_face_end_col
1604 || dpyinfo->mouse_face_past_end)))
1605 {
1606 /* Clear the display of the old active region, if any. */
1607 clear_mouse_face (dpyinfo);
1608
1609 /* Find highest priority overlay that has a mouse-face prop. */
1610 overlay = Qnil;
f0a4139c 1611 for (i = noverlays - 1; i >= 0; --i)
41ad069b
EZ
1612 {
1613 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1614 if (!NILP (mouse_face))
1615 {
1616 overlay = overlay_vec[i];
1617 break;
1618 }
1619 }
1620
1621 /* If no overlay applies, get a text property. */
1622 if (NILP (overlay))
1623 mouse_face = Fget_text_property (position, Qmouse_face,
1624 w->buffer);
1625
1626 /* Handle the overlay case. */
1627 if (! NILP (overlay))
1628 {
1629 /* Find the range of text around this char that
1630 should be active. */
1631 Lisp_Object before, after;
1632 int ignore;
1633
1634 before = Foverlay_start (overlay);
1635 after = Foverlay_end (overlay);
1636 /* Record this as the current active region. */
1637 fast_find_position (w, XFASTINT (before),
1638 &dpyinfo->mouse_face_beg_col,
1639 &dpyinfo->mouse_face_beg_row);
1640 dpyinfo->mouse_face_past_end
1641 = !fast_find_position (w, XFASTINT (after),
1642 &dpyinfo->mouse_face_end_col,
1643 &dpyinfo->mouse_face_end_row);
1644 dpyinfo->mouse_face_window = window;
1645 dpyinfo->mouse_face_face_id
1646 = face_at_buffer_position (w, pos, 0, 0,
1647 &ignore, pos + 1, 1);
1648
1649 /* Display it as active. */
1650 show_mouse_face (dpyinfo, 1);
1651 }
1652 /* Handle the text property case. */
1653 else if (! NILP (mouse_face))
1654 {
1655 /* Find the range of text around this char that
1656 should be active. */
1657 Lisp_Object before, after, beginning, end;
1658 int ignore;
1659
1660 beginning = Fmarker_position (w->start);
1661 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1662 - XFASTINT (w->window_end_pos)));
1663 before
1664 = Fprevious_single_property_change (make_number (pos + 1),
1665 Qmouse_face,
1666 w->buffer, beginning);
1667 after
1668 = Fnext_single_property_change (position, Qmouse_face,
1669 w->buffer, end);
1670 /* Record this as the current active region. */
1671 fast_find_position (w, XFASTINT (before),
1672 &dpyinfo->mouse_face_beg_col,
1673 &dpyinfo->mouse_face_beg_row);
1674 dpyinfo->mouse_face_past_end
1675 = !fast_find_position (w, XFASTINT (after),
1676 &dpyinfo->mouse_face_end_col,
1677 &dpyinfo->mouse_face_end_row);
1678 dpyinfo->mouse_face_window = window;
1679 dpyinfo->mouse_face_face_id
1680 = face_at_buffer_position (w, pos, 0, 0,
1681 &ignore, pos + 1, 1);
1682
1683 /* Display it as active. */
1684 show_mouse_face (dpyinfo, 1);
1685 }
1686 }
1687
1688 /* Look for a `help-echo' property. */
1689 {
1690 Lisp_Object help;
1691 extern Lisp_Object Qhelp_echo;
1692
1693 /* Check overlays first. */
1694 help = Qnil;
f0a4139c
EZ
1695 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
1696 {
1697 overlay = overlay_vec[i];
1698 help = Foverlay_get (overlay, Qhelp_echo);
1699 }
41ad069b 1700
b7e80413 1701 if (!NILP (help))
48c14970
EZ
1702 {
1703 help_echo = help;
1704 help_echo_window = window;
f0a4139c 1705 help_echo_object = overlay;
48c14970
EZ
1706 help_echo_pos = pos;
1707 }
1708 /* Try text properties. */
1709 else if (NILP (help)
1710 && ((STRINGP (glyph->object)
1711 && glyph->charpos >= 0
1712 && glyph->charpos < XSTRING (glyph->object)->size)
1713 || (BUFFERP (glyph->object)
1714 && glyph->charpos >= BEGV
1715 && glyph->charpos < ZV)))
1716 {
1717 help = Fget_text_property (make_number (glyph->charpos),
1718 Qhelp_echo, glyph->object);
1719 if (!NILP (help))
1720 {
1721 help_echo = help;
1722 help_echo_window = window;
1723 help_echo_object = glyph->object;
1724 help_echo_pos = glyph->charpos;
1725 }
1726 }
41ad069b
EZ
1727 }
1728
1729 BEGV = obegv;
1730 ZV = ozv;
1731 current_buffer = obuf;
1732 }
1733 }
1734}
1735
71f65669
EZ
1736static void
1737IT_clear_end_of_line (int first_unused)
f32d4091
KS
1738{
1739 char *spaces, *sp;
1740 int i, j;
039274cf 1741 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936
EZ
1742 extern int fatal_error_in_progress;
1743
2d764c78 1744 if (new_pos_X >= first_unused || fatal_error_in_progress)
aa9ce936 1745 return;
f32d4091
KS
1746
1747 IT_set_face (0);
2d764c78 1748 i = (j = first_unused - new_pos_X) * 2;
e25d9653
EZ
1749 if (termscript)
1750 fprintf (termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
f32d4091 1751 spaces = sp = alloca (i);
aee81730 1752
f32d4091 1753 while (--j >= 0)
aee81730 1754 {
f32d4091
KS
1755 *sp++ = ' ';
1756 *sp++ = ScreenAttrib;
aee81730
RS
1757 }
1758
f32d4091 1759 mouse_off_maybe ();
039274cf
EZ
1760 dosmemput (spaces, i, (int)ScreenPrimary + offset);
1761 if (screen_virtual_segment)
1762 dosv_refresh_virtual_screen (offset, i / 2);
2d764c78
EZ
1763
1764 /* clear_end_of_line_raw on term.c leaves the cursor at first_unused.
1765 Let's follow their lead, in case someone relies on this. */
1766 new_pos_X = first_unused;
aee81730
RS
1767}
1768
71f65669 1769static void
f32d4091
KS
1770IT_clear_screen (void)
1771{
1772 if (termscript)
1773 fprintf (termscript, "<CLR:SCR>");
1774 IT_set_face (0);
1775 mouse_off ();
1776 ScreenClear ();
039274cf
EZ
1777 if (screen_virtual_segment)
1778 dosv_refresh_virtual_screen (0, screen_size);
f32d4091
KS
1779 new_pos_X = new_pos_Y = 0;
1780}
1781
71f65669 1782static void
f32d4091
KS
1783IT_clear_to_end (void)
1784{
1785 if (termscript)
1786 fprintf (termscript, "<CLR:EOS>");
1787
1788 while (new_pos_Y < screen_size_Y) {
1789 new_pos_X = 0;
e25d9653 1790 IT_clear_end_of_line (screen_size_X);
f32d4091
KS
1791 new_pos_Y++;
1792 }
1793}
1794
71f65669 1795static void
f32d4091
KS
1796IT_cursor_to (int y, int x)
1797{
1798 if (termscript)
1799 fprintf (termscript, "\n<XY=%dx%d>", x, y);
1800 new_pos_X = x;
1801 new_pos_Y = y;
1802}
1803
fc171623
KH
1804static int cursor_cleared;
1805
d1d5dc19 1806static void
fc171623
KH
1807IT_display_cursor (int on)
1808{
1809 if (on && cursor_cleared)
1810 {
1811 ScreenSetCursor (current_pos_Y, current_pos_X);
1812 cursor_cleared = 0;
1813 }
1814 else if (!on && !cursor_cleared)
1815 {
1816 ScreenSetCursor (-1, -1);
1817 cursor_cleared = 1;
1818 }
1819}
1820
1821/* Emacs calls cursor-movement functions a lot when it updates the
1822 display (probably a legacy of old terminals where you cannot
1823 update a screen line without first moving the cursor there).
1824 However, cursor movement is expensive on MSDOS (it calls a slow
1825 BIOS function and requires 2 mode switches), while actual screen
1826 updates access the video memory directly and don't depend on
1827 cursor position. To avoid slowing down the redisplay, we cheat:
1828 all functions that move the cursor only set internal variables
1829 which record the cursor position, whereas the cursor is only
1830 moved to its final position whenever screen update is complete.
1831
1832 `IT_cmgoto' is called from the keyboard reading loop and when the
1833 frame update is complete. This means that we are ready for user
1834 input, so we update the cursor position to show where the point is,
1835 and also make the mouse pointer visible.
1836
1837 Special treatment is required when the cursor is in the echo area,
1838 to put the cursor at the end of the text displayed there. */
1839
71f65669
EZ
1840static void
1841IT_cmgoto (FRAME_PTR f)
fc171623
KH
1842{
1843 /* Only set the cursor to where it should be if the display is
1844 already in sync with the window contents. */
2d764c78
EZ
1845 int update_cursor_pos = 1; /* MODIFF == unchanged_modified; */
1846
1847 /* FIXME: This needs to be rewritten for the new redisplay, or
1848 removed. */
1849#if 0
06da1de1
EZ
1850 static int previous_pos_X = -1;
1851
2d764c78
EZ
1852 update_cursor_pos = 1; /* temporary!!! */
1853
06da1de1
EZ
1854 /* If the display is in sync, forget any previous knowledge about
1855 cursor position. This is primarily for unexpected events like
1856 C-g in the minibuffer. */
1857 if (update_cursor_pos && previous_pos_X >= 0)
1858 previous_pos_X = -1;
1859 /* If we are in the echo area, put the cursor at the
1860 end of the echo area message. */
fc171623
KH
1861 if (!update_cursor_pos
1862 && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
1863 {
06da1de1
EZ
1864 int tem_X = current_pos_X, dummy;
1865
1866 if (echo_area_glyphs)
1867 {
1868 tem_X = echo_area_glyphs_length;
1869 /* Save current cursor position, to be restored after the
1870 echo area message is erased. Only remember one level
1871 of previous cursor position. */
1872 if (previous_pos_X == -1)
1873 ScreenGetCursor (&dummy, &previous_pos_X);
1874 }
1875 else if (previous_pos_X >= 0)
1876 {
1877 /* We wind up here after the echo area message is erased.
1878 Restore the cursor position we remembered above. */
1879 tem_X = previous_pos_X;
1880 previous_pos_X = -1;
1881 }
9a599a60 1882
06da1de1 1883 if (current_pos_X != tem_X)
9a599a60
EZ
1884 {
1885 new_pos_X = tem_X;
1886 update_cursor_pos = 1;
1887 }
fc171623 1888 }
2d764c78 1889#endif
fc171623
KH
1890
1891 if (update_cursor_pos
1892 && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
1893 {
1894 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
1895 if (termscript)
1896 fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
1897 }
1898
1899 /* Maybe cursor is invisible, so make it visible. */
1900 IT_display_cursor (1);
1901
1902 /* Mouse pointer should be always visible if we are waiting for
1903 keyboard input. */
1904 if (!mouse_visible)
1905 mouse_on ();
1906}
1907
71f65669
EZ
1908static void
1909IT_reassert_line_highlight (int new, int vpos)
f32d4091
KS
1910{
1911 highlight = new;
f32d4091
KS
1912}
1913
71f65669 1914static void
c77f6f1b 1915IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos)
1b94449f 1916{
f32d4091 1917 highlight = new_highlight;
f32d4091
KS
1918 IT_cursor_to (vpos, 0);
1919 IT_clear_end_of_line (first_unused_hpos);
1920}
1921
71f65669 1922static void
41ad069b 1923IT_update_begin (struct frame *f)
f32d4091 1924{
41ad069b 1925 struct display_info *display_info = FRAME_X_DISPLAY_INFO (f);
b9f80d41 1926 struct frame *mouse_face_frame = display_info->mouse_face_mouse_frame;
41ad069b 1927
f32d4091 1928 highlight = 0;
41ad069b
EZ
1929
1930 BLOCK_INPUT;
1931
b9f80d41 1932 if (f && f == mouse_face_frame)
41ad069b
EZ
1933 {
1934 /* Don't do highlighting for mouse motion during the update. */
1935 display_info->mouse_face_defer = 1;
1936
1937 /* If F needs to be redrawn, simply forget about any prior mouse
1938 highlighting. */
1939 if (FRAME_GARBAGED_P (f))
1940 display_info->mouse_face_window = Qnil;
1941
1942 /* Can we tell that this update does not affect the window
1943 where the mouse highlight is? If so, no need to turn off.
48c14970
EZ
1944 Likewise, don't do anything if none of the enabled rows
1945 contains glyphs highlighted in mouse face. */
8ccb9a54
EZ
1946 if (!NILP (display_info->mouse_face_window)
1947 && WINDOWP (display_info->mouse_face_window))
41ad069b
EZ
1948 {
1949 struct window *w = XWINDOW (display_info->mouse_face_window);
1950 int i;
1951
8ccb9a54
EZ
1952 /* If the mouse highlight is in the window that was deleted
1953 (e.g., if it was popped by completion), clear highlight
1954 unconditionally. */
1955 if (NILP (w->buffer))
1956 display_info->mouse_face_window = Qnil;
1957 else
1958 {
1959 for (i = 0; i < w->desired_matrix->nrows; ++i)
48c14970
EZ
1960 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
1961 && MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
8ccb9a54
EZ
1962 break;
1963 }
41ad069b 1964
8ccb9a54 1965 if (NILP (w->buffer) || i < w->desired_matrix->nrows)
41ad069b
EZ
1966 clear_mouse_face (display_info);
1967 }
1968 }
b9f80d41 1969 else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
41ad069b
EZ
1970 {
1971 /* If the frame with mouse highlight was deleted, invalidate the
1972 highlight info. */
1973 display_info->mouse_face_beg_row = display_info->mouse_face_beg_col = -1;
1974 display_info->mouse_face_end_row = display_info->mouse_face_end_col = -1;
1975 display_info->mouse_face_window = Qnil;
1976 display_info->mouse_face_deferred_gc = 0;
1977 display_info->mouse_face_mouse_frame = NULL;
1978 }
1979
1980 UNBLOCK_INPUT;
f32d4091
KS
1981}
1982
71f65669 1983static void
41ad069b 1984IT_update_end (struct frame *f)
f32d4091 1985{
41ad069b
EZ
1986 highlight = 0;
1987 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
1988}
1989
8ba01a32
EZ
1990Lisp_Object Qcursor_type;
1991
41ad069b
EZ
1992static void
1993IT_frame_up_to_date (struct frame *f)
1994{
1995 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0c3cfc51
EZ
1996 Lisp_Object new_cursor, frame_desired_cursor;
1997 struct window *sw;
41ad069b
EZ
1998
1999 if (dpyinfo->mouse_face_deferred_gc
b9f80d41 2000 || (f && f == dpyinfo->mouse_face_mouse_frame))
41ad069b
EZ
2001 {
2002 BLOCK_INPUT;
2003 if (dpyinfo->mouse_face_mouse_frame)
2004 IT_note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2005 dpyinfo->mouse_face_mouse_x,
2006 dpyinfo->mouse_face_mouse_y);
2007 dpyinfo->mouse_face_deferred_gc = 0;
2008 UNBLOCK_INPUT;
2009 }
2010
0c3cfc51
EZ
2011 /* Set the cursor type to whatever they wanted. In a minibuffer
2012 window, we want the cursor to appear only if we are reading input
2013 from this window, and we want the cursor to be taken from the
2014 frame parameters. For the selected window, we use either its
2015 buffer-local value or the value from the frame parameters if the
2016 buffer doesn't define its local value for the cursor type. */
2017 sw = XWINDOW (f->selected_window);
2018 frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
2019 if (cursor_in_echo_area
2020 && FRAME_HAS_MINIBUF_P (f)
2021 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
2022 && sw == XWINDOW (echo_area_window))
2023 new_cursor = frame_desired_cursor;
2024 else
2025 {
2026 struct buffer *b = XBUFFER (sw->buffer);
2027
2028 if (EQ (b->cursor_type, Qt))
2029 new_cursor = frame_desired_cursor;
2030 else if (NILP (b->cursor_type)) /* nil means no cursor */
2031 new_cursor = Fcons (Qbar, make_number (0));
2032 else
2033 new_cursor = b->cursor_type;
2034 }
2035
2036 IT_set_cursor_type (f, new_cursor);
8ba01a32 2037
41ad069b 2038 IT_cmgoto (f); /* position cursor when update is done */
f32d4091 2039}
1b94449f 2040
c77f6f1b
EZ
2041/* Copy LEN glyphs displayed on a single line whose vertical position
2042 is YPOS, beginning at horizontal position XFROM to horizontal
2043 position XTO, by moving blocks in the video memory. Used by
2044 functions that insert and delete glyphs. */
2045static void
2046IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
2047{
2048 /* The offsets of source and destination relative to the
2049 conventional memorty selector. */
2050 int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary;
2051 int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary;
2052
2053 if (from == to || len <= 0)
2054 return;
2055
2056 _farsetsel (_dos_ds);
2057
2058 /* The source and destination might overlap, so we need to move
2059 glyphs non-destructively. */
2060 if (from > to)
2061 {
2062 for ( ; len; from += 2, to += 2, len--)
2063 _farnspokew (to, _farnspeekw (from));
2064 }
2065 else
2066 {
2067 from += (len - 1) * 2;
2068 to += (len - 1) * 2;
2069 for ( ; len; from -= 2, to -= 2, len--)
2070 _farnspokew (to, _farnspeekw (from));
2071 }
2072 if (screen_virtual_segment)
2073 dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X);
2074}
2075
2076/* Insert and delete glyphs. */
aa9ce936
EZ
2077static void
2078IT_insert_glyphs (start, len)
c77f6f1b 2079 register struct glyph *start;
aa9ce936
EZ
2080 register int len;
2081{
c77f6f1b
EZ
2082 int shift_by_width = screen_size_X - (new_pos_X + len);
2083
2084 /* Shift right the glyphs from the nominal cursor position to the
2085 end of this line. */
2086 IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
2087
2088 /* Now write the glyphs to be inserted. */
2089 IT_write_glyphs (start, len);
aa9ce936
EZ
2090}
2091
2092static void
2093IT_delete_glyphs (n)
2094 register int n;
2095{
2096 abort ();
2097}
2098
211c7152 2099/* set-window-configuration on window.c needs this. */
3bb1f22f
RS
2100void
2101x_set_menu_bar_lines (f, value, oldval)
2102 struct frame *f;
2103 Lisp_Object value, oldval;
2104{
211c7152
EZ
2105 set_menu_bar_lines (f, value, oldval);
2106}
3bb1f22f 2107
984f5aaa 2108/* This was copied from xfaces.c */
3bb1f22f 2109
984f5aaa
EZ
2110extern Lisp_Object Qbackground_color;
2111extern Lisp_Object Qforeground_color;
8ba01a32 2112Lisp_Object Qreverse;
211c7152 2113extern Lisp_Object Qtitle;
3bb1f22f 2114
48ffe371
RS
2115/* IT_set_terminal_modes is called when emacs is started,
2116 resumed, and whenever the screen is redrawn! */
f32d4091 2117
71f65669 2118static void
f32d4091
KS
2119IT_set_terminal_modes (void)
2120{
aee81730 2121 if (termscript)
f32d4091
KS
2122 fprintf (termscript, "\n<SET_TERM>");
2123 highlight = 0;
2124
2125 screen_size_X = ScreenCols ();
2126 screen_size_Y = ScreenRows ();
2127 screen_size = screen_size_X * screen_size_Y;
aee81730 2128
f32d4091
KS
2129 new_pos_X = new_pos_Y = 0;
2130 current_pos_X = current_pos_Y = -1;
2131
2132 if (term_setup_done)
2133 return;
2134 term_setup_done = 1;
aee81730 2135
f32d4091
KS
2136 startup_screen_size_X = screen_size_X;
2137 startup_screen_size_Y = screen_size_Y;
c9adab25 2138 startup_screen_attrib = ScreenAttrib;
f32d4091 2139
039274cf
EZ
2140#if __DJGPP__ > 1
2141 /* Is DOS/V (or any other RSIS software which relocates
2142 the screen) installed? */
2143 {
2144 unsigned short es_value;
2145 __dpmi_regs regs;
2146
2147 regs.h.ah = 0xfe; /* get relocated screen address */
2148 if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
2149 regs.x.es = (ScreenPrimary >> 4) & 0xffff;
2150 else if (screen_old_address) /* already switched to Japanese mode once */
2151 regs.x.es = (screen_old_address >> 4) & 0xffff;
2152 else
2153 regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
2154 regs.x.di = 0;
2155 es_value = regs.x.es;
2156 __dpmi_int (0x10, &regs);
2157
d1d5dc19 2158 if (regs.x.es != es_value)
039274cf 2159 {
d1d5dc19
EZ
2160 /* screen_old_address is only set if ScreenPrimary does NOT
2161 already point to the relocated buffer address returned by
2162 the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
2163 ScreenPrimary to that address at startup under DOS/V. */
2164 if (regs.x.es != (ScreenPrimary >> 4) & 0xffff)
2165 screen_old_address = ScreenPrimary;
039274cf
EZ
2166 screen_virtual_segment = regs.x.es;
2167 screen_virtual_offset = regs.x.di;
2168 ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
2169 }
2170 }
2171#endif /* __DJGPP__ > 1 */
2172
f32d4091
KS
2173 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
2174 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
2175
2176 if (termscript)
c9adab25 2177 fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
039274cf 2178 screen_size_X, screen_size_Y);
76ac1508
RS
2179
2180 bright_bg ();
f32d4091
KS
2181}
2182
48ffe371
RS
2183/* IT_reset_terminal_modes is called when emacs is
2184 suspended or killed. */
f32d4091 2185
71f65669 2186static void
f32d4091
KS
2187IT_reset_terminal_modes (void)
2188{
c9adab25
KH
2189 int display_row_start = (int) ScreenPrimary;
2190 int saved_row_len = startup_screen_size_X * 2;
2191 int update_row_len = ScreenCols () * 2;
2192 int current_rows = ScreenRows ();
2193 int to_next_row = update_row_len;
2194 unsigned char *saved_row = startup_screen_buffer;
2195 int cursor_pos_X = ScreenCols () - 1;
2196 int cursor_pos_Y = ScreenRows () - 1;
2197
f32d4091 2198 if (termscript)
5063b150 2199 fprintf (termscript, "\n<RESET_TERM>");
f32d4091
KS
2200
2201 highlight = 0;
2202
2203 if (!term_setup_done)
2204 return;
2205
c9adab25 2206 mouse_off ();
b36701cc
RS
2207
2208 /* Leave the video system in the same state as we found it,
2209 as far as the blink/bright-background bit is concerned. */
2210 maybe_enable_blinking ();
06b1ea13 2211
c9adab25
KH
2212 /* We have a situation here.
2213 We cannot just do ScreenUpdate(startup_screen_buffer) because
2214 the luser could have changed screen dimensions inside Emacs
2215 and failed (or didn't want) to restore them before killing
2216 Emacs. ScreenUpdate() uses the *current* screen dimensions and
2217 thus will happily use memory outside what was allocated for
2218 `startup_screen_buffer'.
2219 Thus we only restore as much as the current screen dimensions
2220 can hold, and clear the rest (if the saved screen is smaller than
2221 the current) with the color attribute saved at startup. The cursor
2222 is also restored within the visible dimensions. */
2223
2224 ScreenAttrib = startup_screen_attrib;
c9adab25 2225
06b1ea13
EZ
2226 /* Don't restore the screen if we are exiting less than 2 seconds
2227 after startup: we might be crashing, and the screen might show
2228 some vital clues to what's wrong. */
2229 if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
c9adab25 2230 {
06b1ea13 2231 ScreenClear ();
039274cf 2232 if (screen_virtual_segment)
06b1ea13
EZ
2233 dosv_refresh_virtual_screen (0, screen_size);
2234
2235 if (update_row_len > saved_row_len)
2236 update_row_len = saved_row_len;
2237 if (current_rows > startup_screen_size_Y)
2238 current_rows = startup_screen_size_Y;
2239
2240 if (termscript)
2241 fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
2242 update_row_len / 2, current_rows);
2243
2244 while (current_rows--)
2245 {
2246 dosmemput (saved_row, update_row_len, display_row_start);
2247 if (screen_virtual_segment)
2248 dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
2249 update_row_len / 2);
2250 saved_row += saved_row_len;
2251 display_row_start += to_next_row;
2252 }
c9adab25
KH
2253 }
2254 if (startup_pos_X < cursor_pos_X)
2255 cursor_pos_X = startup_pos_X;
2256 if (startup_pos_Y < cursor_pos_Y)
2257 cursor_pos_Y = startup_pos_Y;
2258
2259 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
2260 xfree (startup_screen_buffer);
f32d4091
KS
2261
2262 term_setup_done = 0;
2263}
2264
71f65669
EZ
2265static void
2266IT_set_terminal_window (int foo)
f32d4091
KS
2267{
2268}
2269
2d764c78
EZ
2270/* Remember the screen colors of the curent frame, to serve as the
2271 default colors for newly-created frames. */
2272
2273static int initial_screen_colors[2];
2274
2275DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
2276 Smsdos_remember_default_colors, 1, 1, 0,
2277 "Remember the screen colors of the current frame.")
2278 (frame)
2279 Lisp_Object frame;
2280{
2d764c78
EZ
2281 struct frame *f;
2282
2283 CHECK_FRAME (frame, 0);
2284 f= XFRAME (frame);
2d764c78 2285
546701f5
EZ
2286 initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f);
2287 initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f);
2d764c78
EZ
2288}
2289
f32d4091 2290void
3bb1f22f 2291IT_set_frame_parameters (f, alist)
c77f6f1b 2292 struct frame *f;
f32d4091
KS
2293 Lisp_Object alist;
2294{
2295 Lisp_Object tail;
db722735 2296 int length = XINT (Flength (alist));
2d764c78 2297 int i, j;
db722735
RS
2298 Lisp_Object *parms
2299 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2300 Lisp_Object *values
2301 = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
2d764c78 2302 /* Do we have to reverse the foreground and background colors? */
8ba01a32 2303 int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
2d764c78
EZ
2304 int was_reverse = reverse;
2305 int redraw = 0, fg_set = 0, bg_set = 0;
546701f5 2306 int need_to_reverse;
2d764c78
EZ
2307 unsigned long orig_fg;
2308 unsigned long orig_bg;
546701f5 2309 Lisp_Object frame_bg, frame_fg;
53704a07 2310 extern Lisp_Object Qdefault, QCforeground, QCbackground;
2d764c78
EZ
2311
2312 /* If we are creating a new frame, begin with the original screen colors
2313 used for the initial frame. */
2314 if (alist == Vdefault_frame_alist
2315 && initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
2316 {
2317 FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
2318 FRAME_BACKGROUND_PIXEL (f) = initial_screen_colors[1];
2319 }
2320 orig_fg = FRAME_FOREGROUND_PIXEL (f);
2321 orig_bg = FRAME_BACKGROUND_PIXEL (f);
546701f5
EZ
2322 frame_fg = Fcdr (Fassq (Qforeground_color, f->param_alist));
2323 frame_bg = Fcdr (Fassq (Qbackground_color, f->param_alist));
2324 /* frame_fg and frame_bg could be nil if, for example,
2325 f->param_alist is nil, e.g. if we are called from
2326 Fmake_terminal_frame. */
2327 if (NILP (frame_fg))
2328 frame_fg = build_string (unspecified_fg);
2329 if (NILP (frame_bg))
2330 frame_bg = build_string (unspecified_bg);
db722735
RS
2331
2332 /* Extract parm names and values into those vectors. */
2333 i = 0;
f32d4091
KS
2334 for (tail = alist; CONSP (tail); tail = Fcdr (tail))
2335 {
db722735 2336 Lisp_Object elt;
f32d4091
KS
2337
2338 elt = Fcar (tail);
db722735
RS
2339 parms[i] = Fcar (elt);
2340 CHECK_SYMBOL (parms[i], 1);
2341 values[i] = Fcdr (elt);
2342 i++;
2343 }
2344
2d764c78 2345 j = i;
db722735 2346
2d764c78
EZ
2347 for (i = 0; i < j; i++)
2348 {
1e21fe48
EZ
2349 Lisp_Object prop, val;
2350
2351 prop = parms[i];
2352 val = values[i];
2d764c78 2353
8ba01a32 2354 if (EQ (prop, Qreverse))
2d764c78
EZ
2355 reverse = EQ (val, Qt);
2356 }
546701f5
EZ
2357
2358 need_to_reverse = reverse && !was_reverse;
2359 if (termscript && need_to_reverse)
2d764c78
EZ
2360 fprintf (termscript, "<INVERSE-VIDEO>\n");
2361
2362 /* Now process the alist elements in reverse of specified order. */
db722735
RS
2363 for (i--; i >= 0; i--)
2364 {
1e21fe48
EZ
2365 Lisp_Object prop, val;
2366 Lisp_Object frame;
2367
2368 prop = parms[i];
2369 val = values[i];
f32d4091 2370
4e825084 2371 if (EQ (prop, Qforeground_color))
f32d4091 2372 {
546701f5 2373 unsigned long new_color = load_color (f, NULL, val, need_to_reverse
2d764c78
EZ
2374 ? LFACE_BACKGROUND_INDEX
2375 : LFACE_FOREGROUND_INDEX);
3b620731
EZ
2376 if (new_color != FACE_TTY_DEFAULT_COLOR
2377 && new_color != FACE_TTY_DEFAULT_FG_COLOR
2378 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 2379 {
546701f5 2380 FRAME_FOREGROUND_PIXEL (f) = new_color;
1e21fe48
EZ
2381 /* Make sure the foreground of the default face for this
2382 frame is changed as well. */
2383 XSETFRAME (frame, f);
546701f5 2384 if (need_to_reverse)
1e21fe48 2385 {
1e21fe48
EZ
2386 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2387 val, frame);
546701f5 2388 prop = Qbackground_color;
1e21fe48 2389 }
2d764c78 2390 else
1e21fe48 2391 {
1e21fe48
EZ
2392 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2393 val, frame);
2394 }
f32d4091 2395 redraw = 1;
2d764c78 2396 fg_set = 1;
76ac1508 2397 if (termscript)
a7cf9151 2398 fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
f32d4091
KS
2399 }
2400 }
4e825084 2401 else if (EQ (prop, Qbackground_color))
f32d4091 2402 {
546701f5 2403 unsigned long new_color = load_color (f, NULL, val, need_to_reverse
2d764c78
EZ
2404 ? LFACE_FOREGROUND_INDEX
2405 : LFACE_BACKGROUND_INDEX);
3b620731
EZ
2406 if (new_color != FACE_TTY_DEFAULT_COLOR
2407 && new_color != FACE_TTY_DEFAULT_FG_COLOR
2408 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 2409 {
546701f5 2410 FRAME_BACKGROUND_PIXEL (f) = new_color;
1e21fe48
EZ
2411 /* Make sure the background of the default face for this
2412 frame is changed as well. */
2413 XSETFRAME (frame, f);
546701f5 2414 if (need_to_reverse)
1e21fe48 2415 {
1e21fe48
EZ
2416 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
2417 val, frame);
546701f5 2418 prop = Qforeground_color;
1e21fe48 2419 }
2d764c78 2420 else
1e21fe48 2421 {
1e21fe48
EZ
2422 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
2423 val, frame);
2424 }
f32d4091 2425 redraw = 1;
2d764c78 2426 bg_set = 1;
76ac1508 2427 if (termscript)
a7cf9151 2428 fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
f32d4091
KS
2429 }
2430 }
211c7152
EZ
2431 else if (EQ (prop, Qtitle))
2432 {
2433 x_set_title (f, val);
2434 if (termscript)
2435 fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
2436 }
8ba01a32
EZ
2437 else if (EQ (prop, Qcursor_type))
2438 {
2439 IT_set_cursor_type (f, val);
2440 if (termscript)
2441 fprintf (termscript, "<CTYPE: %s>\n",
2442 EQ (val, Qbar) || CONSP (val) && EQ (XCAR (val), Qbar)
2443 ? "bar" : "box");
2444 }
db722735 2445 store_frame_param (f, prop, val);
2d764c78 2446 }
db722735 2447
2d764c78
EZ
2448 /* If they specified "reverse", but not the colors, we need to swap
2449 the current frame colors. */
546701f5 2450 if (need_to_reverse)
2d764c78 2451 {
1e21fe48
EZ
2452 Lisp_Object frame;
2453
2d764c78
EZ
2454 if (!fg_set)
2455 {
1e21fe48
EZ
2456 XSETFRAME (frame, f);
2457 Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
53704a07
EZ
2458 tty_color_name (f, orig_fg),
2459 frame);
546701f5 2460 store_frame_param (f, Qbackground_color, frame_fg);
2d764c78
EZ
2461 redraw = 1;
2462 }
2463 if (!bg_set)
2464 {
1e21fe48
EZ
2465 XSETFRAME (frame, f);
2466 Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
53704a07
EZ
2467 tty_color_name (f, orig_bg),
2468 frame);
546701f5 2469 store_frame_param (f, Qforeground_color, frame_bg);
2d764c78
EZ
2470 redraw = 1;
2471 }
f32d4091
KS
2472 }
2473
2474 if (redraw)
2475 {
2d764c78
EZ
2476 face_change_count++; /* forces xdisp.c to recompute basic faces */
2477 if (f == SELECTED_FRAME())
3bb1f22f 2478 redraw_frame (f);
f32d4091
KS
2479 }
2480}
2481
a7cf9151
EZ
2482extern void init_frame_faces (FRAME_PTR);
2483
f32d4091
KS
2484#endif /* !HAVE_X_WINDOWS */
2485
2486
48ffe371
RS
2487/* Do we need the internal terminal? */
2488
f32d4091
KS
2489void
2490internal_terminal_init ()
2491{
2492 char *term = getenv ("TERM");
2493 char *colors;
2d764c78 2494 struct frame *sf = SELECTED_FRAME();
f32d4091
KS
2495
2496#ifdef HAVE_X_WINDOWS
2497 if (!inhibit_window_system)
2498 return;
2499#endif
2500
2501 internal_terminal
2502 = (!noninteractive) && term && !strcmp (term, "internal");
2503
2504 if (getenv ("EMACSTEST"))
5063b150 2505 termscript = fopen (getenv ("EMACSTEST"), "wt");
f32d4091
KS
2506
2507#ifndef HAVE_X_WINDOWS
2508 if (!internal_terminal || inhibit_window_system)
2509 {
2d764c78 2510 sf->output_method = output_termcap;
f32d4091
KS
2511 return;
2512 }
2513
2514 Vwindow_system = intern ("pc");
2515 Vwindow_system_version = make_number (1);
2d764c78 2516 sf->output_method = output_msdos_raw;
039274cf
EZ
2517
2518 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */
2519 screen_old_address = 0;
2520
2d764c78
EZ
2521 /* Forget the stale screen colors as well. */
2522 initial_screen_colors[0] = initial_screen_colors[1] = -1;
2523
f32d4091
KS
2524 bzero (&the_only_x_display, sizeof the_only_x_display);
2525 the_only_x_display.background_pixel = 7; /* White */
2526 the_only_x_display.foreground_pixel = 0; /* Black */
76ac1508 2527 bright_bg ();
5063b150 2528 colors = getenv ("EMACSCOLORS");
f32d4091
KS
2529 if (colors && strlen (colors) >= 2)
2530 {
76ac1508
RS
2531 /* The colors use 4 bits each (we enable bright background). */
2532 if (isdigit (colors[0]))
2533 colors[0] -= '0';
2534 else if (isxdigit (colors[0]))
2535 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1bd7b2c7
RS
2536 if (colors[0] >= 0 && colors[0] < 16)
2537 the_only_x_display.foreground_pixel = colors[0];
76ac1508
RS
2538 if (isdigit (colors[1]))
2539 colors[1] -= '0';
2540 else if (isxdigit (colors[1]))
2541 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
2542 if (colors[1] >= 0 && colors[1] < 16)
1bd7b2c7 2543 the_only_x_display.background_pixel = colors[1];
f32d4091
KS
2544 }
2545 the_only_x_display.line_height = 1;
64ec6a02 2546 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
41ad069b
EZ
2547 the_only_x_display.display_info.mouse_face_mouse_frame = NULL;
2548 the_only_x_display.display_info.mouse_face_deferred_gc = 0;
2549 the_only_x_display.display_info.mouse_face_beg_row =
2550 the_only_x_display.display_info.mouse_face_beg_col = -1;
2551 the_only_x_display.display_info.mouse_face_end_row =
2552 the_only_x_display.display_info.mouse_face_end_col = -1;
2553 the_only_x_display.display_info.mouse_face_face_id = DEFAULT_FACE_ID;
2554 the_only_x_display.display_info.mouse_face_window = Qnil;
2555 the_only_x_display.display_info.mouse_face_mouse_x =
2556 the_only_x_display.display_info.mouse_face_mouse_y = 0;
2557 the_only_x_display.display_info.mouse_face_defer = 0;
f32d4091 2558
2d764c78 2559 init_frame_faces (sf);
f32d4091
KS
2560
2561 ring_bell_hook = IT_ring_bell;
aa9ce936
EZ
2562 insert_glyphs_hook = IT_insert_glyphs;
2563 delete_glyphs_hook = IT_delete_glyphs;
f32d4091
KS
2564 write_glyphs_hook = IT_write_glyphs;
2565 cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
2566 clear_to_end_hook = IT_clear_to_end;
2567 clear_end_of_line_hook = IT_clear_end_of_line;
2568 clear_frame_hook = IT_clear_screen;
2569 change_line_highlight_hook = IT_change_line_highlight;
2570 update_begin_hook = IT_update_begin;
2571 update_end_hook = IT_update_end;
2572 reassert_line_highlight_hook = IT_reassert_line_highlight;
41ad069b 2573 frame_up_to_date_hook = IT_frame_up_to_date;
f32d4091
KS
2574
2575 /* These hooks are called by term.c without being checked. */
2576 set_terminal_modes_hook = IT_set_terminal_modes;
2577 reset_terminal_modes_hook = IT_reset_terminal_modes;
2578 set_terminal_window_hook = IT_set_terminal_window;
c77f6f1b 2579 char_ins_del_ok = 0;
f32d4091
KS
2580#endif
2581}
2582
2583dos_get_saved_screen (screen, rows, cols)
2584 char **screen;
2585 int *rows;
2586 int *cols;
2587{
2588#ifndef HAVE_X_WINDOWS
2589 *screen = startup_screen_buffer;
2590 *cols = startup_screen_size_X;
2591 *rows = startup_screen_size_Y;
039274cf 2592 return *screen != (char *)0;
f32d4091
KS
2593#else
2594 return 0;
2595#endif
2596}
3bb1f22f
RS
2597
2598#ifndef HAVE_X_WINDOWS
2599
2600/* We are not X, but we can emulate it well enough for our needs... */
2601void
2602check_x (void)
2603{
2d764c78
EZ
2604 if (! FRAME_MSDOS_P (SELECTED_FRAME()))
2605 error ("Not running under a window system");
3bb1f22f
RS
2606}
2607
2608#endif
2609
5063b150 2610\f
f32d4091
KS
2611/* ----------------------- Keyboard control ----------------------
2612 *
2613 * Keymaps reflect the following keyboard layout:
2614 *
2615 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
2616 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
2617 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
2618 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
2619 * SPACE
2620 */
2621
d1d5dc19
EZ
2622#define Ignore 0x0000
2623#define Normal 0x0000 /* normal key - alt changes scan-code */
2624#define FctKey 0x1000 /* func key if c == 0, else c */
2625#define Special 0x2000 /* func key even if c != 0 */
2626#define ModFct 0x3000 /* special if mod-keys, else 'c' */
2627#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
2628#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
2629#define Grey 0x6000 /* Grey keypad key */
2630
2631#define Alt 0x0100 /* alt scan-code */
2632#define Ctrl 0x0200 /* ctrl scan-code */
2633#define Shift 0x0400 /* shift scan-code */
2634
f32d4091
KS
2635static int extended_kbd; /* 101 (102) keyboard present. */
2636
d1d5dc19
EZ
2637struct kbd_translate {
2638 unsigned char sc;
2639 unsigned char ch;
2640 unsigned short code;
2641};
2642
f32d4091
KS
2643struct dos_keyboard_map
2644{
2645 char *unshifted;
2646 char *shifted;
2647 char *alt_gr;
d1d5dc19 2648 struct kbd_translate *translate_table;
f32d4091
KS
2649};
2650
2651
2652static struct dos_keyboard_map us_keyboard = {
2653/* 0 1 2 3 4 5 */
2654/* 01234567890123456789012345678901234567890 12345678901234 */
2655 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
2656/* 0123456789012345678901234567890123456789 012345678901234 */
2657 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
d1d5dc19
EZ
2658 0, /* no Alt-Gr key */
2659 0 /* no translate table */
f32d4091
KS
2660};
2661
2662static struct dos_keyboard_map fr_keyboard = {
2663/* 0 1 2 3 4 5 */
2664/* 012 3456789012345678901234567890123456789012345678901234 */
2665