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