1 /* MS-DOS specific C utilities. -*- coding: raw-text -*-
2 Copyright (C) 1993, 1994, 1995, 1996, 1997 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 <string.h> /* for bzero and string functions */
37 #include <sys/stat.h> /* for _fixpath */
38 #include <unistd.h> /* for chdir, dup, dup2, etc. */
41 #include <io.h> /* for setmode */
42 #include <dpmi.h> /* for __dpmi_xxx stuff */
43 #include <sys/farptr.h> /* for _farsetsel, _farnspokeb */
44 #include <libc/dosio.h> /* for _USE_LFN */
45 #include <conio.h> /* for cputs */
51 #include "termhooks.h"
52 #include "dispextern.h"
61 /* #include <process.h> */
62 /* Damn that local process.h! Instead we can define P_WAIT ourselves. */
70 #define _dos_ds _go32_info_block.selector_for_linear_memory
76 #include "syssignal.h"
82 /* If other `malloc' than ours is used, force our `sbrk' behave like
83 Unix programs expect (resize memory blocks to keep them contiguous).
84 If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
85 because that's what `gmalloc' expects to get. */
89 int _crt0_startup_flags
= _CRT0_FLAG_UNIX_SBRK
;
90 #else /* not REL_ALLOC */
91 int _crt0_startup_flags
= (_CRT0_FLAG_UNIX_SBRK
| _CRT0_FLAG_FILL_SBRK_MEMORY
);
92 #endif /* not REL_ALLOC */
93 #endif /* GNU_MALLOC */
95 #endif /* not SYSTEM_MALLOC */
96 #endif /* __DJGPP__ > 1 */
115 /* ------------------------ Mouse control ---------------------------
117 * Coordinates are in screen positions and zero based.
118 * Mouse buttons are numbered from left to right and also zero based.
121 int have_mouse
; /* 0: no, 1: enabled, -1: disabled */
122 static int mouse_visible
;
124 static int mouse_last_x
;
125 static int mouse_last_y
;
127 static int mouse_button_translate
[NUM_MOUSE_BUTTONS
];
128 static int mouse_button_count
;
135 if (have_mouse
> 0 && !mouse_visible
)
138 fprintf (termscript
, "<M_ON>");
140 int86 (0x33, ®s
, ®s
);
150 if (have_mouse
> 0 && mouse_visible
)
153 fprintf (termscript
, "<M_OFF>");
155 int86 (0x33, ®s
, ®s
);
161 mouse_get_xy (int *x
, int *y
)
166 int86 (0x33, ®s
, ®s
);
178 fprintf (termscript
, "<M_XY=%dx%d>", x
, y
);
180 mouse_last_x
= regs
.x
.cx
= x
* 8;
181 mouse_last_y
= regs
.x
.dx
= y
* 8;
182 int86 (0x33, ®s
, ®s
);
186 mouse_pressed (b
, xp
, yp
)
191 if (b
>= mouse_button_count
)
194 regs
.x
.bx
= mouse_button_translate
[b
];
195 int86 (0x33, ®s
, ®s
);
197 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
198 return (regs
.x
.bx
!= 0);
202 mouse_released (b
, xp
, yp
)
207 if (b
>= mouse_button_count
)
210 regs
.x
.bx
= mouse_button_translate
[b
];
211 int86 (0x33, ®s
, ®s
);
213 *xp
= regs
.x
.cx
/ 8, *yp
= regs
.x
.dx
/ 8;
214 return (regs
.x
.bx
!= 0);
218 mouse_button_depressed (b
, xp
, yp
)
223 if (b
>= mouse_button_count
)
226 int86 (0x33, ®s
, ®s
);
227 if ((regs
.x
.bx
& (1 << mouse_button_translate
[b
])) != 0)
237 mouse_get_pos (f
, insist
, bar_window
, part
, x
, y
, time
)
240 Lisp_Object
*bar_window
, *x
, *y
;
241 enum scroll_bar_part
*part
;
245 Lisp_Object frame
, tail
;
247 /* Clear the mouse-moved flag for every frame on this display. */
248 FOR_EACH_FRAME (tail
, frame
)
249 XFRAME (frame
)->mouse_moved
= 0;
253 mouse_get_xy (&ix
, &iy
);
254 *time
= event_timestamp ();
255 *x
= make_number (mouse_last_x
= ix
);
256 *y
= make_number (mouse_last_y
= iy
);
264 mouse_get_xy (&x
, &y
);
265 selected_frame
->mouse_moved
|= (x
!= mouse_last_x
|| y
!= mouse_last_y
);
277 fprintf (termscript
, "<M_INIT>");
280 int86 (0x33, ®s
, ®s
);
282 /* Reset the mouse last press/release info. It seems that Windows
283 doesn't do that automatically when function 21h is called, which
284 causes Emacs to ``remember'' the click that switched focus to the
285 window just before Emacs was started from that window. */
286 for (b
= 0; b
< mouse_button_count
; b
++)
288 int dummy_x
, dummy_y
;
290 (void) mouse_pressed (b
, &dummy_x
, &dummy_y
);
291 (void) mouse_released (b
, &dummy_x
, &dummy_y
);
296 regs
.x
.dx
= 8 * (ScreenCols () - 1);
297 int86 (0x33, ®s
, ®s
);
301 regs
.x
.dx
= 8 * (ScreenRows () - 1);
302 int86 (0x33, ®s
, ®s
);
308 /* ------------------------- Screen control ----------------------
312 static int internal_terminal
= 0;
314 #ifndef HAVE_X_WINDOWS
315 extern unsigned char ScreenAttrib
;
316 static int screen_face
;
317 static int highlight
;
319 static int screen_size_X
;
320 static int screen_size_Y
;
321 static int screen_size
;
323 static int current_pos_X
;
324 static int current_pos_Y
;
325 static int new_pos_X
;
326 static int new_pos_Y
;
328 static void *startup_screen_buffer
;
329 static int startup_screen_size_X
;
330 static int startup_screen_size_Y
;
331 static int startup_pos_X
;
332 static int startup_pos_Y
;
333 static unsigned char startup_screen_attrib
;
335 static int term_setup_done
;
337 /* Similar to the_only_frame. */
338 struct x_output the_only_x_display
;
340 /* This is never dereferenced. */
341 Display
*x_current_display
;
343 /* Support for DOS/V (allows Japanese characters to be displayed on
344 standard, non-Japanese, ATs). Only supported for DJGPP v2 and later. */
346 /* Holds the address of the text-mode screen buffer. */
347 static unsigned long screen_old_address
= 0;
348 /* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
349 static unsigned short screen_virtual_segment
= 0;
350 static unsigned short screen_virtual_offset
= 0;
353 /* Update the screen from a part of relocated DOS/V screen buffer which
354 begins at OFFSET and includes COUNT characters. */
356 dosv_refresh_virtual_screen (int offset
, int count
)
360 if (offset
< 0 || count
< 0) /* paranoia; illegal values crash DOS/V */
363 regs
.h
.ah
= 0xff; /* update relocated screen */
364 regs
.x
.es
= screen_virtual_segment
;
365 regs
.x
.di
= screen_virtual_offset
+ offset
;
367 __dpmi_int (0x10, ®s
);
372 dos_direct_output (y
, x
, buf
, len
)
378 int t0
= 2 * (x
+ y
* screen_size_X
);
379 int t
= t0
+ (int) ScreenPrimary
;
384 dosmemput (buf
++, 1, t
);
388 /* This is faster. */
389 for (_farsetsel (_dos_ds
); --len
>= 0; t
+= 2, buf
++)
390 _farnspokeb (t
, *buf
);
392 if (screen_virtual_segment
)
393 dosv_refresh_virtual_screen (t0
, l0
);
398 /* Flash the screen as a substitute for BEEPs. */
402 do_visible_bell (xorattr
)
403 unsigned char xorattr
;
408 movl _ScreenPrimary,%%eax
415 xorb %%al,%%gs:(%%ebx)
431 : "m" (xorattr
), "g" (screen_size
)
432 : "%eax", "%ebx", /* "%gs",*/ "%ecx", "%edx");
436 ScreenVisualBell (void)
438 /* This creates an xor-mask that will swap the default fore- and
439 background colors. */
440 do_visible_bell (((the_only_x_display
.foreground_pixel
441 ^ the_only_x_display
.background_pixel
)
446 #ifndef HAVE_X_WINDOWS
448 static int blink_bit
= -1; /* the state of the blink bit at startup */
450 /* Enable bright background colors. */
456 /* Remember the original state of the blink/bright-background bit.
457 It is stored at 0040:0065h in the BIOS data area. */
459 blink_bit
= (_farpeekb (_dos_ds
, 0x465) & 0x20) == 0x20;
463 int86 (0x10, ®s
, ®s
);
466 /* Disable bright background colors (and enable blinking) if we found
467 the video system in that state at startup. */
469 maybe_enable_blinking (void)
477 int86 (0x10, ®s
, ®s
);
481 /* Set the screen dimensions so that it can show no less than
482 ROWS x COLS frame. */
485 dos_set_window_size (rows
, cols
)
489 Lisp_Object video_mode
;
490 int video_mode_value
;
493 int current_rows
= ScreenRows (), current_cols
= ScreenCols ();
495 if (*rows
== current_rows
&& *cols
== current_cols
)
498 /* Do we have a VGA? */
500 int86 (0x10, ®s
, ®s
);
501 if (regs
.h
.al
== 0x1a && regs
.h
.bl
> 5 && regs
.h
.bl
< 13)
506 /* If the user specified a special video mode for these dimensions,
508 sprintf (video_name
, "screen-dimensions-%dx%d", *rows
, *cols
);
509 video_mode
= XSYMBOL (Fintern_soft (build_string (video_name
),
512 if (INTEGERP (video_mode
)
513 && (video_mode_value
= XINT (video_mode
)) > 0)
515 regs
.x
.ax
= video_mode_value
;
516 int86 (0x10, ®s
, ®s
);
520 /* Must hardware-reset the mouse, or else it won't update
521 its notion of screen dimensions for some non-standard
522 video modes. This is *painfully* slow... */
524 int86 (0x33, ®s
, ®s
);
528 /* Find one of the dimensions supported by standard EGA/VGA
529 which gives us at least the required dimensions. */
538 } std_dimension
[] = {
548 while (i
< sizeof (std_dimension
) / sizeof (std_dimension
[0]))
550 if (std_dimension
[i
].need_vga
<= have_vga
551 && std_dimension
[i
].rows
>= *rows
)
553 if (std_dimension
[i
].rows
!= current_rows
554 || *cols
!= current_cols
)
555 _set_screen_lines (std_dimension
[i
].rows
);
562 #else /* not __DJGPP__ > 1 */
564 else if (*rows
<= 25)
566 if (current_rows
!= 25 || current_cols
!= 80)
569 int86 (0x10, ®s
, ®s
);
572 int86 (0x10, ®s
, ®s
);
575 int86 (0x10, ®s
, ®s
);
577 int86 (0x10, ®s
, ®s
);
580 else if (*rows
<= 50)
581 if (have_vga
&& (current_rows
!= 50 || current_cols
!= 80)
582 || *rows
<= 43 && (current_rows
!= 43 || current_cols
!= 80))
585 int86 (0x10, ®s
, ®s
);
588 int86 (0x10, ®s
, ®s
);
591 int86 (0x10, ®s
, ®s
);
594 int86 (0x10, ®s
, ®s
);
596 #endif /* not __DJGPP__ > 1 */
604 /* Tell the caller what dimensions have been REALLY set. */
605 *rows
= ScreenRows ();
606 *cols
= ScreenCols ();
608 /* Enable bright background colors. */
611 /* FIXME: I'm not sure the above will run at all on DOS/V. But let's
612 be defensive anyway. */
613 if (screen_virtual_segment
)
614 dosv_refresh_virtual_screen (0, *cols
* *rows
);
617 /* If we write a character in the position where the mouse is,
618 the mouse cursor may need to be refreshed. */
628 mouse_get_xy (&x
, &y
);
629 if (y
!= new_pos_Y
|| x
< new_pos_X
)
645 union REGS inregs
, outregs
;
648 intdos (&inregs
, &outregs
);
653 IT_set_face (int face
)
656 extern struct face
*intern_face (/* FRAME_PTR, struct face * */);
658 if (face
== 1 || (face
== 0 && highlight
))
659 fp
= FRAME_MODE_LINE_FACE (foo
);
660 else if (face
<= 0 || face
>= FRAME_N_COMPUTED_FACES (foo
))
661 fp
= FRAME_DEFAULT_FACE (foo
);
663 fp
= intern_face (selected_frame
, FRAME_COMPUTED_FACES (foo
)[face
]);
665 fprintf (termscript
, "<FACE %d: %d/%d>",
666 face
, FACE_FOREGROUND (fp
), FACE_BACKGROUND (fp
));
668 ScreenAttrib
= (FACE_BACKGROUND (fp
) << 4) | FACE_FOREGROUND (fp
);
672 IT_write_glyphs (GLYPH
*str
, int len
)
676 unsigned char *buf
, *bp
;
677 int offset
= 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
);
679 if (len
== 0) return;
681 buf
= bp
= alloca (len
* 2);
685 newface
= FAST_GLYPH_FACE (*str
);
686 if (newface
!= screen_face
)
687 IT_set_face (newface
);
688 ch
= FAST_GLYPH_CHAR (*str
);
689 *bp
++ = (unsigned char)ch
;
690 *bp
++ = ScreenAttrib
;
693 fputc (ch
, termscript
);
698 dosmemput (buf
, 2 * len
, (int)ScreenPrimary
+ offset
);
699 if (screen_virtual_segment
)
700 dosv_refresh_virtual_screen (offset
, len
);
705 IT_clear_end_of_line (int first_unused
)
709 int offset
= 2 * (new_pos_X
+ screen_size_X
* new_pos_Y
);
713 fprintf (termscript
, "<CLR:EOL>");
714 i
= (j
= screen_size_X
- new_pos_X
) * 2;
715 spaces
= sp
= alloca (i
);
720 *sp
++ = ScreenAttrib
;
724 dosmemput (spaces
, i
, (int)ScreenPrimary
+ offset
);
725 if (screen_virtual_segment
)
726 dosv_refresh_virtual_screen (offset
, i
/ 2);
730 IT_clear_screen (void)
733 fprintf (termscript
, "<CLR:SCR>");
737 if (screen_virtual_segment
)
738 dosv_refresh_virtual_screen (0, screen_size
);
739 new_pos_X
= new_pos_Y
= 0;
743 IT_clear_to_end (void)
746 fprintf (termscript
, "<CLR:EOS>");
748 while (new_pos_Y
< screen_size_Y
) {
750 IT_clear_end_of_line (0);
756 IT_cursor_to (int y
, int x
)
759 fprintf (termscript
, "\n<XY=%dx%d>", x
, y
);
764 static int cursor_cleared
;
767 IT_display_cursor (int on
)
769 if (on
&& cursor_cleared
)
771 ScreenSetCursor (current_pos_Y
, current_pos_X
);
774 else if (!on
&& !cursor_cleared
)
776 ScreenSetCursor (-1, -1);
781 /* Emacs calls cursor-movement functions a lot when it updates the
782 display (probably a legacy of old terminals where you cannot
783 update a screen line without first moving the cursor there).
784 However, cursor movement is expensive on MSDOS (it calls a slow
785 BIOS function and requires 2 mode switches), while actual screen
786 updates access the video memory directly and don't depend on
787 cursor position. To avoid slowing down the redisplay, we cheat:
788 all functions that move the cursor only set internal variables
789 which record the cursor position, whereas the cursor is only
790 moved to its final position whenever screen update is complete.
792 `IT_cmgoto' is called from the keyboard reading loop and when the
793 frame update is complete. This means that we are ready for user
794 input, so we update the cursor position to show where the point is,
795 and also make the mouse pointer visible.
797 Special treatment is required when the cursor is in the echo area,
798 to put the cursor at the end of the text displayed there. */
801 IT_cmgoto (FRAME_PTR f
)
803 /* Only set the cursor to where it should be if the display is
804 already in sync with the window contents. */
805 int update_cursor_pos
= MODIFF
== unchanged_modified
;
806 static int previous_pos_X
= -1;
808 /* If the display is in sync, forget any previous knowledge about
809 cursor position. This is primarily for unexpected events like
810 C-g in the minibuffer. */
811 if (update_cursor_pos
&& previous_pos_X
>= 0)
813 /* If we are in the echo area, put the cursor at the
814 end of the echo area message. */
815 if (!update_cursor_pos
816 && XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f
))->top
) <= new_pos_Y
)
818 int tem_X
= current_pos_X
, dummy
;
820 if (echo_area_glyphs
)
822 tem_X
= echo_area_glyphs_length
;
823 /* Save current cursor position, to be restored after the
824 echo area message is erased. Only remember one level
825 of previous cursor position. */
826 if (previous_pos_X
== -1)
827 ScreenGetCursor (&dummy
, &previous_pos_X
);
829 else if (previous_pos_X
>= 0)
831 /* We wind up here after the echo area message is erased.
832 Restore the cursor position we remembered above. */
833 tem_X
= previous_pos_X
;
837 if (current_pos_X
!= tem_X
)
840 update_cursor_pos
= 1;
844 if (update_cursor_pos
845 && (current_pos_X
!= new_pos_X
|| current_pos_Y
!= new_pos_Y
))
847 ScreenSetCursor (current_pos_Y
= new_pos_Y
, current_pos_X
= new_pos_X
);
849 fprintf (termscript
, "\n<CURSOR:%dx%d>", current_pos_X
, current_pos_Y
);
852 /* Maybe cursor is invisible, so make it visible. */
853 IT_display_cursor (1);
855 /* Mouse pointer should be always visible if we are waiting for
862 IT_reassert_line_highlight (int new, int vpos
)
865 IT_set_face (0); /* To possibly clear the highlighting. */
869 IT_change_line_highlight (int new_highlight
, int vpos
, int first_unused_hpos
)
871 highlight
= new_highlight
;
872 IT_set_face (0); /* To possibly clear the highlighting. */
873 IT_cursor_to (vpos
, 0);
874 IT_clear_end_of_line (first_unused_hpos
);
878 IT_update_begin (struct frame
*foo
)
881 IT_set_face (0); /* To possibly clear the highlighting. */
886 IT_update_end (struct frame
*foo
)
890 /* set-window-configuration on window.c needs this. */
892 x_set_menu_bar_lines (f
, value
, oldval
)
894 Lisp_Object value
, oldval
;
896 set_menu_bar_lines (f
, value
, oldval
);
899 /* This was copied from xfns.c */
901 Lisp_Object Qbackground_color
;
902 Lisp_Object Qforeground_color
;
903 extern Lisp_Object Qtitle
;
905 /* IT_set_terminal_modes is called when emacs is started,
906 resumed, and whenever the screen is redrawn! */
909 IT_set_terminal_modes (void)
912 fprintf (termscript
, "\n<SET_TERM>");
915 screen_size_X
= ScreenCols ();
916 screen_size_Y
= ScreenRows ();
917 screen_size
= screen_size_X
* screen_size_Y
;
919 new_pos_X
= new_pos_Y
= 0;
920 current_pos_X
= current_pos_Y
= -1;
926 startup_screen_size_X
= screen_size_X
;
927 startup_screen_size_Y
= screen_size_Y
;
928 startup_screen_attrib
= ScreenAttrib
;
931 /* Is DOS/V (or any other RSIS software which relocates
932 the screen) installed? */
934 unsigned short es_value
;
937 regs
.h
.ah
= 0xfe; /* get relocated screen address */
938 if (ScreenPrimary
== 0xb0000UL
|| ScreenPrimary
== 0xb8000UL
)
939 regs
.x
.es
= (ScreenPrimary
>> 4) & 0xffff;
940 else if (screen_old_address
) /* already switched to Japanese mode once */
941 regs
.x
.es
= (screen_old_address
>> 4) & 0xffff;
943 regs
.x
.es
= ScreenMode () == 7 ? 0xb000 : 0xb800;
945 es_value
= regs
.x
.es
;
946 __dpmi_int (0x10, ®s
);
948 if (regs
.x
.es
!= es_value
&& regs
.x
.es
!= (ScreenPrimary
>> 4) & 0xffff)
950 screen_old_address
= ScreenPrimary
;
951 screen_virtual_segment
= regs
.x
.es
;
952 screen_virtual_offset
= regs
.x
.di
;
953 ScreenPrimary
= (screen_virtual_segment
<< 4) + screen_virtual_offset
;
956 #endif /* __DJGPP__ > 1 */
958 ScreenGetCursor (&startup_pos_Y
, &startup_pos_X
);
959 ScreenRetrieve (startup_screen_buffer
= xmalloc (screen_size
* 2));
962 fprintf (termscript
, "<SCREEN SAVED (dimensions=%dx%d)>\n",
963 screen_size_X
, screen_size_Y
);
968 /* IT_reset_terminal_modes is called when emacs is
969 suspended or killed. */
972 IT_reset_terminal_modes (void)
974 int display_row_start
= (int) ScreenPrimary
;
975 int saved_row_len
= startup_screen_size_X
* 2;
976 int update_row_len
= ScreenCols () * 2;
977 int current_rows
= ScreenRows ();
978 int to_next_row
= update_row_len
;
979 unsigned char *saved_row
= startup_screen_buffer
;
980 int cursor_pos_X
= ScreenCols () - 1;
981 int cursor_pos_Y
= ScreenRows () - 1;
984 fprintf (termscript
, "\n<RESET_TERM>");
988 if (!term_setup_done
)
993 /* Leave the video system in the same state as we found it,
994 as far as the blink/bright-background bit is concerned. */
995 maybe_enable_blinking ();
997 /* We have a situation here.
998 We cannot just do ScreenUpdate(startup_screen_buffer) because
999 the luser could have changed screen dimensions inside Emacs
1000 and failed (or didn't want) to restore them before killing
1001 Emacs. ScreenUpdate() uses the *current* screen dimensions and
1002 thus will happily use memory outside what was allocated for
1003 `startup_screen_buffer'.
1004 Thus we only restore as much as the current screen dimensions
1005 can hold, and clear the rest (if the saved screen is smaller than
1006 the current) with the color attribute saved at startup. The cursor
1007 is also restored within the visible dimensions. */
1009 ScreenAttrib
= startup_screen_attrib
;
1011 if (screen_virtual_segment
)
1012 dosv_refresh_virtual_screen (0, screen_size
);
1014 if (update_row_len
> saved_row_len
)
1015 update_row_len
= saved_row_len
;
1016 if (current_rows
> startup_screen_size_Y
)
1017 current_rows
= startup_screen_size_Y
;
1020 fprintf (termscript
, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
1021 update_row_len
/ 2, current_rows
);
1023 while (current_rows
--)
1025 dosmemput (saved_row
, update_row_len
, display_row_start
);
1026 if (screen_virtual_segment
)
1027 dosv_refresh_virtual_screen (display_row_start
- ScreenPrimary
,
1028 update_row_len
/ 2);
1029 saved_row
+= saved_row_len
;
1030 display_row_start
+= to_next_row
;
1032 if (startup_pos_X
< cursor_pos_X
)
1033 cursor_pos_X
= startup_pos_X
;
1034 if (startup_pos_Y
< cursor_pos_Y
)
1035 cursor_pos_Y
= startup_pos_Y
;
1037 ScreenSetCursor (cursor_pos_Y
, cursor_pos_X
);
1038 xfree (startup_screen_buffer
);
1040 term_setup_done
= 0;
1044 IT_set_terminal_window (int foo
)
1049 IT_set_frame_parameters (f
, alist
)
1054 int length
= XINT (Flength (alist
));
1057 = (Lisp_Object
*) alloca (length
* sizeof (Lisp_Object
));
1059 = (Lisp_Object
*) alloca (length
* sizeof (Lisp_Object
));
1061 extern unsigned long load_color ();
1065 /* Extract parm names and values into those vectors. */
1067 for (tail
= alist
; CONSP (tail
); tail
= Fcdr (tail
))
1072 parms
[i
] = Fcar (elt
);
1073 CHECK_SYMBOL (parms
[i
], 1);
1074 values
[i
] = Fcdr (elt
);
1079 /* Now process them in reverse of specified order. */
1080 for (i
--; i
>= 0; i
--)
1082 Lisp_Object prop
= parms
[i
];
1083 Lisp_Object val
= values
[i
];
1085 if (EQ (prop
, Qforeground_color
))
1087 unsigned long new_color
= load_color (f
, val
);
1088 if (new_color
!= ~0)
1090 FRAME_FOREGROUND_PIXEL (f
) = new_color
;
1093 fprintf (termscript
, "<FGCOLOR %lu>\n", new_color
);
1096 else if (EQ (prop
, Qbackground_color
))
1098 unsigned long new_color
= load_color (f
, val
);
1099 if (new_color
!= ~0)
1101 FRAME_BACKGROUND_PIXEL (f
) = new_color
;
1104 fprintf (termscript
, "<BGCOLOR %lu>\n", new_color
);
1107 else if (EQ (prop
, Qtitle
))
1109 x_set_title (f
, val
);
1111 fprintf (termscript
, "<TITLE: %s>\n", XSTRING (val
)->data
);
1113 else if (EQ (prop
, intern ("reverse")) && EQ (val
, Qt
))
1115 unsigned long fg
= FRAME_FOREGROUND_PIXEL (f
);
1117 FRAME_FOREGROUND_PIXEL (f
) = FRAME_BACKGROUND_PIXEL (f
);
1118 FRAME_BACKGROUND_PIXEL (f
) = fg
;
1120 fprintf (termscript
, "<INVERSE-VIDEO>\n");
1122 store_frame_param (f
, prop
, val
);
1128 extern void recompute_basic_faces (FRAME_PTR
);
1129 extern void redraw_frame (FRAME_PTR
);
1131 recompute_basic_faces (f
);
1132 if (f
== selected_frame
)
1137 extern void init_frame_faces (FRAME_PTR
);
1139 #endif /* !HAVE_X_WINDOWS */
1142 /* Do we need the internal terminal? */
1145 internal_terminal_init ()
1147 char *term
= getenv ("TERM");
1150 #ifdef HAVE_X_WINDOWS
1151 if (!inhibit_window_system
)
1156 = (!noninteractive
) && term
&& !strcmp (term
, "internal");
1158 if (getenv ("EMACSTEST"))
1159 termscript
= fopen (getenv ("EMACSTEST"), "wt");
1161 #ifndef HAVE_X_WINDOWS
1162 if (!internal_terminal
|| inhibit_window_system
)
1164 selected_frame
->output_method
= output_termcap
;
1168 Vwindow_system
= intern ("pc");
1169 Vwindow_system_version
= make_number (1);
1171 /* If Emacs was dumped on DOS/V machine, forget the stale VRAM address. */
1172 screen_old_address
= 0;
1174 bzero (&the_only_x_display
, sizeof the_only_x_display
);
1175 the_only_x_display
.background_pixel
= 7; /* White */
1176 the_only_x_display
.foreground_pixel
= 0; /* Black */
1178 colors
= getenv ("EMACSCOLORS");
1179 if (colors
&& strlen (colors
) >= 2)
1181 /* The colors use 4 bits each (we enable bright background). */
1182 if (isdigit (colors
[0]))
1184 else if (isxdigit (colors
[0]))
1185 colors
[0] -= (isupper (colors
[0]) ? 'A' : 'a') - 10;
1186 if (colors
[0] >= 0 && colors
[0] < 16)
1187 the_only_x_display
.foreground_pixel
= colors
[0];
1188 if (isdigit (colors
[1]))
1190 else if (isxdigit (colors
[1]))
1191 colors
[1] -= (isupper (colors
[1]) ? 'A' : 'a') - 10;
1192 if (colors
[1] >= 0 && colors
[1] < 16)
1193 the_only_x_display
.background_pixel
= colors
[1];
1195 the_only_x_display
.line_height
= 1;
1196 the_only_x_display
.font
= (XFontStruct
*)1; /* must *not* be zero */
1198 init_frame_faces (selected_frame
);
1200 ring_bell_hook
= IT_ring_bell
;
1201 write_glyphs_hook
= IT_write_glyphs
;
1202 cursor_to_hook
= raw_cursor_to_hook
= IT_cursor_to
;
1203 clear_to_end_hook
= IT_clear_to_end
;
1204 clear_end_of_line_hook
= IT_clear_end_of_line
;
1205 clear_frame_hook
= IT_clear_screen
;
1206 change_line_highlight_hook
= IT_change_line_highlight
;
1207 update_begin_hook
= IT_update_begin
;
1208 update_end_hook
= IT_update_end
;
1209 reassert_line_highlight_hook
= IT_reassert_line_highlight
;
1210 frame_up_to_date_hook
= IT_cmgoto
; /* position cursor when update is done */
1212 /* These hooks are called by term.c without being checked. */
1213 set_terminal_modes_hook
= IT_set_terminal_modes
;
1214 reset_terminal_modes_hook
= IT_reset_terminal_modes
;
1215 set_terminal_window_hook
= IT_set_terminal_window
;
1219 dos_get_saved_screen (screen
, rows
, cols
)
1224 #ifndef HAVE_X_WINDOWS
1225 *screen
= startup_screen_buffer
;
1226 *cols
= startup_screen_size_X
;
1227 *rows
= startup_screen_size_Y
;
1228 return *screen
!= (char *)0;
1234 #ifndef HAVE_X_WINDOWS
1236 /* We are not X, but we can emulate it well enough for our needs... */
1240 if (! FRAME_MSDOS_P (selected_frame
))
1241 error ("Not running under a windows system");
1247 /* ----------------------- Keyboard control ----------------------
1249 * Keymaps reflect the following keyboard layout:
1251 * 0 1 2 3 4 5 6 7 8 9 10 11 12 BS
1252 * TAB 15 16 17 18 19 20 21 22 23 24 25 26 (41)
1253 * CLOK 30 31 32 33 34 35 36 37 38 39 40 (41) RET
1254 * SH () 45 46 47 48 49 50 51 52 53 54 SHIFT
1258 static int extended_kbd
; /* 101 (102) keyboard present. */
1260 struct dos_keyboard_map
1268 static struct dos_keyboard_map us_keyboard
= {
1270 /* 01234567890123456789012345678901234567890 12345678901234 */
1271 "`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
1272 /* 0123456789012345678901234567890123456789 012345678901234 */
1273 "~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
1274 0 /* no Alt-Gr key */
1277 static struct dos_keyboard_map fr_keyboard
= {
1279 /* 012 3456789012345678901234567890123456789012345678901234 */
1280 "ý&\82\",(-\8a_\80\85)= azertyuiop^$ qsdfghjklm\97* wxcvbnm;:! ",
1281 /* 0123456789012345678901234567890123456789012345678901234 */
1282 " 1234567890ø+ AZERTYUIOPù\9c QSDFGHJKLM%æ WXCVBN?./õ ",
1283 /* 01234567 89012345678901234567890123456789012345678901234 */
1288 * Italian keyboard support, country code 39.
1291 * added also {,},` as, respectively, AltGr-8, AltGr-9, AltGr-'
1292 * Donated by Stefano Brozzi <brozzis@mag00.cedi.unipr.it>
1294 static struct dos_keyboard_map it_keyboard
= {
1296 /* 0 123456789012345678901234567890123456789012345678901234 */
1297 "\\1234567890'\8d qwertyuiop\8a+ asdfghjkl\95\85\97 zxcvbnm,.- ",
1298 /* 01 23456789012345678901234567890123456789012345678901234 */
1299 "|!\"\9c$%&/()=?^ QWERTYUIOP\82* ASDFGHJKL\87øõ ZXCVBNM;:_ ",
1300 /* 0123456789012345678901234567890123456789012345678901234 */
1304 static struct dos_keyboard_map dk_keyboard
= {
1306 /* 0123456789012345678901234567890123456789012345678901234 */
1307 "«1234567890+| qwertyuiop\86~ asdfghjkl\91\9b' zxcvbnm,.- ",
1308 /* 01 23456789012345678901234567890123456789012345678901234 */
1309 "õ!\"#$%&/()=?` QWERTYUIOP\8f^ ASDFGHJKL\92\9d* ZXCVBNM;:_ ",
1310 /* 0123456789012345678901234567890123456789012345678901234 */
1314 static struct keyboard_layout_list
1317 struct dos_keyboard_map
*keyboard_map
;
1318 } keyboard_layout_list
[] =
1326 static struct dos_keyboard_map
*keyboard
;
1327 static int keyboard_map_all
;
1328 static int international_keyboard
;
1331 dos_set_keyboard (code
, always
)
1336 _go32_dpmi_registers regs
;
1338 /* See if Keyb.Com is installed (for international keyboard support).
1339 Note: calling Int 2Fh via int86 wedges the DOS box on some versions
1340 of Windows 9X! So don't do that! */
1342 regs
.x
.ss
= regs
.x
.sp
= regs
.x
.flags
= 0;
1343 _go32_dpmi_simulate_int (0x2f, ®s
);
1344 if (regs
.h
.al
== 0xff)
1345 international_keyboard
= 1;
1347 /* Initialize to US settings, for countries that don't have their own. */
1348 keyboard
= keyboard_layout_list
[0].keyboard_map
;
1349 keyboard_map_all
= always
;
1350 dos_keyboard_layout
= 1;
1352 for (i
= 0; i
< (sizeof (keyboard_layout_list
)/sizeof (struct keyboard_layout_list
)); i
++)
1353 if (code
== keyboard_layout_list
[i
].country_code
)
1355 keyboard
= keyboard_layout_list
[i
].keyboard_map
;
1356 keyboard_map_all
= always
;
1357 dos_keyboard_layout
= code
;
1363 #define Ignore 0x0000
1364 #define Normal 0x0000 /* normal key - alt changes scan-code */
1365 #define FctKey 0x1000 /* func key if c == 0, else c */
1366 #define Special 0x2000 /* func key even if c != 0 */
1367 #define ModFct 0x3000 /* special if mod-keys, else 'c' */
1368 #define Map 0x4000 /* alt scan-code, map to unshift/shift key */
1369 #define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
1370 #define Grey 0x6000 /* Grey keypad key */
1372 #define Alt 0x0100 /* alt scan-code */
1373 #define Ctrl 0x0200 /* ctrl scan-code */
1374 #define Shift 0x0400 /* shift scan-code */
1378 unsigned char char_code
; /* normal code */
1379 unsigned char meta_code
; /* M- code */
1380 unsigned char keypad_code
; /* keypad code */
1381 unsigned char editkey_code
; /* edit key */
1382 } keypad_translate_map
[] = {
1383 '0', '0', 0xb0, /* kp-0 */ 0x63, /* insert */
1384 '1', '1', 0xb1, /* kp-1 */ 0x57, /* end */
1385 '2', '2', 0xb2, /* kp-2 */ 0x54, /* down */
1386 '3', '3', 0xb3, /* kp-3 */ 0x56, /* next */
1387 '4', '4', 0xb4, /* kp-4 */ 0x51, /* left */
1388 '5', '5', 0xb5, /* kp-5 */ 0xb5, /* kp-5 */
1389 '6', '6', 0xb6, /* kp-6 */ 0x53, /* right */
1390 '7', '7', 0xb7, /* kp-7 */ 0x50, /* home */
1391 '8', '8', 0xb8, /* kp-8 */ 0x52, /* up */
1392 '9', '9', 0xb9, /* kp-9 */ 0x55, /* prior */
1393 '.', '-', 0xae, /* kp-decimal */ 0xff /* delete */
1398 unsigned char char_code
; /* normal code */
1399 unsigned char keypad_code
; /* keypad code */
1400 } grey_key_translate_map
[] = {
1401 '/', 0xaf, /* kp-decimal */
1402 '*', 0xaa, /* kp-multiply */
1403 '-', 0xad, /* kp-subtract */
1404 '+', 0xab, /* kp-add */
1405 '\r', 0x8d /* kp-enter */
1408 static unsigned short
1409 ibmpc_translate_map
[] =
1411 /* --------------- 00 to 0f --------------- */
1412 Normal
| 0xff, /* Ctrl Break + Alt-NNN */
1413 Alt
| ModFct
| 0x1b, /* Escape */
1414 Normal
| 1, /* '1' */
1415 Normal
| 2, /* '2' */
1416 Normal
| 3, /* '3' */
1417 Normal
| 4, /* '4' */
1418 Normal
| 5, /* '5' */
1419 Normal
| 6, /* '6' */
1420 Normal
| 7, /* '7' */
1421 Normal
| 8, /* '8' */
1422 Normal
| 9, /* '9' */
1423 Normal
| 10, /* '0' */
1424 Normal
| 11, /* '-' */
1425 Normal
| 12, /* '=' */
1426 Special
| 0x08, /* Backspace */
1427 ModFct
| 0x74, /* Tab/Backtab */
1429 /* --------------- 10 to 1f --------------- */
1442 ModFct
| 0x0d, /* Return */
1447 /* --------------- 20 to 2f --------------- */
1456 Map
| 40, /* '\'' */
1458 Ignore
, /* Left shift */
1459 Map
| 41, /* '\\' */
1465 /* --------------- 30 to 3f --------------- */
1472 Ignore
, /* Right shift */
1473 Grey
| 1, /* Grey * */
1475 Normal
| ' ', /* ' ' */
1476 Ignore
, /* Caps Lock */
1477 FctKey
| 0xbe, /* F1 */
1478 FctKey
| 0xbf, /* F2 */
1479 FctKey
| 0xc0, /* F3 */
1480 FctKey
| 0xc1, /* F4 */
1481 FctKey
| 0xc2, /* F5 */
1483 /* --------------- 40 to 4f --------------- */
1484 FctKey
| 0xc3, /* F6 */
1485 FctKey
| 0xc4, /* F7 */
1486 FctKey
| 0xc5, /* F8 */
1487 FctKey
| 0xc6, /* F9 */
1488 FctKey
| 0xc7, /* F10 */
1489 Ignore
, /* Num Lock */
1490 Ignore
, /* Scroll Lock */
1491 KeyPad
| 7, /* Home */
1492 KeyPad
| 8, /* Up */
1493 KeyPad
| 9, /* Page Up */
1494 Grey
| 2, /* Grey - */
1495 KeyPad
| 4, /* Left */
1496 KeyPad
| 5, /* Keypad 5 */
1497 KeyPad
| 6, /* Right */
1498 Grey
| 3, /* Grey + */
1499 KeyPad
| 1, /* End */
1501 /* --------------- 50 to 5f --------------- */
1502 KeyPad
| 2, /* Down */
1503 KeyPad
| 3, /* Page Down */
1504 KeyPad
| 0, /* Insert */
1505 KeyPad
| 10, /* Delete */
1506 Shift
| FctKey
| 0xbe, /* (Shift) F1 */
1507 Shift
| FctKey
| 0xbf, /* (Shift) F2 */
1508 Shift
| FctKey
| 0xc0, /* (Shift) F3 */
1509 Shift
| FctKey
| 0xc1, /* (Shift) F4 */
1510 Shift
| FctKey
| 0xc2, /* (Shift) F5 */
1511 Shift
| FctKey
| 0xc3, /* (Shift) F6 */
1512 Shift
| FctKey
| 0xc4, /* (Shift) F7 */
1513 Shift
| FctKey
| 0xc5, /* (Shift) F8 */
1514 Shift
| FctKey
| 0xc6, /* (Shift) F9 */
1515 Shift
| FctKey
| 0xc7, /* (Shift) F10 */
1516 Ctrl
| FctKey
| 0xbe, /* (Ctrl) F1 */
1517 Ctrl
| FctKey
| 0xbf, /* (Ctrl) F2 */
1519 /* --------------- 60 to 6f --------------- */
1520 Ctrl
| FctKey
| 0xc0, /* (Ctrl) F3 */
1521 Ctrl
| FctKey
| 0xc1, /* (Ctrl) F4 */
1522 Ctrl
| FctKey
| 0xc2, /* (Ctrl) F5 */
1523 Ctrl
| FctKey
| 0xc3, /* (Ctrl) F6 */
1524 Ctrl
| FctKey
| 0xc4, /* (Ctrl) F7 */
1525 Ctrl
| FctKey
| 0xc5, /* (Ctrl) F8 */
1526 Ctrl
| FctKey
| 0xc6, /* (Ctrl) F9 */
1527 Ctrl
| FctKey
| 0xc7, /* (Ctrl) F10 */
1528 Alt
| FctKey
| 0xbe, /* (Alt) F1 */
1529 Alt
| FctKey
| 0xbf, /* (Alt) F2 */
1530 Alt
| FctKey
| 0xc0, /* (Alt) F3 */
1531 Alt
| FctKey
| 0xc1, /* (Alt) F4 */
1532 Alt
| FctKey
| 0xc2, /* (Alt) F5 */
1533 Alt
| FctKey
| 0xc3, /* (Alt) F6 */
1534 Alt
| FctKey
| 0xc4, /* (Alt) F7 */
1535 Alt
| FctKey
| 0xc5, /* (Alt) F8 */
1537 /* --------------- 70 to 7f --------------- */
1538 Alt
| FctKey
| 0xc6, /* (Alt) F9 */
1539 Alt
| FctKey
| 0xc7, /* (Alt) F10 */
1540 Ctrl
| FctKey
| 0x6d, /* (Ctrl) Sys Rq */
1541 Ctrl
| KeyPad
| 4, /* (Ctrl) Left */
1542 Ctrl
| KeyPad
| 6, /* (Ctrl) Right */
1543 Ctrl
| KeyPad
| 1, /* (Ctrl) End */
1544 Ctrl
| KeyPad
| 3, /* (Ctrl) Page Down */
1545 Ctrl
| KeyPad
| 7, /* (Ctrl) Home */
1546 Alt
| Map
| 1, /* '1' */
1547 Alt
| Map
| 2, /* '2' */
1548 Alt
| Map
| 3, /* '3' */
1549 Alt
| Map
| 4, /* '4' */
1550 Alt
| Map
| 5, /* '5' */
1551 Alt
| Map
| 6, /* '6' */
1552 Alt
| Map
| 7, /* '7' */
1553 Alt
| Map
| 8, /* '8' */
1555 /* --------------- 80 to 8f --------------- */
1556 Alt
| Map
| 9, /* '9' */
1557 Alt
| Map
| 10, /* '0' */
1558 Alt
| Map
| 11, /* '-' */
1559 Alt
| Map
| 12, /* '=' */
1560 Ctrl
| KeyPad
| 9, /* (Ctrl) Page Up */
1561 FctKey
| 0xc8, /* F11 */
1562 FctKey
| 0xc9, /* F12 */
1563 Shift
| FctKey
| 0xc8, /* (Shift) F11 */
1564 Shift
| FctKey
| 0xc9, /* (Shift) F12 */
1565 Ctrl
| FctKey
| 0xc8, /* (Ctrl) F11 */
1566 Ctrl
| FctKey
| 0xc9, /* (Ctrl) F12 */
1567 Alt
| FctKey
| 0xc8, /* (Alt) F11 */
1568 Alt
| FctKey
| 0xc9, /* (Alt) F12 */
1569 Ctrl
| KeyPad
| 8, /* (Ctrl) Up */
1570 Ctrl
| Grey
| 2, /* (Ctrl) Grey - */
1571 Ctrl
| KeyPad
| 5, /* (Ctrl) Keypad 5 */
1573 /* --------------- 90 to 9f --------------- */
1574 Ctrl
| Grey
| 3, /* (Ctrl) Grey + */
1575 Ctrl
| KeyPad
| 2, /* (Ctrl) Down */
1576 Ctrl
| KeyPad
| 0, /* (Ctrl) Insert */
1577 Ctrl
| KeyPad
| 10, /* (Ctrl) Delete */
1578 Ctrl
| FctKey
| 0x09, /* (Ctrl) Tab */
1579 Ctrl
| Grey
| 0, /* (Ctrl) Grey / */
1580 Ctrl
| Grey
| 1, /* (Ctrl) Grey * */
1581 Alt
| FctKey
| 0x50, /* (Alt) Home */
1582 Alt
| FctKey
| 0x52, /* (Alt) Up */
1583 Alt
| FctKey
| 0x55, /* (Alt) Page Up */
1584 Ignore
, /* NO KEY */
1585 Alt
| FctKey
| 0x51, /* (Alt) Left */
1586 Ignore
, /* NO KEY */
1587 Alt
| FctKey
| 0x53, /* (Alt) Right */
1588 Ignore
, /* NO KEY */
1589 Alt
| FctKey
| 0x57, /* (Alt) End */
1591 /* --------------- a0 to af --------------- */
1592 Alt
| KeyPad
| 2, /* (Alt) Down */
1593 Alt
| KeyPad
| 3, /* (Alt) Page Down */
1594 Alt
| KeyPad
| 0, /* (Alt) Insert */
1595 Alt
| KeyPad
| 10, /* (Alt) Delete */
1596 Alt
| Grey
| 0, /* (Alt) Grey / */
1597 Alt
| FctKey
| 0x09, /* (Alt) Tab */
1598 Alt
| Grey
| 4 /* (Alt) Keypad Enter */
1601 /* These bit-positions corresponds to values returned by BIOS */
1602 #define SHIFT_P 0x0003 /* two bits! */
1603 #define CTRL_P 0x0004
1604 #define ALT_P 0x0008
1605 #define SCRLOCK_P 0x0010
1606 #define NUMLOCK_P 0x0020
1607 #define CAPSLOCK_P 0x0040
1608 #define ALT_GR_P 0x0800
1609 #define SUPER_P 0x4000 /* pseudo */
1610 #define HYPER_P 0x8000 /* pseudo */
1613 dos_get_modifiers (keymask
)
1620 /* Calculate modifier bits */
1621 regs
.h
.ah
= extended_kbd
? 0x12 : 0x02;
1622 int86 (0x16, ®s
, ®s
);
1626 mask
= regs
.h
.al
& (SHIFT_P
| CTRL_P
| ALT_P
|
1627 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
1631 mask
= regs
.h
.al
& (SHIFT_P
|
1632 SCRLOCK_P
| NUMLOCK_P
| CAPSLOCK_P
);
1634 /* Do not break international keyboard support. */
1635 /* When Keyb.Com is loaded, the right Alt key is */
1636 /* used for accessing characters like { and } */
1637 if (regs
.h
.ah
& 2) /* Left ALT pressed ? */
1640 if ((regs
.h
.ah
& 8) != 0) /* Right ALT pressed ? */
1643 if (dos_hyper_key
== 1)
1646 modifiers
|= hyper_modifier
;
1648 else if (dos_super_key
== 1)
1651 modifiers
|= super_modifier
;
1653 else if (!international_keyboard
)
1655 /* If Keyb.Com is NOT installed, let Right Alt behave
1656 like the Left Alt. */
1662 if (regs
.h
.ah
& 1) /* Left CTRL pressed ? */
1665 if (regs
.h
.ah
& 4) /* Right CTRL pressed ? */
1667 if (dos_hyper_key
== 2)
1670 modifiers
|= hyper_modifier
;
1672 else if (dos_super_key
== 2)
1675 modifiers
|= super_modifier
;
1683 modifiers
|= shift_modifier
;
1685 modifiers
|= ctrl_modifier
;
1687 modifiers
|= meta_modifier
;
1694 #define NUM_RECENT_DOSKEYS (100)
1695 int recent_doskeys_index
; /* Index for storing next element into recent_doskeys */
1696 int total_doskeys
; /* Total number of elements stored into recent_doskeys */
1697 Lisp_Object recent_doskeys
; /* A vector, holding the last 100 keystrokes */
1699 DEFUN ("recent-doskeys", Frecent_doskeys
, Srecent_doskeys
, 0, 0, 0,
1700 "Return vector of last 100 keyboard input values seen in dos_rawgetc.\n\
1701 Each input key receives two values in this vector: first the ASCII code,\n\
1702 and then the scan code.")
1705 Lisp_Object
*keys
= XVECTOR (recent_doskeys
)->contents
;
1708 if (total_doskeys
< NUM_RECENT_DOSKEYS
)
1709 return Fvector (total_doskeys
, keys
);
1712 val
= Fvector (NUM_RECENT_DOSKEYS
, keys
);
1713 bcopy (keys
+ recent_doskeys_index
,
1714 XVECTOR (val
)->contents
,
1715 (NUM_RECENT_DOSKEYS
- recent_doskeys_index
) * sizeof (Lisp_Object
));
1717 XVECTOR (val
)->contents
+ NUM_RECENT_DOSKEYS
- recent_doskeys_index
,
1718 recent_doskeys_index
* sizeof (Lisp_Object
));
1723 /* Get a char from keyboard. Function keys are put into the event queue. */
1725 extern void kbd_buffer_store_event (struct input_event
*);
1726 static int mouse_preempted
= 0; /* non-zero when XMenu gobbles mouse events */
1731 struct input_event event
;
1734 #ifndef HAVE_X_WINDOWS
1735 /* Maybe put the cursor where it should be. */
1736 IT_cmgoto (selected_frame
);
1739 /* The following condition is equivalent to `kbhit ()', except that
1740 it uses the bios to do its job. This pleases DESQview/X. */
1741 while ((regs
.h
.ah
= extended_kbd
? 0x11 : 0x01),
1742 int86 (0x16, ®s
, ®s
),
1743 (regs
.x
.flags
& 0x40) == 0)
1746 register unsigned char c
;
1747 int sc
, code
, mask
, kp_mode
;
1750 regs
.h
.ah
= extended_kbd
? 0x10 : 0x00;
1751 int86 (0x16, ®s
, ®s
);
1756 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
1758 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
1759 recent_doskeys_index
= 0;
1760 XVECTOR (recent_doskeys
)->contents
[recent_doskeys_index
++]
1762 if (recent_doskeys_index
== NUM_RECENT_DOSKEYS
)
1763 recent_doskeys_index
= 0;
1765 modifiers
= dos_get_modifiers (&mask
);
1767 #ifndef HAVE_X_WINDOWS
1768 if (!NILP (Vdos_display_scancodes
))
1771 sprintf (buf
, "%02x:%02x*%04x",
1772 (unsigned) (sc
&0xff), (unsigned) c
, mask
);
1773 dos_direct_output (screen_size_Y
- 2, screen_size_X
- 12, buf
, 10);
1781 case 10: /* Ctrl Grey Enter */
1782 code
= Ctrl
| Grey
| 4;
1784 case 13: /* Grey Enter */
1787 case '/': /* Grey / */
1797 if (sc
>= (sizeof (ibmpc_translate_map
) / sizeof (short)))
1799 if ((code
= ibmpc_translate_map
[sc
]) == Ignore
)
1805 /* We only look at the keyboard Ctrl/Shift/Alt keys when
1806 Emacs is ready to read a key. Therefore, if they press
1807 `Alt-x' when Emacs is busy, by the time we get to
1808 `dos_get_modifiers', they might have already released the
1809 Alt key, and Emacs gets just `x', which is BAD.
1810 However, for keys with the `Map' property set, the ASCII
1811 code returns zero iff Alt is pressed. So, when we DON'T
1812 have to support international_keyboard, we don't have to
1813 distinguish between the left and right Alt keys, and we
1814 can set the META modifier for any keys with the `Map'
1815 property if they return zero ASCII code (c = 0). */
1817 || ( (code
& 0xf000) == Map
&& !international_keyboard
))
1818 modifiers
|= meta_modifier
;
1820 modifiers
|= ctrl_modifier
;
1822 modifiers
|= shift_modifier
;
1825 switch (code
& 0xf000)
1828 if (c
&& !(mask
& (SHIFT_P
| ALT_P
| CTRL_P
| HYPER_P
| SUPER_P
)))
1830 c
= 0; /* Special */
1843 if (c
== 0) /* ctrl-break */
1845 return c
; /* ALT-nnn */
1847 if (!keyboard_map_all
)
1856 if (c
&& !(mask
& ALT_P
) && !((mask
& SHIFT_P
) && (mask
& CTRL_P
)))
1857 if (!keyboard_map_all
)
1861 if (mask
& ALT_P
&& code
<= 10 && code
> 0 && dos_keypad_mode
& 0x200)
1862 mask
|= SHIFT_P
; /* ALT-1 => M-! etc. */
1866 code
= keyboard
->shifted
[code
];
1868 modifiers
&= ~shift_modifier
;
1871 if ((mask
& ALT_GR_P
) && keyboard
->alt_gr
&& keyboard
->alt_gr
[code
] != ' ')
1872 code
= keyboard
->alt_gr
[code
];
1874 code
= keyboard
->unshifted
[code
];
1879 if (c
== 0xe0) /* edit key */
1882 if ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) /* numlock on */
1883 kp_mode
= dos_keypad_mode
& 0x03;
1885 kp_mode
= (dos_keypad_mode
>> 4) & 0x03;
1890 if (code
== 10 && dos_decimal_point
)
1891 return dos_decimal_point
;
1892 return keypad_translate_map
[code
].char_code
;
1895 code
= 0xff00 | keypad_translate_map
[code
].keypad_code
;
1899 code
= keypad_translate_map
[code
].meta_code
;
1900 modifiers
= meta_modifier
;
1904 code
= 0xff00 | keypad_translate_map
[code
].editkey_code
;
1911 kp_mode
= ((mask
& (NUMLOCK_P
|CTRL_P
|SHIFT_P
|ALT_P
)) == NUMLOCK_P
) ? 0x04 : 0x40;
1912 if (dos_keypad_mode
& kp_mode
)
1913 code
= 0xff00 | grey_key_translate_map
[code
].keypad_code
;
1915 code
= grey_key_translate_map
[code
].char_code
;
1924 event
.kind
= non_ascii_keystroke
;
1926 event
.kind
= ascii_keystroke
;
1928 event
.modifiers
= modifiers
;
1929 XSETFRAME (event
.frame_or_window
, selected_frame
);
1930 event
.timestamp
= event_timestamp ();
1931 kbd_buffer_store_event (&event
);
1934 if (have_mouse
> 0 && !mouse_preempted
)
1936 int but
, press
, x
, y
, ok
;
1938 /* Check for mouse movement *before* buttons. */
1939 mouse_check_moved ();
1941 for (but
= 0; but
< NUM_MOUSE_BUTTONS
; but
++)
1942 for (press
= 0; press
< 2; press
++)
1944 int button_num
= but
;
1947 ok
= mouse_pressed (but
, &x
, &y
);
1949 ok
= mouse_released (but
, &x
, &y
);
1952 /* Allow a simultaneous press/release of Mouse-1 and
1953 Mouse-2 to simulate Mouse-3 on two-button mice. */
1954 if (mouse_button_count
== 2 && but
< 2)
1956 int x2
, y2
; /* don't clobber original coordinates */
1958 /* If only one button is pressed, wait 100 msec and
1959 check again. This way, Speedy Gonzales isn't
1960 punished, while the slow get their chance. */
1961 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
1962 || !press
&& mouse_released (1-but
, &x2
, &y2
))
1967 if (press
&& mouse_pressed (1-but
, &x2
, &y2
)
1968 || !press
&& mouse_released (1-but
, &x2
, &y2
))
1973 event
.kind
= mouse_click
;
1974 event
.code
= button_num
;
1975 event
.modifiers
= dos_get_modifiers (0)
1976 | (press
? down_modifier
: up_modifier
);
1979 XSETFRAME (event
.frame_or_window
, selected_frame
);
1980 event
.timestamp
= event_timestamp ();
1981 kbd_buffer_store_event (&event
);
1989 static int prev_get_char
= -1;
1991 /* Return 1 if a key is ready to be read without suspending execution. */
1995 if (prev_get_char
!= -1)
1998 return ((prev_get_char
= dos_rawgetc ()) != -1);
2001 /* Read a key. Return -1 if no key is ready. */
2005 if (prev_get_char
!= -1)
2007 int c
= prev_get_char
;
2012 return dos_rawgetc ();
2015 #ifndef HAVE_X_WINDOWS
2016 /* See xterm.c for more info. */
2018 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
2020 register int pix_x
, pix_y
;
2021 register int *x
, *y
;
2025 if (bounds
) abort ();
2027 /* Ignore clipping. */
2034 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
2037 register int *pix_x
, *pix_y
;
2043 /* Simulation of X's menus. Nothing too fancy here -- just make it work
2046 Actually, I don't know the meaning of all the parameters of the functions
2047 here -- I only know how they are called by xmenu.c. I could of course
2048 grab the nearest Xlib manual (down the hall, second-to-last door on the
2049 left), but I don't think it's worth the effort. */
2056 menu
= (XMenu
*) xmalloc (sizeof (XMenu
));
2057 menu
->allocated
= menu
->count
= menu
->panecount
= menu
->width
= 0;
2061 /* Allocate some (more) memory for MENU ensuring that there is room for one
2065 IT_menu_make_room (XMenu
*menu
)
2067 if (menu
->allocated
== 0)
2069 int count
= menu
->allocated
= 10;
2070 menu
->text
= (char **) xmalloc (count
* sizeof (char *));
2071 menu
->submenu
= (XMenu
**) xmalloc (count
* sizeof (XMenu
*));
2072 menu
->panenumber
= (int *) xmalloc (count
* sizeof (int));
2074 else if (menu
->allocated
== menu
->count
)
2076 int count
= menu
->allocated
= menu
->allocated
+ 10;
2078 = (char **) xrealloc (menu
->text
, count
* sizeof (char *));
2080 = (XMenu
**) xrealloc (menu
->submenu
, count
* sizeof (XMenu
*));
2082 = (int *) xrealloc (menu
->panenumber
, count
* sizeof (int));
2086 /* Search the given menu structure for a given pane number. */
2089 IT_menu_search_pane (XMenu
*menu
, int pane
)
2094 for (i
= 0; i
< menu
->count
; i
++)
2095 if (menu
->submenu
[i
])
2097 if (pane
== menu
->panenumber
[i
])
2098 return menu
->submenu
[i
];
2099 if ((try = IT_menu_search_pane (menu
->submenu
[i
], pane
)))
2105 /* Determine how much screen space a given menu needs. */
2108 IT_menu_calc_size (XMenu
*menu
, int *width
, int *height
)
2110 int i
, h2
, w2
, maxsubwidth
, maxheight
;
2113 maxheight
= menu
->count
;
2114 for (i
= 0; i
< menu
->count
; i
++)
2116 if (menu
->submenu
[i
])
2118 IT_menu_calc_size (menu
->submenu
[i
], &w2
, &h2
);
2119 if (w2
> maxsubwidth
) maxsubwidth
= w2
;
2120 if (i
+ h2
> maxheight
) maxheight
= i
+ h2
;
2123 *width
= menu
->width
+ maxsubwidth
;
2124 *height
= maxheight
;
2127 /* Display MENU at (X,Y) using FACES. */
2130 IT_menu_display (XMenu
*menu
, int y
, int x
, int *faces
)
2132 int i
, j
, face
, width
;
2136 int enabled
, mousehere
;
2139 width
= menu
->width
;
2140 text
= (GLYPH
*) xmalloc ((width
+ 2) * sizeof (GLYPH
));
2141 ScreenGetCursor (&row
, &col
);
2142 mouse_get_xy (&mx
, &my
);
2143 IT_update_begin (selected_frame
);
2144 for (i
= 0; i
< menu
->count
; i
++)
2146 IT_cursor_to (y
+ i
, x
);
2148 = (!menu
->submenu
[i
] && menu
->panenumber
[i
]) || (menu
->submenu
[i
]);
2149 mousehere
= (y
+ i
== my
&& x
<= mx
&& mx
< x
+ width
+ 2);
2150 face
= faces
[enabled
+ mousehere
* 2];
2152 *p
++ = FAST_MAKE_GLYPH (' ', face
);
2153 for (j
= 0, q
= menu
->text
[i
]; *q
; j
++)
2156 *p
++ = FAST_MAKE_GLYPH (*q
++, face
);
2157 else /* make '^x' */
2159 *p
++ = FAST_MAKE_GLYPH ('^', face
);
2161 *p
++ = FAST_MAKE_GLYPH (*q
++ + 64, face
);
2165 for (; j
< width
; j
++)
2166 *p
++ = FAST_MAKE_GLYPH (' ', face
);
2167 *p
++ = FAST_MAKE_GLYPH (menu
->submenu
[i
] ? 16 : ' ', face
);
2168 IT_write_glyphs (text
, width
+ 2);
2170 IT_update_end (selected_frame
);
2171 IT_cursor_to (row
, col
);
2175 /* --------------------------- X Menu emulation ---------------------- */
2177 /* Report availability of menus. */
2185 /* Create a brand new menu structure. */
2188 XMenuCreate (Display
*foo1
, Window foo2
, char *foo3
)
2190 return IT_menu_create ();
2193 /* Create a new pane and place it on the outer-most level. It is not
2194 clear that it should be placed out there, but I don't know what else
2198 XMenuAddPane (Display
*foo
, XMenu
*menu
, char *txt
, int enable
)
2206 IT_menu_make_room (menu
);
2207 menu
->submenu
[menu
->count
] = IT_menu_create ();
2208 menu
->text
[menu
->count
] = txt
;
2209 menu
->panenumber
[menu
->count
] = ++menu
->panecount
;
2212 /* Adjust length for possible control characters (which will
2213 be written as ^x). */
2214 for (len
= strlen (txt
), p
= txt
; *p
; p
++)
2218 if (len
> menu
->width
)
2221 return menu
->panecount
;
2224 /* Create a new item in a menu pane. */
2227 XMenuAddSelection (Display
*bar
, XMenu
*menu
, int pane
,
2228 int foo
, char *txt
, int enable
)
2234 if (!(menu
= IT_menu_search_pane (menu
, pane
)))
2236 IT_menu_make_room (menu
);
2237 menu
->submenu
[menu
->count
] = (XMenu
*) 0;
2238 menu
->text
[menu
->count
] = txt
;
2239 menu
->panenumber
[menu
->count
] = enable
;
2242 /* Adjust length for possible control characters (which will
2243 be written as ^x). */
2244 for (len
= strlen (txt
), p
= txt
; *p
; p
++)
2248 if (len
> menu
->width
)
2254 /* Decide where the menu would be placed if requested at (X,Y). */
2257 XMenuLocate (Display
*foo0
, XMenu
*menu
, int foo1
, int foo2
, int x
, int y
,
2258 int *ulx
, int *uly
, int *width
, int *height
)
2260 IT_menu_calc_size (menu
, width
, height
);
2266 struct IT_menu_state
2268 void *screen_behind
;
2275 /* Display menu, wait for user's response, and return that response. */
2278 XMenuActivate (Display
*foo
, XMenu
*menu
, int *pane
, int *selidx
,
2279 int x0
, int y0
, unsigned ButtonMask
, char **txt
)
2281 struct IT_menu_state
*state
;
2285 int faces
[4], selectface
;
2286 int leave
, result
, onepane
;
2287 int title_faces
[4]; /* face to display the menu title */
2288 int buffers_num_deleted
= 0;
2290 /* Just in case we got here without a mouse present... */
2291 if (have_mouse
<= 0)
2292 return XM_IA_SELECT
;
2293 /* Don't allow non-positive x0 and y0, lest the menu will wrap
2294 around the display. */
2300 /* We will process all the mouse events directly, so we had
2301 better prevented dos_rawgetc from stealing them from us. */
2304 state
= alloca (menu
->panecount
* sizeof (struct IT_menu_state
));
2305 screensize
= screen_size
* 2;
2307 = compute_glyph_face (selected_frame
,
2310 intern ("msdos-menu-passive-face")),
2313 = compute_glyph_face (selected_frame
,
2316 intern ("msdos-menu-active-face")),
2319 = face_name_id_number (selected_frame
, intern ("msdos-menu-select-face"));
2320 faces
[2] = compute_glyph_face (selected_frame
, selectface
, faces
[0]);
2321 faces
[3] = compute_glyph_face (selected_frame
, selectface
, faces
[1]);
2323 /* Make sure the menu title is always displayed with
2324 `msdos-menu-active-face', no matter where the mouse pointer is. */
2325 for (i
= 0; i
< 4; i
++)
2326 title_faces
[i
] = faces
[3];
2330 /* Don't let the title for the "Buffers" popup menu include a
2331 digit (which is ugly).
2333 This is a terrible kludge, but I think the "Buffers" case is
2334 the only one where the title includes a number, so it doesn't
2335 seem to be necessary to make this more general. */
2336 if (strncmp (menu
->text
[0], "Buffers 1", 9) == 0)
2338 menu
->text
[0][7] = '\0';
2339 buffers_num_deleted
= 1;
2341 state
[0].menu
= menu
;
2343 ScreenRetrieve (state
[0].screen_behind
= xmalloc (screensize
));
2345 /* Turn off the cursor. Otherwise it shows through the menu
2346 panes, which is ugly. */
2347 IT_display_cursor (0);
2349 IT_menu_display (menu
, y0
- 1, x0
- 1, title_faces
); /* display menu title */
2350 if (buffers_num_deleted
)
2351 menu
->text
[0][7] = ' ';
2352 if ((onepane
= menu
->count
== 1 && menu
->submenu
[0]))
2354 menu
->width
= menu
->submenu
[0]->width
;
2355 state
[0].menu
= menu
->submenu
[0];
2359 state
[0].menu
= menu
;
2361 state
[0].x
= x0
- 1;
2363 state
[0].pane
= onepane
;
2365 mouse_last_x
= -1; /* A hack that forces display. */
2369 if (!mouse_visible
) mouse_on ();
2370 mouse_check_moved ();
2371 if (selected_frame
->mouse_moved
)
2373 selected_frame
->mouse_moved
= 0;
2374 result
= XM_IA_SELECT
;
2375 mouse_get_xy (&x
, &y
);
2376 for (i
= 0; i
< statecount
; i
++)
2377 if (state
[i
].x
<= x
&& x
< state
[i
].x
+ state
[i
].menu
->width
+ 2)
2379 int dy
= y
- state
[i
].y
;
2380 if (0 <= dy
&& dy
< state
[i
].menu
->count
)
2382 if (!state
[i
].menu
->submenu
[dy
])
2383 if (state
[i
].menu
->panenumber
[dy
])
2384 result
= XM_SUCCESS
;
2386 result
= XM_IA_SELECT
;
2387 *pane
= state
[i
].pane
- 1;
2389 /* We hit some part of a menu, so drop extra menus that
2390 have been opened. That does not include an open and
2392 if (i
!= statecount
- 2
2393 || state
[i
].menu
->submenu
[dy
] != state
[i
+1].menu
)
2394 while (i
!= statecount
- 1)
2398 ScreenUpdate (state
[statecount
].screen_behind
);
2399 if (screen_virtual_segment
)
2400 dosv_refresh_virtual_screen (0, screen_size
);
2401 xfree (state
[statecount
].screen_behind
);
2403 if (i
== statecount
- 1 && state
[i
].menu
->submenu
[dy
])
2405 IT_menu_display (state
[i
].menu
,
2409 state
[statecount
].menu
= state
[i
].menu
->submenu
[dy
];
2410 state
[statecount
].pane
= state
[i
].menu
->panenumber
[dy
];
2412 ScreenRetrieve (state
[statecount
].screen_behind
2413 = xmalloc (screensize
));
2415 = state
[i
].x
+ state
[i
].menu
->width
+ 2;
2416 state
[statecount
].y
= y
;
2421 IT_menu_display (state
[statecount
- 1].menu
,
2422 state
[statecount
- 1].y
,
2423 state
[statecount
- 1].x
,
2427 /* We are busy-waiting for the mouse to move, so let's be nice
2428 to other Windows applications by releasing our time slice. */
2430 for (b
= 0; b
< mouse_button_count
&& !leave
; b
++)
2432 /* Only leave if user both pressed and released the mouse, and in
2433 that order. This avoids popping down the menu pane unless
2434 the user is really done with it. */
2435 if (mouse_pressed (b
, &x
, &y
))
2437 while (mouse_button_depressed (b
, &x
, &y
))
2441 (void) mouse_released (b
, &x
, &y
);
2446 ScreenUpdate (state
[0].screen_behind
);
2447 if (screen_virtual_segment
)
2448 dosv_refresh_virtual_screen (0, screen_size
);
2449 while (statecount
--)
2450 xfree (state
[statecount
].screen_behind
);
2451 IT_display_cursor (1); /* turn cursor back on */
2452 /* Clean up any mouse events that are waiting inside Emacs event queue.
2453 These events are likely to be generated before the menu was even
2454 displayed, probably because the user pressed and released the button
2455 (which invoked the menu) too quickly. If we don't remove these events,
2456 Emacs will process them after we return and surprise the user. */
2457 discard_mouse_events ();
2458 /* Allow mouse events generation by dos_rawgetc. */
2463 /* Dispose of a menu. */
2466 XMenuDestroy (Display
*foo
, XMenu
*menu
)
2469 if (menu
->allocated
)
2471 for (i
= 0; i
< menu
->count
; i
++)
2472 if (menu
->submenu
[i
])
2473 XMenuDestroy (foo
, menu
->submenu
[i
]);
2475 xfree (menu
->submenu
);
2476 xfree (menu
->panenumber
);
2482 x_pixel_width (struct frame
*f
)
2484 return FRAME_WIDTH (f
);
2488 x_pixel_height (struct frame
*f
)
2490 return FRAME_HEIGHT (f
);
2492 #endif /* !HAVE_X_WINDOWS */
2494 /* ----------------------- DOS / UNIX conversion --------------------- */
2496 void msdos_downcase_filename (unsigned char *);
2498 /* Destructively turn backslashes into slashes. */
2501 dostounix_filename (p
)
2504 msdos_downcase_filename (p
);
2514 /* Destructively turn slashes into backslashes. */
2517 unixtodos_filename (p
)
2520 if (p
[1] == ':' && *p
>= 'A' && *p
<= 'Z')
2534 /* Get the default directory for a given drive. 0=def, 1=A, 2=B, ... */
2537 getdefdir (drive
, dst
)
2541 char in_path
[4], *p
= in_path
;
2544 /* Generate "X:." (when drive is X) or "." (when drive is 0). */
2547 *p
++ = drive
+ 'A' - 1;
2554 _fixpath (in_path
, dst
);
2558 msdos_downcase_filename (dst
);
2564 /* Remove all CR's that are followed by a LF. */
2569 register unsigned char *buf
;
2571 unsigned char *np
= buf
;
2572 unsigned char *startp
= buf
;
2573 unsigned char *endp
= buf
+ n
;
2577 while (buf
< endp
- 1)
2581 if (*(++buf
) != 0x0a)
2592 #if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 0
2594 /* In DJGPP v2.0, library `write' can call `malloc', which might
2595 cause relocation of the buffer whose address we get in ADDR.
2596 Here is a version of `write' that avoids calling `malloc',
2597 to serve us until such time as the library is fixed.
2598 Actually, what we define here is called `__write', because
2599 `write' is a stub that just jmp's to `__write' (to be
2600 POSIXLY-correct with respect to the global name-space). */
2602 #include <io.h> /* for _write */
2603 #include <libc/dosio.h> /* for __file_handle_modes[] */
2605 static char xbuf
[64 * 1024]; /* DOS cannot write more in one chunk */
2607 #define XBUF_END (xbuf + sizeof (xbuf) - 1)
2610 __write (int handle
, const void *buffer
, size_t count
)
2615 if(__file_handle_modes
[handle
] & O_BINARY
)
2616 return _write (handle
, buffer
, count
);
2620 const char *bp
= buffer
;
2621 int total_written
= 0;
2622 int nmoved
= 0, ncr
= 0;
2626 /* The next test makes sure there's space for at least 2 more
2627 characters in xbuf[], so both CR and LF can be put there. */
2639 if (xbp
>= XBUF_END
|| !count
)
2641 size_t to_write
= nmoved
+ ncr
;
2642 int written
= _write (handle
, xbuf
, to_write
);
2647 total_written
+= nmoved
; /* CRs aren't counted in ret value */
2649 /* If some, but not all were written (disk full?), return
2650 an estimate of the total written bytes not counting CRs. */
2651 if (written
< to_write
)
2652 return total_written
- (to_write
- written
) * nmoved
/to_write
;
2659 return total_written
;
2663 /* A low-level file-renaming function which works around Windows 95 bug.
2664 This is pulled directly out of DJGPP v2.01 library sources, and only
2665 used when you compile with DJGPP v2.0. */
2669 int _rename(const char *old
, const char *new)
2672 int olen
= strlen(old
) + 1;
2674 int use_lfn
= _USE_LFN
;
2675 char tempfile
[FILENAME_MAX
];
2676 const char *orig
= old
;
2679 r
.x
.dx
= __tb_offset
;
2680 r
.x
.di
= __tb_offset
+ olen
;
2681 r
.x
.ds
= r
.x
.es
= __tb_segment
;
2685 /* Windows 95 bug: for some filenames, when you rename
2686 file -> file~ (as in Emacs, to leave a backup), the
2687 short 8+3 alias doesn't change, which effectively
2688 makes OLD and NEW the same file. We must rename
2689 through a temporary file to work around this. */
2691 char *pbase
= 0, *p
;
2692 static char try_char
[] = "abcdefghijklmnopqrstuvwxyz012345789";
2693 int idx
= sizeof(try_char
) - 1;
2695 /* Generate a temporary name. Can't use `tmpnam', since $TMPDIR
2696 might point to another drive, which will fail the DOS call. */
2697 strcpy(tempfile
, old
);
2698 for (p
= tempfile
; *p
; p
++) /* ensure temporary is on the same drive */
2699 if (*p
== '/' || *p
== '\\' || *p
== ':')
2705 strcpy(pbase
, "X$$djren$$.$$temp$$");
2711 *pbase
= try_char
[--idx
];
2712 } while (_chmod(tempfile
, 0) != -1);
2715 _put_path2(tempfile
, olen
);
2717 __dpmi_int(0x21, &r
);
2720 errno
= __doserr_to_errno(r
.x
.ax
);
2724 /* Now create a file with the original name. This will
2725 ensure that NEW will always have a 8+3 alias
2726 different from that of OLD. (Seems to be required
2727 when NameNumericTail in the Registry is set to 0.) */
2728 lfn_fd
= _creat(old
, 0);
2730 olen
= strlen(tempfile
) + 1;
2732 r
.x
.di
= __tb_offset
+ olen
;
2741 _put_path2(new, olen
);
2743 __dpmi_int(0x21, &r
);
2746 if (r
.x
.ax
== 5 && i
== 0) /* access denied */
2747 remove(new); /* and try again */
2750 errno
= __doserr_to_errno(r
.x
.ax
);
2752 /* Restore to original name if we renamed it to temporary. */
2760 _put_path2(orig
, olen
);
2761 _put_path(tempfile
);
2763 __dpmi_int(0x21, &r
);
2772 /* Success. Delete the file possibly created to work
2773 around the Windows 95 bug. */
2775 return (_close (lfn_fd
) == 0) ? remove (orig
) : -1;
2779 #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */
2781 DEFUN ("msdos-long-file-names", Fmsdos_long_file_names
, Smsdos_long_file_names
,
2783 "Return non-nil if long file names are supported on MSDOS.")
2786 return (_USE_LFN
? Qt
: Qnil
);
2789 /* Convert alphabetic characters in a filename to lower-case. */
2792 msdos_downcase_filename (p
)
2793 register unsigned char *p
;
2795 /* Always lower-case drive letters a-z, even if the filesystem
2796 preserves case in filenames.
2797 This is so MSDOS filenames could be compared by string comparison
2798 functions that are case-sensitive. Even case-preserving filesystems
2799 do not distinguish case in drive letters. */
2800 if (p
[1] == ':' && *p
>= 'A' && *p
<= 'Z')
2806 /* Under LFN we expect to get pathnames in their true case. */
2807 if (NILP (Fmsdos_long_file_names ()))
2809 if (*p
>= 'A' && *p
<= 'Z')
2813 DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename
, Smsdos_downcase_filename
,
2815 "Convert alphabetic characters in FILENAME to lower case and return that.\n\
2816 When long filenames are supported, doesn't change FILENAME.\n\
2817 If FILENAME is not a string, returns nil.\n\
2818 The argument object is never altered--the value is a copy.")
2820 Lisp_Object filename
;
2824 if (! STRINGP (filename
))
2827 tem
= Fcopy_sequence (filename
);
2828 msdos_downcase_filename (XSTRING (tem
)->data
);
2832 /* The Emacs root directory as determined by init_environment. */
2834 static char emacsroot
[MAXPATHLEN
];
2837 rootrelativepath (rel
)
2840 static char result
[MAXPATHLEN
+ 10];
2842 strcpy (result
, emacsroot
);
2843 strcat (result
, "/");
2844 strcat (result
, rel
);
2848 /* Define a lot of environment variables if not already defined. Don't
2849 remove anything unless you know what you're doing -- lots of code will
2850 break if one or more of these are missing. */
2853 init_environment (argc
, argv
, skip_args
)
2860 static const char * const tempdirs
[] = {
2861 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2864 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2866 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2867 temporary files and assume "/tmp" if $TMPDIR is unset, which
2868 will break on DOS/Windows. Refuse to work if we cannot find
2869 a directory, not even "c:/", usable for that purpose. */
2870 for (i
= 0; i
< imax
; i
++)
2872 const char *tmp
= tempdirs
[i
];
2875 tmp
= getenv (tmp
+ 1);
2876 /* Note that `access' can lie to us if the directory resides on a
2877 read-only filesystem, like CD-ROM or a write-protected floppy.
2878 The only way to be really sure is to actually create a file and
2879 see if it succeeds. But I think that's too much to ask. */
2880 if (tmp
&& access (tmp
, D_OK
) == 0)
2882 setenv ("TMPDIR", tmp
, 1);
2889 Fcons (build_string ("no usable temporary directories found!!"),
2891 "While setting TMPDIR: ");
2893 /* Find our root from argv[0]. Assuming argv[0] is, say,
2894 "c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
2895 root
= alloca (MAXPATHLEN
+ 20);
2896 _fixpath (argv
[0], root
);
2897 msdos_downcase_filename (root
);
2898 len
= strlen (root
);
2899 while (len
> 0 && root
[len
] != '/' && root
[len
] != ':')
2903 && (strcmp (root
+ len
- 4, "/bin") == 0
2904 || strcmp (root
+ len
- 4, "/src") == 0)) /* under a debugger */
2905 root
[len
- 4] = '\0';
2907 strcpy (root
, "c:/emacs"); /* let's be defensive */
2908 len
= strlen (root
);
2909 strcpy (emacsroot
, root
);
2911 /* We default HOME to our root. */
2912 setenv ("HOME", root
, 0);
2914 /* We default EMACSPATH to root + "/bin". */
2915 strcpy (root
+ len
, "/bin");
2916 setenv ("EMACSPATH", root
, 0);
2918 /* I don't expect anybody to ever use other terminals so the internal
2919 terminal is the default. */
2920 setenv ("TERM", "internal", 0);
2922 #ifdef HAVE_X_WINDOWS
2923 /* Emacs expects DISPLAY to be set. */
2924 setenv ("DISPLAY", "unix:0.0", 0);
2927 /* SHELL is a bit tricky -- COMSPEC is the closest we come, but we must
2928 downcase it and mirror the backslashes. */
2929 s
= getenv ("COMSPEC");
2930 if (!s
) s
= "c:/command.com";
2931 t
= alloca (strlen (s
) + 1);
2933 dostounix_filename (t
);
2934 setenv ("SHELL", t
, 0);
2936 /* PATH is also downcased and backslashes mirrored. */
2937 s
= getenv ("PATH");
2939 t
= alloca (strlen (s
) + 3);
2940 /* Current directory is always considered part of MsDos's path but it is
2941 not normally mentioned. Now it is. */
2942 strcat (strcpy (t
, ".;"), s
);
2943 dostounix_filename (t
); /* Not a single file name, but this should work. */
2944 setenv ("PATH", t
, 1);
2946 /* In some sense all dos users have root privileges, so... */
2947 setenv ("USER", "root", 0);
2948 setenv ("NAME", getenv ("USER"), 0);
2950 /* Time zone determined from country code. To make this possible, the
2951 country code may not span more than one time zone. In other words,
2952 in the USA, you lose. */
2954 switch (dos_country_code
)
2956 case 31: /* Belgium */
2957 case 32: /* The Netherlands */
2958 case 33: /* France */
2959 case 34: /* Spain */
2960 case 36: /* Hungary */
2961 case 38: /* Yugoslavia (or what's left of it?) */
2962 case 39: /* Italy */
2963 case 41: /* Switzerland */
2964 case 42: /* Tjekia */
2965 case 45: /* Denmark */
2966 case 46: /* Sweden */
2967 case 47: /* Norway */
2968 case 48: /* Poland */
2969 case 49: /* Germany */
2970 /* Daylight saving from last Sunday in March to last Sunday in
2971 September, both at 2AM. */
2972 setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
2974 case 44: /* United Kingdom */
2975 case 351: /* Portugal */
2976 case 354: /* Iceland */
2977 setenv ("TZ", "GMT+00", 0);
2979 case 81: /* Japan */
2980 case 82: /* Korea */
2981 setenv ("TZ", "JST-09", 0);
2983 case 90: /* Turkey */
2984 case 358: /* Finland */
2985 setenv ("TZ", "EET-02", 0);
2987 case 972: /* Israel */
2988 /* This is an approximation. (For exact rules, use the
2989 `zoneinfo/israel' file which comes with DJGPP, but you need
2990 to install it in `/usr/share/zoneinfo/' directory first.) */
2991 setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
2999 static int break_stat
; /* BREAK check mode status. */
3000 static int stdin_stat
; /* stdin IOCTL status. */
3004 /* These must be global. */
3005 static _go32_dpmi_seginfo ctrl_break_vector
;
3006 static _go32_dpmi_registers ctrl_break_regs
;
3007 static int ctrlbreakinstalled
= 0;
3009 /* Interrupt level detection of Ctrl-Break. Don't do anything fancy here! */
3012 ctrl_break_func (regs
)
3013 _go32_dpmi_registers
*regs
;
3019 install_ctrl_break_check ()
3021 if (!ctrlbreakinstalled
)
3023 /* Don't press Ctrl-Break if you don't have either DPMI or Emacs
3024 was compiler with Djgpp 1.11 maintenance level 5 or later! */
3025 ctrlbreakinstalled
= 1;
3026 ctrl_break_vector
.pm_offset
= (int) ctrl_break_func
;
3027 _go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector
,
3029 _go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector
);
3033 #endif /* __DJGPP__ < 2 */
3035 /* Turn off Dos' Ctrl-C checking and inhibit interpretation of
3036 control chars by DOS. Determine the keyboard type. */
3041 union REGS inregs
, outregs
;
3042 static int first_time
= 1;
3044 break_stat
= getcbrk ();
3047 install_ctrl_break_check ();
3053 int86 (0x15, &inregs
, &outregs
);
3054 extended_kbd
= (!outregs
.x
.cflag
) && (outregs
.h
.ah
== 0);
3058 if (internal_terminal
3059 #ifdef HAVE_X_WINDOWS
3060 && inhibit_window_system
3064 inregs
.x
.ax
= 0x0021;
3065 int86 (0x33, &inregs
, &outregs
);
3066 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
3069 /* Reportedly, the above doesn't work for some mouse drivers. There
3070 is an additional detection method that should work, but might be
3071 a little slower. Use that as an alternative. */
3072 inregs
.x
.ax
= 0x0000;
3073 int86 (0x33, &inregs
, &outregs
);
3074 have_mouse
= (outregs
.x
.ax
& 0xffff) == 0xffff;
3079 have_mouse
= 1; /* enable mouse */
3082 if (outregs
.x
.bx
== 3)
3084 mouse_button_count
= 3;
3085 mouse_button_translate
[0] = 0; /* Left */
3086 mouse_button_translate
[1] = 2; /* Middle */
3087 mouse_button_translate
[2] = 1; /* Right */
3091 mouse_button_count
= 2;
3092 mouse_button_translate
[0] = 0;
3093 mouse_button_translate
[1] = 1;
3095 mouse_position_hook
= &mouse_get_pos
;
3104 stdin_stat
= setmode (fileno (stdin
), O_BINARY
);
3105 return (stdin_stat
!= -1);
3108 return (setmode (fileno (stdin
), O_BINARY
) != -1);
3110 #else /* __DJGPP__ < 2 */
3114 /* I think it is wrong to overwrite `stdin_stat' every time
3115 but the first one this function is called, but I don't
3116 want to change the way it used to work in v1.x.--EZ */
3118 inregs
.x
.ax
= 0x4400; /* Get IOCTL status. */
3119 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
3120 intdos (&inregs
, &outregs
);
3121 stdin_stat
= outregs
.h
.dl
;
3123 inregs
.x
.dx
= stdin_stat
| 0x0020; /* raw mode */
3124 inregs
.x
.ax
= 0x4401; /* Set IOCTL status */
3125 intdos (&inregs
, &outregs
);
3126 return !outregs
.x
.cflag
;
3128 #endif /* __DJGPP__ < 2 */
3131 /* Restore status of standard input and Ctrl-C checking. */
3136 union REGS inregs
, outregs
;
3138 setcbrk (break_stat
);
3143 return (setmode (fileno (stdin
), stdin_stat
) != -1);
3145 #else /* not __DJGPP__ >= 2 */
3147 inregs
.x
.ax
= 0x4401; /* Set IOCTL status. */
3148 inregs
.x
.bx
= 0x00; /* 0 = stdin. */
3149 inregs
.x
.dx
= stdin_stat
;
3150 intdos (&inregs
, &outregs
);
3151 return !outregs
.x
.cflag
;
3153 #endif /* not __DJGPP__ >= 2 */
3157 /* Run command as specified by ARGV in directory DIR.
3158 The command is run with input from TEMPIN, output to
3159 file TEMPOUT and stderr to TEMPERR. */
3162 run_msdos_command (argv
, working_dir
, tempin
, tempout
, temperr
, envv
)
3163 unsigned char **argv
;
3164 const char *working_dir
;
3165 int tempin
, tempout
, temperr
;
3168 char *saveargv1
, *saveargv2
, *lowcase_argv0
, *pa
, *pl
;
3169 char oldwd
[MAXPATHLEN
+ 1]; /* Fixed size is safe on MSDOS. */
3170 int msshell
, result
= -1;
3171 int inbak
, outbak
, errbak
;
3175 /* Get current directory as MSDOS cwd is not per-process. */
3178 /* If argv[0] is the shell, it might come in any lettercase.
3179 Since `Fmember' is case-sensitive, we need to downcase
3180 argv[0], even if we are on case-preserving filesystems. */
3181 lowcase_argv0
= alloca (strlen (argv
[0]) + 1);
3182 for (pa
= argv
[0], pl
= lowcase_argv0
; *pa
; pl
++)
3185 if (*pl
>= 'A' && *pl
<= 'Z')
3190 cmd
= Ffile_name_nondirectory (build_string (lowcase_argv0
));
3191 msshell
= !NILP (Fmember (cmd
, Fsymbol_value (intern ("msdos-shells"))))
3192 && !strcmp ("-c", argv
[1]);
3195 saveargv1
= argv
[1];
3196 saveargv2
= argv
[2];
3200 char *p
= alloca (strlen (argv
[2]) + 1);
3202 strcpy (argv
[2] = p
, saveargv2
);
3203 while (*p
&& isspace (*p
))
3205 while (*p
&& !isspace (*p
))
3213 chdir (working_dir
);
3217 if (inbak
< 0 || outbak
< 0 || errbak
< 0)
3218 goto done
; /* Allocation might fail due to lack of descriptors. */
3221 mouse_get_xy (&x
, &y
);
3223 dos_ttcooked (); /* do it here while 0 = stdin */
3231 if (msshell
&& !argv
[3])
3233 /* MS-DOS native shells are too restrictive. For starters, they
3234 cannot grok commands longer than 126 characters. In DJGPP v2
3235 and later, `system' is much smarter, so we'll call it instead. */
3239 /* A shell gets a single argument--its full command
3240 line--whose original was saved in `saveargv2'. */
3242 /* Don't let them pass empty command lines to `system', since
3243 with some shells it will try to invoke an interactive shell,
3244 which will hang Emacs. */
3245 for (cmnd
= saveargv2
; *cmnd
&& isspace (*cmnd
); cmnd
++)
3249 extern char **environ
;
3250 int save_system_flags
= __system_flags
;
3252 /* Request the most powerful version of `system'. We need
3253 all the help we can get to avoid calling stock DOS shells. */
3254 __system_flags
= (__system_redirect
3255 | __system_use_shell
3256 | __system_allow_multiple_cmds
3257 | __system_allow_long_cmds
3258 | __system_handle_null_commands
3259 | __system_emulate_chdir
);
3262 result
= system (cmnd
);
3263 __system_flags
= save_system_flags
;
3266 result
= 0; /* emulate Unixy shell behavior with empty cmd line */
3270 #endif /* __DJGPP__ > 1 */
3272 result
= spawnve (P_WAIT
, argv
[0], argv
, envv
);
3285 mouse_moveto (x
, y
);
3288 /* Some programs might change the meaning of the highest bit of the
3289 text attribute byte, so we get blinking characters instead of the
3290 bright background colors. Restore that. */
3297 argv
[1] = saveargv1
;
3298 argv
[2] = saveargv2
;
3306 fprintf (stderr
, "%s not yet implemented\r\n", badfunc
);
3313 /* ------------------------- Compatibility functions -------------------
3318 /* Hostnames for a pc are not really funny,
3319 but they are used in change log so we emulate the best we can. */
3321 gethostname (p
, size
)
3325 char *q
= egetenv ("HOSTNAME");
3332 /* When time zones are set from Ms-Dos too many C-libraries are playing
3333 tricks with time values. We solve this by defining our own version
3334 of `gettimeofday' bypassing GO32. Our version needs to be initialized
3335 once and after each call to `tzset' with TZ changed. That is
3336 accomplished by aliasing tzset to init_gettimeofday. */
3338 static struct tm time_rec
;
3341 gettimeofday (struct timeval
*tp
, struct timezone
*tzp
)
3349 if (t
.ti_hour
< time_rec
.tm_hour
) /* midnight wrap */
3353 time_rec
.tm_year
= d
.da_year
- 1900;
3354 time_rec
.tm_mon
= d
.da_mon
- 1;
3355 time_rec
.tm_mday
= d
.da_day
;
3358 time_rec
.tm_hour
= t
.ti_hour
;
3359 time_rec
.tm_min
= t
.ti_min
;
3360 time_rec
.tm_sec
= t
.ti_sec
;
3363 tm
.tm_gmtoff
= dos_timezone_offset
;
3365 tp
->tv_sec
= mktime (&tm
); /* may modify tm */
3366 tp
->tv_usec
= t
.ti_hund
* (1000000 / 100);
3368 /* Ignore tzp; it's obsolescent. */
3372 #endif /* __DJGPP__ < 2 */
3375 * A list of unimplemented functions that we silently ignore.
3379 unsigned alarm (s
) unsigned s
; {}
3380 fork () { return 0; }
3381 int kill (x
, y
) int x
, y
; { return -1; }
3383 void volatile pause () {}
3384 sigsetmask (x
) int x
; { return 0; }
3385 sigblock (mask
) int mask
; { return 0; }
3388 void request_sigio (void) {}
3389 setpgrp () {return 0; }
3390 setpriority (x
,y
,z
) int x
,y
,z
; { return 0; }
3391 void unrequest_sigio (void) {}
3395 #ifdef POSIX_SIGNALS
3397 /* Augment DJGPP library POSIX signal functions. This is needed
3398 as of DJGPP v2.01, but might be in the library in later releases. */
3400 #include <libc/bss.h>
3402 /* A counter to know when to re-initialize the static sets. */
3403 static int sigprocmask_count
= -1;
3405 /* Which signals are currently blocked (initially none). */
3406 static sigset_t current_mask
;
3408 /* Which signals are pending (initially none). */
3409 static sigset_t pending_signals
;
3411 /* Previous handlers to restore when the blocked signals are unblocked. */
3412 typedef void (*sighandler_t
)(int);
3413 static sighandler_t prev_handlers
[320];
3415 /* A signal handler which just records that a signal occured
3416 (it will be raised later, if and when the signal is unblocked). */
3418 sig_suspender (signo
)
3421 sigaddset (&pending_signals
, signo
);
3425 sigprocmask (how
, new_set
, old_set
)
3427 const sigset_t
*new_set
;
3433 /* If called for the first time, initialize. */
3434 if (sigprocmask_count
!= __bss_count
)
3436 sigprocmask_count
= __bss_count
;
3437 sigemptyset (&pending_signals
);
3438 sigemptyset (¤t_mask
);
3439 for (signo
= 0; signo
< 320; signo
++)
3440 prev_handlers
[signo
] = SIG_ERR
;
3444 *old_set
= current_mask
;
3449 if (how
!= SIG_BLOCK
&& how
!= SIG_UNBLOCK
&& how
!= SIG_SETMASK
)
3455 sigemptyset (&new_mask
);
3457 /* DJGPP supports upto 320 signals. */
3458 for (signo
= 0; signo
< 320; signo
++)
3460 if (sigismember (¤t_mask
, signo
))
3461 sigaddset (&new_mask
, signo
);
3462 else if (sigismember (new_set
, signo
) && how
!= SIG_UNBLOCK
)
3464 sigaddset (&new_mask
, signo
);
3466 /* SIGKILL is silently ignored, as on other platforms. */
3467 if (signo
!= SIGKILL
&& prev_handlers
[signo
] == SIG_ERR
)
3468 prev_handlers
[signo
] = signal (signo
, sig_suspender
);
3470 if (( how
== SIG_UNBLOCK
3471 && sigismember (&new_mask
, signo
)
3472 && sigismember (new_set
, signo
))
3473 || (how
== SIG_SETMASK
3474 && sigismember (&new_mask
, signo
)
3475 && !sigismember (new_set
, signo
)))
3477 sigdelset (&new_mask
, signo
);
3478 if (prev_handlers
[signo
] != SIG_ERR
)
3480 signal (signo
, prev_handlers
[signo
]);
3481 prev_handlers
[signo
] = SIG_ERR
;
3483 if (sigismember (&pending_signals
, signo
))
3485 sigdelset (&pending_signals
, signo
);
3490 current_mask
= new_mask
;
3494 #else /* not POSIX_SIGNALS */
3496 sigsetmask (x
) int x
; { return 0; }
3497 sigblock (mask
) int mask
; { return 0; }
3499 #endif /* not POSIX_SIGNALS */
3500 #endif /* __DJGPP__ > 1 */
3503 #include "sysselect.h"
3505 #ifndef EMACS_TIME_ZERO_OR_NEG_P
3506 #define EMACS_TIME_ZERO_OR_NEG_P(time) \
3507 ((long)(time).tv_sec < 0 \
3508 || ((time).tv_sec == 0 \
3509 && (long)(time).tv_usec <= 0))
3512 /* This yields the rest of the current time slice to the task manager.
3513 It should be called by any code which knows that it has nothing
3514 useful to do except idle.
3516 I don't use __dpmi_yield here, since versions of library before 2.02
3517 called Int 2Fh/AX=1680h there in a way that would wedge the DOS box
3518 on some versions of Windows 9X. */
3521 dos_yield_time_slice (void)
3523 _go32_dpmi_registers r
;
3526 r
.x
.ss
= r
.x
.sp
= r
.x
.flags
= 0;
3527 _go32_dpmi_simulate_int (0x2f, &r
);
3532 /* Only event queue is checked. */
3533 /* We don't have to call timer_check here
3534 because wait_reading_process_input takes care of that. */
3536 sys_select (nfds
, rfds
, wfds
, efds
, timeout
)
3538 SELECT_TYPE
*rfds
, *wfds
, *efds
;
3539 EMACS_TIME
*timeout
;
3547 check_input
= FD_ISSET (0, rfds
);
3558 /* If we are looking only for the terminal, with no timeout,
3559 just read it and wait -- that's more efficient. */
3562 while (!detect_input_pending ())
3564 dos_yield_time_slice ();
3569 EMACS_TIME clnow
, cllast
, cldiff
;
3572 EMACS_SET_SECS_USECS (cllast
, t
.ti_sec
, t
.ti_hund
* 10000L);
3574 while (!check_input
|| !detect_input_pending ())
3577 EMACS_SET_SECS_USECS (clnow
, t
.ti_sec
, t
.ti_hund
* 10000L);
3578 EMACS_SUB_TIME (cldiff
, clnow
, cllast
);
3580 /* When seconds wrap around, we assume that no more than
3581 1 minute passed since last `gettime'. */
3582 if (EMACS_TIME_NEG_P (cldiff
))
3583 EMACS_SET_SECS (cldiff
, EMACS_SECS (cldiff
) + 60);
3584 EMACS_SUB_TIME (*timeout
, *timeout
, cldiff
);
3586 /* Stop when timeout value crosses zero. */
3587 if (EMACS_TIME_ZERO_OR_NEG_P (*timeout
))
3590 dos_yield_time_slice ();
3600 * Define overlaid functions:
3602 * chdir -> sys_chdir
3603 * tzset -> init_gettimeofday
3604 * abort -> dos_abort
3609 extern int chdir ();
3615 int len
= strlen (path
);
3616 char *tmp
= (char *)path
;
3618 if (*tmp
&& tmp
[1] == ':')
3620 if (getdisk () != tolower (tmp
[0]) - 'a')
3621 setdisk (tolower (tmp
[0]) - 'a');
3622 tmp
+= 2; /* strip drive: KFS 1995-07-06 */
3626 if (len
> 1 && (tmp
[len
- 1] == '/'))
3628 char *tmp1
= (char *) alloca (len
+ 1);
3639 extern void tzset (void);
3642 init_gettimeofday ()
3648 ltm
= gtm
= time (NULL
);
3649 ltm
= mktime (lstm
= localtime (<m
));
3650 gtm
= mktime (gmtime (>m
));
3651 time_rec
.tm_hour
= 99; /* force gettimeofday to get date */
3652 time_rec
.tm_isdst
= lstm
->tm_isdst
;
3653 dos_timezone_offset
= time_rec
.tm_gmtoff
= (int)(gtm
- ltm
) / 60;
3660 dos_abort (file
, line
)
3664 char buffer1
[200], buffer2
[400];
3667 sprintf (buffer1
, "<EMACS FATAL ERROR IN %s LINE %d>", file
, line
);
3668 for (i
= j
= 0; buffer1
[i
]; i
++) {
3669 buffer2
[j
++] = buffer1
[i
];
3670 buffer2
[j
++] = 0x70;
3672 dosmemput (buffer2
, j
, (int)ScreenPrimary
);
3673 ScreenSetCursor (2, 0);
3681 ScreenSetCursor (10, 0);
3682 cputs ("\r\n\nEmacs aborted!\r\n");
3684 #if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
3685 if (screen_virtual_segment
)
3686 dosv_refresh_virtual_screen (2 * 10 * screen_size_X
, 4 * screen_size_X
);
3687 #endif /* __DJGPP_MINOR__ < 2 */
3688 /* Generate traceback, so we could tell whodunit. */
3689 signal (SIGINT
, SIG_DFL
);
3690 __asm__
__volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
3696 /* The following two are required so that customization feature
3697 won't complain about unbound variables. */
3698 #ifndef HAVE_X_WINDOWS
3699 /* Search path for bitmap files (xfns.c). */
3700 Lisp_Object Vx_bitmap_file_path
;
3702 #ifndef subprocesses
3703 /* Nonzero means delete a process right away if it exits (process.c). */
3704 static int delete_exited_processes
;
3709 recent_doskeys
= Fmake_vector (make_number (NUM_RECENT_DOSKEYS
), Qnil
);
3710 staticpro (&recent_doskeys
);
3711 #ifndef HAVE_X_WINDOWS
3712 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path
,
3713 "List of directories to search for bitmap files for X.");
3714 Vx_bitmap_file_path
= decode_env_path ((char *) 0, ".");
3716 /* The following two are from xfns.c: */
3717 Qbackground_color
= intern ("background-color");
3718 staticpro (&Qbackground_color
);
3719 Qforeground_color
= intern ("foreground-color");
3720 staticpro (&Qforeground_color
);
3722 #ifndef subprocesses
3723 DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes
,
3724 "*Non-nil means delete processes immediately when they exit.\n\
3725 nil means don't delete them until `list-processes' is run.");
3726 delete_exited_processes
= 0;
3729 defsubr (&Srecent_doskeys
);
3730 defsubr (&Smsdos_long_file_names
);
3731 defsubr (&Smsdos_downcase_filename
);