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