/* MS-DOS specific C utilities.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <sys/param.h>
#include <sys/time.h>
#include <dos.h>
+#include <errno.h>
+#include <sys/stat.h> /* for _fixpath */
+#if __DJGPP__ >= 2
+#include <fcntl.h>
+#include <libc/dosio.h> /* for _USE_LFN */
+#endif
+
#include "dosfns.h"
#include "msdos.h"
#include "systime.h"
/* Damn that local process.h! Instead we can define P_WAIT ourselves. */
#define P_WAIT 1
+#ifndef _USE_LFN
+#define _USE_LFN 0
+#endif
+
+#if __DJGPP__ > 1
+
+#include <signal.h>
+
+#ifndef SYSTEM_MALLOC
+
+#ifdef GNU_MALLOC
+
+/* If other `malloc' than ours is used, force our `sbrk' behave like
+ Unix programs expect (resize memory blocks to keep them contiguous).
+ If `sbrk' from `ralloc.c' is NOT used, also zero-out sbrk'ed memory,
+ because that's what `gmalloc' expects to get. */
+#include <crt0.h>
+
+#ifdef REL_ALLOC
+int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
+#else /* not REL_ALLOC */
+int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
+#endif /* not REL_ALLOC */
+#endif /* GNU_MALLOC */
+
+#endif /* not SYSTEM_MALLOC */
+#endif /* __DJGPP__ > 1 */
static unsigned long
event_timestamp ()
#ifndef HAVE_X_WINDOWS
-/*
- * If we write a character in the position where the mouse is,
- * the mouse cursor may need to be refreshed.
- */
+/* Enable bright background colors. */
+static void
+bright_bg (void)
+{
+ union REGS regs;
+
+ regs.h.bl = 0;
+ regs.x.ax = 0x1003;
+ int86 (0x10, ®s, ®s);
+}
+
+/* Set the screen dimensions so that it can show no less than
+ ROWS x COLS frame. */
+
+void
+dos_set_window_size (rows, cols)
+ int *rows, *cols;
+{
+ char video_name[30];
+ Lisp_Object video_mode;
+ int video_mode_value;
+ int have_vga = 0;
+ union REGS regs;
+ int current_rows = ScreenRows (), current_cols = ScreenCols ();
+
+ if (*rows == current_rows && *cols == current_cols)
+ return;
+
+ /* Do we have a VGA? */
+ regs.x.ax = 0x1a00;
+ int86 (0x10, ®s, ®s);
+ if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
+ have_vga = 1;
+
+ mouse_off ();
+
+ /* If the user specified a special video mode for these dimensions,
+ use that mode. */
+ sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols);
+ video_mode = XSYMBOL (Fintern_soft (build_string (video_name),
+ Qnil))-> value;
+
+ if (INTEGERP (video_mode)
+ && (video_mode_value = XINT (video_mode)) > 0)
+ {
+ regs.x.ax = video_mode_value;
+ int86 (0x10, ®s, ®s);
+
+ if (have_mouse)
+ {
+ /* Must hardware-reset the mouse, or else it won't update
+ its notion of screen dimensions for some non-standard
+ video modes. This is *painfully* slow... */
+ regs.x.ax = 0;
+ int86 (0x33, ®s, ®s);
+ }
+ }
+
+ /* Find one of the dimensions supported by standard EGA/VGA
+ which gives us at least the required dimensions. */
+
+#if __DJGPP__ > 1
+
+ else
+ {
+ static struct {
+ int rows;
+ int need_vga;
+ } std_dimension[] = {
+ {25, 0},
+ {28, 1},
+ {35, 0},
+ {40, 1},
+ {43, 0},
+ {50, 1}
+ };
+ int i = 0;
+
+ while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
+ {
+ if (std_dimension[i].need_vga <= have_vga
+ && std_dimension[i].rows >= *rows)
+ {
+ if (std_dimension[i].rows != current_rows
+ || *cols != current_cols)
+ _set_screen_lines (std_dimension[i].rows);
+ break;
+ }
+ i++;
+ }
+ }
+
+#else /* not __DJGPP__ > 1 */
+
+ else if (*rows <= 25)
+ {
+ if (current_rows != 25 || current_cols != 80)
+ {
+ regs.x.ax = 3;
+ int86 (0x10, ®s, ®s);
+ regs.x.ax = 0x1101;
+ regs.h.bl = 0;
+ int86 (0x10, ®s, ®s);
+ regs.x.ax = 0x1200;
+ regs.h.bl = 32;
+ int86 (0x10, ®s, ®s);
+ regs.x.ax = 3;
+ int86 (0x10, ®s, ®s);
+ }
+ }
+ else if (*rows <= 50)
+ if (have_vga && (current_rows != 50 || current_cols != 80)
+ || *rows <= 43 && (current_rows != 43 || current_cols != 80))
+ {
+ regs.x.ax = 3;
+ int86 (0x10, ®s, ®s);
+ regs.x.ax = 0x1112;
+ regs.h.bl = 0;
+ int86 (0x10, ®s, ®s);
+ regs.x.ax = 0x1200;
+ regs.h.bl = 32;
+ int86 (0x10, ®s, ®s);
+ regs.x.ax = 0x0100;
+ regs.x.cx = 7;
+ int86 (0x10, ®s, ®s);
+ }
+#endif /* not __DJGPP__ > 1 */
+
+ if (have_mouse)
+ {
+ mouse_init ();
+ mouse_on ();
+ }
+
+ /* Tell the caller what dimensions have been REALLY set. */
+ *rows = ScreenRows ();
+ *cols = ScreenCols ();
+
+ /* Enable bright background colors. */
+ bright_bg ();
+}
+
+/* If we write a character in the position where the mouse is,
+ the mouse cursor may need to be refreshed. */
static void
mouse_off_maybe ()
{
}
-/* This was more or less copied from xterm.c */
+/* This was more or less copied from xterm.c
+
+ Nowadays, the corresponding function under X is `x_set_menu_bar_lines_1'
+ on xfns.c */
+
static void
IT_set_menu_bar_lines (window, n)
- Lisp_Object window;
- int n;
+ Lisp_Object window;
+ int n;
{
struct window *w = XWINDOW (window);
XSETFASTINT (w->last_modified, 0);
+ XSETFASTINT (w->last_overlay_modified, 0);
XSETFASTINT (w->top, XFASTINT (w->top) + n);
XSETFASTINT (w->height, XFASTINT (w->height) - n);
}
}
-/*
- * IT_set_terminal_modes is called when emacs is started,
- * resumed, and whenever the screen is redrawn!
- */
+/* This was copied from xfns.c */
+
+void
+x_set_menu_bar_lines (f, value, oldval)
+ struct frame *f;
+ Lisp_Object value, oldval;
+{
+ int nlines;
+ int olines = FRAME_MENU_BAR_LINES (f);
+
+ /* Right now, menu bars don't work properly in minibuf-only frames;
+ most of the commands try to apply themselves to the minibuffer
+ frame itslef, and get an error because you can't switch buffers
+ in or split the minibuffer window. */
+ if (FRAME_MINIBUF_ONLY_P (f))
+ return;
+
+ if (INTEGERP (value))
+ nlines = XINT (value);
+ else
+ nlines = 0;
+
+ FRAME_MENU_BAR_LINES (f) = nlines;
+ IT_set_menu_bar_lines (f->root_window, nlines - olines);
+}
+
+/* IT_set_terminal_modes is called when emacs is started,
+ resumed, and whenever the screen is redrawn! */
static
IT_set_terminal_modes (void)
if (termscript)
fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
screen_size_X, screen_size_Y);
+
+ bright_bg ();
}
-/*
- * IT_reset_terminal_modes is called when emacs is
- * suspended or killed.
- */
+/* IT_reset_terminal_modes is called when emacs is
+ suspended or killed. */
static
IT_reset_terminal_modes (void)
}
void
-IT_set_frame_parameters (frame, alist)
- FRAME_PTR frame;
+IT_set_frame_parameters (f, alist)
+ FRAME_PTR f;
Lisp_Object alist;
{
Lisp_Object tail;
int redraw;
extern unsigned long load_color ();
- FRAME_PTR f = (FRAME_PTR) &the_only_frame;
redraw = 0;
for (tail = alist; CONSP (tail); tail = Fcdr (tail))
{
FRAME_FOREGROUND_PIXEL (f) = new_color;
redraw = 1;
+ if (termscript)
+ fprintf (termscript, "<FGCOLOR %d>\n", new_color);
}
}
else if (EQ (prop, intern ("background-color")))
unsigned long new_color = load_color (f, val);
if (new_color != ~0)
{
- FRAME_BACKGROUND_PIXEL (f) = new_color & ~8;
+ FRAME_BACKGROUND_PIXEL (f) = new_color;
redraw = 1;
+ if (termscript)
+ fprintf (termscript, "<BGCOLOR %d>\n", new_color);
}
}
else if (EQ (prop, intern ("menu-bar-lines")))
- {
- int new;
- int old = FRAME_MENU_BAR_LINES (the_only_frame);
-
- if (INTEGERP (val))
- new = XINT (val);
- else
- new = 0;
- FRAME_MENU_BAR_LINES (f) = new;
- IT_set_menu_bar_lines (the_only_frame.root_window, new - old);
- }
+ x_set_menu_bar_lines (f, val, 0);
}
if (redraw)
{
recompute_basic_faces (f);
- Fredraw_frame (Fselected_frame ());
+ if (f == selected_frame)
+ redraw_frame (f);
}
}
#endif /* !HAVE_X_WINDOWS */
-/* Do we need the internal terminal? */
+/* Do we need the internal terminal? */
+
void
internal_terminal_init ()
{
#ifndef HAVE_X_WINDOWS
if (!internal_terminal || inhibit_window_system)
{
- the_only_frame.output_method = output_termcap;
+ selected_frame->output_method = output_termcap;
return;
}
bzero (&the_only_x_display, sizeof the_only_x_display);
the_only_x_display.background_pixel = 7; /* White */
the_only_x_display.foreground_pixel = 0; /* Black */
+ bright_bg ();
colors = getenv ("EMACSCOLORS");
if (colors && strlen (colors) >= 2)
{
- the_only_x_display.foreground_pixel = colors[0] & 0x07;
- the_only_x_display.background_pixel = colors[1] & 0x07;
+ /* The colors use 4 bits each (we enable bright background). */
+ if (isdigit (colors[0]))
+ colors[0] -= '0';
+ else if (isxdigit (colors[0]))
+ colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
+ if (colors[0] >= 0 && colors[0] < 16)
+ the_only_x_display.foreground_pixel = colors[0];
+ if (isdigit (colors[1]))
+ colors[1] -= '0';
+ else if (isxdigit (colors[1]))
+ colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
+ if (colors[1] >= 0 && colors[1] < 16)
+ the_only_x_display.background_pixel = colors[1];
}
the_only_x_display.line_height = 1;
- the_only_frame.output_data.x = &the_only_x_display;
- the_only_frame.output_method = output_msdos_raw;
the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
- init_frame_faces ((FRAME_PTR) &the_only_frame);
+ init_frame_faces (selected_frame);
ring_bell_hook = IT_ring_bell;
write_glyphs_hook = IT_write_glyphs;
return 0;
#endif
}
+
+#ifndef HAVE_X_WINDOWS
+
+/* We are not X, but we can emulate it well enough for our needs... */
+void
+check_x (void)
+{
+ if (! FRAME_MSDOS_P (selected_frame))
+ error ("Not running under a windows system");
+}
+
+#endif
+
\f
/* ----------------------- Keyboard control ----------------------
*
}
}
- if (regs.h.ah & 1) /* Left CTRL pressed
+ if (regs.h.ah & 1) /* Left CTRL pressed ? */
mask |= CTRL_P;
if (regs.h.ah & 4) /* Right CTRL pressed ? */
}
/* Get a char from keyboard. Function keys are put into the event queue. */
+
static int
dos_rawgetc ()
{
for (but = 0; but < NUM_MOUSE_BUTTONS; but++)
for (press = 0; press < 2; press++)
{
+ int button_num = but;
+
if (press)
ok = mouse_pressed (but, &x, &y);
else
ok = mouse_released (but, &x, &y);
if (ok)
{
+ /* Allow a simultaneous press/release of Mouse-1 and
+ Mouse-2 to simulate Mouse-3 on two-button mice. */
+ if (mouse_button_count == 2 && but < 2)
+ {
+ int x2, y2; /* don't clobber original coordinates */
+
+ /* If only one button is pressed, wait 100 msec and
+ check again. This way, Speedy Gonzales isn't
+ punished, while the slow get their chance. */
+ if (press && mouse_pressed (1-but, &x2, &y2)
+ || !press && mouse_released (1-but, &x2, &y2))
+ button_num = 2;
+ else
+ {
+ delay (100);
+ if (press && mouse_pressed (1-but, &x2, &y2)
+ || !press && mouse_released (1-but, &x2, &y2))
+ button_num = 2;
+ }
+ }
+
event.kind = mouse_click;
- event.code = but;
+ event.code = button_num;
event.modifiers = dos_get_modifiers (0)
| (press ? down_modifier : up_modifier);
event.x = x;
static int prev_get_char = -1;
/* Return 1 if a key is ready to be read without suspending execution. */
+
dos_keysns ()
{
if (prev_get_char != -1)
}
/* Read a key. Return -1 if no key is ready. */
+
dos_keyread ()
{
if (prev_get_char != -1)
*height = maxheight;
}
-/* Display MENU at (X,Y) using FACES. */
+/* Display MENU at (X,Y) using FACES. */
static void
IT_menu_display (XMenu *menu, int y, int x, int *faces)
p = text;
*p++ = FAST_MAKE_GLYPH (' ', face);
for (j = 0, q = menu->text[i]; *q; j++)
- *p++ = FAST_MAKE_GLYPH (*q++, face);
+ {
+ if (*q > 26)
+ *p++ = FAST_MAKE_GLYPH (*q++, face);
+ else /* make '^x' */
+ {
+ *p++ = FAST_MAKE_GLYPH ('^', face);
+ j++;
+ *p++ = FAST_MAKE_GLYPH (*q++ + 64, face);
+ }
+ }
+
for (; j < width; j++)
*p++ = FAST_MAKE_GLYPH (' ', face);
*p++ = FAST_MAKE_GLYPH (menu->submenu[i] ? 16 : ' ', face);
XMenuAddPane (Display *foo, XMenu *menu, char *txt, int enable)
{
int len;
+ char *p;
if (!enable)
abort ();
menu->text[menu->count] = txt;
menu->panenumber[menu->count] = ++menu->panecount;
menu->count++;
- if ((len = strlen (txt)) > menu->width)
+
+ /* Adjust length for possible control characters (which will
+ be written as ^x). */
+ for (len = strlen (txt), p = txt; *p; p++)
+ if (*p < 27)
+ len++;
+
+ if (len > menu->width)
menu->width = len;
+
return menu->panecount;
}
int foo, char *txt, int enable)
{
int len;
+ char *p;
if (pane)
if (!(menu = IT_menu_search_pane (menu, pane)))
menu->text[menu->count] = txt;
menu->panenumber[menu->count] = enable;
menu->count++;
- if ((len = strlen (txt)) > menu->width)
+
+ /* Adjust length for possible control characters (which will
+ be written as ^x). */
+ for (len = strlen (txt), p = txt; *p; p++)
+ if (*p < 27)
+ len++;
+
+ if (len > menu->width)
menu->width = len;
+
return XM_SUCCESS;
}
int faces[4], selectface;
int leave, result, onepane;
int title_faces[4]; /* face to display the menu title */
+ int buffers_num_deleted = 0;
/* Just in case we got here without a mouse present... */
if (have_mouse <= 0)
state = alloca (menu->panecount * sizeof (struct IT_menu_state));
screensize = screen_size * 2;
faces[0]
- = compute_glyph_face (&the_only_frame,
+ = compute_glyph_face (selected_frame,
face_name_id_number
- (&the_only_frame,
+ (selected_frame,
intern ("msdos-menu-passive-face")),
0);
faces[1]
- = compute_glyph_face (&the_only_frame,
+ = compute_glyph_face (selected_frame,
face_name_id_number
- (&the_only_frame,
+ (selected_frame,
intern ("msdos-menu-active-face")),
0);
selectface
- = face_name_id_number (&the_only_frame, intern ("msdos-menu-select-face"));
- faces[2] = compute_glyph_face (&the_only_frame, selectface, faces[0]);
- faces[3] = compute_glyph_face (&the_only_frame, selectface, faces[1]);
+ = face_name_id_number (selected_frame, intern ("msdos-menu-select-face"));
+ faces[2] = compute_glyph_face (selected_frame, selectface, faces[0]);
+ faces[3] = compute_glyph_face (selected_frame, selectface, faces[1]);
/* Make sure the menu title is always displayed with
`msdos-menu-active-face', no matter where the mouse pointer is. */
title_faces[i] = faces[3];
statecount = 1;
+
+ /* Don't let the title for the "Buffers" popup menu include a
+ digit (which is ugly).
+
+ This is a terrible kludge, but I think the "Buffers" case is
+ the only one where the title includes a number, so it doesn't
+ seem to be necessary to make this more general. */
+ if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
+ {
+ menu->text[0][7] = '\0';
+ buffers_num_deleted = 1;
+ }
state[0].menu = menu;
mouse_off ();
ScreenRetrieve (state[0].screen_behind = xmalloc (screensize));
IT_menu_display (menu, y0 - 1, x0 - 1, title_faces); /* display menu title */
+ if (buffers_num_deleted)
+ menu->text[0][7] = ' ';
if ((onepane = menu->count == 1 && menu->submenu[0]))
{
menu->width = menu->submenu[0]->width;
\f
/* ----------------------- DOS / UNIX conversion --------------------- */
+void msdos_downcase_filename (unsigned char *);
+
/* Destructively turn backslashes into slashes. */
void
dostounix_filename (p)
register char *p;
{
+ msdos_downcase_filename (p);
+
while (*p)
{
if (*p == '\\')
unixtodos_filename (p)
register char *p;
{
+ if (p[1] == ':' && *p >= 'A' && *p <= 'Z')
+ {
+ *p += 'a' - 'A';
+ p += 2;
+ }
+
while (*p)
{
if (*p == '/')
int drive;
char *dst;
{
- union REGS regs;
+ char in_path[4], *p = in_path;
+ int e = errno;
- *dst++ = '/';
- regs.h.dl = drive;
- regs.x.si = (int) dst;
- regs.h.ah = 0x47;
- intdos (®s, ®s);
- return !regs.x.cflag;
+ /* Generate "X:." (when drive is X) or "." (when drive is 0). */
+ if (drive != 0)
+ {
+ *p++ = drive + 'A' - 1;
+ *p++ = ':';
+ }
+
+ *p++ = '.';
+ *p = '\0';
+ errno = 0;
+ _fixpath (in_path, dst);
+ if (errno)
+ return 0;
+
+ msdos_downcase_filename (dst);
+
+ errno = e;
+ return 1;
}
/* Remove all CR's that are followed by a LF. */
*np++ = *buf++;
return np - startp;
}
+
+#if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 0
+
+/* In DJGPP v2.0, library `write' can call `malloc', which might
+ cause relocation of the buffer whose address we get in ADDR.
+ Here is a version of `write' that avoids calling `malloc',
+ to serve us until such time as the library is fixed.
+ Actually, what we define here is called `__write', because
+ `write' is a stub that just jmp's to `__write' (to be
+ POSIXLY-correct with respect to the global name-space). */
+
+#include <io.h> /* for _write */
+#include <libc/dosio.h> /* for __file_handle_modes[] */
+
+static char xbuf[64 * 1024]; /* DOS cannot write more in one chunk */
+
+#define XBUF_END (xbuf + sizeof (xbuf) - 1)
+
+int
+__write (int handle, const void *buffer, size_t count)
+{
+ if (count == 0)
+ return 0;
+
+ if(__file_handle_modes[handle] & O_BINARY)
+ return _write (handle, buffer, count);
+ else
+ {
+ char *xbp = xbuf;
+ const char *bp = buffer;
+ int total_written = 0;
+ int nmoved = 0, ncr = 0;
+
+ while (count)
+ {
+ /* The next test makes sure there's space for at least 2 more
+ characters in xbuf[], so both CR and LF can be put there. */
+ if (xbp < XBUF_END)
+ {
+ if (*bp == '\n')
+ {
+ ncr++;
+ *xbp++ = '\r';
+ }
+ *xbp++ = *bp++;
+ nmoved++;
+ count--;
+ }
+ if (xbp >= XBUF_END || !count)
+ {
+ size_t to_write = nmoved + ncr;
+ int written = _write (handle, xbuf, to_write);
+
+ if (written == -1)
+ return -1;
+ else
+ total_written += nmoved; /* CRs aren't counted in ret value */
+
+ /* If some, but not all were written (disk full?), return
+ an estimate of the total written bytes not counting CRs. */
+ if (written < to_write)
+ return total_written - (to_write - written) * nmoved/to_write;
+
+ nmoved = 0;
+ ncr = 0;
+ xbp = xbuf;
+ }
+ }
+ return total_written;
+ }
+}
+
+#endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */
+
+DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names,
+ 0, 0, 0,
+ "Return non-nil if long file names are supported on MSDOS.")
+ ()
+{
+ return (_USE_LFN ? Qt : Qnil);
+}
+
+/* Convert alphabetic characters in a filename to lower-case. */
+
+void
+msdos_downcase_filename (p)
+ register unsigned char *p;
+{
+ /* Always lower-case drive letters a-z, even if the filesystem
+ preserves case in filenames.
+ This is so MSDOS filenames could be compared by string comparison
+ functions that are case-sensitive. Even case-preserving filesystems
+ do not distinguish case in drive letters. */
+ if (p[1] == ':' && *p >= 'A' && *p <= 'Z')
+ {
+ *p += 'a' - 'A';
+ p += 2;
+ }
+
+ /* Under LFN we expect to get pathnames in their true case. */
+ if (NILP (Fmsdos_long_file_names ()))
+ for ( ; *p; p++)
+ if (*p >= 'A' && *p <= 'Z')
+ *p += 'a' - 'A';
+}
+
+DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename, Smsdos_downcase_filename,
+ 1, 1, 0,
+ "Convert alphabetic characters in FILENAME to lower case and return that.\n\
+When long filenames are supported, doesn't change FILENAME.\n\
+If FILENAME is not a string, returns nil.\n\
+The argument object is never altered--the value is a copy.")
+ (filename)
+ Lisp_Object filename;
+{
+ char *fname;
+ Lisp_Object tem;
+
+ if (! STRINGP (filename))
+ return Qnil;
+
+ tem = Fcopy_sequence (filename);
+ msdos_downcase_filename (XSTRING (tem)->data);
+ return tem;
+}
\f
/* The Emacs root directory as determined by init_environment. */
"c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
root = alloca (MAXPATHLEN + 20);
_fixpath (argv[0], root);
- strlwr (root);
+ msdos_downcase_filename (root);
len = strlen (root);
while (len > 0 && root[len] != '/' && root[len] != ':')
len--;
if (!s) s = "c:/command.com";
t = alloca (strlen (s) + 1);
strcpy (t, s);
- strlwr (t);
dostounix_filename (t);
setenv ("SHELL", t, 0);
/* Current directory is always considered part of MsDos's path but it is
not normally mentioned. Now it is. */
strcat (strcpy (t, ".;"), s);
- strlwr (t);
dostounix_filename (t); /* Not a single file name, but this should work. */
setenv ("PATH", t, 1);
setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
break;
}
- init_gettimeofday ();
+ tzset ();
}
\f
static int break_stat; /* BREAK check mode status. */
static int stdin_stat; /* stdin IOCTL status. */
+#if __DJGPP__ < 2
+
/* These must be global. */
static _go32_dpmi_seginfo ctrl_break_vector;
static _go32_dpmi_registers ctrl_break_regs;
}
}
-/*
- * Turn off Dos' Ctrl-C checking and inhibit interpretation of
- * control chars by Dos.
- * Determine the keyboard type.
- */
+#endif /* __DJGPP__ < 2 */
+
+/* Turn off Dos' Ctrl-C checking and inhibit interpretation of
+ control chars by DOS. Determine the keyboard type. */
int
dos_ttraw ()
break_stat = getcbrk ();
setcbrk (0);
+#if __DJGPP__ < 2
install_ctrl_break_check ();
+#endif
if (first_time)
{
mouse_init ();
}
}
-
+
first_time = 0;
+
+#if __DJGPP__ >= 2
+
+ stdin_stat = setmode (fileno (stdin), O_BINARY);
+ return (stdin_stat != -1);
+ }
+ else
+ return (setmode (fileno (stdin), O_BINARY) != -1);
+
+#else /* __DJGPP__ < 2 */
+
}
+ /* I think it is wrong to overwrite `stdin_stat' every time
+ but the first one this function is called, but I don't
+ want to change the way it used to work in v1.x.--EZ */
+
inregs.x.ax = 0x4400; /* Get IOCTL status. */
inregs.x.bx = 0x00; /* 0 = stdin. */
intdos (&inregs, &outregs);
inregs.x.ax = 0x4401; /* Set IOCTL status */
intdos (&inregs, &outregs);
return !outregs.x.cflag;
+
+#endif /* __DJGPP__ < 2 */
}
/* Restore status of standard input and Ctrl-C checking. */
+
int
dos_ttcooked ()
{
setcbrk (break_stat);
mouse_off ();
+#if __DJGPP__ >= 2
+
+ return (setmode (fileno (stdin), stdin_stat) != -1);
+
+#else /* not __DJGPP__ >= 2 */
+
inregs.x.ax = 0x4401; /* Set IOCTL status. */
inregs.x.bx = 0x00; /* 0 = stdin. */
inregs.x.dx = stdin_stat;
intdos (&inregs, &outregs);
return !outregs.x.cflag;
+
+#endif /* not __DJGPP__ >= 2 */
}
\f
/* Run command as specified by ARGV in directory DIR.
The command is run with input from TEMPIN, output to
file TEMPOUT and stderr to TEMPERR. */
+
int
run_msdos_command (argv, dir, tempin, tempout, temperr)
unsigned char **argv;
dup2 (tempout, 1);
dup2 (temperr, 2);
+#if __DJGPP__ > 1
+
+ if (msshell && !argv[3])
+ {
+ /* MS-DOS native shells are too restrictive. For starters, they
+ cannot grok commands longer than 126 characters. In DJGPP v2
+ and later, `system' is much smarter, so we'll call it instead. */
+
+ extern char **environ;
+ environ = envv;
+
+ /* A shell gets a single argument--its full command
+ line--whose original was saved in `saveargv2'. */
+ result = system (saveargv2);
+ }
+ else
+
+#endif /* __DJGPP__ > 1 */
+
result = spawnve (P_WAIT, argv[0], argv, envv);
dup2 (inbak, 0);
exit (1);
}
\f
+#if __DJGPP__ < 2
+
/* ------------------------- Compatibility functions -------------------
* gethostname
* gettimeofday
*/
-/*
- * Hostnames for a pc are not really funny,
- * but they are used in change log so we emulate the best we can.
- */
+/* Hostnames for a pc are not really funny,
+ but they are used in change log so we emulate the best we can. */
gethostname (p, size)
char *p;
return 0;
}
+#endif /* __DJGPP__ < 2 */
/*
* A list of unimplemented functions that we silently ignore.
*/
+#if __DJGPP__ < 2
unsigned alarm (s) unsigned s; {}
fork () { return 0; }
int kill (x, y) int x, y; { return -1; }
nice (p) int p; {}
void volatile pause () {}
+sigsetmask (x) int x; { return 0; }
+#endif
+
request_sigio () {}
setpgrp () {return 0; }
setpriority (x,y,z) int x,y,z; { return 0; }
-sigsetmask (x) int x; { return 0; }
sigblock (mask) int mask; { return 0; }
unrequest_sigio () {}
#ifndef HAVE_SELECT
#include "sysselect.h"
-static struct time last_time = {120, 120, 120, 120};
-static int modeline_time_displayed = 0;
-
-Lisp_Object Vdos_display_time;
-
-static void
-check_timer (t)
- struct time *t;
-{
- int sec, min, hour, hund;
-
- gettime (t);
- sec = t->ti_sec;
- hund = t->ti_hund;
- hour = t->ti_hour;
- min = t->ti_min;
-
- /* Any chance of not getting here 24 hours or more since last time? */
- if (hour == last_time.ti_hour
- && min == last_time.ti_min
- && sec == last_time.ti_sec)
- return;
-
- if (!NILP (Vdos_display_time))
- {
- int interval;
- Lisp_Object dti = XSYMBOL (Fintern_soft (build_string ("display-time-interval"), Qnil))->value;
- int delta_time = ((hour - last_time.ti_hour) * 3600
- + (min - last_time.ti_min) * 60
- + (sec - last_time.ti_sec));
-
- /* Who knows what the user may put into `display-time-interval'? */
- if (!INTEGERP (dti) || (interval = XINT (dti)) <= 0)
- interval = 60;
-
- /* When it's time to renew the display, fake a `wakeup' call. */
- if (!modeline_time_displayed /* first time */
- || delta_time >= interval /* or if we were busy for a long time */
- || interval == 1 /* and every `interval' seconds hence */
- || interval == 60 && sec == 0 /* (usual cases first) */
- || (hour * 3600 + min * 60 + sec) % interval == 0)
- call2 (intern ("display-time-filter"), Qnil,
- build_string ("Wake up!\n"));
-
- modeline_time_displayed = 1;
- }
- else if (modeline_time_displayed)
- {
- modeline_time_displayed = 0;
- Fset (intern ("display-time-string"), build_string (""));
+#ifndef EMACS_TIME_ZERO_OR_NEG_P
+#define EMACS_TIME_ZERO_OR_NEG_P(time) \
+ ((long)(time).tv_sec < 0 \
+ || ((time).tv_sec == 0 \
+ && (long)(time).tv_usec <= 0))
+#endif
- /* Force immediate redisplay of modelines. */
- update_mode_lines++;
- redisplay_preserve_echo_area ();
- }
-
- last_time = *t;
-}
/* Only event queue is checked. */
+/* We don't have to call timer_check here
+ because wait_reading_process_input takes care of that. */
int
sys_select (nfds, rfds, wfds, efds, timeout)
int nfds;
EMACS_TIME *timeout;
{
int check_input;
- long timeoutval, clnow, cllast;
struct time t;
check_input = 0;
just read it and wait -- that's more efficient. */
if (!timeout)
{
- do
- check_timer (&t); /* check timer even if some input is pending */
- while (!detect_input_pending ());
+ while (!detect_input_pending ())
+ {
+#if __DJGPP__ >= 2
+ __dpmi_yield ();
+#endif
+ }
}
else
{
- timeoutval = EMACS_SECS (*timeout) * 100 + EMACS_USECS (*timeout) / 10000;
- check_timer (&t);
- cllast = t.ti_sec * 100 + t.ti_hund;
+ EMACS_TIME clnow, cllast, cldiff;
+
+ gettime (&t);
+ EMACS_SET_SECS_USECS (cllast, t.ti_sec, t.ti_hund * 10000L);
while (!check_input || !detect_input_pending ())
{
- check_timer (&t);
- clnow = t.ti_sec * 100 + t.ti_hund;
- if (clnow < cllast) /* time wrap */
- timeoutval -= clnow + 6000 - cllast;
- else
- timeoutval -= clnow - cllast;
- if (timeoutval <= 0) /* Stop on timer being cleared */
+ gettime (&t);
+ EMACS_SET_SECS_USECS (clnow, t.ti_sec, t.ti_hund * 10000L);
+ EMACS_SUB_TIME (cldiff, clnow, cllast);
+
+ /* When seconds wrap around, we assume that no more than
+ 1 minute passed since last `gettime'. */
+ if (EMACS_TIME_NEG_P (cldiff))
+ EMACS_SET_SECS (cldiff, EMACS_SECS (cldiff) + 60);
+ EMACS_SUB_TIME (*timeout, *timeout, cldiff);
+
+ /* Stop when timeout value crosses zero. */
+ if (EMACS_TIME_ZERO_OR_NEG_P (*timeout))
return 0;
cllast = clnow;
+#if __DJGPP__ >= 2
+ __dpmi_yield ();
+#endif
}
}
dos_ttcooked ();
ScreenSetCursor (10, 0);
cputs ("\r\n\nEmacs aborted!\r\n");
+#if __DJGPP__ > 1
+ /* Generate traceback, so we could tell whodunit. */
+ signal (SIGINT, SIG_DFL);
+ __asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
+#endif
exit (2);
}
#endif
staticpro (&recent_doskeys);
defsubr (&Srecent_doskeys);
-
- DEFVAR_LISP ("dos-display-time", &Vdos_display_time,
- "*When non-nil, `display-time' is in effect on DOS systems.");
- Vdos_display_time = Qnil;
+ defsubr (&Smsdos_long_file_names);
+ defsubr (&Smsdos_downcase_filename);
}
#endif /* MSDOS */