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