return (regs.x.bx != 0);
}
+static int
+mouse_button_depressed (b, xp, yp)
+ int b, *xp, *yp;
+{
+ union REGS regs;
+
+ if (b >= mouse_button_count)
+ return 0;
+ regs.x.ax = 0x0003;
+ int86 (0x33, ®s, ®s);
+ if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0)
+ {
+ *xp = regs.x.cx / 8;
+ *yp = regs.x.dx / 8;
+ return 1;
+ }
+ return 0;
+}
+
void
mouse_get_pos (f, insist, bar_window, part, x, y, time)
FRAME_PTR *f;
mouse_init ()
{
union REGS regs;
+ int b;
if (termscript)
fprintf (termscript, "<M_INIT>");
regs.x.ax = 0x0021;
int86 (0x33, ®s, ®s);
+ /* Reset the mouse last press/release info. It seems that Windows
+ doesn't do that automatically when function 21h is called, which
+ causes Emacs to ``remember'' the click that switched focus to the
+ window just before Emacs was started from that window. */
+ for (b = 0; b < mouse_button_count; b++)
+ {
+ int dummy_x, dummy_y;
+
+ (void) mouse_pressed (b, &dummy_x, &dummy_y);
+ (void) mouse_released (b, &dummy_x, &dummy_y);
+ }
+
regs.x.ax = 0x0007;
regs.x.cx = 0;
regs.x.dx = 8 * (ScreenCols () - 1);
mouse_off ();
}
-static
-IT_ring_bell ()
+static void
+IT_ring_bell (void)
{
if (visible_bell)
{
ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
}
-static
+static void
IT_write_glyphs (GLYPH *str, int len)
{
int newface;
new_pos_X += len;
}
-static
-IT_clear_end_of_line (first_unused)
+static void
+IT_clear_end_of_line (int first_unused)
{
char *spaces, *sp;
int i, j;
dosv_refresh_virtual_screen (offset, i / 2);
}
-static
+static void
IT_clear_screen (void)
{
if (termscript)
new_pos_X = new_pos_Y = 0;
}
-static
+static void
IT_clear_to_end (void)
{
if (termscript)
}
}
-static
+static void
IT_cursor_to (int y, int x)
{
if (termscript)
Special treatment is required when the cursor is in the echo area,
to put the cursor at the end of the text displayed there. */
-static
-IT_cmgoto (f)
- FRAME_PTR f;
+static void
+IT_cmgoto (FRAME_PTR f)
{
/* Only set the cursor to where it should be if the display is
already in sync with the window contents. */
int update_cursor_pos = MODIFF == unchanged_modified;
-
- /* If we are in the echo area, put the cursor at the end of text. */
+ static int previous_pos_X = -1;
+
+ /* If the display is in sync, forget any previous knowledge about
+ cursor position. This is primarily for unexpected events like
+ C-g in the minibuffer. */
+ if (update_cursor_pos && previous_pos_X >= 0)
+ previous_pos_X = -1;
+ /* If we are in the echo area, put the cursor at the
+ end of the echo area message. */
if (!update_cursor_pos
&& XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
{
- new_pos_X = FRAME_DESIRED_GLYPHS (f)->used[new_pos_Y];
- update_cursor_pos = 1;
+ int tem_X = current_pos_X, dummy;
+
+ if (echo_area_glyphs)
+ {
+ tem_X = echo_area_glyphs_length;
+ /* Save current cursor position, to be restored after the
+ echo area message is erased. Only remember one level
+ of previous cursor position. */
+ if (previous_pos_X == -1)
+ ScreenGetCursor (&dummy, &previous_pos_X);
+ }
+ else if (previous_pos_X >= 0)
+ {
+ /* We wind up here after the echo area message is erased.
+ Restore the cursor position we remembered above. */
+ tem_X = previous_pos_X;
+ previous_pos_X = -1;
+ }
+
+ if (current_pos_X != tem_X)
+ {
+ new_pos_X = tem_X;
+ update_cursor_pos = 1;
+ }
}
if (update_cursor_pos
mouse_on ();
}
-static
-IT_reassert_line_highlight (new, vpos)
- int new, vpos;
+static void
+IT_reassert_line_highlight (int new, int vpos)
{
highlight = new;
IT_set_face (0); /* To possibly clear the highlighting. */
}
-static
-IT_change_line_highlight (new_highlight, vpos, first_unused_hpos)
+static void
+IT_change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
{
highlight = new_highlight;
IT_set_face (0); /* To possibly clear the highlighting. */
IT_clear_end_of_line (first_unused_hpos);
}
-static
-IT_update_begin ()
+static void
+IT_update_begin (struct frame *foo)
{
highlight = 0;
IT_set_face (0); /* To possibly clear the highlighting. */
screen_face = -1;
}
-static
-IT_update_end ()
+static void
+IT_update_end (struct frame *foo)
{
}
/* IT_set_terminal_modes is called when emacs is started,
resumed, and whenever the screen is redrawn! */
-static
+static void
IT_set_terminal_modes (void)
{
if (termscript)
/* IT_reset_terminal_modes is called when emacs is
suspended or killed. */
-static
+static void
IT_reset_terminal_modes (void)
{
int display_row_start = (int) ScreenPrimary;
term_setup_done = 0;
}
-static
-IT_set_terminal_window (void)
+static void
+IT_set_terminal_window (int foo)
{
}
int always;
{
int i;
- union REGS regs;
+ _go32_dpmi_registers regs;
- /* See if Keyb.Com is installed (for international keyboard support). */
+ /* See if Keyb.Com is installed (for international keyboard support).
+ Note: calling Int 2Fh via int86 wedges the DOS box on some versions
+ of Windows 9X! So don't do that! */
regs.x.ax = 0xad80;
- int86 (0x2f, ®s, ®s);
+ regs.x.ss = regs.x.sp = regs.x.flags = 0;
+ _go32_dpmi_simulate_int (0x2f, ®s);
if (regs.h.al == 0xff)
international_keyboard = 1;
/* Get a char from keyboard. Function keys are put into the event queue. */
extern void kbd_buffer_store_event (struct input_event *);
+static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
static int
dos_rawgetc ()
kbd_buffer_store_event (&event);
}
- if (have_mouse > 0)
+ if (have_mouse > 0 && !mouse_preempted)
{
int but, press, x, y, ok;
FRAME_PTR f;
register int pix_x, pix_y;
register int *x, *y;
- void /* XRectangle */ *bounds;
+ XRectangle *bounds;
int noclip;
{
if (bounds) abort ();
text = (GLYPH *) xmalloc ((width + 2) * sizeof (GLYPH));
ScreenGetCursor (&row, &col);
mouse_get_xy (&mx, &my);
- IT_update_begin ();
+ IT_update_begin (selected_frame);
for (i = 0; i < menu->count; i++)
{
IT_cursor_to (y + i, x);
*p++ = FAST_MAKE_GLYPH (menu->submenu[i] ? 16 : ' ', face);
IT_write_glyphs (text, width + 2);
}
- IT_update_end ();
+ IT_update_end (selected_frame);
IT_cursor_to (row, col);
xfree (text);
}
if (y0 <= 0)
y0 = 1;
+ /* We will process all the mouse events directly, so we had
+ better prevented dos_rawgetc from stealing them from us. */
+ mouse_preempted++;
+
state = alloca (menu->panecount * sizeof (struct IT_menu_state));
screensize = screen_size * 2;
faces[0]
state[statecount - 1].x,
faces);
}
- for (b = 0; b < mouse_button_count; b++)
+ else
+ /* We are busy-waiting for the mouse to move, so let's be nice
+ to other Windows applications by releasing our time slice. */
+ __dpmi_yield ();
+ for (b = 0; b < mouse_button_count && !leave; b++)
{
- (void) mouse_pressed (b, &x, &y);
- if (mouse_released (b, &x, &y))
- leave = 1;
+ /* Only leave if user both pressed and released the mouse, and in
+ that order. This avoids popping down the menu pane unless
+ the user is really done with it. */
+ if (mouse_pressed (b, &x, &y))
+ {
+ while (mouse_button_depressed (b, &x, &y))
+ __dpmi_yield ();
+ leave = 1;
+ }
+ (void) mouse_released (b, &x, &y);
}
}
while (statecount--)
xfree (state[statecount].screen_behind);
IT_display_cursor (1); /* turn cursor back on */
+ /* Clean up any mouse events that are waiting inside Emacs event queue.
+ These events are likely to be generated before the menu was even
+ displayed, probably because the user pressed and released the button
+ (which invoked the menu) too quickly. If we don't remove these events,
+ Emacs will process them after we return and surprise the user. */
+ discard_mouse_events ();
+ /* Allow mouse events generation by dos_rawgetc. */
+ mouse_preempted--;
return result;
}
{
char *s, *t, *root;
int len;
+ static const char * const tempdirs[] = {
+ "$TMPDIR", "$TEMP", "$TMP", "c:/"
+ };
+ int i;
+ const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
+
+ /* Make sure they have a usable $TMPDIR. Many Emacs functions use
+ temporary files and assume "/tmp" if $TMPDIR is unset, which
+ will break on DOS/Windows. Refuse to work if we cannot find
+ a directory, not even "c:/", usable for that purpose. */
+ for (i = 0; i < imax ; i++)
+ {
+ const char *tmp = tempdirs[i];
+
+ if (*tmp == '$')
+ tmp = getenv (tmp + 1);
+ /* Note that `access' can lie to us if the directory resides on a
+ read-only filesystem, like CD-ROM or a write-protected floppy.
+ The only way to be really sure is to actually create a file and
+ see if it succeeds. But I think that's too much to ask. */
+ if (tmp && access (tmp, D_OK) == 0)
+ {
+ setenv ("TMPDIR", tmp, 1);
+ break;
+ }
+ }
+ if (i >= imax)
+ cmd_error_internal
+ (Fcons (Qerror,
+ Fcons (build_string ("no usable temporary directories found!!"),
+ Qnil)),
+ "While setting TMPDIR: ");
/* Find our root from argv[0]. Assuming argv[0] is, say,
"c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
&& (long)(time).tv_usec <= 0))
#endif
+/* This yields the rest of the current time slice to the task manager.
+ It should be called by any code which knows that it has nothing
+ useful to do except idle.
+
+ I don't use __dpmi_yield here, since versions of library before 2.02
+ called Int 2Fh/AX=1680h there in a way that would wedge the DOS box
+ on some versions of Windows 9X. */
+
+void
+dos_yield_time_slice (void)
+{
+ _go32_dpmi_registers r;
+
+ r.x.ax = 0x1680;
+ r.x.ss = r.x.sp = r.x.flags = 0;
+ _go32_dpmi_simulate_int (0x2f, &r);
+ if (r.h.al == 0x80)
+ errno = ENOSYS;
+}
/* Only event queue is checked. */
/* We don't have to call timer_check here
{
while (!detect_input_pending ())
{
-#if __DJGPP__ >= 2
- __dpmi_yield ();
-#endif
+ dos_yield_time_slice ();
}
}
else
if (EMACS_TIME_ZERO_OR_NEG_P (*timeout))
return 0;
cllast = clnow;
-#if __DJGPP__ >= 2
- __dpmi_yield ();
-#endif
+ dos_yield_time_slice ();
}
}