X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9ab8560dc21300b8d7fe5ce9aee37c2244f4642e..660872b63b75b61d11b09471b5a254e1e5db3c1c:/src/msdos.c diff --git a/src/msdos.c b/src/msdos.c index cfb19c652f..79ac0b9026 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -1,5 +1,6 @@ /* MS-DOS specific C utilities. -*- coding: raw-text -*- - Copyright (C) 1993, 94, 95, 96, 97, 1999 Free Software Foundation, Inc. + Copyright (C) 1993, 94, 95, 96, 97, 1999, 2000, 2001 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -61,6 +62,7 @@ Boston, MA 02111-1307, USA. */ #include "buffer.h" #include "commands.h" #include "blockinput.h" +#include "keyboard.h" #include #include #include @@ -167,6 +169,45 @@ mouse_off () } } +static void +mouse_setup_buttons (int n_buttons) +{ + if (n_buttons == 3) + { + mouse_button_count = 3; + mouse_button_translate[0] = 0; /* Left */ + mouse_button_translate[1] = 2; /* Middle */ + mouse_button_translate[2] = 1; /* Right */ + } + else /* two, what else? */ + { + mouse_button_count = 2; + mouse_button_translate[0] = 0; + mouse_button_translate[1] = 1; + } +} + +DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons, Smsdos_set_mouse_buttons, + 1, 1, "NSet number of mouse buttons to: ", + "Set the number of mouse buttons to use by Emacs.\n\ +This is useful with mice that report the number of buttons inconsistently,\n\ +e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of\n\ +them. This happens with wheeled mice on Windows 9X, for example.") + (nbuttons) + Lisp_Object nbuttons; +{ + int n; + + CHECK_NUMBER (nbuttons, 0); + n = XINT (nbuttons); + if (n < 2 || n > 3) + Fsignal (Qargs_out_of_range, + Fcons (build_string ("only 2 or 3 mouse buttons are supported"), + Fcons (nbuttons, Qnil))); + mouse_setup_buttons (n); + return Qnil; +} + static void mouse_get_xy (int *x, int *y) { @@ -277,11 +318,26 @@ mouse_check_moved () mouse_last_y = y; } +/* Force the mouse driver to ``forget'' about any button clicks until + now. */ +static void +mouse_clear_clicks (void) +{ + int b; + + 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); + } +} + void mouse_init () { union REGS regs; - int b; if (termscript) fprintf (termscript, ""); @@ -293,13 +349,7 @@ mouse_init () 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); - } + mouse_clear_clicks (); regs.x.ax = 0x0007; regs.x.cx = 0; @@ -418,29 +468,29 @@ do_visible_bell (xorattr) unsigned char xorattr; { asm volatile - (" movb $1,%%dl -visible_bell_0: - movl _ScreenPrimary,%%eax - call dosmemsetup - movl %%eax,%%ebx - movl %1,%%ecx - movb %0,%%al - incl %%ebx -visible_bell_1: - xorb %%al,%%gs:(%%ebx) - addl $2,%%ebx - decl %%ecx - jne visible_bell_1 - decb %%dl - jne visible_bell_3 -visible_bell_2: - movzwl %%ax,%%eax - movzwl %%ax,%%eax - movzwl %%ax,%%eax - movzwl %%ax,%%eax - decw %%cx - jne visible_bell_2 - jmp visible_bell_0 + (" movb $1,%%dl \n\ +visible_bell_0: \n\ + movl _ScreenPrimary,%%eax \n\ + call dosmemsetup \n\ + movl %%eax,%%ebx \n\ + movl %1,%%ecx \n\ + movb %0,%%al \n\ + incl %%ebx \n\ +visible_bell_1: \n\ + xorb %%al,%%gs:(%%ebx) \n\ + addl $2,%%ebx \n\ + decl %%ecx \n\ + jne visible_bell_1 \n\ + decb %%dl \n\ + jne visible_bell_3 \n\ +visible_bell_2: \n\ + movzwl %%ax,%%eax \n\ + movzwl %%ax,%%eax \n\ + movzwl %%ax,%%eax \n\ + movzwl %%ax,%%eax \n\ + decw %%cx \n\ + jne visible_bell_2 \n\ + jmp visible_bell_0 \n\ visible_bell_3:" : /* no output */ : "m" (xorattr), "g" (screen_size) @@ -628,6 +678,11 @@ dos_set_window_size (rows, cols) *rows = ScreenRows (); *cols = ScreenCols (); + /* Update Emacs' notion of screen dimensions. */ + screen_size_X = *cols; + screen_size_Y = *rows; + screen_size = *cols * *rows; + #if __DJGPP__ > 1 /* If the dimensions changed, the mouse highlight info is invalid. */ if (current_rows != *rows || current_cols != *cols) @@ -822,12 +877,13 @@ static void IT_set_face (int face) { struct frame *sf = SELECTED_FRAME(); - struct face *fp = FACE_FROM_ID (sf, face); - unsigned long fg, bg; + struct face *fp = FACE_FROM_ID (sf, face); + struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID); + unsigned long fg, bg, dflt_fg, dflt_bg; if (!fp) { - fp = FACE_FROM_ID (sf, DEFAULT_FACE_ID); + fp = dfp; /* The default face for the frame should always be realized and cached. */ if (!fp) @@ -836,6 +892,8 @@ IT_set_face (int face) screen_face = face; fg = fp->foreground; bg = fp->background; + dflt_fg = dfp->foreground; + dflt_bg = dfp->background; /* Don't use invalid colors. In particular, FACE_TTY_DEFAULT_* colors mean use the colors of the default face, except that if @@ -854,14 +912,21 @@ IT_set_face (int face) /* Make sure highlighted lines really stand out, come what may. */ if ((highlight || fp->tty_reverse_p) - && (fg == FRAME_FOREGROUND_PIXEL (sf) - && bg == FRAME_BACKGROUND_PIXEL (sf))) + && (fg == dflt_fg && bg == dflt_bg)) { unsigned long tem = fg; fg = bg; bg = tem; } + /* If the user requested inverse video, obey. */ + if (inverse_video) + { + unsigned long tem2 = fg; + + fg = bg; + bg = tem2; + } if (termscript) fprintf (termscript, "", face, highlight ? "H" : "", fp->foreground, fp->background, fg, bg); @@ -890,9 +955,13 @@ IT_write_glyphs (struct glyph *str, int str_len) register int tlen = GLYPH_TABLE_LENGTH; register Lisp_Object *tbase = GLYPH_TABLE_BASE; - struct coding_system *coding = (CODING_REQUIRE_ENCODING (&terminal_coding) - ? &terminal_coding - : &safe_terminal_coding); + /* If terminal_coding does any conversion, use it, otherwise use + safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here + because it always returns 1 if terminal_coding.src_multibyte is 1. */ + struct coding_system *coding = + (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK + ? &terminal_coding + : &safe_terminal_coding); struct frame *sf; /* Do we need to consider conversion of unibyte characters to @@ -901,6 +970,9 @@ IT_write_glyphs (struct glyph *str, int str_len) = (NILP (current_buffer->enable_multibyte_characters) && unibyte_display_via_language_environment); + unsigned char conversion_buffer[256]; + int conversion_buffer_size = sizeof conversion_buffer; + if (str_len <= 0) return; screen_buf = screen_bp = alloca (str_len * 2); @@ -936,6 +1008,9 @@ IT_write_glyphs (struct glyph *str, int str_len) register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str); int glyph_not_in_table = 0; + /* If g is negative, it means we have a multibyte character + in *str. That's what GLYPH_FROM_CHAR_GLYPH returns for + multibyte characters. */ if (g < 0 || g >= tlen) { /* This glyph doesn't have an entry in Vglyph_table. */ @@ -971,7 +1046,7 @@ IT_write_glyphs (struct glyph *str, int str_len) /* If the face of this glyph is different from the current screen face, update the screen attribute byte. */ - cf = FAST_GLYPH_FACE (g); + cf = str->face_id; if (cf != screen_face) IT_set_face (cf); /* handles invalid faces gracefully */ @@ -997,6 +1072,7 @@ IT_write_glyphs (struct glyph *str, int str_len) } else { + coding->src_multibyte = 1; encode_coding (coding, buf, conversion_buffer, chlen, conversion_buffer_size); chlen -= coding->consumed; @@ -1006,7 +1082,7 @@ IT_write_glyphs (struct glyph *str, int str_len) terminal_coding with Vdos_unsupported_char_glyph. */ if (*conversion_buffer == '?') { - char *cbp = conversion_buffer; + unsigned char *cbp = conversion_buffer; while (cbp < conversion_buffer + enclen && *cbp == '?') *cbp++ = unsupported_char; @@ -1107,11 +1183,18 @@ IT_write_glyphs (struct glyph *str, int str_len) /* This is used for debugging, to turn off note_mouse_highlight. */ int disable_mouse_highlight; -/* If a string, dos_rawgetc generates an event to display that string. - (The display is done in keyboard.c:read_char.) */ +/* If non-nil, dos_rawgetc generates an event to display that string. + (The display is done in keyboard.c:read_char, by calling + show_help_echo.) */ static Lisp_Object help_echo; static Lisp_Object previous_help_echo; /* a helper temporary variable */ +/* These record the window, the object and the position where the help + echo string was generated. */ +static Lisp_Object help_echo_window; +static Lisp_Object help_echo_object; +static int help_echo_pos; + static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */ /* Set the mouse pointer shape according to whether it is in the @@ -1181,6 +1264,9 @@ show_mouse_face (struct display_info *dpyinfo, int hl) if (end_hpos <= start_hpos) continue; + /* Record that some glyphs of this row are displayed in + mouse-face. */ + row->mouse_face_p = hl > 0; if (hl > 0) { int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w); @@ -1293,6 +1379,11 @@ fast_find_position (struct window *w, int pos, int *hpos, int *vpos) } else if (line_start_position > 0) best_row = row; + + /* Don't overstep the last matrix row, lest we get into the + never-never land... */ + if (row->y + 1 >= yb) + break; ++row; } @@ -1370,8 +1461,13 @@ IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p) setting the global variable help_echo to the help string. */ help = Fget_text_property (make_number (glyph->charpos), Qhelp_echo, glyph->object); - if (STRINGP (help)) - help_echo = help; + if (!NILP (help)) + { + help_echo = help; + XSETWINDOW (help_echo_window, w); + help_echo_object = glyph->object; + help_echo_pos = glyph->charpos; + } } } } @@ -1384,7 +1480,7 @@ static void IT_note_mouse_highlight (struct frame *f, int x, int y) { struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - int portion; + int portion = -1; Lisp_Object window; struct window *w; @@ -1443,16 +1539,22 @@ IT_note_mouse_highlight (struct frame *f, int x, int y) && (XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))) { - int pos, i, area; + int pos, i; struct glyph_row *row; struct glyph *glyph; + int nrows = w->current_matrix->nrows; /* Find the glyph under X/Y. */ glyph = NULL; - if (y < w->current_matrix->nrows) + if (y >= 0 && y < nrows) { row = MATRIX_ROW (w->current_matrix, y); - if (row->enabled_p + /* Give up if some row before the one we are looking for is + not enabled. */ + for (i = 0; i <= y; i++) + if (!MATRIX_ROW (w->current_matrix, i)->enabled_p) + break; + if (i > y /* all rows upto and including the one at Y are enabled */ && row->displays_text_p && x < window_box_width (w, TEXT_AREA)) { @@ -1509,14 +1611,16 @@ IT_note_mouse_highlight (struct frame *f, int x, int y) enough space for all, and try again. */ len = 10; overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); - noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL); + noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); if (noverlays > len) { len = noverlays; overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); - noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL); + noverlays = overlays_at (pos, + 0, &overlay_vec, &len, NULL, NULL, 0); } + /* Sort overlays into increasing priority order. */ noverlays = sort_overlays (overlay_vec, noverlays, w); /* Check mouse-face highlighting. */ @@ -1534,7 +1638,7 @@ IT_note_mouse_highlight (struct frame *f, int x, int y) /* Find highest priority overlay that has a mouse-face prop. */ overlay = Qnil; - for (i = 0; i < noverlays; i++) + for (i = noverlays - 1; i >= 0; --i) { mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); if (!NILP (mouse_face)) @@ -1618,22 +1722,38 @@ IT_note_mouse_highlight (struct frame *f, int x, int y) /* Check overlays first. */ help = Qnil; - for (i = 0; i < noverlays && !STRINGP (help); ++i) - help = Foverlay_get (overlay_vec[i], Qhelp_echo); + for (i = noverlays - 1; i >= 0 && NILP (help); --i) + { + overlay = overlay_vec[i]; + help = Foverlay_get (overlay, Qhelp_echo); + } + if (!NILP (help)) + { + help_echo = help; + help_echo_window = window; + help_echo_object = overlay; + help_echo_pos = pos; + } /* Try text properties. */ - if (!STRINGP (help) - && ((STRINGP (glyph->object) - && glyph->charpos >= 0 - && glyph->charpos < XSTRING (glyph->object)->size) - || (BUFFERP (glyph->object) - && glyph->charpos >= BEGV - && glyph->charpos < ZV))) - help = Fget_text_property (make_number (glyph->charpos), - Qhelp_echo, glyph->object); - - if (STRINGP (help)) - help_echo = help; + else if (NILP (help) + && ((STRINGP (glyph->object) + && glyph->charpos >= 0 + && glyph->charpos < XSTRING (glyph->object)->size) + || (BUFFERP (glyph->object) + && glyph->charpos >= BEGV + && glyph->charpos < ZV))) + { + help = Fget_text_property (make_number (glyph->charpos), + Qhelp_echo, glyph->object); + if (!NILP (help)) + { + help_echo = help; + help_echo_window = window; + help_echo_object = glyph->object; + help_echo_pos = glyph->charpos; + } + } } BEGV = obegv; @@ -1833,12 +1953,13 @@ static void IT_update_begin (struct frame *f) { struct display_info *display_info = FRAME_X_DISPLAY_INFO (f); + struct frame *mouse_face_frame = display_info->mouse_face_mouse_frame; highlight = 0; BLOCK_INPUT; - if (f == display_info->mouse_face_mouse_frame) + if (f && f == mouse_face_frame) { /* Don't do highlighting for mouse motion during the update. */ display_info->mouse_face_defer = 1; @@ -1850,9 +1971,8 @@ IT_update_begin (struct frame *f) /* Can we tell that this update does not affect the window where the mouse highlight is? If so, no need to turn off. - Likewise, don't do anything if the frame is garbaged; - in that case, the frame's current matrix that we would use - is all wrong, and we will redisplay that line anyway. */ + Likewise, don't do anything if none of the enabled rows + contains glyphs highlighted in mouse face. */ if (!NILP (display_info->mouse_face_window) && WINDOWP (display_info->mouse_face_window)) { @@ -1867,7 +1987,8 @@ IT_update_begin (struct frame *f) else { for (i = 0; i < w->desired_matrix->nrows; ++i) - if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)) + if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i) + && MATRIX_ROW (w->current_matrix, i)->mouse_face_p) break; } @@ -1875,7 +1996,7 @@ IT_update_begin (struct frame *f) clear_mouse_face (display_info); } } - else if (!FRAME_LIVE_P (display_info->mouse_face_mouse_frame)) + else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame)) { /* If the frame with mouse highlight was deleted, invalidate the highlight info. */ @@ -1906,7 +2027,7 @@ IT_frame_up_to_date (struct frame *f) struct window *sw; if (dpyinfo->mouse_face_deferred_gc - || f == dpyinfo->mouse_face_mouse_frame) + || (f && f == dpyinfo->mouse_face_mouse_frame)) { BLOCK_INPUT; if (dpyinfo->mouse_face_mouse_frame) @@ -2014,10 +2135,10 @@ x_set_menu_bar_lines (f, value, oldval) set_menu_bar_lines (f, value, oldval); } -/* This was copied from xfns.c */ +/* This was copied from xfaces.c */ -Lisp_Object Qbackground_color; -Lisp_Object Qforeground_color; +extern Lisp_Object Qbackground_color; +extern Lisp_Object Qforeground_color; Lisp_Object Qreverse; extern Lisp_Object Qtitle; @@ -2187,17 +2308,25 @@ DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors, (frame) Lisp_Object frame; { - int reverse; struct frame *f; CHECK_FRAME (frame, 0); f= XFRAME (frame); - reverse = EQ (Fcdr (Fassq (intern ("reverse"), f->param_alist)), Qt); - initial_screen_colors[0] - = reverse ? FRAME_BACKGROUND_PIXEL (f) : FRAME_FOREGROUND_PIXEL (f); - initial_screen_colors[1] - = reverse ? FRAME_FOREGROUND_PIXEL (f) : FRAME_BACKGROUND_PIXEL (f); + /* This function is called after applying default-frame-alist to the + initial frame. At that time, if reverse-colors option was + specified in default-frame-alist, it was already applied, and + frame colors are reversed. We need to account for that. */ + if (EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt)) + { + initial_screen_colors[0] = FRAME_BACKGROUND_PIXEL (f); + initial_screen_colors[1] = FRAME_FOREGROUND_PIXEL (f); + } + else + { + initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f); + initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f); + } } void @@ -2216,8 +2345,11 @@ IT_set_frame_parameters (f, alist) int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt); int was_reverse = reverse; int redraw = 0, fg_set = 0, bg_set = 0; + int need_to_reverse; unsigned long orig_fg; unsigned long orig_bg; + Lisp_Object frame_bg, frame_fg; + extern Lisp_Object Qdefault, QCforeground, QCbackground; /* If we are creating a new frame, begin with the original screen colors used for the initial frame. */ @@ -2229,6 +2361,15 @@ IT_set_frame_parameters (f, alist) } orig_fg = FRAME_FOREGROUND_PIXEL (f); orig_bg = FRAME_BACKGROUND_PIXEL (f); + frame_fg = Fcdr (Fassq (Qforeground_color, f->param_alist)); + frame_bg = Fcdr (Fassq (Qbackground_color, f->param_alist)); + /* frame_fg and frame_bg could be nil if, for example, + f->param_alist is nil, e.g. if we are called from + Fmake_terminal_frame. */ + if (NILP (frame_fg)) + frame_fg = build_string (unspecified_fg); + if (NILP (frame_bg)) + frame_bg = build_string (unspecified_bg); /* Extract parm names and values into those vectors. */ i = 0; @@ -2247,58 +2388,86 @@ IT_set_frame_parameters (f, alist) for (i = 0; i < j; i++) { - Lisp_Object prop = parms[i]; - Lisp_Object val = values[i]; + Lisp_Object prop, val; + + prop = parms[i]; + val = values[i]; if (EQ (prop, Qreverse)) reverse = EQ (val, Qt); } - - if (termscript && reverse && !was_reverse) + + need_to_reverse = reverse && !was_reverse; + if (termscript && need_to_reverse) fprintf (termscript, "\n"); /* Now process the alist elements in reverse of specified order. */ for (i--; i >= 0; i--) { - Lisp_Object prop = parms[i]; - Lisp_Object val = values[i]; + Lisp_Object prop, val; + Lisp_Object frame; + + prop = parms[i]; + val = values[i]; if (EQ (prop, Qforeground_color)) { - unsigned long new_color = load_color (f, NULL, val, reverse + unsigned long new_color = load_color (f, NULL, val, need_to_reverse ? LFACE_BACKGROUND_INDEX : LFACE_FOREGROUND_INDEX); if (new_color != FACE_TTY_DEFAULT_COLOR && new_color != FACE_TTY_DEFAULT_FG_COLOR && new_color != FACE_TTY_DEFAULT_BG_COLOR) { - if (reverse) - /* FIXME: should the fore-/background of the default - face change here as well? */ - FRAME_BACKGROUND_PIXEL (f) = new_color; + FRAME_FOREGROUND_PIXEL (f) = new_color; + /* Make sure the foreground of the default face for this + frame is changed as well. */ + XSETFRAME (frame, f); + if (need_to_reverse) + { + Finternal_set_lisp_face_attribute (Qdefault, QCbackground, + val, frame); + prop = Qbackground_color; + bg_set = 1; + } else - FRAME_FOREGROUND_PIXEL (f) = new_color; + { + Finternal_set_lisp_face_attribute (Qdefault, QCforeground, + val, frame); + fg_set = 1; + } redraw = 1; - fg_set = 1; if (termscript) fprintf (termscript, "\n", new_color); } } else if (EQ (prop, Qbackground_color)) { - unsigned long new_color = load_color (f, NULL, val, reverse + unsigned long new_color = load_color (f, NULL, val, need_to_reverse ? LFACE_FOREGROUND_INDEX : LFACE_BACKGROUND_INDEX); if (new_color != FACE_TTY_DEFAULT_COLOR && new_color != FACE_TTY_DEFAULT_FG_COLOR && new_color != FACE_TTY_DEFAULT_BG_COLOR) { - if (reverse) - FRAME_FOREGROUND_PIXEL (f) = new_color; + FRAME_BACKGROUND_PIXEL (f) = new_color; + /* Make sure the background of the default face for this + frame is changed as well. */ + XSETFRAME (frame, f); + if (need_to_reverse) + { + Finternal_set_lisp_face_attribute (Qdefault, QCforeground, + val, frame); + prop = Qforeground_color; + fg_set = 1; + } else - FRAME_BACKGROUND_PIXEL (f) = new_color; + { + Finternal_set_lisp_face_attribute (Qdefault, QCbackground, + val, frame); + bg_set = 1; + } redraw = 1; - bg_set = 1; if (termscript) fprintf (termscript, "\n", new_color); } @@ -2322,16 +2491,24 @@ IT_set_frame_parameters (f, alist) /* If they specified "reverse", but not the colors, we need to swap the current frame colors. */ - if (reverse && !was_reverse) + if (need_to_reverse) { + Lisp_Object frame; + if (!fg_set) { - FRAME_BACKGROUND_PIXEL (f) = orig_fg; + XSETFRAME (frame, f); + Finternal_set_lisp_face_attribute (Qdefault, QCforeground, + tty_color_name (f, orig_bg), + frame); redraw = 1; } if (!bg_set) { - FRAME_FOREGROUND_PIXEL (f) = orig_bg; + XSETFRAME (frame, f); + Finternal_set_lisp_face_attribute (Qdefault, QCbackground, + tty_color_name (f, orig_fg), + frame); redraw = 1; } } @@ -2987,9 +3164,6 @@ and then the scan code.") } /* Get a char from keyboard. Function keys are put into the event queue. */ - -extern void kbd_buffer_store_event (struct input_event *); - static int dos_rawgetc () { @@ -3212,6 +3386,7 @@ dos_rawgetc () event.code = code; event.modifiers = modifiers; event.frame_or_window = selected_frame; + event.arg = Qnil; event.timestamp = event_timestamp (); kbd_buffer_store_event (&event); } @@ -3229,16 +3404,26 @@ dos_rawgetc () if (mouse_last_x != mouse_prev_x || mouse_last_y != mouse_prev_y) { previous_help_echo = help_echo; - help_echo = Qnil; + help_echo = help_echo_object = help_echo_window = Qnil; + help_echo_pos = -1; IT_note_mouse_highlight (SELECTED_FRAME(), mouse_last_x, mouse_last_y); /* If the contents of the global variable help_echo has changed, generate a HELP_EVENT. */ - if (STRINGP (help_echo) || STRINGP (previous_help_echo)) + if (!NILP (help_echo) || !NILP (previous_help_echo)) { + /* HELP_EVENT takes 2 events in the event loop. */ event.kind = HELP_EVENT; - event.frame_or_window = Fcons (selected_frame, help_echo); + event.frame_or_window = selected_frame; + event.arg = help_echo_object; + event.x = make_number (help_echo_pos); event.timestamp = event_timestamp (); + event.code = 0; + kbd_buffer_store_event (&event); + if (WINDOWP (help_echo_window)) + event.frame_or_window = help_echo_window; + event.arg = help_echo; + event.code = 1; kbd_buffer_store_event (&event); } } @@ -3282,6 +3467,7 @@ dos_rawgetc () event.x = x; event.y = y; event.frame_or_window = selected_frame; + event.arg = Qnil; event.timestamp = event_timestamp (); kbd_buffer_store_event (&event); } @@ -3353,7 +3539,11 @@ glyph_to_pixel_coords (f, x, y, pix_x, pix_y) grab the nearest Xlib manual (down the hall, second-to-last door on the left), but I don't think it's worth the effort. */ +/* These hold text of the current and the previous menu help messages. */ static char *menu_help_message, *prev_menu_help_message; +/* Pane number and item number of the menu item which generated the + last menu help message. */ +static int menu_help_paneno, menu_help_itemno; static XMenu * IT_menu_create () @@ -3437,7 +3627,7 @@ IT_menu_calc_size (XMenu *menu, int *width, int *height) /* Display MENU at (X,Y) using FACES. */ static void -IT_menu_display (XMenu *menu, int y, int x, int *faces, int disp_help) +IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help) { int i, j, face, width; struct glyph *text, *p; @@ -3463,8 +3653,14 @@ IT_menu_display (XMenu *menu, int y, int x, int *faces, int disp_help) = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]); mousehere = (y + i == my && x <= mx && mx < x + width + 2); face = faces[enabled + mousehere * 2]; + /* The following if clause means that we display the menu help + strings even if the menu item is currently disabled. */ if (disp_help && enabled + mousehere * 2 >= 2) - menu_help_message = menu->help_text[i]; + { + menu_help_message = menu->help_text[i]; + menu_help_paneno = pn - 1; + menu_help_itemno = i; + } p = text; SET_CHAR_GLYPH (*p, ' ', face, 0); p++; @@ -3609,7 +3805,7 @@ struct IT_menu_state int XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, int x0, int y0, unsigned ButtonMask, char **txt, - void (*help_callback)(char *)) + void (*help_callback)(char *, int, int)) { struct IT_menu_state *state; int statecount; @@ -3621,6 +3817,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, int title_faces[4]; /* face to display the menu title */ int buffers_num_deleted = 0; struct frame *sf = SELECTED_FRAME(); + Lisp_Object saved_echo_area_message; /* Just in case we got here without a mouse present... */ if (have_mouse <= 0) @@ -3633,7 +3830,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, y0 = 1; /* We will process all the mouse events directly, so we had - better prevented dos_rawgetc from stealing them from us. */ + better prevent dos_rawgetc from stealing them from us. */ mouse_preempted++; state = alloca (menu->panecount * sizeof (struct IT_menu_state)); @@ -3668,6 +3865,11 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, menu->text[0][7] = '\0'; buffers_num_deleted = 1; } + + /* We need to save the current echo area message, so that we could + restore it below, before we exit. See the commentary below, + before the call to message_with_string. */ + saved_echo_area_message = Fcurrent_message (); state[0].menu = menu; mouse_off (); ScreenRetrieve (state[0].screen_behind = xmalloc (screensize)); @@ -3677,7 +3879,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, IT_display_cursor (0); /* Display the menu title. */ - IT_menu_display (menu, y0 - 1, x0 - 1, title_faces, 0); + IT_menu_display (menu, y0 - 1, x0 - 1, 1, title_faces, 0); if (buffers_num_deleted) menu->text[0][7] = ' '; if ((onepane = menu->count == 1 && menu->submenu[0])) @@ -3736,6 +3938,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, IT_menu_display (state[i].menu, state[i].y, state[i].x, + state[i].pane, faces, 1); state[statecount].menu = state[i].menu->submenu[dy]; state[statecount].pane = state[i].menu->panenumber[dy]; @@ -3752,6 +3955,7 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, IT_menu_display (state[statecount - 1].menu, state[statecount - 1].y, state[statecount - 1].x, + state[statecount - 1].pane, faces, 1); } else @@ -3759,7 +3963,8 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, if ((menu_help_message || prev_menu_help_message) && menu_help_message != prev_menu_help_message) { - help_callback (menu_help_message); + help_callback (menu_help_message, + menu_help_paneno, menu_help_itemno); IT_display_cursor (0); prev_menu_help_message = menu_help_message; } @@ -3786,6 +3991,26 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, ScreenUpdate (state[0].screen_behind); if (screen_virtual_segment) dosv_refresh_virtual_screen (0, screen_size); + + /* We have a situation here. ScreenUpdate has just restored the + screen contents as it was before we started drawing this menu. + That includes any echo area message that could have been + displayed back then. (In reality, that echo area message will + almost always be the ``keystroke echo'' that echoes the sequence + of menu items chosen by the user.) However, if the menu had some + help messages, then displaying those messages caused Emacs to + forget about the original echo area message. So when + ScreenUpdate restored it, it created a discrepancy between the + actual screen contents and what Emacs internal data structures + know about it. + + To avoid this conflict, we force Emacs to restore the original + echo area message as we found it when we entered this function. + The irony of this is that we then erase the restored message + right away, so the only purpose of restoring it is so that + erasing it works correctly... */ + if (! NILP (saved_echo_area_message)) + message_with_string ("%s", saved_echo_area_message, 0); message (0); while (statecount--) xfree (state[statecount].screen_behind); @@ -3796,6 +4021,9 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, (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 (); + mouse_clear_clicks (); + if (!kbd_buffer_events_waiting (1)) + clear_input_pending (); /* Allow mouse events generation by dos_rawgetc. */ mouse_preempted--; return result; @@ -4429,20 +4657,7 @@ dos_ttraw () { have_mouse = 1; /* enable mouse */ mouse_visible = 0; - - if (outregs.x.bx == 3) - { - mouse_button_count = 3; - mouse_button_translate[0] = 0; /* Left */ - mouse_button_translate[1] = 2; /* Middle */ - mouse_button_translate[2] = 1; /* Right */ - } - else - { - mouse_button_count = 2; - mouse_button_translate[0] = 0; - mouse_button_translate[1] = 1; - } + mouse_setup_buttons (outregs.x.bx); mouse_position_hook = &mouse_get_pos; mouse_init (); } @@ -4563,18 +4778,23 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv) saveargv1 = argv[1]; saveargv2 = argv[2]; argv[1] = "/c"; - if (argv[2]) + /* We only need to mirror slashes if a DOS shell will be invoked + not via `system' (which does the mirroring itself). Yes, that + means DJGPP v1.x will lose here. */ + if (argv[2] && argv[3]) { char *p = alloca (strlen (argv[2]) + 1); strcpy (argv[2] = p, saveargv2); while (*p && isspace (*p)) p++; - while (*p && !isspace (*p)) - if (*p == '/') - *p++ = '\\'; - else - p++; + while (*p) + { + if (*p == '/') + *p++ = '\\'; + else + p++; + } } } @@ -4615,6 +4835,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv) if (*cmnd) { extern char **environ; + char **save_env = environ; int save_system_flags = __system_flags; /* Request the most powerful version of `system'. We need @@ -4629,6 +4850,7 @@ run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv) environ = envv; result = system (cmnd); __system_flags = save_system_flags; + environ = save_env; } else result = 0; /* emulate Unixy shell behavior with empty cmd line */ @@ -5080,10 +5302,15 @@ syms_of_msdos () recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil); staticpro (&recent_doskeys); #ifndef HAVE_X_WINDOWS - staticpro (&help_echo); help_echo = Qnil; - staticpro (&previous_help_echo); + staticpro (&help_echo); + help_echo_object = Qnil; + staticpro (&help_echo_object); + help_echo_window = Qnil; + staticpro (&help_echo_window); previous_help_echo = Qnil; + staticpro (&previous_help_echo); + help_echo_pos = -1; DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path, "List of directories to search for bitmap files for X."); @@ -5095,11 +5322,7 @@ For example, if a block cursor is over a tab, it will be drawn as\n\ wide as that tab on the display. (No effect on MS-DOS.)"); x_stretch_cursor_p = 0; - /* The following three are from xfns.c: */ - Qbackground_color = intern ("background-color"); - staticpro (&Qbackground_color); - Qforeground_color = intern ("foreground-color"); - staticpro (&Qforeground_color); + /* The following two are from xfns.c: */ Qbar = intern ("bar"); staticpro (&Qbar); Qcursor_type = intern ("cursor-type"); @@ -5109,7 +5332,7 @@ wide as that tab on the display. (No effect on MS-DOS.)"); DEFVAR_LISP ("dos-unsupported-char-glyph", &Vdos_unsupported_char_glyph, "*Glyph to display instead of chars not supported by current codepage.\n\ - +\n\ This variable is used only by MSDOS terminals."); Vdos_unsupported_char_glyph = '\177'; #endif @@ -5124,6 +5347,7 @@ nil means don't delete them until `list-processes' is run."); defsubr (&Smsdos_long_file_names); defsubr (&Smsdos_downcase_filename); defsubr (&Smsdos_remember_default_colors); + defsubr (&Smsdos_set_mouse_buttons); } #endif /* MSDOS */