diff options
Diffstat (limited to 'src/xdisp.c')
-rw-r--r-- | src/xdisp.c | 592 |
1 files changed, 405 insertions, 187 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 80d4d52531a..ad28dacf4e5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -816,11 +816,11 @@ Lisp_Object previous_help_echo_string; #ifdef HAVE_WINDOW_SYSTEM /* Non-zero means an hourglass cursor is currently shown. */ -bool hourglass_shown_p; +static bool hourglass_shown_p; /* If non-null, an asynchronous timer that, when it expires, displays an hourglass cursor on all frames. */ -struct atimer *hourglass_atimer; +static struct atimer *hourglass_atimer; #endif /* HAVE_WINDOW_SYSTEM */ @@ -1024,6 +1024,8 @@ window_text_bottom_y (struct window *w) if (WINDOW_WANTS_MODELINE_P (w)) height -= CURRENT_MODE_LINE_HEIGHT (w); + height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w); + return height; } @@ -1068,6 +1070,7 @@ window_box_height (struct window *w) eassert (height >= 0); height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w); + height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w); /* Note: the code below that determines the mode-line/header-line height is essentially the same as that contained in the macro @@ -1141,7 +1144,7 @@ window_box_left_offset (struct window *w, enum glyph_row_area area) area AREA of window W. ANY_AREA means return the right edge of the whole window, to the left of the right fringe of W. */ -int +static int window_box_right_offset (struct window *w, enum glyph_row_area area) { /* Don't return more than the window's pixel width. */ @@ -1957,8 +1960,8 @@ pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y, if (pix_y < 0) pix_y = 0; - else if (pix_y > FRAME_LINES (f)) - pix_y = FRAME_LINES (f); + else if (pix_y > FRAME_TOTAL_LINES (f)) + pix_y = FRAME_TOTAL_LINES (f); } } #endif @@ -2174,7 +2177,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int if (s->x > r.x) { - r.width -= s->x - r.x; + if (r.width >= s->x - r.x) + r.width -= s->x - r.x; + else /* R2L hscrolled row with cursor outside text area */ + r.width = 0; r.x = s->x; } r.width = min (r.width, glyph->pixel_width); @@ -2296,10 +2302,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row, glyph, and `x-stretch-block-cursor' is nil, don't draw a rectangle as wide as the glyph, but use a canonical character width instead. */ - wd = glyph->pixel_width - 1; -#if defined (HAVE_NTGUI) || defined (HAVE_NS) - wd++; /* Why? */ -#endif + wd = glyph->pixel_width; x = w->phys_cursor.x; if (x < 0) @@ -2501,7 +2504,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) gx = WINDOW_PIXEL_WIDTH (w) - width; goto row_glyph; - case ON_SCROLL_BAR: + case ON_VERTICAL_SCROLL_BAR: gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) ? 0 : (window_box_right_offset (w, RIGHT_MARGIN_AREA) @@ -2535,7 +2538,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) gy = 0; /* The bottom divider prevails. */ height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); - goto add_edge;; + goto add_edge; case ON_BOTTOM_DIVIDER: gx = 0; @@ -2623,15 +2626,14 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap) { ptrdiff_t i; ptrdiff_t count = SPECPDL_INDEX (); - struct gcpro gcpro1; - Lisp_Object *args = alloca (nargs * word_size); + Lisp_Object *args; + USE_SAFE_ALLOCA; + SAFE_ALLOCA_LISP (args, nargs); args[0] = func; for (i = 1; i < nargs; i++) args[i] = va_arg (ap, Lisp_Object); - GCPRO1 (args[0]); - gcpro1.nvars = nargs; specbind (Qinhibit_redisplay, Qt); if (inhibit_quit) specbind (Qinhibit_quit, Qt); @@ -2639,7 +2641,7 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap) so there is no possibility of wanting to redisplay. */ val = internal_condition_case_n (Ffuncall, nargs, args, Qt, safe_eval_handler); - UNGCPRO; + SAFE_FREE (); val = unbind_to (count, val); } @@ -2971,10 +2973,6 @@ init_iterator (struct it *it, struct window *w, it->glyph_row = row; it->area = TEXT_AREA; - /* Forget any previous info about this row being reversed. */ - if (it->glyph_row) - it->glyph_row->reversed_p = 0; - /* Get the dimensions of the display area. The display area consists of the visible window area plus a horizontally scrolled part to the left of the window. All x-values are relative to the @@ -3669,6 +3667,7 @@ next_overlay_change (ptrdiff_t pos) ptrdiff_t i, noverlays; ptrdiff_t endpos; Lisp_Object *overlays; + USE_SAFE_ALLOCA; /* Get all overlays at the given position. */ GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1); @@ -3685,6 +3684,7 @@ next_overlay_change (ptrdiff_t pos) endpos = min (endpos, oendpos); } + SAFE_FREE (); return endpos; } @@ -5130,7 +5130,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, if (it) { - int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);; + int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); if (CONSP (XCDR (XCDR (spec)))) { @@ -5745,10 +5745,11 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) Lisp_Object overlay, window, str, invisible; struct Lisp_Overlay *ov; ptrdiff_t start, end; - ptrdiff_t size = 20; ptrdiff_t n = 0, i, j; int invis_p; - struct overlay_entry *entries = alloca (size * sizeof *entries); + struct overlay_entry entriesbuf[20]; + ptrdiff_t size = ARRAYELTS (entriesbuf); + struct overlay_entry *entries = entriesbuf; USE_SAFE_ALLOCA; if (charpos <= 0) @@ -6931,7 +6932,8 @@ get_next_display_element (struct it *it) is R..." */ /* FIXME: Do we need an exception for characters from display tables? */ - if (it->bidi_p && it->bidi_it.type == STRONG_R) + if (it->bidi_p && it->bidi_it.type == STRONG_R + && !inhibit_bidi_mirroring) it->c = bidi_mirror_char (it->c); /* Map via display table or translate control characters. IT->c, IT->len etc. have been set to the next character by @@ -8344,7 +8346,7 @@ next_element_from_buffer (struct it *it) /* Get the next character, maybe multibyte. */ p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); - if (it->multibyte_p && !ASCII_BYTE_P (*p)) + if (it->multibyte_p && !ASCII_CHAR_P (*p)) it->c = STRING_CHAR_AND_LENGTH (p, it->len); else it->c = *p, it->len = 1; @@ -10027,9 +10029,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte) for (i = 0; i < nbytes; i += char_bytes) { c = string_char_and_length (msg + i, &char_bytes); - work[0] = (ASCII_CHAR_P (c) - ? c - : multibyte_char_to_unibyte (c)); + work[0] = CHAR_TO_BYTE8 (c); insert_1_both (work, 1, 1, 1, 0, 0); } } @@ -10204,9 +10204,9 @@ message3 (Lisp_Object m) { ptrdiff_t nbytes = SBYTES (m); bool multibyte = STRING_MULTIBYTE (m); + char *buffer; USE_SAFE_ALLOCA; - char *buffer = SAFE_ALLOCA (nbytes); - memcpy (buffer, SDATA (m), nbytes); + SAFE_ALLOCA_STRING (buffer, m); message_dolog (buffer, nbytes, 1, multibyte); SAFE_FREE (); } @@ -10311,19 +10311,17 @@ message_with_string (const char *m, Lisp_Object string, int log) { if (m) { - /* ENCODE_SYSTEM below can GC and/or relocate the Lisp - String whose data pointer might be passed to us in M. So - we use a local copy. */ - char *fmt = xstrdup (m); + /* ENCODE_SYSTEM below can GC and/or relocate the + Lisp data, so make sure we don't use it here. */ + eassert (relocatable_string_data_p (m) != 1); if (noninteractive_need_newline) putc ('\n', stderr); noninteractive_need_newline = 0; - fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string))); + fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string))); if (!cursor_in_echo_area) fprintf (stderr, "\n"); fflush (stderr); - xfree (fmt); } } else if (INTERACTIVE) @@ -10410,11 +10408,13 @@ vmessage (const char *m, va_list ap) { ptrdiff_t len; ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f); - char *message_buf = alloca (maxsize + 1); + USE_SAFE_ALLOCA; + char *message_buf = SAFE_ALLOCA (maxsize + 1); len = doprnt (message_buf, maxsize, m, 0, ap); message3 (make_string (message_buf, len)); + SAFE_FREE (); } else message1 (0); @@ -10580,6 +10580,7 @@ with_echo_area_buffer (struct window *w, int which, { wset_buffer (w, buffer); set_marker_both (w->pointm, buffer, BEG, BEG_BYTE); + set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE); } bset_undo_list (current_buffer, Qt); @@ -10618,7 +10619,7 @@ with_echo_area_buffer_unwind_data (struct window *w) Vwith_echo_area_save_vector = Qnil; if (NILP (vector)) - vector = Fmake_vector (make_number (9), Qnil); + vector = Fmake_vector (make_number (11), Qnil); XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i; ASET (vector, i, Vdeactivate_mark); ++i; @@ -10630,12 +10631,14 @@ with_echo_area_buffer_unwind_data (struct window *w) ASET (vector, i, w->contents); ++i; ASET (vector, i, make_number (marker_position (w->pointm))); ++i; ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i; + ASET (vector, i, make_number (marker_position (w->old_pointm))); ++i; + ASET (vector, i, make_number (marker_byte_position (w->old_pointm))); ++i; ASET (vector, i, make_number (marker_position (w->start))); ++i; ASET (vector, i, make_number (marker_byte_position (w->start))); ++i; } else { - int end = i + 6; + int end = i + 8; for (; i < end; ++i) ASET (vector, i, Qnil); } @@ -10667,9 +10670,12 @@ unwind_with_echo_area_buffer (Lisp_Object vector) set_marker_both (w->pointm, buffer, XFASTINT (AREF (vector, 5)), XFASTINT (AREF (vector, 6))); - set_marker_both (w->start, buffer, + set_marker_both (w->old_pointm, buffer, XFASTINT (AREF (vector, 7)), XFASTINT (AREF (vector, 8))); + set_marker_both (w->start, buffer, + XFASTINT (AREF (vector, 9)), + XFASTINT (AREF (vector, 10))); } Vwith_echo_area_save_vector = vector; @@ -11918,11 +11924,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) #ifdef HAVE_WINDOW_SYSTEM -/* Tool-bar item index of the item on which a mouse button was pressed - or -1. */ - -int last_tool_bar_item; - /* Select `frame' temporarily without running all the code in do_switch_frame. FIXME: Maybe do_switch_frame should be trimmed down similarly @@ -11949,7 +11950,7 @@ update_tool_bar (struct frame *f, int save_match_data) int do_update = FRAME_EXTERNAL_TOOL_BAR (f); #else int do_update = (WINDOWP (f->tool_bar_window) - && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0); + && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0); #endif if (do_update) @@ -12045,11 +12046,11 @@ static void build_desired_tool_bar_string (struct frame *f) { int i, size, size_needed; - struct gcpro gcpro1, gcpro2, gcpro3; - Lisp_Object image, plist, props; + struct gcpro gcpro1, gcpro2; + Lisp_Object image, plist; - image = plist = props = Qnil; - GCPRO3 (image, plist, props); + image = plist = Qnil; + GCPRO2 (image, plist); /* Prepare F->desired_tool_bar_string. If we can reuse it, do so. Otherwise, make a new string. */ @@ -12068,9 +12069,12 @@ build_desired_tool_bar_string (struct frame *f) (f, Fmake_string (make_number (size_needed), make_number (' '))); else { - props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil); + AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil); + struct gcpro gcpro1; + GCPRO1 (props); Fremove_text_properties (make_number (0), make_number (size), props, f->desired_tool_bar_string); + UNGCPRO; } /* Put a `display' property on the string for the images to display, @@ -12181,8 +12185,10 @@ build_desired_tool_bar_string (struct frame *f) the start of this item's properties in the tool-bar items vector. */ image = Fcons (Qimage, plist); - props = list4 (Qdisplay, image, - Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)); + AUTO_LIST4 (props, Qdisplay, image, Qmenu_item, + make_number (i * TOOL_BAR_ITEM_NSLOTS)); + struct gcpro gcpro1; + GCPRO1 (props); /* Let the last image hide all remaining spaces in the tool bar string. The string can be longer than needed when we reuse a @@ -12193,6 +12199,7 @@ build_desired_tool_bar_string (struct frame *f) end = i + 1; Fadd_text_properties (make_number (i), make_number (end), props, f->desired_tool_bar_string); + UNGCPRO; #undef PROP } @@ -12333,16 +12340,9 @@ display_tool_bar_line (struct it *it, int height) } -/* Max tool-bar height. Basically, this is what makes all other windows - disappear when the frame gets too small. Rethink this! */ - -#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \ - ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f))) - /* Value is the number of pixels needed to make all tool-bar items of frame F visible. The actual number of glyph rows needed is returned in *N_ROWS if non-NULL. */ - static int tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) { @@ -12356,6 +12356,7 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) /* Initialize an iterator for iteration over F->desired_tool_bar_string in the tool-bar window of frame F. */ init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID); + temp_row->reversed_p = false; it.first_visible_x = 0; it.last_visible_x = WINDOW_PIXEL_WIDTH (w); reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); @@ -12381,11 +12382,6 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) #endif /* !USE_GTK && !HAVE_NS */ -#if defined USE_GTK || defined HAVE_NS -EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST; -EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST; -#endif - DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height, 0, 2, 0, doc: /* Return the number of lines occupied by the tool bar of FRAME. @@ -12416,7 +12412,6 @@ PIXELWISE non-nil means return the height of the tool bar in pixels. */) /* Display the tool-bar of frame F. Value is non-zero if tool-bar's height should be changed. */ - static int redisplay_tool_bar (struct frame *f) { @@ -12438,7 +12433,7 @@ redisplay_tool_bar (struct frame *f) can turn off tool-bars by specifying tool-bar-lines zero. */ if (!WINDOWP (f->tool_bar_window) || (w = XWINDOW (f->tool_bar_window), - WINDOW_PIXEL_HEIGHT (w) == 0)) + WINDOW_TOTAL_LINES (w) == 0)) return 0; /* Set up an iterator for the tool-bar window. */ @@ -12446,6 +12441,7 @@ redisplay_tool_bar (struct frame *f) it.first_visible_x = 0; it.last_visible_x = WINDOW_PIXEL_WIDTH (w); row = it.glyph_row; + row->reversed_p = false; /* Build a string that represents the contents of the tool-bar. */ build_desired_tool_bar_string (f); @@ -12465,14 +12461,7 @@ redisplay_tool_bar (struct frame *f) if (new_height != WINDOW_PIXEL_HEIGHT (w)) { - Lisp_Object frame; - int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1) - / FRAME_LINE_HEIGHT (f)); - - XSETFRAME (frame, f); - Fmodify_frame_parameters (frame, - list1 (Fcons (Qtool_bar_lines, - make_number (new_lines)))); + x_change_tool_bar_height (f, new_height); /* Always do that now. */ clear_glyph_matrix (w->desired_matrix); f->fonts_changed = 1; @@ -12525,14 +12514,11 @@ redisplay_tool_bar (struct frame *f) if (!NILP (Vauto_resize_tool_bars)) { - /* Do we really allow the toolbar to occupy the whole frame? */ - int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f); int change_height_p = 0; /* If we couldn't display everything, change the tool-bar's height if there is room for more. */ - if (IT_STRING_CHARPOS (it) < it.end_charpos - && it.current_y < max_tool_bar_height) + if (IT_STRING_CHARPOS (it) < it.end_charpos) change_height_p = 1; /* We subtract 1 because display_tool_bar_line advances the @@ -12551,15 +12537,13 @@ redisplay_tool_bar (struct frame *f) /* If row displays tool-bar items, but is partially visible, change the tool-bar's height. */ if (MATRIX_ROW_DISPLAYS_TEXT_P (row) - && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y - && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height) + && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y) change_height_p = 1; /* Resize windows as needed by changing the `tool-bar-lines' frame parameter. */ if (change_height_p) { - Lisp_Object frame; int nrows; int new_height = tool_bar_height (f, &nrows, 1); @@ -12571,35 +12555,12 @@ redisplay_tool_bar (struct frame *f) if (change_height_p) { - /* Current size of the tool-bar window in canonical line - units. */ - int old_lines = WINDOW_TOTAL_LINES (w); - /* Required size of the tool-bar window in canonical - line units. */ - int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1) - / FRAME_LINE_HEIGHT (f)); - /* Maximum size of the tool-bar window in canonical line - units that this frame can allow. */ - int max_lines = - WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1; - - /* Don't try to change the tool-bar window size and set - the fonts_changed flag unless really necessary. That - flag causes redisplay to give up and retry - redisplaying the frame from scratch, so setting it - unnecessarily can lead to nasty redisplay loops. */ - if (new_lines <= max_lines - && eabs (new_lines - old_lines) >= 1) - { - XSETFRAME (frame, f); - Fmodify_frame_parameters (frame, - list1 (Fcons (Qtool_bar_lines, - make_number (new_lines)))); - clear_glyph_matrix (w->desired_matrix); - f->n_tool_bar_rows = nrows; - f->fonts_changed = 1; - return 1; - } + x_change_tool_bar_height (f, new_height); + clear_glyph_matrix (w->desired_matrix); + f->n_tool_bar_rows = nrows; + f->fonts_changed = 1; + + return 1; } } } @@ -12724,7 +12685,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, where the button was pressed, disregarding where it was released. */ if (NILP (Vmouse_highlight) && !down_p) - prop_idx = last_tool_bar_item; + prop_idx = f->last_tool_bar_item; /* If item is disabled, do nothing. */ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); @@ -12736,7 +12697,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, /* Show item in pressed state. */ if (!NILP (Vmouse_highlight)) show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); - last_tool_bar_item = prop_idx; + f->last_tool_bar_item = prop_idx; } else { @@ -12761,7 +12722,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, event.arg = key; event.modifiers = modifiers; kbd_buffer_store_event (&event); - last_tool_bar_item = -1; + f->last_tool_bar_item = -1; } } @@ -12811,8 +12772,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) mouse_down_p = (x_mouse_grabbed (dpyinfo) && f == dpyinfo->last_mouse_frame); - if (mouse_down_p - && last_tool_bar_item != prop_idx) + if (mouse_down_p && f->last_tool_bar_item != prop_idx) return; draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; @@ -12934,7 +12894,20 @@ hscroll_window_tree (Lisp_Object window) /* Scroll when cursor is inside this scroll margin. */ h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w); + /* If the position of this window's point has explicitly + changed, no more suspend auto hscrolling. */ + if (NILP (Fequal (Fwindow_point (window), Fwindow_old_point (window)))) + w->suspend_auto_hscroll = 0; + + /* Remember window point. */ + Fset_marker (w->old_pointm, + ((w == XWINDOW (selected_window)) + ? make_number (BUF_PT (XBUFFER (w->contents))) + : Fmarker_position (w->pointm)), + w->contents); + if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents)) + && w->suspend_auto_hscroll == 0 /* In some pathological cases, like restoring a window configuration into a frame that is much smaller than the one from which the configuration was saved, we @@ -12947,8 +12920,7 @@ hscroll_window_tree (Lisp_Object window) inside the left margin and the window is already hscrolled. */ && ((!row_r2l_p - && ((w->hscroll - && w->cursor.x <= h_margin) + && ((w->hscroll && w->cursor.x <= h_margin) || (cursor_row->enabled_p && cursor_row->truncated_on_right_p && (w->cursor.x >= text_area_width - h_margin)))) @@ -15839,9 +15811,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste return rc; } -#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK -static -#endif + void set_vertical_scroll_bar (struct window *w) { @@ -15880,6 +15850,71 @@ set_vertical_scroll_bar (struct window *w) } +void +set_horizontal_scroll_bar (struct window *w) +{ + int start, end, whole, portion; + + if (!MINI_WINDOW_P (w) + || (w == XWINDOW (minibuf_window) + && NILP (echo_area_buffer[0]))) + { + struct buffer *b = XBUFFER (w->contents); + struct buffer *old_buffer = NULL; + struct it it; + struct text_pos startp; + + if (b != current_buffer) + { + old_buffer = current_buffer; + set_buffer_internal (b); + } + + SET_TEXT_POS_FROM_MARKER (startp, w->start); + start_display (&it, w, startp); + it.last_visible_x = INT_MAX; + whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1, + MOVE_TO_X | MOVE_TO_Y); + /* whole = move_it_to (&it, w->window_end_pos, INT_MAX, + window_box_height (w), -1, + MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); */ + + start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)); + end = start + window_box_width (w, TEXT_AREA); + portion = end - start; + /* After enlarging a horizontally scrolled window such that it + gets at least as wide as the text it contains, make sure that + the thumb doesn't fill the entire scroll bar so we can still + drag it back to see the entire text. */ + whole = max (whole, end); + + if (it.bidi_p) + { + Lisp_Object pdir; + + pdir = Fcurrent_bidi_paragraph_direction (Qnil); + if (EQ (pdir, Qright_to_left)) + { + start = whole - end; + end = start + portion; + } + } + + if (old_buffer) + set_buffer_internal (old_buffer); + } + else + start = end = whole = portion = 0; + + w->hscroll_whole = whole; + + /* Indicate what this scroll bar ought to be displaying now. */ + if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook) + (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook) + (w, portion, whole, start); +} + + /* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only selected_window is redisplayed. @@ -16093,6 +16128,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) { ptrdiff_t new_pt = marker_position (w->pointm); ptrdiff_t new_pt_byte = marker_byte_position (w->pointm); + if (new_pt < BEGV) { new_pt = BEGV; @@ -16866,7 +16902,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) redisplay_tool_bar (f); #else if (WINDOWP (f->tool_bar_window) - && (FRAME_TOOL_BAR_HEIGHT (f) > 0 + && (FRAME_TOOL_BAR_LINES (f) > 0 || !NILP (Vauto_resize_tool_bars)) && redisplay_tool_bar (f)) ignore_mouse_drag_p = 1; @@ -16906,10 +16942,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) ; finish_scroll_bars: - if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) + if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) { - /* Set the thumb's position and size. */ - set_vertical_scroll_bar (w); + if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) + /* Set the thumb's position and size. */ + set_vertical_scroll_bar (w); + + if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) + /* Set the thumb's position and size. */ + set_horizontal_scroll_bar (w); /* Note that we actually used the scroll bar attached to this window, so it shouldn't be deleted at the end of redisplay. */ @@ -16965,6 +17006,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) /* Initialize iterator and info to start at POS. */ start_display (&it, w, pos); + it.glyph_row->reversed_p = false; /* Display all lines of W. */ while (it.current_y < it.last_visible_y) @@ -17148,6 +17190,7 @@ try_window_reusing_current_matrix (struct window *w) && it.current.dpvec_index < 0) break; + it.glyph_row->reversed_p = false; if (display_line (&it)) last_text_row = it.glyph_row - 1; @@ -18168,6 +18211,11 @@ try_window_id (struct window *w) w->cursor.vpos = -1; last_text_row = NULL; overlay_arrow_seen = 0; + if (it.current_y < it.last_visible_y + && !f->fonts_changed + && (first_unchanged_at_end_row == NULL + || IT_CHARPOS (it) < stop_pos)) + it.glyph_row->reversed_p = false; while (it.current_y < it.last_visible_y && !f->fonts_changed && (first_unchanged_at_end_row == NULL @@ -18712,10 +18760,10 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs) else if (glyphs == 1) { int area; + char s[SHRT_MAX + 4]; for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) { - char *s = alloca (row->used[area] + 4); int i; for (i = 0; i < row->used[area]; ++i) @@ -18868,7 +18916,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) struct buffer *buffer = XBUFFER (w->contents); struct buffer *old = current_buffer; const unsigned char *arrow_string = SDATA (overlay_arrow_string); - int arrow_len = SCHARS (overlay_arrow_string); + ptrdiff_t arrow_len = SCHARS (overlay_arrow_string); const unsigned char *arrow_end = arrow_string + arrow_len; const unsigned char *p; struct it it; @@ -18877,6 +18925,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) set_buffer_temp (buffer); init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID); + scratch_glyph_row.reversed_p = false; it.glyph_row->used[TEXT_AREA] = 0; SET_TEXT_POS (it.position, 0, 0); @@ -20915,7 +20964,8 @@ See also `bidi-paragraph-direction'. */) the previous non-empty line. */ if (pos >= ZV && pos > BEGV) DEC_BOTH (pos, bytepos); - if (fast_looking_at (build_string ("[\f\t ]*\n"), + AUTO_STRING (trailing_white_space, "[\f\t ]*\n"); + if (fast_looking_at (trailing_white_space, pos, bytepos, ZV, ZV_BYTE, Qnil) > 0) { while ((c = FETCH_BYTE (bytepos)) == '\n' @@ -21026,7 +21076,7 @@ Value is the new character position of point. */) if ((gpt->resolved_level - row->reversed_p) % 2 == 0) new_pos += (row->reversed_p ? -dir : dir); else - new_pos -= (row->reversed_p ? -dir : dir);; + new_pos -= (row->reversed_p ? -dir : dir); } else if (BUFFERP (g->object)) new_pos = g->charpos; @@ -21416,6 +21466,114 @@ Value is the new character position of point. */) #undef ROW_GLYPH_NEWLINE_P } +DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels, + Sbidi_resolved_levels, 0, 1, 0, + doc: /* Return the resolved bidirectional levels of characters at VPOS. + +The resolved levels are produced by the Emacs bidi reordering engine +that implements the UBA, the Unicode Bidirectional Algorithm. Please +read the Unicode Standard Annex 9 (UAX#9) for background information +about these levels. + +VPOS is the zero-based number of the current window's screen line +for which to produce the resolved levels. If VPOS is nil or omitted, +it defaults to the screen line of point. If the window displays a +header line, VPOS of zero will report on the header line, and first +line of text in the window will have VPOS of 1. + +Value is an array of resolved levels, indexed by glyph number. +Glyphs are numbered from zero starting from the beginning of the +screen line, i.e. the left edge of the window for left-to-right lines +and from the right edge for right-to-left lines. The resolved levels +are produced only for the window's text area; text in display margins +is not included. + +If the selected window's display is not up-to-date, or if the specified +screen line does not display text, this function returns nil. It is +highly recommended to bind this function to some simple key, like F8, +in order to avoid these problems. + +This function exists mainly for testing the correctness of the +Emacs UBA implementation, in particular with the test suite. */) + (Lisp_Object vpos) +{ + struct window *w = XWINDOW (selected_window); + struct buffer *b = XBUFFER (w->contents); + int nrow; + struct glyph_row *row; + + if (NILP (vpos)) + { + int d1, d2, d3, d4, d5; + + pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow); + } + else + { + CHECK_NUMBER_COERCE_MARKER (vpos); + nrow = XINT (vpos); + } + + /* We require up-to-date glyph matrix for this window. */ + if (w->window_end_valid + && !windows_or_buffers_changed + && b + && !b->clip_changed + && !b->prevent_redisplay_optimizations_p + && !window_outdated (w) + && nrow >= 0 + && nrow < w->current_matrix->nrows + && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p + && MATRIX_ROW_DISPLAYS_TEXT_P (row)) + { + struct glyph *g, *e, *g1; + int nglyphs, i; + Lisp_Object levels; + + if (!row->reversed_p) /* Left-to-right glyph row. */ + { + g = g1 = row->glyphs[TEXT_AREA]; + e = g + row->used[TEXT_AREA]; + + /* Skip over glyphs at the start of the row that was + generated by redisplay for its own needs. */ + while (g < e + && INTEGERP (g->object) + && g->charpos < 0) + g++; + g1 = g; + + /* Count the "interesting" glyphs in this row. */ + for (nglyphs = 0; g < e && !INTEGERP (g->object); g++) + nglyphs++; + + /* Create and fill the array. */ + levels = make_uninit_vector (nglyphs); + for (i = 0; g1 < g; i++, g1++) + ASET (levels, i, make_number (g1->resolved_level)); + } + else /* Right-to-left glyph row. */ + { + g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1; + e = row->glyphs[TEXT_AREA] - 1; + while (g > e + && INTEGERP (g->object) + && g->charpos < 0) + g--; + g1 = g; + for (nglyphs = 0; g > e && !INTEGERP (g->object); g--) + nglyphs++; + levels = make_uninit_vector (nglyphs); + for (i = 0; g1 > g; i++, g1--) + ASET (levels, i, make_number (g1->resolved_level)); + } + return levels; + } + else + return Qnil; +} + + /*********************************************************************** Menu Bar @@ -21494,6 +21652,7 @@ display_menu_bar (struct window *w) clear_glyph_row (row); row->enabled_p = true; row->full_width_p = 1; + row->reversed_p = false; } /* Display all items of the menu bar. */ @@ -22727,10 +22886,8 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_ } else if (CHARACTERP (eoltype)) { - unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH); int c = XFASTINT (eoltype); - eol_str_len = CHAR_STRING (c, tmp); - eol_str = tmp; + return buf + CHAR_STRING (c, (unsigned char *) buf); } else { @@ -22866,7 +23023,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, } case 'e': -#ifndef SYSTEM_MALLOC +#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC { if (NILP (Vmemory_full)) return ""; @@ -23007,7 +23164,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, return decode_mode_spec_buf; no_value: { - char* p = decode_mode_spec_buf; + char *p = decode_mode_spec_buf; int pad = width - 2; while (pad-- > 0) *p++ = ' '; @@ -23759,7 +23916,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)); } - prop = buffer_local_value_1 (prop, it->w->contents); + prop = buffer_local_value (prop, it->w->contents); if (EQ (prop, Qunbound)) prop = Qnil; } @@ -23811,7 +23968,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (pixels); } - car = buffer_local_value_1 (car, it->w->contents); + car = buffer_local_value (car, it->w->contents); if (EQ (car, Qunbound)) car = Qnil; } @@ -23988,7 +24145,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id, #endif { eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); } return face; @@ -24011,7 +24168,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, /* Make sure X resources of the face are allocated. */ eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); if (two_byte_p) *two_byte_p = 0; @@ -24328,7 +24485,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end) s->ybase += voffset; /* The case that face->gc == 0 is handled when drawing the glyph - string by calling PREPARE_FACE_FOR_DISPLAY. */ + string by calling prepare_face_for_display. */ eassert (s->face); return glyph - s->row->glyphs[s->area]; } @@ -24646,7 +24803,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) face_id = (row)->glyphs[area][START].face_id; \ \ s = alloca (sizeof *s); \ - char2b = alloca ((END - START) * sizeof *char2b); \ + SAFE_NALLOCA (char2b, 1, (END) - (START)); \ INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&HEAD, &TAIL, s); \ s->x = (X); \ @@ -24674,7 +24831,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) struct glyph_string *first_s = NULL; \ int n; \ \ - char2b = alloca (cmp->glyph_len * sizeof *char2b); \ + SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \ \ /* Make glyph_strings for each glyph sequence that is drawable by \ the same face, and append them to HEAD/TAIL. */ \ @@ -24709,7 +24866,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) gstring = (composition_gstring_from_id \ ((row)->glyphs[area][START].u.cmp.id)); \ s = alloca (sizeof *s); \ - char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b); \ + SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \ INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&(HEAD), &(TAIL), s); \ s->x = (X); \ @@ -24861,6 +25018,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, BUILD_GLYPH_STRINGS will modify its start parameter. That's the reason we use a separate variable `i'. */ i = start; + USE_SAFE_ALLOCA; BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x); if (tail) x_reached = tail->x + tail->background_width; @@ -24926,13 +25084,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_head = head; j = i; BUILD_GLYPH_STRINGS (j, start, h, t, overlap_hl, dummy_x, last_x); start = i; compute_overhangs_and_x (t, head->x, 1); prepend_glyph_string_lists (&head, &tail, h, t); - clip_head = head; + if (clip_head == NULL) + clip_head = head; } /* Prepend glyph strings for glyphs in front of the first glyph @@ -24953,7 +25114,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_head = head; + if (hl == overlap_hl || clip_head == NULL) + clip_head = head; BUILD_GLYPH_STRINGS (i, start, h, t, overlap_hl, dummy_x, last_x); for (s = h; s; s = s->next) @@ -24977,13 +25139,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_tail = tail; BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); /* Because BUILD_GLYPH_STRINGS updates the first argument, we don't have `end = i;' here. */ compute_overhangs_and_x (h, tail->x + tail->width, 0); append_glyph_string_lists (&head, &tail, h, t); - clip_tail = tail; + if (clip_tail == NULL) + clip_tail = tail; } /* Append glyph strings for glyphs following the last glyph @@ -25001,7 +25166,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_tail = tail; + if (hl == overlap_hl || clip_tail == NULL) + clip_tail = tail; i++; /* We must include the Ith glyph. */ BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); @@ -25052,6 +25218,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, RELEASE_HDC (hdc, f); + SAFE_FREE (); return x_reached; } @@ -25137,8 +25304,7 @@ append_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -25221,8 +25387,7 @@ append_composite_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } ++it->glyph_row->used[area]; @@ -25269,7 +25434,7 @@ produce_image_glyph (struct it *it) face = FACE_FROM_ID (it->f, it->face_id); eassert (face); /* Make sure X resources of the face is loaded. */ - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->image_id < 0) { @@ -25410,8 +25575,7 @@ produce_image_glyph (struct it *it) if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } ++it->glyph_row->used[area]; @@ -25499,8 +25663,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object, if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } else @@ -25565,7 +25728,7 @@ produce_stretch_glyph (struct it *it) { struct face *face = FACE_FROM_ID (it->f, it->face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); } #endif @@ -25959,8 +26122,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len, if (it->bidi_p) { glyph->resolved_level = it->bidi_it.resolved_level; - if ((it->bidi_it.type & 7) != it->bidi_it.type) - emacs_abort (); + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); glyph->bidi_type = it->bidi_it.type; } ++it->glyph_row->used[area]; @@ -26028,7 +26190,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) face = FACE_FROM_ID (it->f, face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) { @@ -26044,7 +26206,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c); str = buf; } - for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++) + for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++) code[len] = font->driver->encode_char (font, str[len]); upper_len = (len + 1) / 2; font->driver->text_extents (font, code, upper_len, @@ -27369,9 +27531,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row, /* Erase the image of a cursor of window W from the screen. */ -#ifndef HAVE_NTGUI -static -#endif void erase_phys_cursor (struct window *w) { @@ -27451,7 +27610,7 @@ erase_phys_cursor (struct window *w) /* Maybe clear the display under the cursor. */ if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) { - int x, y, left_x; + int x, y; int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); int width; @@ -27460,13 +27619,15 @@ erase_phys_cursor (struct window *w) goto mark_cursor_off; width = cursor_glyph->pixel_width; - left_x = window_box_left_offset (w, TEXT_AREA); x = w->phys_cursor.x; - if (x < left_x) - width -= left_x - x; + if (x < 0) + { + width += x; + x = 0; + } width = min (width, window_box_width (w, TEXT_AREA) - x); y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y)); - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x)); + x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x); if (width > 0) FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height); @@ -28901,8 +29062,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, else if (area == ON_MODE_LINE) { Lisp_Object default_help - = buffer_local_value_1 (Qmode_line_default_help_echo, - w->contents); + = buffer_local_value (Qmode_line_default_help_echo, + w->contents); if (STRINGP (default_help)) { @@ -29196,7 +29357,8 @@ note_mouse_highlight (struct frame *f, int x, int y) else cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE - || part == ON_SCROLL_BAR) + || part == ON_VERTICAL_SCROLL_BAR + || part == ON_HORIZONTAL_SCROLL_BAR) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else cursor = FRAME_X_OUTPUT (f)->text_cursor; @@ -29319,6 +29481,8 @@ note_mouse_highlight (struct frame *f, int x, int y) /* Is this char mouse-active or does it have help-echo? */ position = make_number (pos); + USE_SAFE_ALLOCA; + if (BUFFERP (object)) { /* Put all the overlays we want in a vector in overlay_vec. */ @@ -29600,6 +29764,7 @@ note_mouse_highlight (struct frame *f, int x, int y) BEGV = obegv; ZV = ozv; current_buffer = obuf; + SAFE_FREE (); } set_cursor: @@ -30117,8 +30282,8 @@ expose_frame (struct frame *f, int x, int y, int w, int h) if (w == 0 || h == 0) { r.x = r.y = 0; - r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f); - r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f); + r.width = FRAME_TEXT_WIDTH (f); + r.height = FRAME_TEXT_HEIGHT (f); } else { @@ -30373,6 +30538,7 @@ syms_of_xdisp (void) DEFSYM (Qright_to_left, "right-to-left"); DEFSYM (Qleft_to_right, "left-to-right"); + defsubr (&Sbidi_resolved_levels); #ifdef HAVE_WINDOW_SYSTEM DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p, @@ -30404,8 +30570,9 @@ A value of nil means no special handling of these characters. */); DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer, doc: /* The pointer shape to show in void text areas. -A value of nil means to show the text pointer. Other options are `arrow', -`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'. */); +A value of nil means to show the text pointer. Other options are +`arrow', `text', `hand', `vdrag', `hdrag', `nhdrag', `modeline', and +`hourglass'. */); Vvoid_text_area_pointer = Qarrow; DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay, @@ -30778,6 +30945,12 @@ To add a prefix to continuation lines, use `wrap-prefix'. */); doc: /* Non-nil means don't free realized faces. Internal use only. */); inhibit_free_realized_faces = 0; + DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring, + doc: /* Non-nil means don't mirror characters even when bidi context requires that. +Intended for use during debugging and for testing bidi display; +see biditest.el in the test suite. */); + inhibit_bidi_mirroring = 0; + #ifdef GLYPH_DEBUG DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id, doc: /* Inhibit try_window_id display optimization. */); @@ -30900,10 +31073,10 @@ init_xdisp (void) r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f); r->total_cols = FRAME_COLS (f); r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f); - r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f); + r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f); r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f); - m->top_line = FRAME_LINES (f) - 1; + m->top_line = FRAME_TOTAL_LINES (f) - 1; m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f); m->total_cols = FRAME_COLS (f); m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f); @@ -30936,7 +31109,38 @@ init_xdisp (void) /* Platform-independent portion of hourglass implementation. */ +/* Timer function of hourglass_atimer. */ + +static void +show_hourglass (struct atimer *timer) +{ + /* The timer implementation will cancel this timer automatically + after this function has run. Set hourglass_atimer to null + so that we know the timer doesn't have to be canceled. */ + hourglass_atimer = NULL; + + if (!hourglass_shown_p) + { + Lisp_Object tail, frame; + + block_input (); + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f) + && FRAME_RIF (f)->show_hourglass) + FRAME_RIF (f)->show_hourglass (f); + } + + hourglass_shown_p = 1; + unblock_input (); + } +} + /* Cancel a currently active hourglass timer, and start a new one. */ + void start_hourglass (void) { @@ -30955,20 +31159,13 @@ start_hourglass (void) else delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0); -#ifdef HAVE_NTGUI - { - extern void w32_note_current_window (void); - w32_note_current_window (); - } -#endif /* HAVE_NTGUI */ - hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay, show_hourglass, NULL); } - /* Cancel the hourglass cursor timer if active, hide a busy cursor if shown. */ + void cancel_hourglass (void) { @@ -30979,7 +31176,28 @@ cancel_hourglass (void) } if (hourglass_shown_p) - hide_hourglass (); + { + Lisp_Object tail, frame; + + block_input (); + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f) + && FRAME_RIF (f)->hide_hourglass) + FRAME_RIF (f)->hide_hourglass (f); +#ifdef HAVE_NTGUI + /* No cursors on non GUI frames - restore to stock arrow cursor. */ + else if (!FRAME_W32_P (f)) + w32_arrow_cursor (); +#endif + } + + hourglass_shown_p = 0; + unblock_input (); + } } #endif /* HAVE_WINDOW_SYSTEM */ |