1 /* MS-DOS specific C utilities.
2 Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Morten Welinder */
22 /* New display, keyboard, and mouse control by Kim F. Storm */
24 /* Note: some of the stuff here was taken from end of sysdep.c in demacs. */
32 #include <sys/param.h>
36 #include <sys/stat.h> /* for _fixpath */
39 #include <libc/dosio.h> /* for _USE_LFN */
45 #include "termhooks.h"
46 #include "dispextern.h"
53 /* #include <process.h> */
54 /* Damn that local process.h! Instead we can define P_WAIT ourselves. */
69 /* If other `malloc' than ours is used, force our `sbrk' behave like
70 Unix programs expect (resize memory blocks to keep them contiguous).
71 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
72 because that's what `gmalloc' expects to get. */
76 int _crt0_startup_flags
= _CRT0_FLAG_UNIX_SBRK
;
77 #else /* not REL_ALLOC */
78 int _crt0_startup_flags
= (_CRT0_FLAG_UNIX_SBRK
| _CRT0_FLAG_FILL_SBRK_MEMORY
);
79 #endif /* not REL_ALLOC */
80 #endif /* GNU_MALLOC */
82 #endif /* not SYSTEM_MALLOC */
83 #endif /* __DJGPP__ > 1 */
102 /* ------------------------ Mouse control ---------------------------
104 * Coordinates are in screen positions and zero based.
105 * Mouse buttons are numbered from left to right and also zero based.
108 int have_mouse
; /* 0: no, 1: enabled, -1: disabled */
109 static int mouse_visible
;
111 static int mouse_last_x
;
112 static int mouse_last_y
;
114 static int mouse_button_translate
[NUM_MOUSE_BUTTONS
];
115 static int mouse_button_count
;
122 if (have_mouse
> 0 && !mouse_visible
)
125 fprintf (termscript
, "<M_ON>");
127 int86 (0x33, ®s
, ®s
);
137 if (have_mouse
> 0 && mouse_visible
)
140 fprintf (termscript
, "<M_OFF>");
142 int86 (0x33, ®s
, ®s
);
154 fprintf (termscript
, "<M_XY=%dx%d>", x
, y
);
156 mouse_last_x
= regs
.x
.cx
= x
* 8;
157 mouse_last_y
= regs
.x
.dx
= y
* 8;
158 int86 (0x33, ®s
, ®s
);
162 mouse_pressed (b
, xp
, yp
)
167 if (b
>= mouse_button_count
)
170 regs
.x
.bx
= mouse_button_translate
[b
];
171 int86 (0x33, ®s
, ®s
);
173 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
174 return (regs
.x
.bx
!= 0);
178 mouse_released (b
, xp
, yp
)
183 if (b
>= mouse_button_count
)
186 regs
.x
.bx
= mouse_button_translate
[b
];
187 int86 (0x33, ®s
, ®s
);
189 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
190 return (regs
.x
.bx
!= 0);
194 mouse_get_xy (int *x
, int *y
)
199 int86 (0x33, ®s
, ®s
);
205 mouse_get_pos (f
, insist
, bar_window
, part
, x
, y
, time
)
208 Lisp_Object
*bar_window
, *x
, *y
;
209 enum scroll_bar_part
*part
;
216 int86 (0x33, ®s
, ®s
);
219 mouse_get_xy (&ix
, &iy
);
220 selected_frame
->mouse_moved
= 0;
221 *x
= make_number (ix
);
222 *y
= make_number (iy
);
223 *time
= event_timestamp ();
231 mouse_get_xy (&x
, &y
);
232 selected_frame
->mouse_moved
|= (x
!= mouse_last_x
|| y
!= mouse_last_y
);
243 fprintf (termscript
, "<M_INIT>");
246 int86 (0x33, ®s
, ®s
);
250 regs
.x
.dx
= 8 * (ScreenCols () - 1);
251 int86 (0x33, ®s
, ®s
);
255 regs
.x
.dx
= 8 * (ScreenRows () - 1);
256 int86 (0x33, ®s
, ®s
);
262 /* ------------------------- Screen control ----------------------
266 static int internal_terminal
= 0;
268 #ifndef HAVE_X_WINDOWS
269 extern unsigned char ScreenAttrib
;
270 static int screen_face
;
271 static int highlight
;
273 static int screen_size_X
;
274 static int screen_size_Y
;
275 static int screen_size
;
277 static int current_pos_X
;
278 static int current_pos_Y
;
279 static int new_pos_X
;
280 static int new_pos_Y
;
282 static void *startup_screen_buffer
;
283 static int startup_screen_size_X
;
284 static int startup_screen_size_Y
;
285 static int startup_pos_X
;
286 static int startup_pos_Y
;
287 static unsigned char startup_screen_attrib
;
289 static int term_setup_done
;
291 /* Similar to the_only_frame. */
292 struct x_output the_only_x_display
;
294 /* This is never dereferenced. */
295 Display
*x_current_display
;
298 #define SCREEN_SET_CURSOR() \
299 if (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y) \
300 ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X)
303 dos_direct_output (y
, x
, buf
, len
)
309 int t
= (int) ScreenPrimary
+ 2 * (x
+ y
* screen_size_X
);
312 dosmemput (buf
++, 1, t
);
318 /* Flash the screen as a substitute for BEEPs. */
322 do_visible_bell (xorattr
)
323 unsigned char xorattr
;
328 movl _ScreenPrimary,%%eax
335 xorb %%al,%%gs:(%%ebx)
351 : "m" (xorattr
), "g" (screen_size
)
352 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
356 ScreenVisualBell (void)
358 /* This creates an xor-mask that will swap the default fore- and
359 background colors. */
360 do_visible_bell (((the_only_x_display
.foreground_pixel
361 ^ the_only_x_display
.background_pixel
)
366 #ifndef HAVE_X_WINDOWS
368 /* Enable bright background colors. */
376 int86 (0x10, ®s
, ®s
);
379 /* Set the screen dimensions so that it can show no less than
380 ROWS x COLS frame. */
383 dos_set_window_size (rows
, cols
)
387 Lisp_Object video_mode
;
388 int video_mode_value
;
391 int current_rows
= ScreenRows (), current_cols
= ScreenCols ();
393 if (*rows
== current_rows
&& *cols
== current_cols
)
396 /* Do we have a VGA? */
398 int86 (0x10, ®s
, ®s
);
399 if (regs
.h
.al
== 0x1a && regs
.h
.bl
> 5 && regs
.h
.bl
< 13)
404 /* If the user specified a special video mode for these dimensions,
406 sprintf (video_name
, "screen-dimensions-%dx%d", *rows
, *cols
);
407 video_mode
= XSYMBOL (Fintern_soft (build_string (video_name
),
410 if (INTEGERP (video_mode
)
411 && (video_mode_value
= XINT (video_mode
)) > 0)
413 regs
.x
.ax
= video_mode_value
;
414 int86 (0x10, ®s
, ®s
);
418 /* Must hardware-reset the mouse, or else it won't update
419 its notion of screen dimensions for some non-standard
420 video modes. This is *painfully* slow... */
422 int86 (0x33, ®s
, ®s
);
426 /* Find one of the dimensions supported by standard EGA/VGA
427 which gives us at least the required dimensions. */
436 } std_dimension
[] = {
446 while (i
< sizeof (std_dimension
) / sizeof (std_dimension
[0]))
448 if (std_dimension
[i
].need_vga
<= have_vga
449 && std_dimension
[i
].rows
>= *rows
)
451 if (std_dimension
[i
].rows
!= current_rows
452 || *cols
!= current_cols
)
453 _set_screen_lines (std_dimension
[i
].rows
);
460 #else /* not __DJGPP__ > 1 */
462 else if (*rows
<= 25)
464 if (current_rows
!= 25 || current_cols
!= 80)
467 int86 (0x10, ®s
, ®s
);
470 int86 (0x10, ®s
, ®s
);
473 int86 (0x10, ®s
, ®s
);
475 int86 (0x10, ®s
, ®s
);
478 else if (*rows
<= 50)
479 if (have_vga
&& (current_rows
!= 50 || current_cols
!= 80)
480 || *rows
<= 43 && (current_rows
!= 43 || current_cols
!= 80))
483 int86 (0x10, ®s
, ®s
);
486 int86 (0x10, ®s
, ®s
);
489 int86 (0x10, ®s
, ®s
);
492 int86 (0x10, ®s
, ®s
);
494 #endif /* not __DJGPP__ > 1 */
502 /* Tell the caller what dimensions have been REALLY set. */
503 *rows
= ScreenRows ();
504 *cols
= ScreenCols ();
506 /* Enable bright background colors. */
510 /* If we write a character in the position where the mouse is,
511 the mouse cursor may need to be refreshed. */
521 mouse_get_xy (&x
, &y
);
522 if (y
!= new_pos_Y
|| x
< new_pos_X
)
538 union REGS inregs
, outregs
;
541 intdos (&inregs
, &outregs
);
546 IT_set_face (int face
)
549 extern struct face
*intern_face (/* FRAME_PTR, struct face * */);
551 if (face
== 1 || (face
== 0 && highlight
))
552 fp
= FRAME_MODE_LINE_FACE (foo
);
553 else if (face
<= 0 || face
>= FRAME_N_COMPUTED_FACES (foo
))
554 fp
= FRAME_DEFAULT_FACE (foo
);
556 fp
= intern_face (selected_frame
, FRAME_COMPUTED_FACES (foo
)[face
]);
558 fprintf (termscript
, "<FACE:%d:%d>", FACE_FOREGROUND (fp
), FACE_BACKGROUND (fp
));
560 ScreenAttrib
= (FACE_BACKGROUND (fp
) << 4) | FACE_FOREGROUND (fp
);
564 IT_write_glyphs (GLYPH
*str
, int len
)
568 unsigned char *buf
, *bp
;
570 if (len
== 0) return;
572 buf
= bp
= alloca (len
* 2);
576 newface
= FAST_GLYPH_FACE (*str
);
577 if (newface
!= screen_face
)
578 IT_set_face (newface
);
579 ch
= FAST_GLYPH_CHAR (*str
);
580 *bp
++ = (unsigned char)ch
;
581 *bp
++ = ScreenAttrib
;
584 fputc (ch
, termscript
);
589 dosmemput (buf
, 2 * len
,
590 (int)ScreenPrimary
+ 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
));
595 IT_clear_end_of_line (first_unused
)
602 fprintf (termscript
, "<CLR:EOL>");
603 i
= (j
= screen_size_X
- new_pos_X
) * 2;
604 spaces
= sp
= alloca (i
);
609 *sp
++ = ScreenAttrib
;
613 dosmemput (spaces
, i
,
614 (int)ScreenPrimary
+ 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
));
618 IT_clear_screen (void)
621 fprintf (termscript
, "<CLR:SCR>");
625 new_pos_X
= new_pos_Y
= 0;
629 IT_clear_to_end (void)
632 fprintf (termscript
, "<CLR:EOS>");
634 while (new_pos_Y
< screen_size_Y
) {
636 IT_clear_end_of_line (0);
642 IT_cursor_to (int y
, int x
)
645 fprintf (termscript
, "\n<XY=%dx%d>", x
, y
);
651 IT_reassert_line_highlight (new, vpos
)
655 IT_set_face (0); /* To possibly clear the highlighting. */
659 IT_change_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
661 highlight
= new_highlight
;
662 IT_set_face (0); /* To possibly clear the highlighting. */
663 IT_cursor_to (vpos
, 0);
664 IT_clear_end_of_line (first_unused_hpos
);
671 IT_set_face (0); /* To possibly clear the highlighting. */
680 /* This was more or less copied from xterm.c */
683 IT_set_menu_bar_lines (window
, n
)
687 struct window
*w
= XWINDOW (window
);
689 XSETFASTINT (w
->last_modified
, 0);
690 XSETFASTINT (w
->top
, XFASTINT (w
->top
) + n
);
691 XSETFASTINT (w
->height
, XFASTINT (w
->height
) - n
);
693 /* Handle just the top child in a vertical split. */
694 if (!NILP (w
->vchild
))
695 IT_set_menu_bar_lines (w
->vchild
, n
);
697 /* Adjust all children in a horizontal split. */
698 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
700 w
= XWINDOW (window
);
701 IT_set_menu_bar_lines (window
, n
);
705 /* IT_set_terminal_modes is called when emacs is started,
706 resumed, and whenever the screen is redrawn! */
709 IT_set_terminal_modes (void)
716 fprintf (termscript
, "\n<SET_TERM>");
719 screen_size_X
= ScreenCols ();
720 screen_size_Y
= ScreenRows ();
721 screen_size
= screen_size_X
* screen_size_Y
;
723 new_pos_X
= new_pos_Y
= 0;
724 current_pos_X
= current_pos_Y
= -1;
730 startup_screen_size_X
= screen_size_X
;
731 startup_screen_size_Y
= screen_size_Y
;
732 startup_screen_attrib
= ScreenAttrib
;
734 ScreenGetCursor (&startup_pos_Y
, &startup_pos_X
);
735 ScreenRetrieve (startup_screen_buffer
= xmalloc (screen_size
* 2));
738 fprintf (termscript
, "<SCREEN SAVED (dimensions=%dx%d)>\n",
739 screen_size_X
, screen_size_Y
);
744 /* IT_reset_terminal_modes is called when emacs is
745 suspended or killed. */
748 IT_reset_terminal_modes (void)
750 int display_row_start
= (int) ScreenPrimary
;
751 int saved_row_len
= startup_screen_size_X
* 2;
752 int update_row_len
= ScreenCols () * 2;
753 int current_rows
= ScreenRows ();
754 int to_next_row
= update_row_len
;
755 unsigned char *saved_row
= startup_screen_buffer
;
756 int cursor_pos_X
= ScreenCols () - 1;
757 int cursor_pos_Y
= ScreenRows () - 1;
760 fprintf (termscript
, "\n<RESET_TERM>");
764 if (!term_setup_done
)
769 /* We have a situation here.
770 We cannot just do ScreenUpdate(startup_screen_buffer) because
771 the luser could have changed screen dimensions inside Emacs
772 and failed (or didn't want) to restore them before killing
773 Emacs. ScreenUpdate() uses the *current* screen dimensions and
774 thus will happily use memory outside what was allocated for
775 `startup_screen_buffer'.
776 Thus we only restore as much as the current screen dimensions
777 can hold, and clear the rest (if the saved screen is smaller than
778 the current) with the color attribute saved at startup. The cursor
779 is also restored within the visible dimensions. */
781 ScreenAttrib
= startup_screen_attrib
;
784 if (update_row_len
> saved_row_len
)
785 update_row_len
= saved_row_len
;
786 if (current_rows
> startup_screen_size_Y
)
787 current_rows
= startup_screen_size_Y
;
790 fprintf (termscript
, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
791 update_row_len
/ 2, current_rows
);
793 while (current_rows
--)
795 dosmemput (saved_row
, update_row_len
, display_row_start
);
796 saved_row
+= saved_row_len
;
797 display_row_start
+= to_next_row
;
799 if (startup_pos_X
< cursor_pos_X
)
800 cursor_pos_X
= startup_pos_X
;
801 if (startup_pos_Y
< cursor_pos_Y
)
802 cursor_pos_Y
= startup_pos_Y
;
804 ScreenSetCursor (cursor_pos_Y
, cursor_pos_X
);
805 xfree (startup_screen_buffer
);
811 IT_set_terminal_window (void)
816 IT_set_frame_parameters (frame
, alist
)
822 extern unsigned long load_color ();
823 FRAME_PTR f
= (FRAME_PTR
) &the_only_frame
;
826 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
828 Lisp_Object elt
, prop
, val
;
833 CHECK_SYMBOL (prop
, 1);
835 if (EQ (prop
, intern ("foreground-color")))
837 unsigned long new_color
= load_color (f
, val
);
840 FRAME_FOREGROUND_PIXEL (f
) = new_color
;
843 fprintf (termscript
, "<FGCOLOR %d>\n", new_color
);
846 else if (EQ (prop
, intern ("background-color")))
848 unsigned long new_color
= load_color (f
, val
);
851 FRAME_BACKGROUND_PIXEL (f
) = new_color
;
854 fprintf (termscript
, "<BGCOLOR %d>\n", new_color
);
857 else if (EQ (prop
, intern ("menu-bar-lines")))
860 int old
= FRAME_MENU_BAR_LINES (the_only_frame
);
866 FRAME_MENU_BAR_LINES (f
) = new;
867 IT_set_menu_bar_lines (the_only_frame
.root_window
, new - old
);
873 recompute_basic_faces (f
);
874 Fredraw_frame (Fselected_frame ());
878 #endif /* !HAVE_X_WINDOWS */
881 /* Do we need the internal terminal? */
884 internal_terminal_init ()
886 char *term
= getenv ("TERM");
889 #ifdef HAVE_X_WINDOWS
890 if (!inhibit_window_system
)
895 = (!noninteractive
) && term
&& !strcmp (term
, "internal");
897 if (getenv ("EMACSTEST"))
898 termscript
= fopen (getenv ("EMACSTEST"), "wt");
900 #ifndef HAVE_X_WINDOWS
901 if (!internal_terminal
|| inhibit_window_system
)
903 the_only_frame
.output_method
= output_termcap
;
907 Vwindow_system
= intern ("pc");
908 Vwindow_system_version
= make_number (1);
910 bzero (&the_only_x_display
, sizeof the_only_x_display
);
911 the_only_x_display
.background_pixel
= 7; /* White */
912 the_only_x_display
.foreground_pixel
= 0; /* Black */
914 colors
= getenv ("EMACSCOLORS");
915 if (colors
&& strlen (colors
) >= 2)
917 /* The colors use 4 bits each (we enable bright background). */
918 if (isdigit (colors
[0]))
920 else if (isxdigit (colors
[0]))
921 colors
[0] -= (isupper (colors
[0]) ? 'A' : 'a') - 10;
922 if (colors
[0] >= 0 && colors
[0] < 16)
923 the_only_x_display
.foreground_pixel
= colors
[0];
924 if (isdigit (colors
[1]))
926 else if (isxdigit (colors
[1]))
927 colors
[1] -= (isupper (colors
[1]) ? 'A' : 'a') - 10;
928 if (colors
[1] >= 0 && colors
[1] < 16)
929 the_only_x_display
.background_pixel
= colors
[1];
931 the_only_x_display
.line_height
= 1;
932 the_only_frame
.output_data
.x
= &the_only_x_display
;
933 the_only_frame
.output_method
= output_msdos_raw
;
934 the_only_x_display
.font
= (XFontStruct
*)1; /* must *not* be zero */
936 init_frame_faces ((FRAME_PTR
) &the_only_frame
);
938 ring_bell_hook
= IT_ring_bell
;
939 write_glyphs_hook
= IT_write_glyphs
;
940 cursor_to_hook
= raw_cursor_to_hook
= IT_cursor_to
;
941 clear_to_end_hook
= IT_clear_to_end
;
942 clear_end_of_line_hook
= IT_clear_end_of_line
;
943 clear_frame_hook
= IT_clear_screen
;
944 change_line_highlight_hook
= IT_change_line_highlight
;
945 update_begin_hook
= IT_update_begin
;
946 update_end_hook
= IT_update_end
;
947 reassert_line_highlight_hook
= IT_reassert_line_highlight
;
949 /* These hooks are called by term.c without being checked. */
950 set_terminal_modes_hook
= IT_set_terminal_modes
;
951 reset_terminal_modes_hook
= IT_reset_terminal_modes
;
952 set_terminal_window_hook
= IT_set_terminal_window
;
956 dos_get_saved_screen (screen
, rows
, cols
)
961 #ifndef HAVE_X_WINDOWS
962 *screen
= startup_screen_buffer
;
963 *cols
= startup_screen_size_X
;
964 *rows
= startup_screen_size_Y
;
971 /* ----------------------- Keyboard control ----------------------
973 * Keymaps reflect the following keyboard layout:
975 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
976 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
977 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
978 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
982 static int extended_kbd
; /* 101 (102) keyboard present. */
984 struct dos_keyboard_map
992 static struct dos_keyboard_map us_keyboard
= {
994 /* 01234567890123456789012345678901234567890 12345678901234 */
995 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
996 /* 0123456789012345678901234567890123456789 012345678901234 */
997 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
998 0 /* no Alt-Gr key */
1001 static struct dos_keyboard_map fr_keyboard
= {
1003 /* 012 3456789012345678901234567890123456789012345678901234 */
1004 "ý&\82\",(-\8a_\80\85)= azertyuiop^$ qsdfghjklm\97* wxcvbnm;:! ",
1005 /* 0123456789012345678901234567890123456789012345678901234 */
1006 " 1234567890ø+ AZERTYUIOPù\9c QSDFGHJKLM%æ WXCVBN?./õ ",
1007 /* 01234567 89012345678901234567890123456789012345678901234 */
1011 static struct dos_keyboard_map dk_keyboard
= {
1013 /* 0123456789012345678901234567890123456789012345678901234 */
1014 "«1234567890+| qwertyuiop\86~ asdfghjkl\91\9b' zxcvbnm,.- ",
1015 /* 01 23456789012345678901234567890123456789012345678901234 */
1016 "õ!\"#$%&/()=?` QWERTYUIOP\8f^ ASDFGHJKL\92\9d* ZXCVBNM;:_ ",
1017 /* 0123456789012345678901234567890123456789012345678901234 */
1021 static struct keyboard_layout_list
1024 struct dos_keyboard_map
*keyboard_map
;
1025 } keyboard_layout_list
[] =
1032 static struct dos_keyboard_map
*keyboard
;
1033 static int keyboard_map_all
;
1036 dos_set_keyboard (code
, always
)
1042 /* Initialize to US settings, for countries that don't have their own. */
1043 keyboard
= keyboard_layout_list
[0].keyboard_map
;
1044 keyboard_map_all
= always
;
1045 dos_keyboard_layout
= 1;
1047 for (i
= 0; i
< (sizeof (keyboard_layout_list
)/sizeof (struct keyboard_layout_list
)); i
++)
1048 if (code
== keyboard_layout_list
[i
].country_code
)
1050 keyboard
= keyboard_layout_list
[i
].keyboard_map
;
1051 keyboard_map_all
= always
;
1052 dos_keyboard_layout
= code
;
1058 #define Ignore 0x0000
1059 #define Normal 0x0000 /* normal key - alt changes scan-code */
1060 #define FctKey 0x1000 /* func key if c == 0, else c */
1061 #define Special 0x2000 /* func key even if c != 0 */
1062 #define ModFct 0x3000 /* special if mod-keys, else 'c' */
1063 #define Map 0x4000 /* alt scan-code, map to unshift/shift key */
1064 #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
1065 #define Grey 0x6000 /* Grey keypad key */
1067 #define Alt 0x0100 /* alt scan-code */
1068 #define Ctrl 0x0200 /* ctrl scan-code */
1069 #define Shift 0x0400 /* shift scan-code */
1073 unsigned char char_code
; /* normal code */
1074 unsigned char meta_code
; /* M- code */
1075 unsigned char keypad_code
; /* keypad code */
1076 unsigned char editkey_code
; /* edit key */
1077 } keypad_translate_map
[] = {
1078 '0', '0', 0xb0, /* kp-0 */ 0x63, /* insert */
1079 '1', '1', 0xb1, /* kp-1 */ 0x57, /* end */
1080 '2', '2', 0xb2, /* kp-2 */ 0x54, /* down */
1081 '3', '3', 0xb3, /* kp-3 */ 0x56, /* next */
1082 '4', '4', 0xb4, /* kp-4 */ 0x51, /* left */
1083 '5', '5', 0xb5, /* kp-5 */ 0xb5, /* kp-5 */
1084 '6', '6', 0xb6, /* kp-6 */ 0x53, /* right */
1085 '7', '7', 0xb7, /* kp-7 */ 0x50, /* home */
1086 '8', '8', 0xb8, /* kp-8 */ 0x52, /* up */
1087 '9', '9', 0xb9, /* kp-9 */ 0x55, /* prior */
1088 '.', '-', 0xae, /* kp-decimal */ 0xff /* delete */
1093 unsigned char char_code
; /* normal code */
1094 unsigned char keypad_code
; /* keypad code */
1095 } grey_key_translate_map
[] = {
1096 '/', 0xaf, /* kp-decimal */
1097 '*', 0xaa, /* kp-multiply */
1098 '-', 0xad, /* kp-subtract */
1099 '+', 0xab, /* kp-add */
1100 '\r', 0x8d /* kp-enter */
1103 static unsigned short
1104 ibmpc_translate_map
[] =
1106 /* --------------- 00 to 0f --------------- */
1107 Normal
| 0xff, /* Ctrl Break + Alt-NNN */
1108 Alt
| ModFct
| 0x1b, /* Escape */
1109 Normal
| 1, /* '1' */
1110 Normal
| 2, /* '2' */
1111 Normal
| 3, /* '3' */
1112 Normal
| 4, /* '4' */
1113 Normal
| 5, /* '5' */
1114 Normal
| 6, /* '6' */
1115 Normal
| 7, /* '7' */
1116 Normal
| 8, /* '8' */
1117 Normal
| 9, /* '9' */
1118 Normal
| 10, /* '0' */
1119 Normal
| 11, /* '-' */
1120 Normal
| 12, /* '=' */
1121 Special
| 0x08, /* Backspace */
1122 ModFct
| 0x74, /* Tab/Backtab */
1124 /* --------------- 10 to 1f --------------- */
1137 ModFct
| 0x0d, /* Return */
1142 /* --------------- 20 to 2f --------------- */
1151 Map
| 40, /* '\'' */
1153 Ignore
, /* Left shift */
1154 Map
| 41, /* '\\' */
1160 /* --------------- 30 to 3f --------------- */
1167 Ignore
, /* Right shift */
1168 Grey
| 1, /* Grey * */
1170 Normal
| ' ', /* ' ' */
1171 Ignore
, /* Caps Lock */
1172 FctKey
| 0xbe, /* F1 */
1173 FctKey
| 0xbf, /* F2 */
1174 FctKey
| 0xc0, /* F3 */
1175 FctKey
| 0xc1, /* F4 */
1176 FctKey
| 0xc2, /* F5 */
1178 /* --------------- 40 to 4f --------------- */
1179 FctKey
| 0xc3, /* F6 */
1180 FctKey
| 0xc4, /* F7 */
1181 FctKey
| 0xc5, /* F8 */
1182 FctKey
| 0xc6, /* F9 */
1183 FctKey
| 0xc7, /* F10 */
1184 Ignore
, /* Num Lock */
1185 Ignore
, /* Scroll Lock */
1186 KeyPad
| 7, /* Home */
1187 KeyPad
| 8, /* Up */
1188 KeyPad
| 9, /* Page Up */
1189 Grey
| 2, /* Grey - */
1190 KeyPad
| 4, /* Left */
1191 KeyPad
| 5, /* Keypad 5 */
1192 KeyPad
| 6, /* Right */
1193 Grey
| 3, /* Grey + */
1194 KeyPad
| 1, /* End */
1196 /* --------------- 50 to 5f --------------- */
1197 KeyPad
| 2, /* Down */
1198 KeyPad
| 3, /* Page Down */
1199 KeyPad
| 0, /* Insert */
1200 KeyPad
| 10, /* Delete */
1201 Shift
| FctKey
| 0xbe, /* (Shift) F1 */
1202 Shift
| FctKey
| 0xbf, /* (Shift) F2 */
1203 Shift
| FctKey
| 0xc0, /* (Shift) F3 */
1204 Shift
| FctKey
| 0xc1, /* (Shift) F4 */
1205 Shift
| FctKey
| 0xc2, /* (Shift) F5 */
1206 Shift
| FctKey
| 0xc3, /* (Shift) F6 */
1207 Shift
| FctKey
| 0xc4, /* (Shift) F7 */
1208 Shift
| FctKey
| 0xc5, /* (Shift) F8 */
1209 Shift
| FctKey
| 0xc6, /* (Shift) F9 */
1210 Shift
| FctKey
| 0xc7, /* (Shift) F10 */
1211 Ctrl
| FctKey
| 0xbe, /* (Ctrl) F1 */
1212 Ctrl
| FctKey
| 0xbf, /* (Ctrl) F2 */
1214 /* --------------- 60 to 6f --------------- */
1215 Ctrl
| FctKey
| 0xc0, /* (Ctrl) F3 */
1216 Ctrl
| FctKey
| 0xc1, /* (Ctrl) F4 */
1217 Ctrl
| FctKey
| 0xc2, /* (Ctrl) F5 */
1218 Ctrl
| FctKey
| 0xc3, /* (Ctrl) F6 */
1219 Ctrl
| FctKey
| 0xc4, /* (Ctrl) F7 */
1220 Ctrl
| FctKey
| 0xc5, /* (Ctrl) F8 */
1221 Ctrl
| FctKey
| 0xc6, /* (Ctrl) F9 */
1222 Ctrl
| FctKey
| 0xc7, /* (Ctrl) F10 */
1223 Alt
| FctKey
| 0xbe, /* (Alt) F1 */
1224 Alt
| FctKey
| 0xbf, /* (Alt) F2 */
1225 Alt
| FctKey
| 0xc0, /* (Alt) F3 */
1226 Alt
| FctKey
| 0xc1, /* (Alt) F4 */
1227 Alt
| FctKey
| 0xc2, /* (Alt) F5 */
1228 Alt
| FctKey
| 0xc3, /* (Alt) F6 */
1229 Alt
| FctKey
| 0xc4, /* (Alt) F7 */
1230 Alt
| FctKey
| 0xc5, /* (Alt) F8 */
1232 /* --------------- 70 to 7f --------------- */
1233 Alt
| FctKey
| 0xc6, /* (Alt) F9 */
1234 Alt
| FctKey
| 0xc7, /* (Alt) F10 */
1235 Ctrl
| FctKey
| 0x6d, /* (Ctrl) Sys Rq */
1236 Ctrl
| KeyPad
| 4, /* (Ctrl) Left */
1237 Ctrl
| KeyPad
| 6, /* (Ctrl) Right */
1238 Ctrl
| KeyPad
| 1, /* (Ctrl) End */
1239 Ctrl
| KeyPad
| 3, /* (Ctrl) Page Down */
1240 Ctrl
| KeyPad
| 7, /* (Ctrl) Home */
1241 Alt
| Map
| 1, /* '1' */
1242 Alt
| Map
| 2, /* '2' */
1243 Alt
| Map
| 3, /* '3' */
1244 Alt
| Map
| 4, /* '4' */
1245 Alt
| Map
| 5, /* '5' */
1246 Alt
| Map
| 6, /* '6' */
1247 Alt
| Map
| 7, /* '7' */
1248 Alt
| Map
| 8, /* '8' */
1250 /* --------------- 80 to 8f --------------- */
1251 Alt
| Map
| 9, /* '9' */
1252 Alt
| Map
| 10, /* '0' */
1253 Alt
| Map
| 11, /* '-' */
1254 Alt
| Map
| 12, /* '=' */
1255 Ctrl
| KeyPad
| 9, /* (Ctrl) Page Up */
1256 FctKey
| 0xc8, /* F11 */
1257 FctKey
| 0xc9, /* F12 */
1258 Shift
| FctKey
| 0xc8, /* (Shift) F11 */
1259 Shift
| FctKey
| 0xc9, /* (Shift) F12 */
1260 Ctrl
| FctKey
| 0xc8, /* (Ctrl) F11 */
1261 Ctrl
| FctKey
| 0xc9, /* (Ctrl) F12 */
1262 Alt
| FctKey
| 0xc8, /* (Alt) F11 */
1263 Alt
| FctKey
| 0xc9, /* (Alt) F12 */
1264 Ctrl
| KeyPad
| 8, /* (Ctrl) Up */
1265 Ctrl
| Grey
| 2, /* (Ctrl) Grey - */
1266 Ctrl
| KeyPad
| 5, /* (Ctrl) Keypad 5 */
1268 /* --------------- 90 to 9f --------------- */
1269 Ctrl
| Grey
| 3, /* (Ctrl) Grey + */
1270 Ctrl
| KeyPad
| 2, /* (Ctrl) Down */
1271 Ctrl
| KeyPad
| 0, /* (Ctrl) Insert */
1272 Ctrl
| KeyPad
| 10, /* (Ctrl) Delete */
1273 Ctrl
| FctKey
| 0x09, /* (Ctrl) Tab */
1274 Ctrl
| Grey
| 0, /* (Ctrl) Grey / */
1275 Ctrl
| Grey
| 1, /* (Ctrl) Grey * */
1276 Alt
| FctKey
| 0x50, /* (Alt) Home */
1277 Alt
| FctKey
| 0x52, /* (Alt) Up */
1278 Alt
| FctKey
| 0x55, /* (Alt) Page Up */
1279 Ignore
, /* NO KEY */
1280 Alt
| FctKey
| 0x51, /* (Alt) Left */
1281 Ignore
, /* NO KEY */
1282 Alt
| FctKey
| 0x53, /* (Alt) Right */
1283 Ignore
, /* NO KEY */
1284 Alt
| FctKey
| 0x57, /* (Alt) End */
1286 /* --------------- a0 to af --------------- */
1287 Alt
| KeyPad
| 2, /* (Alt) Down */
1288 Alt
| KeyPad
| 3, /* (Alt) Page Down */
1289 Alt
| KeyPad
| 0, /* (Alt) Insert */
1290 Alt
| KeyPad
| 10, /* (Alt) Delete */
1291 Alt
| Grey
| 0, /* (Alt) Grey / */
1292 Alt
| FctKey
| 0x09, /* (Alt) Tab */
1293 Alt
| Grey
| 4 /* (Alt) Keypad Enter */
1296 /* These bit-positions corresponds to values returned by BIOS */
1297 #define SHIFT_P 0x0003 /* two bits! */
1298 #define CTRL_P 0x0004
1299 #define ALT_P 0x0008
1300 #define SCRLOCK_P 0x0010
1301 #define NUMLOCK_P 0x0020
1302 #define CAPSLOCK_P 0x0040
1303 #define ALT_GR_P 0x0800
1304 #define SUPER_P 0x4000 /* pseudo */
1305 #define HYPER_P 0x8000 /* pseudo */
1308 dos_get_modifiers (keymask
)
1315 /* Calculate modifier bits */
1316 regs
.h
.ah
= extended_kbd
? 0x12 : 0x02;
1317 int86 (0x16, ®s
, ®s
);
1321 mask
= regs
.h
.al
& (SHIFT_P
| CTRL_P
| ALT_P
|
1322 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
1326 mask
= regs
.h
.al
& (SHIFT_P
|
1327 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
1329 /* Do not break international keyboard support. */
1330 /* When Keyb.Com is loaded, the right Alt key is */
1331 /* used for accessing characters like { and } */
1332 if (regs
.h
.ah
& 2) /* Left ALT pressed ? */
1335 if ((regs
.h
.ah
& 8) != 0) /* Right ALT pressed ? */
1338 if (dos_hyper_key
== 1)
1341 modifiers
|= hyper_modifier
;
1343 else if (dos_super_key
== 1)
1346 modifiers
|= super_modifier
;
1350 if (regs
.h
.ah
& 1) /* Left CTRL pressed ? */
1353 if (regs
.h
.ah
& 4) /* Right CTRL pressed ? */
1355 if (dos_hyper_key
== 2)
1358 modifiers
|= hyper_modifier
;
1360 else if (dos_super_key
== 2)
1363 modifiers
|= super_modifier
;
1371 modifiers
|= shift_modifier
;
1373 modifiers
|= ctrl_modifier
;
1375 modifiers
|= meta_modifier
;
1382 #define NUM_RECENT_DOSKEYS (100)
1383 int recent_doskeys_index
; /* Index for storing next element into recent_doskeys */
1384 int total_doskeys
; /* Total number of elements stored into recent_doskeys */
1385 Lisp_Object recent_doskeys
; /* A vector, holding the last 100 keystrokes */
1387 DEFUN ("recent-doskeys", Frecent_doskeys
, Srecent_doskeys
, 0, 0, 0,
1388 "Return vector of last 100 keyboard input values seen in dos_rawgetc.\n\
1389 Each input key receives two values in this vector: first the ASCII code,\n\
1390 and then the scan code.")
1393 Lisp_Object
*keys
= XVECTOR (recent_doskeys
)->contents
;
1396 if (total_doskeys
< NUM_RECENT_DOSKEYS
)
1397 return Fvector (total_doskeys
, keys
);
1400 val
= Fvector (NUM_RECENT_DOSKEYS
, keys
);
1401 bcopy (keys
+ recent_doskeys_index
,
1402 XVECTOR (val
)->contents
,
1403 (NUM_RECENT_DOSKEYS
- recent_doskeys_index
) * sizeof (Lisp_Object
));
1405 XVECTOR (val
)->contents
+ NUM_RECENT_DOSKEYS
- recent_doskeys_index
,
1406 recent_doskeys_index
* sizeof (Lisp_Object
));
1411 /* Get a char from keyboard. Function keys are put into the event queue. */
1416 struct input_event event
;
1419 #ifndef HAVE_X_WINDOWS
1420 SCREEN_SET_CURSOR ();
1421 if (!mouse_visible
) mouse_on ();
1424 /* The following condition is equivalent to `kbhit ()', except that
1425 it uses the bios to do its job. This pleases DESQview/X. */
1426 while ((regs
.h
.ah
= extended_kbd
? 0x11 : 0x01),
1427 int86 (0x16, ®s
, ®s
),
1428 (regs
.x
.flags
& 0x40) == 0)
1431 register unsigned char c
;
1432 int sc
, code
, mask
, kp_mode
;
1435 regs
.h
.ah
= extended_kbd
? 0x10 : 0x00;
1436 int86 (0x16, ®s
, ®s
);
1441 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
1443 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
1444 recent_doskeys_index
= 0;
1445 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
1447 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
1448 recent_doskeys_index
= 0;
1450 modifiers
= dos_get_modifiers (&mask
);
1452 #ifndef HAVE_X_WINDOWS
1453 if (!NILP (Vdos_display_scancodes
))
1456 sprintf (buf
, "%02x:%02x*%04x",
1457 (unsigned) (sc
&0xff), (unsigned) c
, mask
);
1458 dos_direct_output (screen_size_Y
- 2, screen_size_X
- 12, buf
, 10);
1466 case 10: /* Ctrl Grey Enter */
1467 code
= Ctrl
| Grey
| 4;
1469 case 13: /* Grey Enter */
1472 case '/': /* Grey / */
1482 if (sc
>= (sizeof (ibmpc_translate_map
) / sizeof (short)))
1484 if ((code
= ibmpc_translate_map
[sc
]) == Ignore
)
1491 modifiers
|= meta_modifier
;
1493 modifiers
|= ctrl_modifier
;
1495 modifiers
|= shift_modifier
;
1498 switch (code
& 0xf000)
1501 if (c
&& !(mask
& (SHIFT_P
| ALT_P
| CTRL_P
| HYPER_P
| SUPER_P
)))
1503 c
= 0; /* Special */
1516 if (c
== 0) /* ctrl-break */
1518 return c
; /* ALT-nnn */
1520 if (!keyboard_map_all
)
1529 if (c
&& !(mask
& ALT_P
) && !((mask
& SHIFT_P
) && (mask
& CTRL_P
)))
1530 if (!keyboard_map_all
)
1534 if (mask
& ALT_P
&& code
<= 10 && code
> 0 && dos_keypad_mode
& 0x200)
1535 mask
|= SHIFT_P
; /* ALT-1 => M-! etc. */
1539 code
= keyboard
->shifted
[code
];
1541 modifiers
&= ~shift_modifier
;
1544 if ((mask
& ALT_GR_P
) && keyboard
->alt_gr
&& keyboard
->alt_gr
[code
] != ' ')
1545 code
= keyboard
->alt_gr
[code
];
1547 code
= keyboard
->unshifted
[code
];
1552 if (c
== 0xe0) /* edit key */
1555 if ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) /* numlock on */
1556 kp_mode
= dos_keypad_mode
& 0x03;
1558 kp_mode
= (dos_keypad_mode
>> 4) & 0x03;
1563 if (code
== 10 && dos_decimal_point
)
1564 return dos_decimal_point
;
1565 return keypad_translate_map
[code
].char_code
;
1568 code
= 0xff00 | keypad_translate_map
[code
].keypad_code
;
1572 code
= keypad_translate_map
[code
].meta_code
;
1573 modifiers
= meta_modifier
;
1577 code
= 0xff00 | keypad_translate_map
[code
].editkey_code
;
1584 kp_mode
= ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) ? 0x04 : 0x40;
1585 if (dos_keypad_mode
& kp_mode
)
1586 code
= 0xff00 | grey_key_translate_map
[code
].keypad_code
;
1588 code
= grey_key_translate_map
[code
].char_code
;
1597 event
.kind
= non_ascii_keystroke
;
1599 event
.kind
= ascii_keystroke
;
1601 event
.modifiers
= modifiers
;
1602 XSETFRAME (event
.frame_or_window
, selected_frame
);
1603 event
.timestamp
= event_timestamp ();
1604 kbd_buffer_store_event (&event
);
1609 int but
, press
, x
, y
, ok
;
1611 /* Check for mouse movement *before* buttons. */
1612 mouse_check_moved ();
1614 for (but
= 0; but
< NUM_MOUSE_BUTTONS
; but
++)
1615 for (press
= 0; press
< 2; press
++)
1617 int button_num
= but
;
1620 ok
= mouse_pressed (but
, &x
, &y
);
1622 ok
= mouse_released (but
, &x
, &y
);
1625 /* Allow a simultaneous press/release of Mouse-1 and
1626 Mouse-2 to simulate Mouse-3 on two-button mice. */
1627 if (mouse_button_count
== 2 && but
< 2)
1629 int x2
, y2
; /* don't clobber original coordinates */
1631 /* If only one button is pressed, wait 100 msec and
1632 check again. This way, Speedy Gonzales isn't
1633 punished, while the slow get their chance. */
1634 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
1635 || !press
&& mouse_released (1-but
, &x2
, &y2
))
1640 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
1641 || !press
&& mouse_released (1-but
, &x2
, &y2
))
1646 event
.kind
= mouse_click
;
1647 event
.code
= button_num
;
1648 event
.modifiers
= dos_get_modifiers (0)
1649 | (press
? down_modifier
: up_modifier
);
1652 XSETFRAME (event
.frame_or_window
, selected_frame
);
1653 event
.timestamp
= event_timestamp ();
1654 kbd_buffer_store_event (&event
);
1662 static int prev_get_char
= -1;
1664 /* Return 1 if a key is ready to be read without suspending execution. */
1668 if (prev_get_char
!= -1)
1671 return ((prev_get_char
= dos_rawgetc ()) != -1);
1674 /* Read a key. Return -1 if no key is ready. */
1678 if (prev_get_char
!= -1)
1680 int c
= prev_get_char
;
1685 return dos_rawgetc ();
1688 #ifndef HAVE_X_WINDOWS
1689 /* See xterm.c for more info. */
1691 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
1693 register int pix_x
, pix_y
;
1694 register int *x
, *y
;
1695 void /* XRectangle */ *bounds
;
1698 if (bounds
) abort ();
1700 /* Ignore clipping. */
1707 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
1710 register int *pix_x
, *pix_y
;
1716 /* Simulation of X's menus. Nothing too fancy here -- just make it work
1719 Actually, I don't know the meaning of all the parameters of the functions
1720 here -- I only know how they are called by xmenu.c. I could of course
1721 grab the nearest Xlib manual (down the hall, second-to-last door on the
1722 left), but I don't think it's worth the effort. */
1729 menu
= (XMenu
*) xmalloc (sizeof (XMenu
));
1730 menu
->allocated
= menu
->count
= menu
->panecount
= menu
->width
= 0;
1734 /* Allocate some (more) memory for MENU ensuring that there is room for one
1738 IT_menu_make_room (XMenu
*menu
)
1740 if (menu
->allocated
== 0)
1742 int count
= menu
->allocated
= 10;
1743 menu
->text
= (char **) xmalloc (count
* sizeof (char *));
1744 menu
->submenu
= (XMenu
**) xmalloc (count
* sizeof (XMenu
*));
1745 menu
->panenumber
= (int *) xmalloc (count
* sizeof (int));
1747 else if (menu
->allocated
== menu
->count
)
1749 int count
= menu
->allocated
= menu
->allocated
+ 10;
1751 = (char **) xrealloc (menu
->text
, count
* sizeof (char *));
1753 = (XMenu
**) xrealloc (menu
->submenu
, count
* sizeof (XMenu
*));
1755 = (int *) xrealloc (menu
->panenumber
, count
* sizeof (int));
1759 /* Search the given menu structure for a given pane number. */
1762 IT_menu_search_pane (XMenu
*menu
, int pane
)
1767 for (i
= 0; i
< menu
->count
; i
++)
1768 if (menu
->submenu
[i
])
1770 if (pane
== menu
->panenumber
[i
])
1771 return menu
->submenu
[i
];
1772 if ((try = IT_menu_search_pane (menu
->submenu
[i
], pane
)))
1778 /* Determine how much screen space a given menu needs. */
1781 IT_menu_calc_size (XMenu
*menu
, int *width
, int *height
)
1783 int i
, h2
, w2
, maxsubwidth
, maxheight
;
1786 maxheight
= menu
->count
;
1787 for (i
= 0; i
< menu
->count
; i
++)
1789 if (menu
->submenu
[i
])
1791 IT_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
1792 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
1793 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
1796 *width
= menu
->width
+ maxsubwidth
;
1797 *height
= maxheight
;
1800 /* Display MENU at (X,Y) using FACES. */
1803 IT_menu_display (XMenu
*menu
, int y
, int x
, int *faces
)
1805 int i
, j
, face
, width
;
1809 int enabled
, mousehere
;
1812 width
= menu
->width
;
1813 text
= (GLYPH
*) xmalloc ((width
+ 2) * sizeof (GLYPH
));
1814 ScreenGetCursor (&row
, &col
);
1815 mouse_get_xy (&mx
, &my
);
1817 for (i
= 0; i
< menu
->count
; i
++)
1819 IT_cursor_to (y
+ i
, x
);
1821 = (!menu
->submenu
[i
] && menu
->panenumber
[i
]) || (menu
->submenu
[i
]);
1822 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ width
+ 2);
1823 face
= faces
[enabled
+ mousehere
* 2];
1825 *p
++ = FAST_MAKE_GLYPH (' ', face
);
1826 for (j
= 0, q
= menu
->text
[i
]; *q
; j
++)
1827 *p
++ = FAST_MAKE_GLYPH (*q
++, face
);
1828 for (; j
< width
; j
++)
1829 *p
++ = FAST_MAKE_GLYPH (' ', face
);
1830 *p
++ = FAST_MAKE_GLYPH (menu
->submenu
[i
] ? 16 : ' ', face
);
1831 IT_write_glyphs (text
, width
+ 2);
1834 IT_cursor_to (row
, col
);
1838 /* --------------------------- X Menu emulation ---------------------- */
1840 /* Report availability of menus. */
1848 /* Create a brand new menu structure. */
1851 XMenuCreate (Display
*foo1
, Window foo2
, char *foo3
)
1853 return IT_menu_create ();
1856 /* Create a new pane and place it on the outer-most level. It is not
1857 clear that it should be placed out there, but I don't know what else
1861 XMenuAddPane (Display
*foo
, XMenu
*menu
, char *txt
, int enable
)
1868 IT_menu_make_room (menu
);
1869 menu
->submenu
[menu
->count
] = IT_menu_create ();
1870 menu
->text
[menu
->count
] = txt
;
1871 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
1873 if ((len
= strlen (txt
)) > menu
->width
)
1875 return menu
->panecount
;
1878 /* Create a new item in a menu pane. */
1881 XMenuAddSelection (Display
*bar
, XMenu
*menu
, int pane
,
1882 int foo
, char *txt
, int enable
)
1887 if (!(menu
= IT_menu_search_pane (menu
, pane
)))
1889 IT_menu_make_room (menu
);
1890 menu
->submenu
[menu
->count
] = (XMenu
*) 0;
1891 menu
->text
[menu
->count
] = txt
;
1892 menu
->panenumber
[menu
->count
] = enable
;
1894 if ((len
= strlen (txt
)) > menu
->width
)
1899 /* Decide where the menu would be placed if requested at (X,Y). */
1902 XMenuLocate (Display
*foo0
, XMenu
*menu
, int foo1
, int foo2
, int x
, int y
,
1903 int *ulx
, int *uly
, int *width
, int *height
)
1905 IT_menu_calc_size (menu
, width
, height
);
1911 struct IT_menu_state
1913 void *screen_behind
;
1920 /* Display menu, wait for user's response, and return that response. */
1923 XMenuActivate (Display
*foo
, XMenu
*menu
, int *pane
, int *selidx
,
1924 int x0
, int y0
, unsigned ButtonMask
, char **txt
)
1926 struct IT_menu_state
*state
;
1930 int faces
[4], selectface
;
1931 int leave
, result
, onepane
;
1932 int title_faces
[4]; /* face to display the menu title */
1934 /* Just in case we got here without a mouse present... */
1935 if (have_mouse
<= 0)
1936 return XM_IA_SELECT
;
1938 state
= alloca (menu
->panecount
* sizeof (struct IT_menu_state
));
1939 screensize
= screen_size
* 2;
1941 = compute_glyph_face (&the_only_frame
,
1944 intern ("msdos-menu-passive-face")),
1947 = compute_glyph_face (&the_only_frame
,
1950 intern ("msdos-menu-active-face")),
1953 = face_name_id_number (&the_only_frame
, intern ("msdos-menu-select-face"));
1954 faces
[2] = compute_glyph_face (&the_only_frame
, selectface
, faces
[0]);
1955 faces
[3] = compute_glyph_face (&the_only_frame
, selectface
, faces
[1]);
1957 /* Make sure the menu title is always displayed with
1958 `msdos-menu-active-face', no matter where the mouse pointer is. */
1959 for (i
= 0; i
< 4; i
++)
1960 title_faces
[i
] = faces
[3];
1963 state
[0].menu
= menu
;
1965 ScreenRetrieve (state
[0].screen_behind
= xmalloc (screensize
));
1967 IT_menu_display (menu
, y0
- 1, x0
- 1, title_faces
); /* display menu title */
1968 if ((onepane
= menu
->count
== 1 && menu
->submenu
[0]))
1970 menu
->width
= menu
->submenu
[0]->width
;
1971 state
[0].menu
= menu
->submenu
[0];
1975 state
[0].menu
= menu
;
1977 state
[0].x
= x0
- 1;
1979 state
[0].pane
= onepane
;
1981 mouse_last_x
= -1; /* A hack that forces display. */
1985 if (!mouse_visible
) mouse_on ();
1986 mouse_check_moved ();
1987 if (selected_frame
->mouse_moved
)
1989 selected_frame
->mouse_moved
= 0;
1990 result
= XM_IA_SELECT
;
1991 mouse_get_xy (&x
, &y
);
1992 for (i
= 0; i
< statecount
; i
++)
1993 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
1995 int dy
= y
- state
[i
].y
;
1996 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
1998 if (!state
[i
].menu
->submenu
[dy
])
1999 if (state
[i
].menu
->panenumber
[dy
])
2000 result
= XM_SUCCESS
;
2002 result
= XM_IA_SELECT
;
2003 *pane
= state
[i
].pane
- 1;
2005 /* We hit some part of a menu, so drop extra menus that
2006 have been opened. That does not include an open and
2008 if (i
!= statecount
- 2
2009 || state
[i
].menu
->submenu
[dy
] != state
[i
+1].menu
)
2010 while (i
!= statecount
- 1)
2014 ScreenUpdate (state
[statecount
].screen_behind
);
2015 xfree (state
[statecount
].screen_behind
);
2017 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
2019 IT_menu_display (state
[i
].menu
,
2023 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
2024 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
2026 ScreenRetrieve (state
[statecount
].screen_behind
2027 = xmalloc (screensize
));
2029 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
2030 state
[statecount
].y
= y
;
2035 IT_menu_display (state
[statecount
- 1].menu
,
2036 state
[statecount
- 1].y
,
2037 state
[statecount
- 1].x
,
2040 for (b
= 0; b
< mouse_button_count
; b
++)
2042 (void) mouse_pressed (b
, &x
, &y
);
2043 if (mouse_released (b
, &x
, &y
))
2049 ScreenUpdate (state
[0].screen_behind
);
2050 while (statecount
--)
2051 xfree (state
[statecount
].screen_behind
);
2055 /* Dispose of a menu. */
2058 XMenuDestroy (Display
*foo
, XMenu
*menu
)
2061 if (menu
->allocated
)
2063 for (i
= 0; i
< menu
->count
; i
++)
2064 if (menu
->submenu
[i
])
2065 XMenuDestroy (foo
, menu
->submenu
[i
]);
2067 xfree (menu
->submenu
);
2068 xfree (menu
->panenumber
);
2074 x_pixel_width (struct frame
*f
)
2076 return FRAME_WIDTH (f
);
2080 x_pixel_height (struct frame
*f
)
2082 return FRAME_HEIGHT (f
);
2084 #endif /* !HAVE_X_WINDOWS */
2086 /* ----------------------- DOS / UNIX conversion --------------------- */
2088 /* Destructively turn backslashes into slashes. */
2091 dostounix_filename (p
)
2102 /* Destructively turn slashes into backslashes. */
2105 unixtodos_filename (p
)
2116 /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
2117 void msdos_downcase_filename (unsigned char *);
2120 getdefdir (drive
, dst
)
2124 char in_path
[4], *p
= in_path
;
2127 /* Generate "X:." (when drive is X) or "." (when drive is 0). */
2130 *p
++ = drive
+ 'A' - 1;
2137 _fixpath (in_path
, dst
);
2141 msdos_downcase_filename (dst
);
2147 /* Remove all CR's that are followed by a LF. */
2152 register unsigned char *buf
;
2154 unsigned char *np
= buf
;
2155 unsigned char *startp
= buf
;
2156 unsigned char *endp
= buf
+ n
;
2161 while (buf
< endp
- 1)
2165 if (*(++buf
) != 0x0a)
2176 #if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 0
2178 /* In DJGPP v2.0, library `write' can call `malloc', which might
2179 cause relocation of the buffer whose address we get in ADDR.
2180 Here is a version of `write' that avoids calling `malloc',
2181 to serve us until such time as the library is fixed.
2182 Actually, what we define here is called `__write', because
2183 `write' is a stub that just jmp's to `__write' (to be
2184 POSIXLY-correct with respect to the global name-space). */
2186 #include <io.h> /* for _write */
2187 #include <libc/dosio.h> /* for __file_handle_modes[] */
2189 static char xbuf
[64 * 1024]; /* DOS cannot write more in one chunk */
2191 #define XBUF_END (xbuf + sizeof (xbuf) - 1)
2194 __write (int handle
, const void *buffer
, size_t count
)
2199 if(__file_handle_modes
[handle
] & O_BINARY
)
2200 return _write (handle
, buffer
, count
);
2204 const char *bp
= buffer
;
2205 int total_written
= 0;
2206 int nmoved
= 0, ncr
= 0;
2210 /* The next test makes sure there's space for at least 2 more
2211 characters in xbuf[], so both CR and LF can be put there. */
2223 if (xbp
>= XBUF_END
|| !count
)
2225 size_t to_write
= nmoved
+ ncr
;
2226 int written
= _write (handle
, xbuf
, to_write
);
2231 total_written
+= nmoved
; /* CRs aren't counted in ret value */
2233 /* If some, but not all were written (disk full?), return
2234 an estimate of the total written bytes not counting CRs. */
2235 if (written
< to_write
)
2236 return total_written
- (to_write
- written
) * nmoved
/to_write
;
2243 return total_written
;
2247 #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */
2249 DEFUN ("msdos-long-file-names", Fmsdos_long_file_names
, Smsdos_long_file_names
,
2251 "Return non-nil if long file names are supported on MSDOS.")
2254 return (_USE_LFN
? Qt
: Qnil
);
2257 /* Convert alphabetic characters in a filename to lower-case. */
2260 msdos_downcase_filename (p
)
2261 register unsigned char *p
;
2263 /* Under LFN we expect to get pathnames in their true case. */
2264 if (NILP (Fmsdos_long_file_names ()))
2266 if (*p
>= 'A' && *p
<= 'Z')
2270 DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename
, Smsdos_downcase_filename
,
2272 "Convert alphabetic characters in FILENAME to lower case and return that.\n\
2273 When long filenames are supported, doesn't change FILENAME.\n\
2274 If FILENAME is not a string, returns nil.\n\
2275 The argument object is never altered--the value is a copy.")
2277 Lisp_Object filename
;
2282 if (! STRINGP (filename
))
2285 tem
= Fcopy_sequence (filename
);
2286 msdos_downcase_filename (XSTRING (tem
)->data
);
2290 /* The Emacs root directory as determined by init_environment. */
2292 static char emacsroot
[MAXPATHLEN
];
2295 rootrelativepath (rel
)
2298 static char result
[MAXPATHLEN
+ 10];
2300 strcpy (result
, emacsroot
);
2301 strcat (result
, "/");
2302 strcat (result
, rel
);
2306 /* Define a lot of environment variables if not already defined. Don't
2307 remove anything unless you know what you're doing -- lots of code will
2308 break if one or more of these are missing. */
2311 init_environment (argc
, argv
, skip_args
)
2319 /* Find our root from argv[0]. Assuming argv[0] is, say,
2320 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
2321 root
= alloca (MAXPATHLEN
+ 20);
2322 _fixpath (argv
[0], root
);
2324 len
= strlen (root
);
2325 while (len
> 0 && root
[len
] != '/' && root
[len
] != ':')
2328 if (len
> 4 && strcmp (root
+ len
- 4, "/bin") == 0)
2329 root
[len
- 4] = '\0';
2331 strcpy (root
, "c:/emacs"); /* Only under debuggers, I think. */
2332 len
= strlen (root
);
2333 strcpy (emacsroot
, root
);
2335 /* We default HOME to our root. */
2336 setenv ("HOME", root
, 0);
2338 /* We default EMACSPATH to root + "/bin". */
2339 strcpy (root
+ len
, "/bin");
2340 setenv ("EMACSPATH", root
, 0);
2342 /* I don't expect anybody to ever use other terminals so the internal
2343 terminal is the default. */
2344 setenv ("TERM", "internal", 0);
2346 #ifdef HAVE_X_WINDOWS
2347 /* Emacs expects DISPLAY to be set. */
2348 setenv ("DISPLAY", "unix:0.0", 0);
2351 /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
2352 downcase it and mirror the backslashes. */
2353 s
= getenv ("COMSPEC");
2354 if (!s
) s
= "c:/command.com";
2355 t
= alloca (strlen (s
) + 1);
2358 dostounix_filename (t
);
2359 setenv ("SHELL", t
, 0);
2361 /* PATH is also downcased and backslashes mirrored. */
2362 s
= getenv ("PATH");
2364 t
= alloca (strlen (s
) + 3);
2365 /* Current directory is always considered part of MsDos's path but it is
2366 not normally mentioned. Now it is. */
2367 strcat (strcpy (t
, ".;"), s
);
2369 dostounix_filename (t
); /* Not a single file name, but this should work. */
2370 setenv ("PATH", t
, 1);
2372 /* In some sense all dos users have root privileges, so... */
2373 setenv ("USER", "root", 0);
2374 setenv ("NAME", getenv ("USER"), 0);
2376 /* Time zone determined from country code. To make this possible, the
2377 country code may not span more than one time zone. In other words,
2378 in the USA, you lose. */
2380 switch (dos_country_code
)
2382 case 31: /* Belgium */
2383 case 32: /* The Netherlands */
2384 case 33: /* France */
2385 case 34: /* Spain */
2386 case 36: /* Hungary */
2387 case 38: /* Yugoslavia (or what's left of it?) */
2388 case 39: /* Italy */
2389 case 41: /* Switzerland */
2390 case 42: /* Tjekia */
2391 case 45: /* Denmark */
2392 case 46: /* Sweden */
2393 case 47: /* Norway */
2394 case 48: /* Poland */
2395 case 49: /* Germany */
2396 /* Daylight saving from last Sunday in March to last Sunday in
2397 September, both at 2AM. */
2398 setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
2400 case 44: /* United Kingdom */
2401 case 351: /* Portugal */
2402 case 354: /* Iceland */
2403 setenv ("TZ", "GMT+00", 0);
2405 case 81: /* Japan */
2406 case 82: /* Korea */
2407 setenv ("TZ", "JST-09", 0);
2409 case 90: /* Turkey */
2410 case 358: /* Finland */
2411 setenv ("TZ", "EET-02", 0);
2413 case 972: /* Israel */
2414 /* This is an approximation. (For exact rules, use the
2415 `zoneinfo/israel' file which comes with DJGPP, but you need
2416 to install it in `/usr/share/zoneinfo/' directory first.) */
2417 setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
2425 static int break_stat
; /* BREAK check mode status. */
2426 static int stdin_stat
; /* stdin IOCTL status. */
2430 /* These must be global. */
2431 static _go32_dpmi_seginfo ctrl_break_vector
;
2432 static _go32_dpmi_registers ctrl_break_regs
;
2433 static int ctrlbreakinstalled
= 0;
2435 /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
2438 ctrl_break_func (regs
)
2439 _go32_dpmi_registers
*regs
;
2445 install_ctrl_break_check ()
2447 if (!ctrlbreakinstalled
)
2449 /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
2450 was compiler with Djgpp 1.11 maintenance level 5 or later! */
2451 ctrlbreakinstalled
= 1;
2452 ctrl_break_vector
.pm_offset
= (int) ctrl_break_func
;
2453 _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector
,
2455 _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector
);
2459 #endif /* __DJGPP__ < 2 */
2461 /* Turn off Dos' Ctrl-C checking and inhibit interpretation of
2462 control chars by DOS. Determine the keyboard type. */
2467 union REGS inregs
, outregs
;
2468 static int first_time
= 1;
2470 break_stat
= getcbrk ();
2473 install_ctrl_break_check ();
2479 int86 (0x15, &inregs
, &outregs
);
2480 extended_kbd
= (!outregs
.x
.cflag
) && (outregs
.h
.ah
== 0);
2484 if (internal_terminal
2485 #ifdef HAVE_X_WINDOWS
2486 && inhibit_window_system
2490 inregs
.x
.ax
= 0x0021;
2491 int86 (0x33, &inregs
, &outregs
);
2492 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
2495 /* Reportedly, the above doesn't work for some mouse drivers. There
2496 is an additional detection method that should work, but might be
2497 a little slower. Use that as an alternative. */
2498 inregs
.x
.ax
= 0x0000;
2499 int86 (0x33, &inregs
, &outregs
);
2500 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
2505 have_mouse
= 1; /* enable mouse */
2508 if (outregs
.x
.bx
== 3)
2510 mouse_button_count
= 3;
2511 mouse_button_translate
[0] = 0; /* Left */
2512 mouse_button_translate
[1] = 2; /* Middle */
2513 mouse_button_translate
[2] = 1; /* Right */
2517 mouse_button_count
= 2;
2518 mouse_button_translate
[0] = 0;
2519 mouse_button_translate
[1] = 1;
2521 mouse_position_hook
= &mouse_get_pos
;
2530 stdin_stat
= setmode (fileno (stdin
), O_BINARY
);
2531 return (stdin_stat
!= -1);
2534 return (setmode (fileno (stdin
), O_BINARY
) != -1);
2536 #else /* __DJGPP__ < 2 */
2540 /* I think it is wrong to overwrite `stdin_stat' every time
2541 but the first one this function is called, but I don't
2542 want to change the way it used to work in v1.x.--EZ */
2544 inregs
.x
.ax
= 0x4400; /* Get IOCTL status. */
2545 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
2546 intdos (&inregs
, &outregs
);
2547 stdin_stat
= outregs
.h
.dl
;
2549 inregs
.x
.dx
= stdin_stat
| 0x0020; /* raw mode */
2550 inregs
.x
.ax
= 0x4401; /* Set IOCTL status */
2551 intdos (&inregs
, &outregs
);
2552 return !outregs
.x
.cflag
;
2554 #endif /* __DJGPP__ < 2 */
2557 /* Restore status of standard input and Ctrl-C checking. */
2562 union REGS inregs
, outregs
;
2564 setcbrk (break_stat
);
2569 return (setmode (fileno (stdin
), stdin_stat
) != -1);
2571 #else /* not __DJGPP__ >= 2 */
2573 inregs
.x
.ax
= 0x4401; /* Set IOCTL status. */
2574 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
2575 inregs
.x
.dx
= stdin_stat
;
2576 intdos (&inregs
, &outregs
);
2577 return !outregs
.x
.cflag
;
2579 #endif /* not __DJGPP__ >= 2 */
2583 /* Run command as specified by ARGV in directory DIR.
2584 The command is run with input from TEMPIN, output to
2585 file TEMPOUT and stderr to TEMPERR. */
2588 run_msdos_command (argv
, dir
, tempin
, tempout
, temperr
)
2589 unsigned char **argv
;
2591 int tempin
, tempout
, temperr
;
2593 char *saveargv1
, *saveargv2
, **envv
;
2594 char oldwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
2595 int msshell
, result
= -1;
2596 int in
, out
, inbak
, outbak
, errbak
;
2600 /* Get current directory as MSDOS cwd is not per-process. */
2603 cmd
= Ffile_name_nondirectory (build_string (argv
[0]));
2604 msshell
= !NILP (Fmember (cmd
, Fsymbol_value (intern ("msdos-shells"))))
2605 && !strcmp ("-c", argv
[1]);
2608 saveargv1
= argv
[1];
2609 saveargv2
= argv
[2];
2613 char *p
= alloca (strlen (argv
[2]) + 1);
2615 strcpy (argv
[2] = p
, saveargv2
);
2616 while (*p
&& isspace (*p
))
2618 while (*p
&& !isspace (*p
))
2626 /* Build the environment array. */
2628 extern Lisp_Object Vprocess_environment
;
2629 Lisp_Object tmp
, lst
;
2632 lst
= Vprocess_environment
;
2633 len
= XFASTINT (Flength (lst
));
2635 envv
= alloca ((len
+ 1) * sizeof (char *));
2636 for (i
= 0; i
< len
; i
++)
2640 CHECK_STRING (tmp
, 0);
2641 envv
[i
] = alloca (XSTRING (tmp
)->size
+ 1);
2642 strcpy (envv
[i
], XSTRING (tmp
)->data
);
2644 envv
[len
] = (char *) 0;
2648 chdir (XSTRING (dir
)->data
);
2652 if (inbak
< 0 || outbak
< 0 || errbak
< 0)
2653 goto done
; /* Allocation might fail due to lack of descriptors. */
2656 mouse_get_xy (&x
, &y
);
2658 dos_ttcooked (); /* do it here while 0 = stdin */
2666 if (msshell
&& !argv
[3])
2668 /* MS-DOS native shells are too restrictive. For starters, they
2669 cannot grok commands longer than 126 characters. In DJGPP v2
2670 and later, `system' is much smarter, so we'll call it instead. */
2672 extern char **environ
;
2675 /* A shell gets a single argument--its full command
2676 line--whose original was saved in `saveargv2'. */
2677 result
= system (saveargv2
);
2681 #endif /* __DJGPP__ > 1 */
2683 result
= spawnve (P_WAIT
, argv
[0], argv
, envv
);
2696 mouse_moveto (x
, y
);
2703 argv
[1] = saveargv1
;
2704 argv
[2] = saveargv2
;
2712 fprintf (stderr
, "%s not yet implemented\r\n", badfunc
);
2719 /* ------------------------- Compatibility functions -------------------
2724 /* Hostnames for a pc are not really funny,
2725 but they are used in change log so we emulate the best we can. */
2727 gethostname (p
, size
)
2731 char *q
= egetenv ("HOSTNAME");
2738 /* When time zones are set from Ms-Dos too many C-libraries are playing
2739 tricks with time values. We solve this by defining our own version
2740 of `gettimeofday' bypassing GO32. Our version needs to be initialized
2741 once and after each call to `tzset' with TZ changed. That is
2742 accomplished by aliasing tzset to init_gettimeofday. */
2744 static struct tm time_rec
;
2747 gettimeofday (struct timeval
*tp
, struct timezone
*tzp
)
2755 if (t
.ti_hour
< time_rec
.tm_hour
) /* midnight wrap */
2759 time_rec
.tm_year
= d
.da_year
- 1900;
2760 time_rec
.tm_mon
= d
.da_mon
- 1;
2761 time_rec
.tm_mday
= d
.da_day
;
2764 time_rec
.tm_hour
= t
.ti_hour
;
2765 time_rec
.tm_min
= t
.ti_min
;
2766 time_rec
.tm_sec
= t
.ti_sec
;
2769 tm
.tm_gmtoff
= dos_timezone_offset
;
2771 tp
->tv_sec
= mktime (&tm
); /* may modify tm */
2772 tp
->tv_usec
= t
.ti_hund
* (1000000 / 100);
2774 /* Ignore tzp; it's obsolescent. */
2778 #endif /* __DJGPP__ < 2 */
2781 * A list of unimplemented functions that we silently ignore.
2785 unsigned alarm (s
) unsigned s
; {}
2786 fork () { return 0; }
2787 int kill (x
, y
) int x
, y
; { return -1; }
2789 void volatile pause () {}
2790 sigsetmask (x
) int x
; { return 0; }
2794 setpgrp () {return 0; }
2795 setpriority (x
,y
,z
) int x
,y
,z
; { return 0; }
2796 sigblock (mask
) int mask
; { return 0; }
2797 unrequest_sigio () {}
2800 #include "sysselect.h"
2802 #ifndef EMACS_TIME_ZERO_OR_NEG_P
2803 #define EMACS_TIME_ZERO_OR_NEG_P(time) \
2804 ((long)(time).tv_sec < 0 \
2805 || ((time).tv_sec == 0 \
2806 && (long)(time).tv_usec <= 0))
2810 /* Only event queue is checked. */
2811 /* We don't have to call timer_check here
2812 because wait_reading_process_input takes care of that. */
2814 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
2816 SELECT_TYPE
*rfds
, *wfds
, *efds
;
2817 EMACS_TIME
*timeout
;
2825 check_input
= FD_ISSET (0, rfds
);
2836 /* If we are looking only for the terminal, with no timeout,
2837 just read it and wait -- that's more efficient. */
2840 while (!detect_input_pending ())
2849 EMACS_TIME clnow
, cllast
, cldiff
;
2852 EMACS_SET_SECS_USECS (cllast
, t
.ti_sec
, t
.ti_hund
* 10000L);
2854 while (!check_input
|| !detect_input_pending ())
2857 EMACS_SET_SECS_USECS (clnow
, t
.ti_sec
, t
.ti_hund
* 10000L);
2858 EMACS_SUB_TIME (cldiff
, clnow
, cllast
);
2860 /* When seconds wrap around, we assume that no more than
2861 1 minute passed since last `gettime'. */
2862 if (EMACS_TIME_NEG_P (cldiff
))
2863 EMACS_SET_SECS (cldiff
, EMACS_SECS (cldiff
) + 60);
2864 EMACS_SUB_TIME (*timeout
, *timeout
, cldiff
);
2866 /* Stop when timeout value crosses zero. */
2867 if (EMACS_TIME_ZERO_OR_NEG_P (*timeout
))
2882 * Define overlaid functions:
2884 * chdir -> sys_chdir
2885 * tzset -> init_gettimeofday
2886 * abort -> dos_abort
2891 extern int chdir ();
2897 int len
= strlen (path
);
2898 char *tmp
= (char *)path
;
2900 if (*tmp
&& tmp
[1] == ':')
2902 if (getdisk () != tolower (tmp
[0]) - 'a')
2903 setdisk (tolower (tmp
[0]) - 'a');
2904 tmp
+= 2; /* strip drive: KFS 1995-07-06 */
2908 if (len
> 1 && (tmp
[len
- 1] == '/'))
2910 char *tmp1
= (char *) alloca (len
+ 1);
2921 extern void tzset (void);
2924 init_gettimeofday ()
2930 ltm
= gtm
= time (NULL
);
2931 ltm
= mktime (lstm
= localtime (<m
));
2932 gtm
= mktime (gmtime (>m
));
2933 time_rec
.tm_hour
= 99; /* force gettimeofday to get date */
2934 time_rec
.tm_isdst
= lstm
->tm_isdst
;
2935 dos_timezone_offset
= time_rec
.tm_gmtoff
= (int)(gtm
- ltm
) / 60;
2942 dos_abort (file
, line
)
2946 char buffer1
[200], buffer2
[400];
2949 sprintf (buffer1
, "<EMACS FATAL ERROR IN %s LINE %d>", file
, line
);
2950 for (i
= j
= 0; buffer1
[i
]; i
++) {
2951 buffer2
[j
++] = buffer1
[i
];
2952 buffer2
[j
++] = 0x70;
2954 dosmemput (buffer2
, j
, (int)ScreenPrimary
);
2955 ScreenSetCursor (2, 0);
2963 ScreenSetCursor (10, 0);
2964 cputs ("\r\n\nEmacs aborted!\r\n");
2966 /* Generate traceback, so we could tell whodunit. */
2967 signal (SIGINT
, SIG_DFL
);
2968 __asm__
__volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
2976 recent_doskeys
= Fmake_vector (make_number (NUM_RECENT_DOSKEYS
), Qnil
);
2977 staticpro (&recent_doskeys
);
2979 defsubr (&Srecent_doskeys
);
2980 defsubr (&Smsdos_long_file_names
);
2981 defsubr (&Smsdos_downcase_filename
);