Correct the position of point in some line-up functions.
[bpt/emacs.git] / src / msdos.c
CommitLineData
c6a6499f 1/* MS-DOS specific C utilities. -*- coding: raw-text -*-
95df8112 2
ab422c4d 3Copyright (C) 1993-1997, 1999-2013 Free Software Foundation, Inc.
1b94449f
RS
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
1b94449f 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
1b94449f
RS
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1b94449f 19
9da6e765 20/* Contributed by Morten Welinder */
f32d4091 21/* New display, keyboard, and mouse control by Kim F. Storm */
9da6e765 22
1b94449f
RS
23/* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
24
48984716 25#include <config.h>
1b94449f
RS
26
27#ifdef MSDOS
d7306fe6 28#include <setjmp.h>
1b94449f
RS
29#include "lisp.h"
30#include <stdio.h>
06b1ea13 31#include <time.h>
1b94449f
RS
32#include <sys/param.h>
33#include <sys/time.h>
e3ac1281 34/* gettime and settime in dos.h clash with their namesakes from
0d23c240
EZ
35 gnulib, so we move out of our way the prototypes in dos.h. */
36#define gettime dos_h_gettime_
37#define settime dos_h_settime_
1b94449f 38#include <dos.h>
0d23c240
EZ
39#undef gettime
40#undef settime
d21e67b5
RS
41#include <errno.h>
42#include <sys/stat.h> /* for _fixpath */
a7cf9151 43#include <unistd.h> /* for chdir, dup, dup2, etc. */
bf794306 44#include <dir.h> /* for getdisk */
affa509c 45#pragma pack(0) /* dir.h does a pack(4), which isn't GCC's default */
1bd7b2c7 46#include <fcntl.h>
a7cf9151 47#include <io.h> /* for setmode */
fc171623
KH
48#include <dpmi.h> /* for __dpmi_xxx stuff */
49#include <sys/farptr.h> /* for _farsetsel, _farnspokeb */
d21e67b5 50#include <libc/dosio.h> /* for _USE_LFN */
a7cf9151 51#include <conio.h> /* for cputs */
1bd7b2c7 52
1b94449f
RS
53#include "msdos.h"
54#include "systime.h"
3e1944a3 55#include "frame.h"
1b94449f 56#include "termhooks.h"
aa9ce936 57#include "termchar.h"
87485d6f 58#include "dispextern.h"
c77f6f1b 59#include "dosfns.h"
87485d6f 60#include "termopts.h"
83be827a 61#include "character.h"
aa9ce936
EZ
62#include "coding.h"
63#include "disptab.h"
87485d6f 64#include "window.h"
fc171623
KH
65#include "buffer.h"
66#include "commands.h"
41ad069b 67#include "blockinput.h"
97dd288b 68#include "keyboard.h"
6b61353c 69#include "intervals.h"
1b94449f
RS
70#include <go32.h>
71#include <pc.h>
72#include <ctype.h>
73/* #include <process.h> */
891ef8f7
EZ
74/* Damn that local process.h! Instead we can define P_WAIT and
75 spawnve ourselves. */
1b94449f 76#define P_WAIT 1
891ef8f7 77extern int spawnve (int, const char *, char *const [], char *const []);
1b94449f 78
d21e67b5
RS
79#ifndef _USE_LFN
80#define _USE_LFN 0
81#endif
82
b36701cc
RS
83#ifndef _dos_ds
84#define _dos_ds _go32_info_block.selector_for_linear_memory
85#endif
86
8748735b 87#include <signal.h>
417a04bb 88#include "syssignal.h"
8748735b 89
7c106b1e
EZ
90#include "careadlinkat.h"
91#include "allocator.h"
92
1bd7b2c7
RS
93#ifndef SYSTEM_MALLOC
94
95#ifdef GNU_MALLOC
96
97/* If other `malloc' than ours is used, force our `sbrk' behave like
98 Unix programs expect (resize memory blocks to keep them contiguous).
99 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
100 because that's what `gmalloc' expects to get. */
101#include <crt0.h>
102
103#ifdef REL_ALLOC
104int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
105#else /* not REL_ALLOC */
106int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
107#endif /* not REL_ALLOC */
108#endif /* GNU_MALLOC */
109
110#endif /* not SYSTEM_MALLOC */
aee81730 111
0d23c240 112/* Return the current timestamp in milliseconds since midnight. */
aee81730 113static unsigned long
3a8ce822 114event_timestamp (void)
aee81730 115{
0d23c240 116 struct timespec t;
aee81730 117 unsigned long s;
56e19ec4 118
aee81730 119 gettime (&t);
0d23c240
EZ
120 s = t.tv_sec;
121 s %= 86400;
aee81730 122 s *= 1000;
0d23c240 123 s += t.tv_nsec * 1000000;
56e19ec4 124
aee81730
RS
125 return s;
126}
127
f32d4091
KS
128\f
129/* ------------------------ Mouse control ---------------------------
130 *
131 * Coordinates are in screen positions and zero based.
132 * Mouse buttons are numbered from left to right and also zero based.
133 */
1b94449f 134
0c3cfc51
EZ
135/* This used to be in termhooks.h, but mainstream Emacs code no longer
136 uses it, and it was removed... */
137#define NUM_MOUSE_BUTTONS (5)
138
f32d4091
KS
139int have_mouse; /* 0: no, 1: enabled, -1: disabled */
140static int mouse_visible;
1b94449f 141
f32d4091
KS
142static int mouse_last_x;
143static int mouse_last_y;
1b94449f 144
f32d4091
KS
145static int mouse_button_translate[NUM_MOUSE_BUTTONS];
146static int mouse_button_count;
1b94449f 147
f32d4091 148void
3a8ce822 149mouse_on (void)
1b94449f 150{
1b94449f 151 union REGS regs;
1b94449f 152
f32d4091 153 if (have_mouse > 0 && !mouse_visible)
1b94449f 154 {
3e1944a3
EZ
155 struct tty_display_info *tty = CURTTY ();
156
157 if (tty->termscript)
158 fprintf (tty->termscript, "<M_ON>");
f32d4091
KS
159 regs.x.ax = 0x0001;
160 int86 (0x33, &regs, &regs);
161 mouse_visible = 1;
1b94449f 162 }
1b94449f
RS
163}
164
f32d4091 165void
3a8ce822 166mouse_off (void)
1b94449f 167{
f32d4091 168 union REGS regs;
1b94449f 169
f32d4091 170 if (have_mouse > 0 && mouse_visible)
1b94449f 171 {
3e1944a3
EZ
172 struct tty_display_info *tty = CURTTY ();
173
174 if (tty->termscript)
175 fprintf (tty->termscript, "<M_OFF>");
f32d4091
KS
176 regs.x.ax = 0x0002;
177 int86 (0x33, &regs, &regs);
178 mouse_visible = 0;
1b94449f 179 }
1b94449f
RS
180}
181
8f190436
EZ
182static void
183mouse_setup_buttons (int n_buttons)
184{
185 if (n_buttons == 3)
186 {
187 mouse_button_count = 3;
188 mouse_button_translate[0] = 0; /* Left */
189 mouse_button_translate[1] = 2; /* Middle */
190 mouse_button_translate[2] = 1; /* Right */
191 }
192 else /* two, what else? */
193 {
194 mouse_button_count = 2;
195 mouse_button_translate[0] = 0;
196 mouse_button_translate[1] = 1;
197 }
198}
199
200DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons, Smsdos_set_mouse_buttons,
201 1, 1, "NSet number of mouse buttons to: ",
70da46c3
PJ
202 doc: /* Set the number of mouse buttons to use by Emacs.
203This is useful with mice that report the number of buttons inconsistently,
204e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of
205them. This happens with wheeled mice on Windows 9X, for example. */)
5842a27b 206 (Lisp_Object nbuttons)
8f190436 207{
e7522695
EZ
208 int n;
209
b7826503 210 CHECK_NUMBER (nbuttons);
e7522695
EZ
211 n = XINT (nbuttons);
212 if (n < 2 || n > 3)
ebe061ca
KS
213 xsignal2 (Qargs_out_of_range,
214 build_string ("only 2 or 3 mouse buttons are supported"),
215 nbuttons);
e7522695 216 mouse_setup_buttons (n);
8f190436
EZ
217 return Qnil;
218}
219
211c7152
EZ
220static void
221mouse_get_xy (int *x, int *y)
222{
223 union REGS regs;
224
225 regs.x.ax = 0x0003;
226 int86 (0x33, &regs, &regs);
227 *x = regs.x.cx / 8;
228 *y = regs.x.dx / 8;
229}
230
f32d4091 231void
3a8ce822 232mouse_moveto (int x, int y)
1b94449f 233{
f32d4091 234 union REGS regs;
3e1944a3 235 struct tty_display_info *tty = CURTTY ();
1b94449f 236
3e1944a3
EZ
237 if (tty->termscript)
238 fprintf (tty->termscript, "<M_XY=%dx%d>", x, y);
f32d4091
KS
239 regs.x.ax = 0x0004;
240 mouse_last_x = regs.x.cx = x * 8;
241 mouse_last_y = regs.x.dx = y * 8;
242 int86 (0x33, &regs, &regs);
1b94449f
RS
243}
244
f32d4091 245static int
3a8ce822 246mouse_pressed (int b, int *xp, int *yp)
1b94449f 247{
f32d4091 248 union REGS regs;
1b94449f 249
f32d4091
KS
250 if (b >= mouse_button_count)
251 return 0;
252 regs.x.ax = 0x0005;
253 regs.x.bx = mouse_button_translate[b];
254 int86 (0x33, &regs, &regs);
255 if (regs.x.bx)
256 *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
257 return (regs.x.bx != 0);
1b94449f
RS
258}
259
f32d4091 260static int
3a8ce822 261mouse_released (int b, int *xp, int *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 275static int
3a8ce822 276mouse_button_depressed (int b, int *xp, int *yp)
0c7bc1aa
EZ
277{
278 union REGS regs;
279
280 if (b >= mouse_button_count)
281 return 0;
282 regs.x.ax = 0x0003;
283 int86 (0x33, &regs, &regs);
284 if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0)
285 {
286 *xp = regs.x.cx / 8;
287 *yp = regs.x.dx / 8;
288 return 1;
289 }
290 return 0;
291}
292
f32d4091 293void
3a8ce822
EZ
294mouse_get_pos (FRAME_PTR *f, int insist, Lisp_Object *bar_window,
295 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
9fbd6841 296 Time *time)
f32d4091
KS
297{
298 int ix, iy;
211c7152
EZ
299 Lisp_Object frame, tail;
300
301 /* Clear the mouse-moved flag for every frame on this display. */
302 FOR_EACH_FRAME (tail, frame)
303 XFRAME (frame)->mouse_moved = 0;
f32d4091 304
5e617bc2 305 *f = SELECTED_FRAME ();
f32d4091
KS
306 *bar_window = Qnil;
307 mouse_get_xy (&ix, &iy);
f32d4091 308 *time = event_timestamp ();
211c7152
EZ
309 *x = make_number (mouse_last_x = ix);
310 *y = make_number (mouse_last_y = iy);
f32d4091 311}
1b94449f 312
f32d4091 313static void
3a8ce822 314mouse_check_moved (void)
1b94449f 315{
aee81730 316 int x, y;
1b94449f 317
f32d4091 318 mouse_get_xy (&x, &y);
5e617bc2 319 SELECTED_FRAME ()->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
f32d4091
KS
320 mouse_last_x = x;
321 mouse_last_y = y;
322}
1b94449f 323
97dd288b
EZ
324/* Force the mouse driver to ``forget'' about any button clicks until
325 now. */
326static void
327mouse_clear_clicks (void)
328{
329 int b;
330
331 for (b = 0; b < mouse_button_count; b++)
332 {
333 int dummy_x, dummy_y;
334
335 (void) mouse_pressed (b, &dummy_x, &dummy_y);
336 (void) mouse_released (b, &dummy_x, &dummy_y);
337 }
338}
339
f32d4091 340void
3a8ce822 341mouse_init (void)
f32d4091
KS
342{
343 union REGS regs;
3e1944a3 344 struct tty_display_info *tty = CURTTY ();
647c32eb 345
3e1944a3
EZ
346 if (tty->termscript)
347 fprintf (tty->termscript, "<M_INIT>");
1b94449f 348
f32d4091
KS
349 regs.x.ax = 0x0021;
350 int86 (0x33, &regs, &regs);
091d0bdf 351
0c7bc1aa
EZ
352 /* Reset the mouse last press/release info. It seems that Windows
353 doesn't do that automatically when function 21h is called, which
354 causes Emacs to ``remember'' the click that switched focus to the
355 window just before Emacs was started from that window. */
97dd288b 356 mouse_clear_clicks ();
0c7bc1aa 357
f32d4091
KS
358 regs.x.ax = 0x0007;
359 regs.x.cx = 0;
360 regs.x.dx = 8 * (ScreenCols () - 1);
361 int86 (0x33, &regs, &regs);
1b94449f 362
f32d4091
KS
363 regs.x.ax = 0x0008;
364 regs.x.cx = 0;
365 regs.x.dx = 8 * (ScreenRows () - 1);
366 int86 (0x33, &regs, &regs);
1b94449f 367
f32d4091
KS
368 mouse_moveto (0, 0);
369 mouse_visible = 0;
370}
3eb1dbb6 371\f
f32d4091
KS
372/* ------------------------- Screen control ----------------------
373 *
374 */
aee81730 375
f32d4091 376static int internal_terminal = 0;
aee81730 377
f32d4091
KS
378#ifndef HAVE_X_WINDOWS
379extern unsigned char ScreenAttrib;
380static int screen_face;
aee81730 381
f32d4091
KS
382static int screen_size_X;
383static int screen_size_Y;
384static int screen_size;
1b94449f 385
f32d4091
KS
386static int current_pos_X;
387static int current_pos_Y;
388static int new_pos_X;
389static int new_pos_Y;
1b94449f 390
f32d4091
KS
391static void *startup_screen_buffer;
392static int startup_screen_size_X;
393static int startup_screen_size_Y;
394static int startup_pos_X;
395static int startup_pos_Y;
c9adab25 396static unsigned char startup_screen_attrib;
1b94449f 397
06b1ea13
EZ
398static clock_t startup_time;
399
f32d4091 400static int term_setup_done;
1b94449f 401
8ba01a32
EZ
402static unsigned short outside_cursor;
403
f32d4091 404/* Similar to the_only_frame. */
3e1944a3 405struct tty_display_info the_only_display_info;
1b94449f 406
039274cf
EZ
407/* Support for DOS/V (allows Japanese characters to be displayed on
408 standard, non-Japanese, ATs). Only supported for DJGPP v2 and later. */
409
410/* Holds the address of the text-mode screen buffer. */
411static unsigned long screen_old_address = 0;
412/* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
413static unsigned short screen_virtual_segment = 0;
414static unsigned short screen_virtual_offset = 0;
6b61353c
KH
415extern Lisp_Object Qcursor_type;
416extern Lisp_Object Qbar, Qhbar;
8ba01a32 417
9ccf54e9 418/* The screen colors of the current frame, which serve as the default
deece6f5
EZ
419 colors for newly-created frames. */
420static int initial_screen_colors[2];
421
039274cf
EZ
422/* Update the screen from a part of relocated DOS/V screen buffer which
423 begins at OFFSET and includes COUNT characters. */
424static void
425dosv_refresh_virtual_screen (int offset, int count)
426{
427 __dpmi_regs regs;
428
9ab8560d 429 if (offset < 0 || count < 0) /* paranoia; invalid values crash DOS/V */
40437cf5
EZ
430 return;
431
039274cf
EZ
432 regs.h.ah = 0xff; /* update relocated screen */
433 regs.x.es = screen_virtual_segment;
434 regs.x.di = screen_virtual_offset + offset;
435 regs.x.cx = count;
436 __dpmi_int (0x10, &regs);
437}
039274cf 438
d1d5dc19 439static void
3a8ce822 440dos_direct_output (int y, int x, char *buf, int len)
1b94449f 441{
40437cf5
EZ
442 int t0 = 2 * (x + y * screen_size_X);
443 int t = t0 + (int) ScreenPrimary;
039274cf 444 int l0 = len;
fc171623 445
fc171623
KH
446 /* This is faster. */
447 for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
448 _farnspokeb (t, *buf);
039274cf
EZ
449
450 if (screen_virtual_segment)
451 dosv_refresh_virtual_screen (t0, l0);
f32d4091
KS
452}
453#endif
454
455#ifndef HAVE_X_WINDOWS
456
b36701cc
RS
457static int blink_bit = -1; /* the state of the blink bit at startup */
458
76ac1508
RS
459/* Enable bright background colors. */
460static void
461bright_bg (void)
462{
463 union REGS regs;
464
b36701cc
RS
465 /* Remember the original state of the blink/bright-background bit.
466 It is stored at 0040:0065h in the BIOS data area. */
467 if (blink_bit == -1)
468 blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
469
76ac1508
RS
470 regs.h.bl = 0;
471 regs.x.ax = 0x1003;
472 int86 (0x10, &regs, &regs);
473}
474
b36701cc
RS
475/* Disable bright background colors (and enable blinking) if we found
476 the video system in that state at startup. */
477static void
478maybe_enable_blinking (void)
479{
480 if (blink_bit == 1)
481 {
482 union REGS regs;
483
484 regs.h.bl = 1;
485 regs.x.ax = 0x1003;
486 int86 (0x10, &regs, &regs);
487 }
488}
489
8ba01a32
EZ
490/* Return non-zero if the system has a VGA adapter. */
491static int
492vga_installed (void)
493{
494 union REGS regs;
495
496 regs.x.ax = 0x1a00;
497 int86 (0x10, &regs, &regs);
498 if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
499 return 1;
500 return 0;
501}
502
4a96d4d2
KH
503/* Set the screen dimensions so that it can show no less than
504 ROWS x COLS frame. */
48ffe371 505
4a96d4d2 506void
3a8ce822 507dos_set_window_size (int *rows, int *cols)
4a96d4d2
KH
508{
509 char video_name[30];
4a96d4d2 510 union REGS regs;
56e19ec4
EZ
511 Lisp_Object video_mode;
512 int video_mode_value, have_vga = 0;
4a96d4d2
KH
513 int current_rows = ScreenRows (), current_cols = ScreenCols ();
514
515 if (*rows == current_rows && *cols == current_cols)
516 return;
517
4a96d4d2 518 mouse_off ();
8ba01a32 519 have_vga = vga_installed ();
4a96d4d2 520
48ffe371 521 /* If the user specified a special video mode for these dimensions,
4a96d4d2 522 use that mode. */
15dbb4d6
PE
523 video_mode
524 = Fsymbol_value (Fintern_soft (make_formatted_string
a8290ec3
DA
525 (video_name, "screen-dimensions-%dx%d",
526 *rows, *cols), Qnil));
4a96d4d2
KH
527
528 if (INTEGERP (video_mode)
529 && (video_mode_value = XINT (video_mode)) > 0)
530 {
531 regs.x.ax = video_mode_value;
532 int86 (0x10, &regs, &regs);
48ffe371
RS
533
534 if (have_mouse)
535 {
536 /* Must hardware-reset the mouse, or else it won't update
537 its notion of screen dimensions for some non-standard
538 video modes. This is *painfully* slow... */
539 regs.x.ax = 0;
540 int86 (0x33, &regs, &regs);
541 }
4a96d4d2
KH
542 }
543
544 /* Find one of the dimensions supported by standard EGA/VGA
545 which gives us at least the required dimensions. */
4a96d4d2
KH
546 else
547 {
548 static struct {
56e19ec4 549 int rows, need_vga;
4a96d4d2
KH
550 } std_dimension[] = {
551 {25, 0},
552 {28, 1},
553 {35, 0},
554 {40, 1},
555 {43, 0},
556 {50, 1}
557 };
558 int i = 0;
559
560 while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
561 {
562 if (std_dimension[i].need_vga <= have_vga
563 && std_dimension[i].rows >= *rows)
564 {
565 if (std_dimension[i].rows != current_rows
566 || *cols != current_cols)
48ffe371 567 _set_screen_lines (std_dimension[i].rows);
4a96d4d2
KH
568 break;
569 }
48ffe371 570 i++;
4a96d4d2
KH
571 }
572 }
573
4a96d4d2
KH
574
575 if (have_mouse)
576 {
4a96d4d2
KH
577 mouse_init ();
578 mouse_on ();
579 }
580
581 /* Tell the caller what dimensions have been REALLY set. */
582 *rows = ScreenRows ();
583 *cols = ScreenCols ();
76ac1508 584
bed43f1d
EZ
585 /* Update Emacs' notion of screen dimensions. */
586 screen_size_X = *cols;
587 screen_size_Y = *rows;
588 screen_size = *cols * *rows;
589
41ad069b
EZ
590 /* If the dimensions changed, the mouse highlight info is invalid. */
591 if (current_rows != *rows || current_cols != *cols)
592 {
5e617bc2 593 struct frame *f = SELECTED_FRAME ();
34574c02
EZ
594 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
595 Lisp_Object window = hlinfo->mouse_face_window;
41ad069b 596
d3d50620 597 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
41ad069b 598 {
34574c02
EZ
599 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
600 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
601 hlinfo->mouse_face_window = Qnil;
41ad069b
EZ
602 }
603 }
41ad069b 604
76ac1508
RS
605 /* Enable bright background colors. */
606 bright_bg ();
039274cf
EZ
607
608 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
609 be defensive anyway. */
610 if (screen_virtual_segment)
611 dosv_refresh_virtual_screen (0, *cols * *rows);
4a96d4d2
KH
612}
613
48ffe371
RS
614/* If we write a character in the position where the mouse is,
615 the mouse cursor may need to be refreshed. */
09e2ac30
RS
616
617static void
3a8ce822 618mouse_off_maybe (void)
09e2ac30 619{
f32d4091 620 int x, y;
56e19ec4 621
f32d4091
KS
622 if (!mouse_visible)
623 return;
56e19ec4 624
f32d4091
KS
625 mouse_get_xy (&x, &y);
626 if (y != new_pos_Y || x < new_pos_X)
627 return;
56e19ec4 628
f32d4091
KS
629 mouse_off ();
630}
631
8ba01a32
EZ
632#define DEFAULT_CURSOR_START (-1)
633#define DEFAULT_CURSOR_WIDTH (-1)
634#define BOX_CURSOR_WIDTH (-32)
635
636/* Set cursor to begin at scan line START_LINE in the character cell
637 and extend for WIDTH scan lines. Scan lines are counted from top
638 of the character cell, starting from zero. */
639static void
640msdos_set_cursor_shape (struct frame *f, int start_line, int width)
641{
8ba01a32
EZ
642 unsigned desired_cursor;
643 __dpmi_regs regs;
644 int max_line, top_line, bot_line;
3e1944a3 645 struct tty_display_info *tty = FRAME_TTY (f);
8ba01a32
EZ
646
647 /* Avoid the costly BIOS call if F isn't the currently selected
648 frame. Allow for NULL as unconditionally meaning the selected
649 frame. */
5e617bc2 650 if (f && f != SELECTED_FRAME ())
8ba01a32
EZ
651 return;
652
3e1944a3
EZ
653 if (tty->termscript)
654 fprintf (tty->termscript, "\nCURSOR SHAPE=(%d,%d)", start_line, width);
b106731c 655
8ba01a32
EZ
656 /* The character cell size in scan lines is stored at 40:85 in the
657 BIOS data area. */
658 max_line = _farpeekw (_dos_ds, 0x485) - 1;
659 switch (max_line)
660 {
661 default: /* this relies on CGA cursor emulation being ON! */
662 case 7:
663 bot_line = 7;
664 break;
665 case 9:
666 bot_line = 9;
667 break;
668 case 13:
669 bot_line = 12;
670 break;
671 case 15:
672 bot_line = 14;
673 break;
674 }
675
676 if (width < 0)
677 {
678 if (width == BOX_CURSOR_WIDTH)
679 {
680 top_line = 0;
681 bot_line = max_line;
682 }
683 else if (start_line != DEFAULT_CURSOR_START)
684 {
685 top_line = start_line;
686 bot_line = top_line - width - 1;
687 }
688 else if (width != DEFAULT_CURSOR_WIDTH)
689 {
690 top_line = 0;
691 bot_line = -1 - width;
692 }
693 else
694 top_line = bot_line + 1;
695 }
696 else if (width == 0)
697 {
698 /* [31, 0] seems to DTRT for all screen sizes. */
699 top_line = 31;
700 bot_line = 0;
701 }
702 else /* WIDTH is positive */
703 {
704 if (start_line != DEFAULT_CURSOR_START)
705 bot_line = start_line;
706 top_line = bot_line - (width - 1);
707 }
708
709 /* If the current cursor shape is already what they want, we are
710 history here. */
711 desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
712 if (desired_cursor == _farpeekw (_dos_ds, 0x460))
713 return;
714
715 regs.h.ah = 1;
716 regs.x.cx = desired_cursor;
717 __dpmi_int (0x10, &regs);
8ba01a32
EZ
718}
719
720static void
721IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
722{
a0738471 723 if (EQ (cursor_type, Qbar) || EQ (cursor_type, Qhbar))
8ba01a32
EZ
724 {
725 /* Just BAR means the normal EGA/VGA cursor. */
726 msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
727 }
a0738471
EZ
728 else if (CONSP (cursor_type)
729 && (EQ (XCAR (cursor_type), Qbar)
730 || EQ (XCAR (cursor_type), Qhbar)))
8ba01a32
EZ
731 {
732 Lisp_Object bar_parms = XCDR (cursor_type);
733 int width;
734
735 if (INTEGERP (bar_parms))
736 {
737 /* Feature: negative WIDTH means cursor at the top
738 of the character cell, zero means invisible cursor. */
739 width = XINT (bar_parms);
740 msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
741 width);
742 }
743 else if (CONSP (bar_parms)
744 && INTEGERP (XCAR (bar_parms))
745 && INTEGERP (XCDR (bar_parms)))
746 {
747 int start_line = XINT (XCDR (bar_parms));
748
749 width = XINT (XCAR (bar_parms));
750 msdos_set_cursor_shape (f, start_line, width);
751 }
752 }
753 else
b106731c
EZ
754 {
755 /* Treat anything unknown as "box cursor". This includes nil, so
756 that a frame which doesn't specify a cursor type gets a box,
757 which is the default in Emacs. */
758 msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
759 }
8ba01a32
EZ
760}
761
71f65669 762static void
3e1944a3 763IT_ring_bell (struct frame *f)
f32d4091
KS
764{
765 if (visible_bell)
aee81730 766 {
f32d4091
KS
767 mouse_off ();
768 ScreenVisualBell ();
aee81730 769 }
f32d4091 770 else
3635be47
RS
771 {
772 union REGS inregs, outregs;
773 inregs.h.ah = 2;
774 inregs.h.dl = 7;
775 intdos (&inregs, &outregs);
776 }
09e2ac30
RS
777}
778
c77f6f1b
EZ
779/* Given a face id FACE, extract the face parameters to be used for
780 display until the face changes. The face parameters (actually, its
781 color) are used to construct the video attribute byte for each
782 glyph during the construction of the buffer that is then blitted to
783 the video RAM. */
f32d4091
KS
784static void
785IT_set_face (int face)
786{
5e617bc2 787 struct frame *sf = SELECTED_FRAME ();
546701f5
EZ
788 struct face *fp = FACE_FROM_ID (sf, face);
789 struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
790 unsigned long fg, bg, dflt_fg, dflt_bg;
3e1944a3 791 struct tty_display_info *tty = FRAME_TTY (sf);
f32d4091 792
c77f6f1b 793 if (!fp)
e30aee93 794 {
546701f5 795 fp = dfp;
e30aee93
EZ
796 /* The default face for the frame should always be realized and
797 cached. */
798 if (!fp)
1088b922 799 emacs_abort ();
e30aee93 800 }
f32d4091 801 screen_face = face;
c77f6f1b
EZ
802 fg = fp->foreground;
803 bg = fp->background;
546701f5
EZ
804 dflt_fg = dfp->foreground;
805 dflt_bg = dfp->background;
c77f6f1b 806
abcce93a
MB
807 /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_* colors
808 mean use the colors of the default face. Note that we assume all
809 16 colors to be available for the background, since Emacs switches
810 on this mode (and loses the blinking attribute) at startup. */
f9d2fdc4 811 if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731 812 fg = FRAME_FOREGROUND_PIXEL (sf);
f9d2fdc4 813 else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
3b620731
EZ
814 fg = FRAME_BACKGROUND_PIXEL (sf);
815 if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
816 bg = FRAME_BACKGROUND_PIXEL (sf);
f9d2fdc4 817 else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
3b620731
EZ
818 bg = FRAME_FOREGROUND_PIXEL (sf);
819
820 /* Make sure highlighted lines really stand out, come what may. */
abcce93a 821 if (fp->tty_reverse_p && (fg == dflt_fg && bg == dflt_bg))
3b620731
EZ
822 {
823 unsigned long tem = fg;
824
825 fg = bg;
826 bg = tem;
827 }
76648534
EZ
828 /* If the user requested inverse video, obey. */
829 if (inverse_video)
830 {
831 unsigned long tem2 = fg;
832
833 fg = bg;
834 bg = tem2;
835 }
3e1944a3 836 if (tty->termscript)
891ef8f7 837 fprintf (tty->termscript, "<FACE %d: %lu/%lu[FG:%lu/BG:%lu]>", face,
abcce93a 838 fp->foreground, fp->background, fg, bg);
c77f6f1b
EZ
839 if (fg >= 0 && fg < 16)
840 {
841 ScreenAttrib &= 0xf0;
842 ScreenAttrib |= fg;
843 }
844 if (bg >= 0 && bg < 16)
845 {
846 ScreenAttrib &= 0x0f;
847 ScreenAttrib |= ((bg & 0x0f) << 4);
848 }
f32d4091
KS
849}
850
aff01dd9
EZ
851/* According to RBIL (INTERRUP.A, V-1000), 160 is the maximum possible
852 width of a DOS display in any known text mode. We multiply by 2 to
7ee6a1d3 853 accommodate the screen attribute byte. */
aff01dd9
EZ
854#define MAX_SCREEN_BUF 160*2
855
3e1944a3
EZ
856extern unsigned char *encode_terminal_code (struct glyph *, int,
857 struct coding_system *);
7ef4b50c 858
71f65669 859static void
3e1944a3 860IT_write_glyphs (struct frame *f, struct glyph *str, int str_len)
f32d4091 861{
aff01dd9 862 unsigned char screen_buf[MAX_SCREEN_BUF], *screen_bp, *bp;
039274cf 863 int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
aa9ce936 864 register int sl = str_len;
3e1944a3 865 struct tty_display_info *tty = FRAME_TTY (f);
2d764c78 866 struct frame *sf;
3e1944a3 867 unsigned char *conversion_buffer;
87485d6f 868
3e1944a3
EZ
869 /* If terminal_coding does any conversion, use it, otherwise use
870 safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
871 because it always returns 1 if terminal_coding.src_multibyte is 1. */
872 struct coding_system *coding = FRAME_TERMINAL_CODING (f);
873
874 if (!(coding->common_flags & CODING_REQUIRE_ENCODING_MASK))
875 coding = &safe_terminal_coding;
648648a9 876
3b620731 877 if (str_len <= 0) return;
56e19ec4 878
5e617bc2 879 sf = SELECTED_FRAME ();
e30aee93
EZ
880
881 /* Since faces get cached and uncached behind our back, we can't
882 rely on their indices in the cache being consistent across
883 invocations. So always reset the screen face to the default
884 face of the frame, before writing glyphs, and let the glyphs
885 set the right face if it's different from the default. */
886 IT_set_face (DEFAULT_FACE_ID);
56e19ec4 887
aa9ce936
EZ
888 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
889 the tail. */
3e1944a3 890 coding->mode &= ~CODING_MODE_LAST_BLOCK;
aff01dd9 891 screen_bp = &screen_buf[0];
3e1944a3 892 while (sl > 0)
aa9ce936 893 {
3e1944a3 894 int cf;
aff01dd9 895 int n;
aa9ce936 896
aff01dd9
EZ
897 /* If the face of this glyph is different from the current
898 screen face, update the screen attribute byte. */
899 cf = str->face_id;
900 if (cf != screen_face)
901 IT_set_face (cf); /* handles invalid faces gracefully */
902
903 /* Identify a run of glyphs with the same face. */
904 for (n = 1; n < sl; ++n)
905 if (str[n].face_id != cf)
906 break;
907
908 if (n >= sl)
909 /* This is the last glyph. */
910 coding->mode |= CODING_MODE_LAST_BLOCK;
911
912 conversion_buffer = encode_terminal_code (str, n, coding);
913 if (coding->produced > 0)
aa9ce936 914 {
aff01dd9
EZ
915 /* Copy the encoded bytes to the screen buffer. */
916 for (bp = conversion_buffer; coding->produced--; bp++)
aa9ce936 917 {
aff01dd9
EZ
918 /* Paranoia: discard bytes that would overrun the end of
919 the screen buffer. */
920 if (screen_bp - screen_buf <= MAX_SCREEN_BUF - 2)
aa9ce936 921 {
aff01dd9
EZ
922 *screen_bp++ = (unsigned char)*bp;
923 *screen_bp++ = ScreenAttrib;
aa9ce936 924 }
aff01dd9
EZ
925 if (tty->termscript)
926 fputc (*bp, tty->termscript);
aa9ce936
EZ
927 }
928 }
aff01dd9
EZ
929 /* Update STR and its remaining length. */
930 str += n;
931 sl -= n;
aee81730
RS
932 }
933
aff01dd9 934 /* Dump whatever we have in the screen buffer. */
f32d4091 935 mouse_off_maybe ();
aa9ce936 936 dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
039274cf 937 if (screen_virtual_segment)
aa9ce936
EZ
938 dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
939 new_pos_X += (screen_bp - screen_buf) / 2;
f32d4091 940}
aee81730 941
41ad069b
EZ
942/************************************************************************
943 Mouse Highlight (and friends..)
944 ************************************************************************/
945
ee8ceff8 946/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
9005a471
EZ
947static Lisp_Object last_mouse_window;
948
41ad069b
EZ
949static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
950
d009ae66
EZ
951int
952popup_activated (void)
41ad069b 953{
d009ae66 954 return mouse_preempted;
41ad069b
EZ
955}
956
d009ae66 957/* Draw TEXT_AREA glyphs between START and END of glyph row ROW on
28118eb6
EZ
958 window W. X is relative to TEXT_AREA in W. HL is a face override
959 for drawing the glyphs. */
d009ae66 960void
28118eb6
EZ
961tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
962 int start_hpos, int end_hpos,
963 enum draw_glyphs_face hl)
41ad069b 964{
41ad069b 965 struct frame *f = XFRAME (WINDOW_FRAME (w));
3e1944a3 966 struct tty_display_info *tty = FRAME_TTY (f);
34574c02 967 Mouse_HLInfo *hlinfo = &tty->mouse_highlight;
41ad069b 968
d009ae66 969 if (hl == DRAW_MOUSE_FACE)
41ad069b 970 {
d009ae66
EZ
971 int vpos = row->y + WINDOW_TOP_EDGE_Y (w);
972 int kstart = start_hpos + WINDOW_LEFT_EDGE_X (w);
973 int nglyphs = end_hpos - start_hpos;
974 int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
975 int start_offset = offset;
41ad069b 976
d009ae66
EZ
977 if (tty->termscript)
978 fprintf (tty->termscript, "\n<MH+ %d-%d:%d>",
979 kstart, kstart + nglyphs - 1, vpos);
56e19ec4 980
d009ae66 981 mouse_off ();
34574c02 982 IT_set_face (hlinfo->mouse_face_face_id);
d009ae66
EZ
983 /* Since we are going to change only the _colors_ of already
984 displayed text, there's no need to go through all the pain of
985 generating and encoding the text from the glyphs. Instead,
986 we simply poke the attribute byte of each affected position
987 in video memory with the colors computed by IT_set_face! */
988 _farsetsel (_dos_ds);
989 while (nglyphs--)
41ad069b 990 {
d009ae66
EZ
991 _farnspokeb (offset, ScreenAttrib);
992 offset += 2;
41ad069b 993 }
d009ae66
EZ
994 if (screen_virtual_segment)
995 dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
996 mouse_on ();
41ad069b 997 }
d009ae66 998 else if (hl == DRAW_NORMAL_TEXT)
41ad069b 999 {
d009ae66
EZ
1000 /* We are removing a previously-drawn mouse highlight. The
1001 safest way to do so is to redraw the glyphs anew, since all
1002 kinds of faces and display tables could have changed behind
1003 our back. */
1004 int nglyphs = end_hpos - start_hpos;
1005 int save_x = new_pos_X, save_y = new_pos_Y;
1006
1007 if (end_hpos >= row->used[TEXT_AREA])
1008 nglyphs = row->used[TEXT_AREA] - start_hpos;
1009
1010 /* IT_write_glyphs writes at cursor position, so we need to
1011 temporarily move cursor coordinates to the beginning of
1012 the highlight region. */
1013 new_pos_X = start_hpos + WINDOW_LEFT_EDGE_X (w);
1014 new_pos_Y = row->y + WINDOW_TOP_EDGE_Y (w);
41ad069b 1015
d009ae66
EZ
1016 if (tty->termscript)
1017 fprintf (tty->termscript, "<MH- %d-%d:%d>",
1018 new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
1019 IT_write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
1020 if (tty->termscript)
1021 fputs ("\n", tty->termscript);
1022 new_pos_X = save_x;
1023 new_pos_Y = save_y;
41ad069b
EZ
1024 }
1025}
1026
71f65669 1027static void
3e1944a3 1028IT_clear_end_of_line (struct frame *f, int first_unused)
f32d4091
KS
1029{
1030 char *spaces, *sp;
56e19ec4 1031 int i, j, offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
3e1944a3 1032 struct tty_display_info *tty = FRAME_TTY (f);
aa9ce936 1033
2d764c78 1034 if (new_pos_X >= first_unused || fatal_error_in_progress)
aa9ce936 1035 return;
f32d4091
KS
1036
1037 IT_set_face (0);
2d764c78 1038 i = (j = first_unused - new_pos_X) * 2;
3e1944a3
EZ
1039 if (tty->termscript)
1040 fprintf (tty->termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
f32d4091 1041 spaces = sp = alloca (i);
56e19ec4 1042
f32d4091 1043 while (--j >= 0)
aee81730 1044 {
f32d4091
KS
1045 *sp++ = ' ';
1046 *sp++ = ScreenAttrib;
aee81730
RS
1047 }
1048
f32d4091 1049 mouse_off_maybe ();
039274cf
EZ
1050 dosmemput (spaces, i, (int)ScreenPrimary + offset);
1051 if (screen_virtual_segment)
1052 dosv_refresh_virtual_screen (offset, i / 2);
2d764c78
EZ
1053
1054 /* clear_end_of_line_raw on term.c leaves the cursor at first_unused.
1055 Let's follow their lead, in case someone relies on this. */
1056 new_pos_X = first_unused;
aee81730
RS
1057}
1058
71f65669 1059static void
3e1944a3 1060IT_clear_screen (struct frame *f)
f32d4091 1061{
3e1944a3
EZ
1062 struct tty_display_info *tty = FRAME_TTY (f);
1063
1064 if (tty->termscript)
1065 fprintf (tty->termscript, "<CLR:SCR>");
deece6f5
EZ
1066 /* We are sometimes called (from clear_garbaged_frames) when a new
1067 frame is being created, but its faces are not yet realized. In
1068 such a case we cannot call IT_set_face, since it will fail to find
1069 any valid faces and will abort. Instead, use the initial screen
1070 colors; that should mimic what a Unix tty does, which simply clears
1071 the screen with whatever default colors are in use. */
1072 if (FACE_FROM_ID (SELECTED_FRAME (), DEFAULT_FACE_ID) == NULL)
1073 ScreenAttrib = (initial_screen_colors[0] << 4) | initial_screen_colors[1];
1074 else
1075 IT_set_face (0);
f32d4091
KS
1076 mouse_off ();
1077 ScreenClear ();
039274cf
EZ
1078 if (screen_virtual_segment)
1079 dosv_refresh_virtual_screen (0, screen_size);
f32d4091
KS
1080 new_pos_X = new_pos_Y = 0;
1081}
1082
71f65669 1083static void
3e1944a3 1084IT_clear_to_end (struct frame *f)
f32d4091 1085{
3e1944a3
EZ
1086 struct tty_display_info *tty = FRAME_TTY (f);
1087
1088 if (tty->termscript)
1089 fprintf (tty->termscript, "<CLR:EOS>");
f32d4091
KS
1090
1091 while (new_pos_Y < screen_size_Y) {
1092 new_pos_X = 0;
3e1944a3 1093 IT_clear_end_of_line (f, screen_size_X);
f32d4091
KS
1094 new_pos_Y++;
1095 }
1096}
1097
71f65669 1098static void
3e1944a3 1099IT_cursor_to (struct frame *f, int y, int x)
f32d4091 1100{
3e1944a3
EZ
1101 struct tty_display_info *tty = FRAME_TTY (f);
1102
1103 if (tty->termscript)
1104 fprintf (tty->termscript, "\n<XY=%dx%d>", x, y);
f32d4091
KS
1105 new_pos_X = x;
1106 new_pos_Y = y;
1107}
1108
fc171623
KH
1109static int cursor_cleared;
1110
d1d5dc19 1111static void
fc171623
KH
1112IT_display_cursor (int on)
1113{
3e1944a3
EZ
1114 struct tty_display_info *tty = CURTTY ();
1115
fc171623
KH
1116 if (on && cursor_cleared)
1117 {
1118 ScreenSetCursor (current_pos_Y, current_pos_X);
1119 cursor_cleared = 0;
b04021eb 1120 if (tty->termscript)
cb4545ad
EZ
1121 fprintf (tty->termscript, "\nCURSOR ON (%dx%d)",
1122 current_pos_Y, current_pos_X);
fc171623
KH
1123 }
1124 else if (!on && !cursor_cleared)
1125 {
1126 ScreenSetCursor (-1, -1);
1127 cursor_cleared = 1;
b04021eb 1128 if (tty->termscript)
cb4545ad
EZ
1129 fprintf (tty->termscript, "\nCURSOR OFF (%dx%d)",
1130 current_pos_Y, current_pos_X);
fc171623
KH
1131 }
1132}
1133
1134/* Emacs calls cursor-movement functions a lot when it updates the
1135 display (probably a legacy of old terminals where you cannot
1136 update a screen line without first moving the cursor there).
1137 However, cursor movement is expensive on MSDOS (it calls a slow
1138 BIOS function and requires 2 mode switches), while actual screen
1139 updates access the video memory directly and don't depend on
1140 cursor position. To avoid slowing down the redisplay, we cheat:
1141 all functions that move the cursor only set internal variables
1142 which record the cursor position, whereas the cursor is only
1143 moved to its final position whenever screen update is complete.
1144
1145 `IT_cmgoto' is called from the keyboard reading loop and when the
1146 frame update is complete. This means that we are ready for user
1147 input, so we update the cursor position to show where the point is,
1148 and also make the mouse pointer visible.
1149
1150 Special treatment is required when the cursor is in the echo area,
1151 to put the cursor at the end of the text displayed there. */
1152
71f65669
EZ
1153static void
1154IT_cmgoto (FRAME_PTR f)
fc171623
KH
1155{
1156 /* Only set the cursor to where it should be if the display is
1157 already in sync with the window contents. */
2d764c78 1158 int update_cursor_pos = 1; /* MODIFF == unchanged_modified; */
3e1944a3 1159 struct tty_display_info *tty = FRAME_TTY (f);
2d764c78
EZ
1160
1161 /* FIXME: This needs to be rewritten for the new redisplay, or
1162 removed. */
1163#if 0
06da1de1
EZ
1164 static int previous_pos_X = -1;
1165
2d764c78
EZ
1166 update_cursor_pos = 1; /* temporary!!! */
1167
06da1de1
EZ
1168 /* If the display is in sync, forget any previous knowledge about
1169 cursor position. This is primarily for unexpected events like
1170 C-g in the minibuffer. */
1171 if (update_cursor_pos && previous_pos_X >= 0)
1172 previous_pos_X = -1;
1173 /* If we are in the echo area, put the cursor at the
1174 end of the echo area message. */
fc171623 1175 if (!update_cursor_pos
c655f6fd 1176 && WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f))) <= new_pos_Y)
fc171623 1177 {
06da1de1
EZ
1178 int tem_X = current_pos_X, dummy;
1179
1180 if (echo_area_glyphs)
1181 {
1182 tem_X = echo_area_glyphs_length;
1183 /* Save current cursor position, to be restored after the
1184 echo area message is erased. Only remember one level
1185 of previous cursor position. */
1186 if (previous_pos_X == -1)
1187 ScreenGetCursor (&dummy, &previous_pos_X);
1188 }
1189 else if (previous_pos_X >= 0)
1190 {
1191 /* We wind up here after the echo area message is erased.
1192 Restore the cursor position we remembered above. */
1193 tem_X = previous_pos_X;
1194 previous_pos_X = -1;
1195 }
9a599a60 1196
06da1de1 1197 if (current_pos_X != tem_X)
9a599a60
EZ
1198 {
1199 new_pos_X = tem_X;
1200 update_cursor_pos = 1;
1201 }
fc171623 1202 }
2d764c78 1203#endif
fc171623
KH
1204
1205 if (update_cursor_pos
1206 && (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
1207 {
1208 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
3e1944a3
EZ
1209 if (tty->termscript)
1210 fprintf (tty->termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
fc171623
KH
1211 }
1212
1213 /* Maybe cursor is invisible, so make it visible. */
1214 IT_display_cursor (1);
1215
1216 /* Mouse pointer should be always visible if we are waiting for
1217 keyboard input. */
1218 if (!mouse_visible)
1219 mouse_on ();
1220}
1221
71f65669 1222static void
41ad069b 1223IT_update_begin (struct frame *f)
f32d4091 1224{
3e1944a3 1225 struct tty_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
34574c02
EZ
1226 Mouse_HLInfo *hlinfo = &display_info->mouse_highlight;
1227 struct frame *mouse_face_frame = hlinfo->mouse_face_mouse_frame;
41ad069b 1228
7ccd1daf
EZ
1229 if (display_info->termscript)
1230 fprintf (display_info->termscript, "\n\n<UPDATE_BEGIN");
1231
4d7e6e51 1232 block_input ();
41ad069b 1233
b9f80d41 1234 if (f && f == mouse_face_frame)
41ad069b
EZ
1235 {
1236 /* Don't do highlighting for mouse motion during the update. */
34574c02 1237 hlinfo->mouse_face_defer = 1;
41ad069b
EZ
1238
1239 /* If F needs to be redrawn, simply forget about any prior mouse
1240 highlighting. */
1241 if (FRAME_GARBAGED_P (f))
34574c02 1242 hlinfo->mouse_face_window = Qnil;
41ad069b
EZ
1243
1244 /* Can we tell that this update does not affect the window
1245 where the mouse highlight is? If so, no need to turn off.
48c14970
EZ
1246 Likewise, don't do anything if none of the enabled rows
1247 contains glyphs highlighted in mouse face. */
34574c02
EZ
1248 if (!NILP (hlinfo->mouse_face_window)
1249 && WINDOWP (hlinfo->mouse_face_window))
41ad069b 1250 {
34574c02 1251 struct window *w = XWINDOW (hlinfo->mouse_face_window);
41ad069b
EZ
1252 int i;
1253
8ccb9a54
EZ
1254 /* If the mouse highlight is in the window that was deleted
1255 (e.g., if it was popped by completion), clear highlight
1256 unconditionally. */
d3d50620 1257 if (NILP (w->buffer))
34574c02 1258 hlinfo->mouse_face_window = Qnil;
8ccb9a54
EZ
1259 else
1260 {
1261 for (i = 0; i < w->desired_matrix->nrows; ++i)
48c14970
EZ
1262 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
1263 && MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
8ccb9a54
EZ
1264 break;
1265 }
41ad069b 1266
d3d50620 1267 if (NILP (w->buffer) || i < w->desired_matrix->nrows)
34574c02 1268 clear_mouse_face (hlinfo);
41ad069b
EZ
1269 }
1270 }
b9f80d41 1271 else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
41ad069b
EZ
1272 {
1273 /* If the frame with mouse highlight was deleted, invalidate the
1274 highlight info. */
34574c02
EZ
1275 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
1276 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
1277 hlinfo->mouse_face_window = Qnil;
34574c02 1278 hlinfo->mouse_face_mouse_frame = NULL;
41ad069b
EZ
1279 }
1280
4d7e6e51 1281 unblock_input ();
f32d4091
KS
1282}
1283
71f65669 1284static void
41ad069b 1285IT_update_end (struct frame *f)
f32d4091 1286{
7ccd1daf
EZ
1287 struct tty_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1288
1289 if (dpyinfo->termscript)
1290 fprintf (dpyinfo->termscript, "\n<UPDATE_END\n");
34574c02 1291 dpyinfo->mouse_highlight.mouse_face_defer = 0;
41ad069b
EZ
1292}
1293
1294static void
1295IT_frame_up_to_date (struct frame *f)
1296{
0c3cfc51
EZ
1297 Lisp_Object new_cursor, frame_desired_cursor;
1298 struct window *sw;
41ad069b 1299
5c747675 1300 FRAME_MOUSE_UPDATE (f);
41ad069b 1301
0c3cfc51
EZ
1302 /* Set the cursor type to whatever they wanted. In a minibuffer
1303 window, we want the cursor to appear only if we are reading input
1304 from this window, and we want the cursor to be taken from the
1305 frame parameters. For the selected window, we use either its
1306 buffer-local value or the value from the frame parameters if the
1307 buffer doesn't define its local value for the cursor type. */
e69b0960
DA
1308 sw = XWINDOW (f->selected_window);
1309 frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
0c3cfc51
EZ
1310 if (cursor_in_echo_area
1311 && FRAME_HAS_MINIBUF_P (f)
1312 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
1313 && sw == XWINDOW (echo_area_window))
1314 new_cursor = frame_desired_cursor;
1315 else
1316 {
d3d50620 1317 struct buffer *b = XBUFFER (sw->buffer);
0c3cfc51 1318
4b4deea2 1319 if (EQ (BVAR (b,cursor_type), Qt))
0c3cfc51 1320 new_cursor = frame_desired_cursor;
4b4deea2 1321 else if (NILP (BVAR (b, cursor_type))) /* nil means no cursor */
0c3cfc51
EZ
1322 new_cursor = Fcons (Qbar, make_number (0));
1323 else
4b4deea2 1324 new_cursor = BVAR (b, cursor_type);
0c3cfc51
EZ
1325 }
1326
1327 IT_set_cursor_type (f, new_cursor);
8ba01a32 1328
41ad069b 1329 IT_cmgoto (f); /* position cursor when update is done */
f32d4091 1330}
1b94449f 1331
c77f6f1b
EZ
1332/* Copy LEN glyphs displayed on a single line whose vertical position
1333 is YPOS, beginning at horizontal position XFROM to horizontal
1334 position XTO, by moving blocks in the video memory. Used by
1335 functions that insert and delete glyphs. */
1336static void
1337IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
1338{
1339 /* The offsets of source and destination relative to the
53964682 1340 conventional memory selector. */
c77f6f1b
EZ
1341 int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary;
1342 int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary;
1343
1344 if (from == to || len <= 0)
1345 return;
1346
1347 _farsetsel (_dos_ds);
1348
1349 /* The source and destination might overlap, so we need to move
1350 glyphs non-destructively. */
1351 if (from > to)
1352 {
1353 for ( ; len; from += 2, to += 2, len--)
1354 _farnspokew (to, _farnspeekw (from));
1355 }
1356 else
1357 {
1358 from += (len - 1) * 2;
1359 to += (len - 1) * 2;
1360 for ( ; len; from -= 2, to -= 2, len--)
1361 _farnspokew (to, _farnspeekw (from));
1362 }
1363 if (screen_virtual_segment)
1364 dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X);
1365}
1366
1367/* Insert and delete glyphs. */
aa9ce936 1368static void
3a8ce822 1369IT_insert_glyphs (struct frame *f, struct glyph *start, int len)
aa9ce936 1370{
c77f6f1b
EZ
1371 int shift_by_width = screen_size_X - (new_pos_X + len);
1372
1373 /* Shift right the glyphs from the nominal cursor position to the
1374 end of this line. */
1375 IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
1376
1377 /* Now write the glyphs to be inserted. */
3e1944a3 1378 IT_write_glyphs (f, start, len);
aa9ce936
EZ
1379}
1380
1381static void
3a8ce822 1382IT_delete_glyphs (struct frame *f, int n)
aa9ce936 1383{
1088b922 1384 emacs_abort ();
aa9ce936
EZ
1385}
1386
211c7152 1387/* set-window-configuration on window.c needs this. */
3bb1f22f 1388void
3a8ce822 1389x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
3bb1f22f 1390{
211c7152
EZ
1391 set_menu_bar_lines (f, value, oldval);
1392}
3bb1f22f 1393
984f5aaa 1394/* This was copied from xfaces.c */
3bb1f22f 1395
984f5aaa
EZ
1396extern Lisp_Object Qbackground_color;
1397extern Lisp_Object Qforeground_color;
8ba01a32 1398Lisp_Object Qreverse;
211c7152 1399extern Lisp_Object Qtitle;
3bb1f22f 1400
48ffe371
RS
1401/* IT_set_terminal_modes is called when emacs is started,
1402 resumed, and whenever the screen is redrawn! */
f32d4091 1403
71f65669 1404static void
3e1944a3 1405IT_set_terminal_modes (struct terminal *term)
f32d4091 1406{
3e1944a3
EZ
1407 struct tty_display_info *tty;
1408
1409 /* If called with initial terminal, it's too early to do anything
1410 useful. */
1411 if (term->type == output_initial)
1412 return;
1413
1414 tty = term->display_info.tty;
1415
1416 if (tty->termscript)
1417 fprintf (tty->termscript, "\n<SET_TERM>");
f32d4091
KS
1418
1419 screen_size_X = ScreenCols ();
1420 screen_size_Y = ScreenRows ();
1421 screen_size = screen_size_X * screen_size_Y;
56e19ec4 1422
f32d4091
KS
1423 new_pos_X = new_pos_Y = 0;
1424 current_pos_X = current_pos_Y = -1;
1425
1426 if (term_setup_done)
1427 return;
1428 term_setup_done = 1;
56e19ec4 1429
f32d4091
KS
1430 startup_screen_size_X = screen_size_X;
1431 startup_screen_size_Y = screen_size_Y;
c9adab25 1432 startup_screen_attrib = ScreenAttrib;
f32d4091 1433
039274cf
EZ
1434 /* Is DOS/V (or any other RSIS software which relocates
1435 the screen) installed? */
1436 {
1437 unsigned short es_value;
1438 __dpmi_regs regs;
1439
1440 regs.h.ah = 0xfe; /* get relocated screen address */
1441 if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
1442 regs.x.es = (ScreenPrimary >> 4) & 0xffff;
1443 else if (screen_old_address) /* already switched to Japanese mode once */
1444 regs.x.es = (screen_old_address >> 4) & 0xffff;
1445 else
1446 regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
1447 regs.x.di = 0;
1448 es_value = regs.x.es;
1449 __dpmi_int (0x10, &regs);
1450
d1d5dc19 1451 if (regs.x.es != es_value)
039274cf 1452 {
d1d5dc19
EZ
1453 /* screen_old_address is only set if ScreenPrimary does NOT
1454 already point to the relocated buffer address returned by
1455 the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
1456 ScreenPrimary to that address at startup under DOS/V. */
891ef8f7 1457 if (regs.x.es != ((ScreenPrimary >> 4) & 0xffff))
d1d5dc19 1458 screen_old_address = ScreenPrimary;
039274cf
EZ
1459 screen_virtual_segment = regs.x.es;
1460 screen_virtual_offset = regs.x.di;
1461 ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
1462 }
1463 }
039274cf 1464
f32d4091
KS
1465 ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
1466 ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
1467
76ac1508 1468 bright_bg ();
f32d4091
KS
1469}
1470
48ffe371
RS
1471/* IT_reset_terminal_modes is called when emacs is
1472 suspended or killed. */
f32d4091 1473
71f65669 1474static void
3e1944a3 1475IT_reset_terminal_modes (struct terminal *term)
f32d4091 1476{
c9adab25
KH
1477 int display_row_start = (int) ScreenPrimary;
1478 int saved_row_len = startup_screen_size_X * 2;
56e19ec4 1479 int update_row_len = ScreenCols () * 2, current_rows = ScreenRows ();
c9adab25
KH
1480 int to_next_row = update_row_len;
1481 unsigned char *saved_row = startup_screen_buffer;
56e19ec4 1482 int cursor_pos_X = ScreenCols () - 1, cursor_pos_Y = ScreenRows () - 1;
3e1944a3 1483 struct tty_display_info *tty = term->display_info.tty;
c9adab25 1484
3e1944a3
EZ
1485 if (tty->termscript)
1486 fprintf (tty->termscript, "\n<RESET_TERM>");
f32d4091 1487
f32d4091
KS
1488 if (!term_setup_done)
1489 return;
56e19ec4 1490
c9adab25 1491 mouse_off ();
b36701cc
RS
1492
1493 /* Leave the video system in the same state as we found it,
1494 as far as the blink/bright-background bit is concerned. */
1495 maybe_enable_blinking ();
06b1ea13 1496
c9adab25
KH
1497 /* We have a situation here.
1498 We cannot just do ScreenUpdate(startup_screen_buffer) because
1499 the luser could have changed screen dimensions inside Emacs
1500 and failed (or didn't want) to restore them before killing
1501 Emacs. ScreenUpdate() uses the *current* screen dimensions and
1502 thus will happily use memory outside what was allocated for
1503 `startup_screen_buffer'.
1504 Thus we only restore as much as the current screen dimensions
1505 can hold, and clear the rest (if the saved screen is smaller than
1506 the current) with the color attribute saved at startup. The cursor
1507 is also restored within the visible dimensions. */
1508
1509 ScreenAttrib = startup_screen_attrib;
c9adab25 1510
06b1ea13
EZ
1511 /* Don't restore the screen if we are exiting less than 2 seconds
1512 after startup: we might be crashing, and the screen might show
1513 some vital clues to what's wrong. */
1514 if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
c9adab25 1515 {
06b1ea13 1516 ScreenClear ();
039274cf 1517 if (screen_virtual_segment)
06b1ea13
EZ
1518 dosv_refresh_virtual_screen (0, screen_size);
1519
1520 if (update_row_len > saved_row_len)
1521 update_row_len = saved_row_len;
1522 if (current_rows > startup_screen_size_Y)
1523 current_rows = startup_screen_size_Y;
1524
3e1944a3
EZ
1525 if (tty->termscript)
1526 fprintf (tty->termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
06b1ea13
EZ
1527 update_row_len / 2, current_rows);
1528
1529 while (current_rows--)
1530 {
1531 dosmemput (saved_row, update_row_len, display_row_start);
1532 if (screen_virtual_segment)
1533 dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
1534 update_row_len / 2);
1535 saved_row += saved_row_len;
1536 display_row_start += to_next_row;
1537 }
c9adab25
KH
1538 }
1539 if (startup_pos_X < cursor_pos_X)
1540 cursor_pos_X = startup_pos_X;
1541 if (startup_pos_Y < cursor_pos_Y)
1542 cursor_pos_Y = startup_pos_Y;
1543
1544 ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
1545 xfree (startup_screen_buffer);
3e1944a3 1546 startup_screen_buffer = NULL;
f32d4091
KS
1547
1548 term_setup_done = 0;
1549}
1550
71f65669 1551static void
3e1944a3 1552IT_set_terminal_window (struct frame *f, int foo)
f32d4091
KS
1553{
1554}
1555
20db1522 1556/* Remember the screen colors of the current frame, to serve as the
2d764c78 1557 default colors for newly-created frames. */
2d764c78
EZ
1558DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
1559 Smsdos_remember_default_colors, 1, 1, 0,
70da46c3 1560 doc: /* Remember the screen colors of the current frame. */)
5842a27b 1561 (Lisp_Object frame)
2d764c78 1562{
2d764c78
EZ
1563 struct frame *f;
1564
b7826503 1565 CHECK_FRAME (frame);
f12dae2f 1566 f = XFRAME (frame);
2d764c78 1567
ff12cd1d
EZ
1568 /* This function is called after applying default-frame-alist to the
1569 initial frame. At that time, if reverse-colors option was
1570 specified in default-frame-alist, it was already applied, and
f12dae2f
EZ
1571 frame colors are reversed. */
1572 initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f);
1573 initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f);
891ef8f7
EZ
1574
1575 return Qnil;
2d764c78
EZ
1576}
1577
f32d4091 1578void
3a8ce822 1579IT_set_frame_parameters (struct frame *f, Lisp_Object alist)
f32d4091
KS
1580{
1581 Lisp_Object tail;
56e19ec4 1582 int i, j, length = XINT (Flength (alist));
db722735 1583 Lisp_Object *parms
663e2b3f 1584 = (Lisp_Object *) alloca (length * word_size);
db722735 1585 Lisp_Object *values
663e2b3f 1586 = (Lisp_Object *) alloca (length * word_size);
2d764c78 1587 /* Do we have to reverse the foreground and background colors? */
e69b0960 1588 int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
2d764c78 1589 int redraw = 0, fg_set = 0, bg_set = 0;
56e19ec4 1590 unsigned long orig_fg, orig_bg;
3e1944a3 1591 struct tty_display_info *tty = FRAME_TTY (f);
2d764c78
EZ
1592
1593 /* If we are creating a new frame, begin with the original screen colors
1594 used for the initial frame. */
76ea4cc9 1595 if (!f->default_face_done_p
2d764c78
EZ
1596 && initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
1597 {
1598 FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
1599 FRAME_BACKGROUND_PIXEL (f) = initial_screen_colors[1];
f12dae2f 1600 init_frame_faces (f);
76ea4cc9 1601 f->default_face_done_p = 1;
2d764c78 1602 }
76ea4cc9
EZ
1603 orig_fg = reverse ? FRAME_BACKGROUND_PIXEL (f) : FRAME_FOREGROUND_PIXEL (f);
1604 orig_bg = reverse ? FRAME_FOREGROUND_PIXEL (f) : FRAME_BACKGROUND_PIXEL (f);
db722735
RS
1605
1606 /* Extract parm names and values into those vectors. */
1607 i = 0;
7d7bbefd 1608 for (tail = alist; CONSP (tail); tail = XCDR (tail))
f32d4091 1609 {
34348bd4 1610 Lisp_Object elt = XCAR (tail);
db722735 1611 parms[i] = Fcar (elt);
b7826503 1612 CHECK_SYMBOL (parms[i]);
db722735
RS
1613 values[i] = Fcdr (elt);
1614 i++;
1615 }
1616
2d764c78 1617 j = i;
db722735 1618
2d764c78
EZ
1619 for (i = 0; i < j; i++)
1620 {
1e21fe48
EZ
1621 Lisp_Object prop, val;
1622
1623 prop = parms[i];
1624 val = values[i];
2d764c78 1625
8ba01a32 1626 if (EQ (prop, Qreverse))
2d764c78
EZ
1627 reverse = EQ (val, Qt);
1628 }
546701f5 1629
76ea4cc9 1630 if (tty->termscript && reverse)
3e1944a3 1631 fprintf (tty->termscript, "<INVERSE-VIDEO>\n");
2d764c78
EZ
1632
1633 /* Now process the alist elements in reverse of specified order. */
db722735
RS
1634 for (i--; i >= 0; i--)
1635 {
76ea4cc9 1636 Lisp_Object prop, val;
1e21fe48
EZ
1637
1638 prop = parms[i];
1639 val = values[i];
f32d4091 1640
4e825084 1641 if (EQ (prop, Qforeground_color))
f32d4091 1642 {
76ea4cc9 1643 unsigned long new_color = load_color (f, NULL, val, reverse
2d764c78
EZ
1644 ? LFACE_BACKGROUND_INDEX
1645 : LFACE_FOREGROUND_INDEX);
3b620731
EZ
1646 if (new_color != FACE_TTY_DEFAULT_COLOR
1647 && new_color != FACE_TTY_DEFAULT_FG_COLOR
1648 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 1649 {
76ea4cc9
EZ
1650 if (!reverse)
1651 {
1652 FRAME_FOREGROUND_PIXEL (f) = new_color;
1653 /* Make sure the foreground of the default face for
1654 this frame is changed as well. */
1655 update_face_from_frame_parameter (f, Qforeground_color, val);
1656 fg_set = 1;
1657 if (tty->termscript)
1658 fprintf (tty->termscript, "<FGCOLOR %lu>\n", new_color);
1659 }
1660 else
1661 {
1662 FRAME_BACKGROUND_PIXEL (f) = new_color;
1663 update_face_from_frame_parameter (f, Qbackground_color, val);
1664 bg_set = 1;
1665 if (tty->termscript)
1666 fprintf (tty->termscript, "<BGCOLOR %lu>\n", new_color);
1667 }
f32d4091
KS
1668 redraw = 1;
1669 }
1670 }
4e825084 1671 else if (EQ (prop, Qbackground_color))
f32d4091 1672 {
76ea4cc9 1673 unsigned long new_color = load_color (f, NULL, val, reverse
2d764c78
EZ
1674 ? LFACE_FOREGROUND_INDEX
1675 : LFACE_BACKGROUND_INDEX);
3b620731
EZ
1676 if (new_color != FACE_TTY_DEFAULT_COLOR
1677 && new_color != FACE_TTY_DEFAULT_FG_COLOR
1678 && new_color != FACE_TTY_DEFAULT_BG_COLOR)
f32d4091 1679 {
76ea4cc9
EZ
1680 if (!reverse)
1681 {
1682 FRAME_BACKGROUND_PIXEL (f) = new_color;
1683 /* Make sure the background of the default face for
1684 this frame is changed as well. */
1685 bg_set = 1;
1686 update_face_from_frame_parameter (f, Qbackground_color, val);
1687 if (tty->termscript)
1688 fprintf (tty->termscript, "<BGCOLOR %lu>\n", new_color);
1689 }
1690 else
1691 {
1692 FRAME_FOREGROUND_PIXEL (f) = new_color;
1693 fg_set = 1;
1694 update_face_from_frame_parameter (f, Qforeground_color, val);
1695 if (tty->termscript)
1696 fprintf (tty->termscript, "<FGCOLOR %lu>\n", new_color);
1697 }
f32d4091
KS
1698 redraw = 1;
1699 }
1700 }
211c7152
EZ
1701 else if (EQ (prop, Qtitle))
1702 {
1703 x_set_title (f, val);
3e1944a3
EZ
1704 if (tty->termscript)
1705 fprintf (tty->termscript, "<TITLE: %s>\n", SDATA (val));
211c7152 1706 }
8ba01a32
EZ
1707 else if (EQ (prop, Qcursor_type))
1708 {
1709 IT_set_cursor_type (f, val);
3e1944a3
EZ
1710 if (tty->termscript)
1711 fprintf (tty->termscript, "<CTYPE: %s>\n",
891ef8f7
EZ
1712 EQ (val, Qbar)
1713 || EQ (val, Qhbar)
1714 || (CONSP (val) && (EQ (XCAR (val), Qbar)
1715 || EQ (XCAR (val), Qhbar)))
8ba01a32
EZ
1716 ? "bar" : "box");
1717 }
3e1944a3
EZ
1718 else if (EQ (prop, Qtty_type))
1719 {
1720 internal_terminal_init ();
1721 if (tty->termscript)
1722 fprintf (tty->termscript, "<TERM_INIT done, TTY_TYPE: %.*s>\n",
1723 SBYTES (val), SDATA (val));
1724 }
db722735 1725 store_frame_param (f, prop, val);
2d764c78 1726 }
db722735 1727
2d764c78
EZ
1728 /* If they specified "reverse", but not the colors, we need to swap
1729 the current frame colors. */
76ea4cc9 1730 if (reverse)
2d764c78
EZ
1731 {
1732 if (!fg_set)
1733 {
76ea4cc9
EZ
1734 FRAME_FOREGROUND_PIXEL (f) = orig_bg;
1735 update_face_from_frame_parameter (f, Qforeground_color,
1736 tty_color_name (f, orig_bg));
2d764c78
EZ
1737 redraw = 1;
1738 }
1739 if (!bg_set)
1740 {
76ea4cc9
EZ
1741 FRAME_BACKGROUND_PIXEL (f) = orig_fg;
1742 update_face_from_frame_parameter (f, Qbackground_color,
1743 tty_color_name (f, orig_fg));
2d764c78
EZ
1744 redraw = 1;
1745 }
f32d4091
KS
1746 }
1747
1748 if (redraw)
1749 {
2d764c78 1750 face_change_count++; /* forces xdisp.c to recompute basic faces */
5e617bc2 1751 if (f == SELECTED_FRAME ())
3bb1f22f 1752 redraw_frame (f);
f32d4091
KS
1753 }
1754}
1755
a7cf9151
EZ
1756extern void init_frame_faces (FRAME_PTR);
1757
f32d4091
KS
1758#endif /* !HAVE_X_WINDOWS */
1759
1760
48ffe371
RS
1761/* Do we need the internal terminal? */
1762
f32d4091 1763void
3a8ce822 1764internal_terminal_init (void)
f32d4091 1765{
2306a735 1766 static int init_needed = 1;
56e19ec4 1767 char *term = getenv ("TERM"), *colors;
5e617bc2 1768 struct frame *sf = SELECTED_FRAME ();
3e1944a3 1769 struct tty_display_info *tty;
f32d4091
KS
1770
1771#ifdef HAVE_X_WINDOWS
1772 if (!inhibit_window_system)
1773 return;
1774#endif
1775
3e1944a3
EZ
1776 /* If this is the initial terminal, we are done here. */
1777 if (sf->output_method == output_initial)
1778 return;
1779
f32d4091
KS
1780 internal_terminal
1781 = (!noninteractive) && term && !strcmp (term, "internal");
1782
f32d4091
KS
1783#ifndef HAVE_X_WINDOWS
1784 if (!internal_terminal || inhibit_window_system)
1785 {
2d764c78 1786 sf->output_method = output_termcap;
f32d4091
KS
1787 return;
1788 }
1789
3e1944a3 1790 tty = FRAME_TTY (sf);
15dbb4d6 1791 kset_window_system (current_kboard, Qpc);
f12dae2f 1792 sf->output_method = output_msdos_raw;
2306a735 1793 if (init_needed)
3e1944a3 1794 {
2306a735
EZ
1795 if (!tty->termscript && getenv ("EMACSTEST"))
1796 tty->termscript = fopen (getenv ("EMACSTEST"), "wt");
1797 if (tty->termscript)
1798 {
1799 time_t now = time (NULL);
1800 struct tm *tnow = localtime (&now);
1801 char tbuf[100];
3e1944a3 1802
2306a735
EZ
1803 strftime (tbuf, sizeof (tbuf) - 1, "%a %b %e %Y %H:%M:%S %Z", tnow);
1804 fprintf (tty->termscript, "\nEmacs session started at %s\n", tbuf);
1805 fprintf (tty->termscript, "=====================\n\n");
1806 }
3e1944a3 1807
2306a735 1808 Vinitial_window_system = Qpc;
23415acf 1809 Vwindow_system_version = make_number (24); /* RE Emacs version */
2306a735 1810 tty->terminal->type = output_msdos_raw;
039274cf 1811
2306a735
EZ
1812 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM
1813 address. */
1814 screen_old_address = 0;
039274cf 1815
2306a735
EZ
1816 /* Forget the stale screen colors as well. */
1817 initial_screen_colors[0] = initial_screen_colors[1] = -1;
2d764c78 1818
2306a735
EZ
1819 FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = 7; /* White */
1820 FRAME_FOREGROUND_PIXEL (SELECTED_FRAME ()) = 0; /* Black */
1821 bright_bg ();
1822 colors = getenv ("EMACSCOLORS");
1823 if (colors && strlen (colors) >= 2)
1824 {
1825 /* The colors use 4 bits each (we enable bright background). */
1826 if (isdigit (colors[0]))
1827 colors[0] -= '0';
1828 else if (isxdigit (colors[0]))
1829 colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
1830 if (colors[0] >= 0 && colors[0] < 16)
1831 FRAME_FOREGROUND_PIXEL (SELECTED_FRAME ()) = colors[0];
1832 if (isdigit (colors[1]))
1833 colors[1] -= '0';
1834 else if (isxdigit (colors[1]))
1835 colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
1836 if (colors[1] >= 0 && colors[1] < 16)
1837 FRAME_BACKGROUND_PIXEL (SELECTED_FRAME ()) = colors[1];
1838 }
34574c02 1839 the_only_display_info.mouse_highlight.mouse_face_mouse_frame = NULL;
34574c02
EZ
1840 the_only_display_info.mouse_highlight.mouse_face_beg_row =
1841 the_only_display_info.mouse_highlight.mouse_face_beg_col = -1;
1842 the_only_display_info.mouse_highlight.mouse_face_end_row =
1843 the_only_display_info.mouse_highlight.mouse_face_end_col = -1;
1844 the_only_display_info.mouse_highlight.mouse_face_face_id = DEFAULT_FACE_ID;
1845 the_only_display_info.mouse_highlight.mouse_face_window = Qnil;
1846 the_only_display_info.mouse_highlight.mouse_face_mouse_x =
1847 the_only_display_info.mouse_highlight.mouse_face_mouse_y = 0;
1848 the_only_display_info.mouse_highlight.mouse_face_defer = 0;
1849 the_only_display_info.mouse_highlight.mouse_face_hidden = 0;
2306a735
EZ
1850
1851 if (have_mouse) /* detected in dos_ttraw, which see */
1852 {
1853 have_mouse = 1; /* enable mouse */
1854 mouse_visible = 0;
1855 mouse_setup_buttons (mouse_button_count);
1856 tty->terminal->mouse_position_hook = &mouse_get_pos;
1857 mouse_init ();
1858 }
f32d4091 1859
2306a735
EZ
1860 if (tty->termscript && screen_size)
1861 fprintf (tty->termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
1862 screen_size_X, screen_size_Y);
f32d4091 1863
f12dae2f 1864 init_frame_faces (sf);
2306a735
EZ
1865 init_needed = 0;
1866 }
f32d4091
KS
1867#endif
1868}
1869
3e1944a3
EZ
1870void
1871initialize_msdos_display (struct terminal *term)
1872{
1873 term->rif = 0; /* we don't support window-based display */
1874 term->cursor_to_hook = term->raw_cursor_to_hook = IT_cursor_to;
1875 term->clear_to_end_hook = IT_clear_to_end;
1876 term->clear_frame_hook = IT_clear_screen;
1877 term->clear_end_of_line_hook = IT_clear_end_of_line;
1878 term->ins_del_lines_hook = 0;
1879 term->insert_glyphs_hook = IT_insert_glyphs;
1880 term->write_glyphs_hook = IT_write_glyphs;
1881 term->delete_glyphs_hook = IT_delete_glyphs;
1882 term->ring_bell_hook = IT_ring_bell;
1883 term->reset_terminal_modes_hook = IT_reset_terminal_modes;
1884 term->set_terminal_modes_hook = IT_set_terminal_modes;
1885 term->set_terminal_window_hook = IT_set_terminal_window;
1886 term->update_begin_hook = IT_update_begin;
1887 term->update_end_hook = IT_update_end;
1888 term->frame_up_to_date_hook = IT_frame_up_to_date;
1889 term->mouse_position_hook = 0; /* set later by dos_ttraw */
1890 term->frame_rehighlight_hook = 0;
1891 term->frame_raise_lower_hook = 0;
1892 term->set_vertical_scroll_bar_hook = 0;
1893 term->condemn_scroll_bars_hook = 0;
1894 term->redeem_scroll_bar_hook = 0;
1895 term->judge_scroll_bars_hook = 0;
1896 term->read_socket_hook = &tty_read_avail_input; /* from keyboard.c */
1897}
1898
3a8ce822
EZ
1899int
1900dos_get_saved_screen (char **screen, int *rows, int *cols)
f32d4091
KS
1901{
1902#ifndef HAVE_X_WINDOWS
1903 *screen = startup_screen_buffer;
1904 *cols = startup_screen_size_X;
1905 *rows = startup_screen_size_Y;
039274cf 1906 return *screen != (char *)0;
f32d4091
KS
1907#else
1908 return 0;
56e19ec4 1909#endif
f32d4091 1910}
3bb1f22f
RS
1911
1912#ifndef HAVE_X_WINDOWS
1913
1914/* We are not X, but we can emulate it well enough for our needs... */
1915void
1916check_x (void)
1917{
5e617bc2 1918 if (! FRAME_MSDOS_P (SELECTED_FRAME ()))
2d764c78 1919 error ("Not running under a window system");
3bb1f22f
RS
1920}
1921
1922#endif
1923
5063b150 1924\f
f32d4091
KS
1925/* ----------------------- Keyboard control ----------------------
1926 *
1927 * Keymaps reflect the following keyboard layout:
1928 *
1929 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
1930 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
1931 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
1932 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
1933 * SPACE
1934 */
1935
d1d5dc19
EZ
1936#define Ignore 0x0000
1937#define Normal 0x0000 /* normal key - alt changes scan-code */
1938#define FctKey 0x1000 /* func key if c == 0, else c */
1939#define Special 0x2000 /* func key even if c != 0 */
1940#define ModFct 0x3000 /* special if mod-keys, else 'c' */
1941#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
1942#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
1943#define Grey 0x6000 /* Grey keypad key */
1944
1945#define Alt 0x0100 /* alt scan-code */
1946#define Ctrl 0x0200 /* ctrl scan-code */
1947#define Shift 0x0400 /* shift scan-code */
1948
db9cd97a 1949static int extended_kbd; /* 101 (102) keyboard present. */
f32d4091 1950
d1d5dc19
EZ
1951struct kbd_translate {
1952 unsigned char sc;
1953 unsigned char ch;
1954 unsigned short code;
1955};
1956
f32d4091
KS
1957struct dos_keyboard_map
1958{
1959 char *unshifted;
1960 char *shifted;
1961 char *alt_gr;
d1d5dc19 1962 struct kbd_translate *translate_table;
f32d4091
KS
1963};
1964
1965
1966static struct dos_keyboard_map us_keyboard = {
1967/* 0 1 2 3 4 5 */
1968/* 01234567890123456789012345678901234567890 12345678901234 */
1969 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
1970/* 0123456789012345678901234567890123456789 012345678901234 */
1971 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
d1d5dc19
EZ
1972 0, /* no Alt-Gr key */
1973 0 /* no translate table */
f32d4091
KS
1974};
1975
1976static struct dos_keyboard_map fr_keyboard = {
1977/* 0 1 2 3 4 5 */
1978/* 012 3456789012345678901234567890123456789012345678901234 */
1979