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