commit 80864c2a04597d31ba453c9af69d35b15c4e1e24 (HEAD, refs/remotes/origin/master) Author: Martin Rudalics Date: Tue Mar 8 08:51:38 2016 +0100 Optionally reuse tooltip frames instead of deleting/recreating them. * src/frame.c (tooltip_reuse_hidden_frame): New option. * src/w32fns.c (x_create_tip_frame): Remove argument TEXT. Fix handling of dividers. (x_hide_tip): New function. (Fx_show_tip): Try to reuse old tooltip frame when `tooltip-reuse-hidden-frame' is non-nil and frame parameters have not changed. Insert STRING here instead of passing it to x_create_tip_frame. Compute size of tooltip window with Fwindow_text_pixel_size. Obey Vw32_tooltip_extra_pixels when padding tooltip window. (Fx_hide_tip): Call x_hide_tip. (Vw32_tooltip_extra_pixels): New variable. * src/xdisp.c (Fwindow_text_pixel_size): Don't return negative y value. Fix doc-string. * src/xfns.c (x_create_tip_frame): Remove argument TEXT. Call make_frame with mini_p argument false. (x_hide_tip): New function. (Fx_show_tip): Try to reuse old tooltip frame when `tooltip-reuse-hidden-frame' is non-nil and frame parameters have not changed. Insert STRING here instead of passing it to x_create_tip_frame. Compute size of tooltip window with Fwindow_text_pixel_size. (Fx_hide_tip): Call x_hide_tip. * lisp/cus-start.el (tooltip-reuse-hidden-frame): Add customization entry. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 5be61ce..1c10bf7 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -311,6 +311,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of (const :tag "Always" t) (repeat (symbol :tag "Parameter"))) "25.1") + (tooltip-reuse-hidden-frame tooltip boolean "26.1") ;; fringe.c (overflow-newline-into-fringe fringe boolean) ;; image.c diff --git a/src/frame.c b/src/frame.c index fd9f3ce..d536468 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5262,6 +5262,21 @@ The function `frame--size-history' displays the value of this variable in a more readable form. */); frame_size_history = Qnil; + DEFVAR_BOOL ("tooltip-reuse-hidden-frame", tooltip_reuse_hidden_frame, + doc: /* Non-nil means reuse hidden tooltip frames. +When this is nil, delete a tooltip frame when hiding the associated +tooltip. When this is non-nil, make the tooltip frame invisible only, +so it can be reused when the next tooltip is shown. + +Setting this to non-nil may drastically reduce the consing overhead +incurred by creating new tooltip frames. However, a value of non-nil +means also that intermittent changes of faces or `default-frame-alist' +are not applied when showing a tooltip in a reused frame. + +This variable is effective only with the X toolkit (and there only when +Gtk+ tooltips are not used) and on Windows. */); + tooltip_reuse_hidden_frame = false; + staticpro (&Vframe_list); defsubr (&Sframep); diff --git a/src/w32fns.c b/src/w32fns.c index 0fe6a6f..568a45a 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -6422,8 +6422,6 @@ no value of TYPE (always string in the MS Windows case). */) Tool tips ***********************************************************************/ -static Lisp_Object x_create_tip_frame (struct w32_display_info *, - Lisp_Object, Lisp_Object); static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, Lisp_Object, int, int, int *, int *); @@ -6458,8 +6456,7 @@ unwind_create_tip_frame (Lisp_Object frame) /* Create a frame for a tooltip on the display described by DPYINFO. - PARMS is a list of frame parameters. TEXT is the string to - display in the tip frame. Value is the frame. + PARMS is a list of frame parameters. Value is the frame. Note that functions called here, esp. x_default_parameter can signal errors, for instance when a specified color name is @@ -6467,8 +6464,7 @@ unwind_create_tip_frame (Lisp_Object frame) when this happens. */ static Lisp_Object -x_create_tip_frame (struct w32_display_info *dpyinfo, - Lisp_Object parms, Lisp_Object text) +x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) { struct frame *f; Lisp_Object frame; @@ -6477,8 +6473,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, ptrdiff_t count = SPECPDL_INDEX (); struct kboard *kb; bool face_change_before = face_change; - Lisp_Object buffer; - struct buffer *old_buffer; int x_width = 0, x_height = 0; /* Use this general default value to start with until we know if @@ -6502,23 +6496,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, frame = Qnil; /* Make a frame without minibuffer nor mode-line. */ f = make_frame (false); - f->wants_modeline = 0; + f->wants_modeline = false; XSETFRAME (frame, f); - AUTO_STRING (tip, " *tip*"); - buffer = Fget_buffer_create (tip); - /* Use set_window_buffer instead of Fset_window_buffer (see - discussion of bug#11984, bug#12025, bug#12026). */ - set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false); - old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (buffer)); - bset_truncate_lines (current_buffer, Qnil); - specbind (Qinhibit_read_only, Qt); - specbind (Qinhibit_modification_hooks, Qt); - Ferase_buffer (); - Finsert (1, &text); - set_buffer_internal_1 (old_buffer); - record_unwind_protect (unwind_create_tip_frame, frame); /* By setting the output method, we're essentially saying that @@ -6552,7 +6532,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, { fset_name (f, name); f->explicit_name = true; - /* use the frame's title when getting resources for this frame. */ + /* Use the frame's title when getting resources for this frame. */ specbind (Qx_resource_name, name); } @@ -6582,14 +6562,10 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, parms = Fcons (Fcons (Qinternal_border_width, value), parms); } + x_default_parameter (f, parms, Qinternal_border_width, make_number (1), "internalBorderWidth", "internalBorderWidth", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qright_divider_width, make_number (0), - NULL, NULL, RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qbottom_divider_width, make_number (0), - NULL, NULL, RES_TYPE_NUMBER); - /* Also do the stuff which must be set before the window exists. */ x_default_parameter (f, parms, Qforeground_color, build_string ("black"), "foreground", "Foreground", RES_TYPE_STRING); @@ -6616,6 +6592,9 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, f->fringe_cols = 0; f->left_fringe_width = 0; f->right_fringe_width = 0; + /* No dividers on tip frame. */ + f->right_divider_width = 0; + f->bottom_divider_width = 0; block_input (); my_create_tip_window (f); @@ -6642,7 +6621,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, SET_FRAME_LINES (f, 0); adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame); - /* Add `tooltip' frame parameter's default value. */ if (NILP (Fframe_parameter (frame, Qtooltip))) Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); @@ -6660,8 +6638,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object fg = Fframe_parameter (frame, Qforeground_color); Lisp_Object colors = Qnil; - /* Set tip_frame here, so that */ - tip_frame = frame; call2 (Qface_set_after_frame_default, frame, Qnil); if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) @@ -6793,6 +6769,48 @@ compute_tip_xy (struct frame *f, *root_x = min_x; } +/* Hide tooltip. Delete its frame if DELETE is true. */ +static Lisp_Object +x_hide_tip (bool delete) +{ + if (!NILP (tip_timer)) + { + call1 (Qcancel_timer, tip_timer); + tip_timer = Qnil; + } + + if (NILP (tip_frame) + || (!delete && FRAMEP (tip_frame) + && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) + return Qnil; + else + { + ptrdiff_t count; + Lisp_Object was_open = Qnil; + + count = SPECPDL_INDEX (); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); + + if (FRAMEP (tip_frame)) + { + if (delete) + { + delete_frame (tip_frame, Qnil); + tip_frame = Qnil; + } + else + x_make_frame_invisible (XFRAME (tip_frame)); + + was_open = Qt; + } + else + tip_frame = Qnil; + + return unbind_to (count, was_open); + } +} + DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, doc: /* Show STRING in a \"tooltip\" window on frame FRAME. @@ -6826,15 +6844,16 @@ A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { - struct frame *f; + struct frame *f, *tip_f; struct window *w; int root_x, root_y; struct buffer *old_buffer; struct text_pos pos; int i, width, height; - bool seen_reversed_p; int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); + ptrdiff_t count_1; + Lisp_Object window, size; specbind (Qinhibit_redisplay, Qt); @@ -6858,91 +6877,155 @@ Text larger than the specified size is clipped. */) if (NILP (last_show_tip_args)) last_show_tip_args = Fmake_vector (make_number (3), Qnil); - if (!NILP (tip_frame)) + if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) { Lisp_Object last_string = AREF (last_show_tip_args, 0); Lisp_Object last_frame = AREF (last_show_tip_args, 1); Lisp_Object last_parms = AREF (last_show_tip_args, 2); - if (EQ (frame, last_frame) - && !NILP (Fequal (last_string, string)) + if (FRAME_VISIBLE_P (XFRAME (tip_frame)) + && EQ (frame, last_frame) + && !NILP (Fequal_including_properties (last_string, string)) && !NILP (Fequal (last_parms, parms))) { - struct frame *f = XFRAME (tip_frame); - /* Only DX and DY have changed. */ + tip_f = XFRAME (tip_frame); if (!NILP (tip_timer)) { Lisp_Object timer = tip_timer; + tip_timer = Qnil; call1 (Qcancel_timer, timer); } block_input (); - compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f), - FRAME_PIXEL_HEIGHT (f), &root_x, &root_y); + compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), + FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y); /* Put tooltip in topmost group and in position. */ - SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST, + SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST, root_x, root_y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); /* Ensure tooltip is on top of other topmost windows (eg menus). */ - SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP, + SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); + /* Let redisplay know that we have made the frame visible already. */ + SET_FRAME_VISIBLE (tip_f, 1); + ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE); unblock_input (); + goto start_timer; } - } + else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame)) + { + bool delete = false; + Lisp_Object tail, elt, parm, last; - /* Hide a previous tip, if any. */ - Fx_hide_tip (); + /* Check if every parameter in PARMS has the same value in + last_parms. This may destruct last_parms which, however, + will be recreated below. */ + for (tail = parms; CONSP (tail); tail = XCDR (tail)) + { + elt = XCAR (tail); + parm = Fcar (elt); + /* The left, top, right and bottom parameters are handled + by compute_tip_xy so they can be ignored here. */ + if (!EQ (parm, Qleft) && !EQ (parm, Qtop) + && !EQ (parm, Qright) && !EQ (parm, Qbottom)) + { + last = Fassq (parm, last_parms); + if (NILP (Fequal (Fcdr (elt), Fcdr (last)))) + { + /* We lost, delete the old tooltip. */ + delete = true; + break; + } + else + last_parms = call2 (Qassq_delete_all, parm, last_parms); + } + else + last_parms = call2 (Qassq_delete_all, parm, last_parms); + } + + /* Now check if there's a parameter left in last_parms with a + non-nil value. */ + for (tail = last_parms; CONSP (tail); tail = XCDR (tail)) + { + elt = XCAR (tail); + parm = Fcar (elt); + if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright) + && !EQ (parm, Qbottom) && !NILP (Fcdr (elt))) + { + /* We lost, delete the old tooltip. */ + delete = true; + break; + } + } + + x_hide_tip (delete); + } + else + x_hide_tip (true); + } + else + x_hide_tip (true); ASET (last_show_tip_args, 0, string); ASET (last_show_tip_args, 1, frame); ASET (last_show_tip_args, 2, parms); - /* Add default values to frame parameters. */ - if (NILP (Fassq (Qname, parms))) - parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); - if (NILP (Fassq (Qinternal_border_width, parms))) - parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); - if (NILP (Fassq (Qright_divider_width, parms))) - parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms); - if (NILP (Fassq (Qbottom_divider_width, parms))) - parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms); - if (NILP (Fassq (Qborder_width, parms))) - parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); - if (NILP (Fassq (Qborder_color, parms))) - parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); - if (NILP (Fassq (Qbackground_color, parms))) - parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), - parms); - /* Block input until the tip has been fully drawn, to avoid crashes when drawing tips in menus. */ block_input (); - /* Create a frame for the tooltip, and record it in the global - variable tip_frame. */ - frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string); - f = XFRAME (frame); + if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) + { + /* Add default values to frame parameters. */ + if (NILP (Fassq (Qname, parms))) + parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); + if (NILP (Fassq (Qinternal_border_width, parms))) + parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); + if (NILP (Fassq (Qborder_width, parms))) + parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); + if (NILP (Fassq (Qborder_color, parms))) + parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); + if (NILP (Fassq (Qbackground_color, parms))) + parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), + parms); + + /* Create a frame for the tooltip, and record it in the global + variable tip_frame. */ + if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) + { + /* Creating the tip frame failed. */ + unblock_input (); + return unbind_to (count, Qnil); + } + } + + tip_f = XFRAME (tip_frame); + window = FRAME_ROOT_WINDOW (tip_f); + AUTO_STRING (tip, " *tip*"); + set_window_buffer (window, Fget_buffer_create (tip), false, false); + w = XWINDOW (window); + w->pseudo_window_p = true; - /* Set up the frame's root window. */ - w = XWINDOW (FRAME_ROOT_WINDOW (f)); + /* Set up the frame's root window. Note: The following code does not + try to size the window or its frame correctly. Its only purpose is + to make the subsequent text size calculations work. The right + sizes should get installed when the toolkit gets back to us. */ w->left_col = 0; w->top_line = 0; w->pixel_left = 0; w->pixel_top = 0; if (CONSP (Vx_max_tooltip_size) - && INTEGERP (XCAR (Vx_max_tooltip_size)) - && XINT (XCAR (Vx_max_tooltip_size)) > 0 - && INTEGERP (XCDR (Vx_max_tooltip_size)) - && XINT (XCDR (Vx_max_tooltip_size)) > 0) + && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX) + && RANGED_INTEGERP (1, XCDR (Vx_max_tooltip_size), INT_MAX)) { w->total_cols = XFASTINT (XCAR (Vx_max_tooltip_size)); w->total_lines = XFASTINT (XCDR (Vx_max_tooltip_size)); @@ -6953,164 +7036,71 @@ Text larger than the specified size is clipped. */) w->total_lines = 40; } - w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f); - w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f); - - FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w); - adjust_frame_glyphs (f); - w->pseudo_window_p = true; + w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f); + w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f); + FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w); + adjust_frame_glyphs (tip_f); - /* Display the tooltip text in a temporary buffer. */ + /* Insert STRING into the root window's buffer and fit the frame to + the buffer. */ + count_1 = SPECPDL_INDEX (); old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents)); + set_buffer_internal_1 (XBUFFER (w->contents)); bset_truncate_lines (current_buffer, Qnil); + specbind (Qinhibit_read_only, Qt); + specbind (Qinhibit_modification_hooks, Qt); + specbind (Qinhibit_point_motion_hooks, Qt); + Ferase_buffer (); + Finsert (1, &string); clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); SET_TEXT_POS (pos, BEGV, BEGV_BYTE); - try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); - - /* Compute width and height of the tooltip. */ - width = height = 0; - seen_reversed_p = false; - for (i = 0; i < w->desired_matrix->nrows; ++i) - { - struct glyph_row *row = &w->desired_matrix->rows[i]; - struct glyph *last; - int row_width; - - /* Stop at the first empty row at the end. */ - if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row)) - break; - - /* Let the row go over the full width of the frame. */ - row->full_width_p = true; - - row_width = row->pixel_width; - if (row->used[TEXT_AREA]) - { - if (!row->reversed_p) - { - /* There's a glyph at the end of rows that is used to - place the cursor there. Don't include the width of - this glyph. */ - last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1]; - if (NILP (last->object)) - row_width -= last->pixel_width; - } - else - { - /* There could be a stretch glyph at the beginning of R2L - rows that is produced by extend_face_to_end_of_line. - Don't count that glyph. */ - struct glyph *g = row->glyphs[TEXT_AREA]; - - if (g->type == STRETCH_GLYPH && NILP (g->object)) - { - row_width -= g->pixel_width; - seen_reversed_p = true; - } - } - } - - height += row->height; - width = max (width, row_width); - } - - /* If we've seen partial-length R2L rows, we need to re-adjust the - tool-tip frame width and redisplay it again, to avoid over-wide - tips due to the stretch glyph that extends R2L lines to full - width of the frame. */ - if (seen_reversed_p) - { - /* PXW: Why do we do the pixel-to-cols conversion only if - seen_reversed_p holds? Don't we have to set other fields of - the window/frame structure? - - w->total_cols and FRAME_TOTAL_COLS want the width in columns, - not in pixels. */ - w->pixel_width = width; - width /= WINDOW_FRAME_COLUMN_WIDTH (w); - w->total_cols = width; - FRAME_TOTAL_COLS (f) = width; - SET_FRAME_WIDTH (f, width); - adjust_frame_glyphs (f); - w->pseudo_window_p = 1; - clear_glyph_matrix (w->desired_matrix); - clear_glyph_matrix (w->current_matrix); - try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); - width = height = 0; - /* Recompute width and height of the tooltip. */ - for (i = 0; i < w->desired_matrix->nrows; ++i) - { - struct glyph_row *row = &w->desired_matrix->rows[i]; - struct glyph *last; - int row_width; - - if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row)) - break; - row->full_width_p = true; - row_width = row->pixel_width; - if (row->used[TEXT_AREA] && !row->reversed_p) - { - last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1]; - if (NILP (last->object)) - row_width -= last->pixel_width; - } - - height += row->height; - width = max (width, row_width); - } - } - - /* Add the frame's internal border to the width and height the w32 - window should have. */ - height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f); - width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f); - - /* Move the tooltip window where the mouse pointer is. Resize and - show it. - - PXW: This should use the frame's pixel coordinates. */ - compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); - + try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); + /* Calculate size of tooltip window. */ + size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, + make_number (w->pixel_height), Qnil); + /* Add the frame's internal border to calculated size. */ + width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + /* Calculate position of tooltip frame. */ + compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y); + + /* Show tooltip frame. */ { - /* Adjust Window size to take border into account. */ RECT rect; + int pad = (NUMBERP (Vw32_tooltip_extra_pixels) + ? max (0, XINT (Vw32_tooltip_extra_pixels)) + : FRAME_COLUMN_WIDTH (tip_f)); + rect.left = rect.top = 0; rect.right = width; rect.bottom = height; - AdjustWindowRect (&rect, f->output_data.w32->dwStyle, false); - - /* Position and size tooltip, and put it in the topmost group. - The add-on of FRAME_COLUMN_WIDTH to the 5th argument is a - peculiarity of w32 display: without it, some fonts cause the - last character of the tip to be truncated or wrapped around to - the next line. */ - SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST, + AdjustWindowRect (&rect, tip_f->output_data.w32->dwStyle, + FRAME_EXTERNAL_MENU_BAR (tip_f)); + + /* Position and size tooltip and put it in the topmost group. */ + SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOPMOST, root_x, root_y, - rect.right - rect.left + FRAME_COLUMN_WIDTH (f), + rect.right - rect.left + pad, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER); /* Ensure tooltip is on top of other topmost windows (eg menus). */ - SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP, + SetWindowPos (FRAME_W32_WINDOW (tip_f), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER); /* Let redisplay know that we have made the frame visible already. */ - SET_FRAME_VISIBLE (f, 1); + SET_FRAME_VISIBLE (tip_f, 1); - ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE); + ShowWindow (FRAME_W32_WINDOW (tip_f), SW_SHOWNOACTIVATE); } - /* Draw into the window. */ w->must_be_updated_p = true; update_single_window (w); - - unblock_input (); - - /* Restore original current buffer. */ set_buffer_internal_1 (old_buffer); + unbind_to (count_1, Qnil); + unblock_input (); windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: @@ -7127,31 +7117,7 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, Value is t if tooltip was open, nil otherwise. */) (void) { - ptrdiff_t count; - Lisp_Object deleted, frame, timer; - - /* Return quickly if nothing to do. */ - if (NILP (tip_timer) && NILP (tip_frame)) - return Qnil; - - frame = tip_frame; - timer = tip_timer; - tip_frame = tip_timer = deleted = Qnil; - - count = SPECPDL_INDEX (); - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); - - if (!NILP (timer)) - call1 (Qcancel_timer, timer); - - if (FRAMEP (frame)) - { - delete_frame (frame, Qnil); - deleted = Qt; - } - - return unbind_to (count, deleted); + return x_hide_tip (!tooltip_reuse_hidden_frame); } /*********************************************************************** @@ -9751,6 +9717,7 @@ syms_of_w32fns (void) DEFSYM (Qmm_size, "mm-size"); DEFSYM (Qframes, "frames"); DEFSYM (Qtip_frame, "tip-frame"); + DEFSYM (Qassq_delete_all, "assq-delete-all"); DEFSYM (Qunicode_sip, "unicode-sip"); #if defined WINDOWSNT && !defined HAVE_DBUS DEFSYM (QCicon, ":icon"); @@ -10063,6 +10030,18 @@ Default is nil. This variable has effect only on Windows Vista and later. */); w32_disable_new_uniscribe_apis = 0; + DEFVAR_LISP ("w32-tooltip-extra-pixels", + Vw32_tooltip_extra_pixels, + doc: /* Number of pixels added after tooltip text. +On Windows some fonts may cause the last character of a tooltip be +truncated or wrapped around to the next line. Adding some extra space +at the end of the toooltip works around this problem. + +This variable specifies the number of pixels that shall be added. The +default value t means to add the width of one canonical character of the +tip frame. */); + Vw32_tooltip_extra_pixels = Qt; + #if 0 /* TODO: Port to W32 */ defsubr (&Sx_change_window_property); defsubr (&Sx_delete_window_property); diff --git a/src/xdisp.c b/src/xdisp.c index b9d496e..5b96144 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -9794,26 +9794,28 @@ the maximum pixel-height of all text lines. The optional argument FROM, if non-nil, specifies the first text position and defaults to the minimum accessible position of the buffer. -If FROM is t, use the minimum accessible position that is not a newline -character. TO, if non-nil, specifies the last text position and +If FROM is t, use the minimum accessible position that starts a +non-empty line. TO, if non-nil, specifies the last text position and defaults to the maximum accessible position of the buffer. If TO is t, -use the maximum accessible position that is not a newline character. +use the maximum accessible position that ends a non-empty line. The optional argument X-LIMIT, if non-nil, specifies the maximum text width that can be returned. X-LIMIT nil or omitted, means to use the -pixel-width of WINDOW's body; use this if you do not intend to change -the width of WINDOW. Use the maximum width WINDOW may assume if you -intend to change WINDOW's width. In any case, text whose x-coordinate -is beyond X-LIMIT is ignored. Since calculating the width of long lines -can take some time, it's always a good idea to make this argument as -small as possible; in particular, if the buffer contains long lines that -shall be truncated anyway. +pixel-width of WINDOW's body; use this if you want to know how high +WINDOW should be become in order to fit all of its buffer's text with +the width of WINDOW unaltered. Use the maximum width WINDOW may assume +if you intend to change WINDOW's width. In any case, text whose +x-coordinate is beyond X-LIMIT is ignored. Since calculating the width +of long lines can take some time, it's always a good idea to make this +argument as small as possible; in particular, if the buffer contains +long lines that shall be truncated anyway. The optional argument Y-LIMIT, if non-nil, specifies the maximum text -height that can be returned. Text lines whose y-coordinate is beyond -Y-LIMIT are ignored. Since calculating the text height of a large -buffer can take some time, it makes sense to specify this argument if -the size of the buffer is unknown. +height (exluding the height of the mode- or header-line, if any) that +can be returned. Text lines whose y-coordinate is beyond Y-LIMIT are +ignored. Since calculating the text height of a large buffer can take +some time, it makes sense to specify this argument if the size of the +buffer is large or unknown. Optional argument MODE-AND-HEADER-LINE nil or omitted means do not include the height of the mode- or header-line of WINDOW in the return @@ -9831,7 +9833,7 @@ include the height of both, if present, in the return value. */) ptrdiff_t start, end, pos; struct text_pos startp; void *itdata = NULL; - int c, max_y = -1, x = 0, y = 0; + int c, max_x = 0, max_y = 0, x = 0, y = 0; CHECK_BUFFER (buffer); b = XBUFFER (buffer); @@ -9876,11 +9878,13 @@ include the height of both, if present, in the return value. */) end = max (start, min (XINT (to), ZV)); } - if (!NILP (y_limit)) - { - CHECK_NUMBER (y_limit); - max_y = min (XINT (y_limit), INT_MAX); - } + if (!NILP (x_limit) && RANGED_INTEGERP (0, x_limit, INT_MAX)) + max_x = XINT (x_limit); + + if (NILP (y_limit)) + max_y = INT_MAX; + else if (RANGED_INTEGERP (0, y_limit, INT_MAX)) + max_y = XINT (y_limit); itdata = bidi_shelve_cache (); SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start)); @@ -9890,27 +9894,30 @@ include the height of both, if present, in the return value. */) x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y); else { - CHECK_NUMBER (x_limit); - it.last_visible_x = min (XINT (x_limit), INFINITY); + it.last_visible_x = max_x; /* Actually, we never want move_it_to stop at to_x. But to make sure that move_it_in_display_line_to always moves far enough, - we set it to INT_MAX and specify MOVE_TO_X. */ - x = move_it_to (&it, end, INT_MAX, max_y, -1, - MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); + we set it to INT_MAX and specify MOVE_TO_X. Also bound width + value by X-LIMIT. */ + x = min (move_it_to (&it, end, INT_MAX, max_y, -1, + MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y), + max_x); } - y = it.current_y + it.max_ascent + it.max_descent; + /* Subtract height of header-line which was counted automatically by + start_display. */ + y = min (it.current_y + it.max_ascent + it.max_descent + - WINDOW_HEADER_LINE_HEIGHT (w), + max_y); - if (!EQ (mode_and_header_line, Qheader_line) - && !EQ (mode_and_header_line, Qt)) - /* Do not count the header-line which was counted automatically by - start_display. */ - y = y - WINDOW_HEADER_LINE_HEIGHT (w); + if (EQ (mode_and_header_line, Qheader_line) + || EQ (mode_and_header_line, Qt)) + /* Re-add height of header-line as requested. */ + y = y + WINDOW_HEADER_LINE_HEIGHT (w); if (EQ (mode_and_header_line, Qmode_line) || EQ (mode_and_header_line, Qt)) - /* Do count the mode-line which is not included automatically by - start_display. */ + /* Add height of mode-line as requested. */ y = y + WINDOW_MODE_LINE_HEIGHT (w); bidi_unshelve_cache (itdata, false); diff --git a/src/xfns.c b/src/xfns.c index 2a50a5a..c1ce1b7 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -5303,8 +5303,6 @@ no value of TYPE (always string in the MS Windows case). */) Tool tips ***********************************************************************/ -static Lisp_Object x_create_tip_frame (struct x_display_info *, - Lisp_Object, Lisp_Object); static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, Lisp_Object, int, int, int *, int *); @@ -5348,9 +5346,7 @@ unwind_create_tip_frame (Lisp_Object frame) when this happens. */ static Lisp_Object -x_create_tip_frame (struct x_display_info *dpyinfo, - Lisp_Object parms, - Lisp_Object text) +x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) { struct frame *f; Lisp_Object frame; @@ -5359,7 +5355,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, ptrdiff_t count = SPECPDL_INDEX (); bool face_change_before = face_change; Lisp_Object buffer; - struct buffer *old_buffer; int x_width = 0, x_height = 0; if (!dpyinfo->terminal->name) @@ -5375,23 +5370,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, error ("Invalid frame name--not a string or nil"); frame = Qnil; - f = make_frame (true); + f = make_frame (false); + f->wants_modeline = false; XSETFRAME (frame, f); - - AUTO_STRING (tip, " *tip*"); - buffer = Fget_buffer_create (tip); - /* Use set_window_buffer instead of Fset_window_buffer (see - discussion of bug#11984, bug#12025, bug#12026). */ - set_window_buffer (FRAME_ROOT_WINDOW (f), buffer, false, false); - old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (buffer)); - bset_truncate_lines (current_buffer, Qnil); - specbind (Qinhibit_read_only, Qt); - specbind (Qinhibit_modification_hooks, Qt); - Ferase_buffer (); - Finsert (1, &text); - set_buffer_internal_1 (old_buffer); - record_unwind_protect (unwind_create_tip_frame, frame); f->terminal = dpyinfo->terminal; @@ -5633,8 +5614,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, { Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); - /* Set tip_frame here, so that */ - tip_frame = frame; call2 (Qface_set_after_frame_default, frame, Qnil); if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) @@ -5773,6 +5752,85 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object } +/* Hide tooltip. Delete its frame if DELETE is true. */ +static Lisp_Object +x_hide_tip (bool delete) +{ + if (!NILP (tip_timer)) + { + call1 (Qcancel_timer, tip_timer); + tip_timer = Qnil; + } + + + if (NILP (tip_frame) + || (!delete && FRAMEP (tip_frame) + && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) + return Qnil; + else + { + ptrdiff_t count; + Lisp_Object was_open = Qnil; + + count = SPECPDL_INDEX (); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); + +#ifdef USE_GTK + { + /* When using system tooltip, tip_frame is the Emacs frame on + which the tip is shown. */ + struct frame *f = XFRAME (tip_frame); + + if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) + { + tip_frame = Qnil; + was_open = Qt; + } + } +#endif + + if (FRAMEP (tip_frame)) + { + if (delete) + { + delete_frame (tip_frame, Qnil); + tip_frame = Qnil; + } + else + x_make_frame_invisible (XFRAME (tip_frame)); + + was_open = Qt; + +#ifdef USE_LUCID + /* Bloodcurdling hack alert: The Lucid menu bar widget's + redisplay procedure is not called when a tip frame over + menu items is unmapped. Redisplay the menu manually... */ + { + Widget w; + struct frame *f = SELECTED_FRAME (); + if (FRAME_X_P (f) && FRAME_LIVE_P (f)) + { + w = f->output_data.x->menubar_widget; + + if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen) + && w != NULL) + { + block_input (); + xlwmenu_redisplay (w); + unblock_input (); + } + } + } +#endif /* USE_LUCID */ + } + else + tip_frame = Qnil; + + return unbind_to (count, was_open); + } +} + DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, doc: /* Show STRING in a "tooltip" window on frame FRAME. A tooltip window is a small X window displaying a string. @@ -5805,15 +5863,16 @@ A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { - struct frame *f; + struct frame *f, *tip_f; struct window *w; int root_x, root_y; struct buffer *old_buffer; struct text_pos pos; - int i, width, height; - bool seen_reversed_p; + int width, height; int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); + ptrdiff_t count_1; + Lisp_Object window, size; specbind (Qinhibit_redisplay, Qt); @@ -5862,22 +5921,23 @@ Text larger than the specified size is clipped. */) if (NILP (last_show_tip_args)) last_show_tip_args = Fmake_vector (make_number (3), Qnil); - if (!NILP (tip_frame)) + if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) { Lisp_Object last_string = AREF (last_show_tip_args, 0); Lisp_Object last_frame = AREF (last_show_tip_args, 1); Lisp_Object last_parms = AREF (last_show_tip_args, 2); - if (EQ (frame, last_frame) - && !NILP (Fequal (last_string, string)) + if (FRAME_VISIBLE_P (XFRAME (tip_frame)) + && EQ (frame, last_frame) + && !NILP (Fequal_including_properties (last_string, string)) && !NILP (Fequal (last_parms, parms))) { - struct frame *tip_f = XFRAME (tip_frame); - /* Only DX and DY have changed. */ + tip_f = XFRAME (tip_frame); if (!NILP (tip_timer)) { Lisp_Object timer = tip_timer; + tip_timer = Qnil; call1 (Qcancel_timer, timer); } @@ -5888,41 +5948,103 @@ Text larger than the specified size is clipped. */) XMoveWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f), root_x, root_y); unblock_input (); + goto start_timer; } - } + else if (tooltip_reuse_hidden_frame && EQ (frame, last_frame)) + { + bool delete = false; + Lisp_Object tail, elt, parm, last; + + /* Check if every parameter in PARMS has the same value in + last_parms unless it should be ignored by means of + Vtooltip_reuse_hidden_frame_parameters. This may destruct + last_parms which, however, will be recreated below. */ + for (tail = parms; CONSP (tail); tail = XCDR (tail)) + { + elt = XCAR (tail); + parm = Fcar (elt); + /* The left, top, right and bottom parameters are handled + by compute_tip_xy so they can be ignored here. */ + if (!EQ (parm, Qleft) && !EQ (parm, Qtop) + && !EQ (parm, Qright) && !EQ (parm, Qbottom)) + { + last = Fassq (parm, last_parms); + if (NILP (Fequal (Fcdr (elt), Fcdr (last)))) + { + /* We lost, delete the old tooltip. */ + delete = true; + break; + } + else + last_parms = call2 (Qassq_delete_all, parm, last_parms); + } + else + last_parms = call2 (Qassq_delete_all, parm, last_parms); + } - /* Hide a previous tip, if any. */ - Fx_hide_tip (); + /* Now check if every parameter in what is left of last_parms + with a non-nil value has an association in PARMS unless it + should be ignored by means of + Vtooltip_reuse_hidden_frame_parameters. */ + for (tail = last_parms; CONSP (tail); tail = XCDR (tail)) + { + elt = XCAR (tail); + parm = Fcar (elt); + if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright) + && !EQ (parm, Qbottom) && !NILP (Fcdr (elt))) + { + /* We lost, delete the old tooltip. */ + delete = true; + break; + } + } + + x_hide_tip (delete); + } + else + x_hide_tip (true); + } + else + x_hide_tip (true); ASET (last_show_tip_args, 0, string); ASET (last_show_tip_args, 1, frame); ASET (last_show_tip_args, 2, parms); - /* Add default values to frame parameters. */ - if (NILP (Fassq (Qname, parms))) - parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); - if (NILP (Fassq (Qinternal_border_width, parms))) - parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); - if (NILP (Fassq (Qborder_width, parms))) - parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); - if (NILP (Fassq (Qbottom_divider_width, parms))) - parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms); - if (NILP (Fassq (Qright_divider_width, parms))) - parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms); - if (NILP (Fassq (Qborder_color, parms))) - parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); - if (NILP (Fassq (Qbackground_color, parms))) - parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), - parms); - - /* Create a frame for the tooltip, and record it in the global - variable tip_frame. */ - frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, string); - f = XFRAME (frame); - - /* Set up the frame's root window. */ - w = XWINDOW (FRAME_ROOT_WINDOW (f)); + if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) + { + /* Add default values to frame parameters. */ + if (NILP (Fassq (Qname, parms))) + parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); + if (NILP (Fassq (Qinternal_border_width, parms))) + parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms); + if (NILP (Fassq (Qborder_width, parms))) + parms = Fcons (Fcons (Qborder_width, make_number (1)), parms); + if (NILP (Fassq (Qborder_color, parms))) + parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); + if (NILP (Fassq (Qbackground_color, parms))) + parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), + parms); + + /* Create a frame for the tooltip, and record it in the global + variable tip_frame. */ + if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms))) + /* Creating the tip frame failed. */ + return unbind_to (count, Qnil); + } + + tip_f = XFRAME (tip_frame); + window = FRAME_ROOT_WINDOW (tip_f); + AUTO_STRING (tip, " *tip*"); + set_window_buffer (window, Fget_buffer_create (tip), false, false); + w = XWINDOW (window); + w->pseudo_window_p = true; + + /* Set up the frame's root window. Note: The following code does not + try to size the window or its frame correctly. Its only purpose is + to make the subsequent text size calculations work. The right + sizes should get installed when the toolkit gets back to us. */ w->left_col = 0; w->top_line = 0; w->pixel_left = 0; @@ -5941,130 +6063,47 @@ Text larger than the specified size is clipped. */) w->total_lines = 40; } - w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f); - w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f); - - FRAME_TOTAL_COLS (f) = w->total_cols; - adjust_frame_glyphs (f); - w->pseudo_window_p = true; + w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f); + w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f); + FRAME_TOTAL_COLS (tip_f) = w->total_cols; + adjust_frame_glyphs (tip_f); - /* Display the tooltip text in a temporary buffer. */ + /* Insert STRING into root window's buffer and fit the frame to the + buffer. */ + count_1 = SPECPDL_INDEX (); old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->contents)); + set_buffer_internal_1 (XBUFFER (w->contents)); bset_truncate_lines (current_buffer, Qnil); + specbind (Qinhibit_read_only, Qt); + specbind (Qinhibit_modification_hooks, Qt); + specbind (Qinhibit_point_motion_hooks, Qt); + Ferase_buffer (); + Finsert (1, &string); clear_glyph_matrix (w->desired_matrix); clear_glyph_matrix (w->current_matrix); SET_TEXT_POS (pos, BEGV, BEGV_BYTE); - try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); - - /* Compute width and height of the tooltip. */ - width = height = 0; - seen_reversed_p = false; - for (i = 0; i < w->desired_matrix->nrows; ++i) - { - struct glyph_row *row = &w->desired_matrix->rows[i]; - struct glyph *last; - int row_width; - - /* Stop at the first empty row at the end. */ - if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row)) - break; - - /* Let the row go over the full width of the frame. */ - row->full_width_p = true; - - row_width = row->pixel_width; - if (row->used[TEXT_AREA]) - { - /* There's a glyph at the end of rows that is used to place - the cursor there. Don't include the width of this glyph. */ - if (!row->reversed_p) - { - last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1]; - if (NILP (last->object)) - row_width -= last->pixel_width; - } - else - { - /* There could be a stretch glyph at the beginning of R2L - rows that is produced by extend_face_to_end_of_line. - Don't count that glyph. */ - struct glyph *g = row->glyphs[TEXT_AREA]; - - if (g->type == STRETCH_GLYPH && NILP (g->object)) - { - row_width -= g->pixel_width; - seen_reversed_p = true; - } - } - } - - height += row->height; - width = max (width, row_width); - } - - /* If we've seen partial-length R2L rows, we need to re-adjust the - tool-tip frame width and redisplay it again, to avoid over-wide - tips due to the stretch glyph that extends R2L lines to full - width of the frame. */ - if (seen_reversed_p) - { - /* w->total_cols and FRAME_TOTAL_COLS want the width in columns, - not in pixels. */ - w->pixel_width = width; - width /= WINDOW_FRAME_COLUMN_WIDTH (w); - w->total_cols = width; - FRAME_TOTAL_COLS (f) = width; - SET_FRAME_WIDTH (f, width); - adjust_frame_glyphs (f); - clear_glyph_matrix (w->desired_matrix); - clear_glyph_matrix (w->current_matrix); - try_window (FRAME_ROOT_WINDOW (f), pos, 0); - width = height = 0; - /* Recompute width and height of the tooltip. */ - for (i = 0; i < w->desired_matrix->nrows; ++i) - { - struct glyph_row *row = &w->desired_matrix->rows[i]; - struct glyph *last; - int row_width; - - if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row)) - break; - row->full_width_p = true; - row_width = row->pixel_width; - if (row->used[TEXT_AREA] && !row->reversed_p) - { - last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1]; - if (NILP (last->object)) - row_width -= last->pixel_width; - } - - height += row->height; - width = max (width, row_width); - } - } - - /* Add the frame's internal border to the width and height the X - window should have. */ - height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f); - width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f); - - /* Move the tooltip window where the mouse pointer is. Resize and - show it. */ - compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); - + try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); + /* Calculate size of tooltip window. */ + size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, + make_number (w->pixel_height), Qnil); + /* Add the frame's internal border to calculated size. */ + width = XINT (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + height = XINT (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + + /* Calculate position of tooltip frame. */ + compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y); + + /* Show tooltip frame. */ block_input (); - XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f), root_x, root_y, width, height); - XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f)); unblock_input (); - /* Draw into the window. */ w->must_be_updated_p = true; update_single_window (w); - - /* Restore original current buffer. */ set_buffer_internal_1 (old_buffer); + unbind_to (count_1, Qnil); windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: @@ -6081,66 +6120,9 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, Value is t if tooltip was open, nil otherwise. */) (void) { - ptrdiff_t count; - Lisp_Object deleted, frame, timer; - - /* Return quickly if nothing to do. */ - if (NILP (tip_timer) && NILP (tip_frame)) - return Qnil; - - frame = tip_frame; - timer = tip_timer; - tip_frame = tip_timer = deleted = Qnil; - - count = SPECPDL_INDEX (); - specbind (Qinhibit_redisplay, Qt); - specbind (Qinhibit_quit, Qt); - - if (!NILP (timer)) - call1 (Qcancel_timer, timer); - -#ifdef USE_GTK - { - /* When using system tooltip, tip_frame is the Emacs frame on which - the tip is shown. */ - struct frame *f = XFRAME (frame); - if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) - frame = Qnil; - } -#endif - - if (FRAMEP (frame)) - { - delete_frame (frame, Qnil); - deleted = Qt; - -#ifdef USE_LUCID - /* Bloodcurdling hack alert: The Lucid menu bar widget's - redisplay procedure is not called when a tip frame over menu - items is unmapped. Redisplay the menu manually... */ - { - Widget w; - struct frame *f = SELECTED_FRAME (); - if (FRAME_X_P (f) && FRAME_LIVE_P (f)) - { - w = f->output_data.x->menubar_widget; - - if (!DoesSaveUnders (FRAME_DISPLAY_INFO (f)->screen) - && w != NULL) - { - block_input (); - xlwmenu_redisplay (w); - unblock_input (); - } - } - } -#endif /* USE_LUCID */ - } - - return unbind_to (count, deleted); + return x_hide_tip (!tooltip_reuse_hidden_frame); } - /*********************************************************************** File selection dialog @@ -6802,6 +6784,7 @@ syms_of_xfns (void) DEFSYM (Qcancel_timer, "cancel-timer"); DEFSYM (Qfont_param, "font-parameter"); DEFSYM (Qmono, "mono"); + DEFSYM (Qassq_delete_all, "assq-delete-all"); #ifdef USE_CAIRO DEFSYM (Qpdf, "pdf"); commit 59c7a5d71145d88933a535e222bdf30105e7d382 Author: Paul Eggert Date: Mon Mar 7 18:54:25 2016 -0800 Assume getaddrinfo in C code * admin/CPP-DEFINES, configure.ac: Remove HAVE_GETADDRINFO, HAVE_H_ERRNO. All uses removed. * doc/lispref/processes.texi (Network, Network Processes), etc/NEWS: Say that port numbers can be integer strings. * lib-src/pop.c (h_errno) [!WINDOWSNT && !HAVE_H_ERRNO]: Remove decl. (socket_connection): Assume HAVE_GETADDRINFO. * lisp/mpc.el (mpc--proc-connect): * lisp/net/network-stream.el (open-network-stream): It’s now OK to use integer strings as port numbers. * src/process.c (conv_numerical_to_lisp) [!HAVE_GETADDRINFO]: Remove. (Fmake_network_process): Assume HAVE_GETADDRINFO. diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES index 9064053..d9df152 100644 --- a/admin/CPP-DEFINES +++ b/admin/CPP-DEFINES @@ -147,7 +147,6 @@ HAVE_FUTIMES HAVE_FUTIMESAT HAVE_GAI_STRERROR HAVE_GCONF -HAVE_GETADDRINFO HAVE_GETDELIM HAVE_GETGRENT HAVE_GETHOSTNAME @@ -184,7 +183,6 @@ HAVE_GTK_WIDGET_GET_WINDOW HAVE_GTK_WIDGET_SET_HAS_WINDOW HAVE_GTK_WINDOW_SET_HAS_RESIZE_GRIP HAVE_G_TYPE_INIT -HAVE_H_ERRNO HAVE_IFADDRS_H HAVE_IMAGEMAGICK HAVE_INET_SOCKETS diff --git a/configure.ac b/configure.ac index 61287d7..940a1e2 100644 --- a/configure.ac +++ b/configure.ac @@ -3701,20 +3701,6 @@ fi AC_SUBST(LIBXML2_LIBS) AC_SUBST(LIBXML2_CFLAGS) -# If netdb.h doesn't declare h_errno, we must declare it by hand. -# On MinGW, that is provided by nt/inc/sys/socket.h and w32.c. -if test "${opsys}" = "mingw32"; then - emacs_cv_netdb_declares_h_errno=yes -fi -AC_CACHE_CHECK(whether netdb declares h_errno, - emacs_cv_netdb_declares_h_errno, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[return h_errno;]])], - emacs_cv_netdb_declares_h_errno=yes, emacs_cv_netdb_declares_h_errno=no)]) -if test $emacs_cv_netdb_declares_h_errno = yes; then - AC_DEFINE(HAVE_H_ERRNO, 1, [Define to 1 if netdb.h declares h_errno.]) -fi - # Check for mail-locking functions in a "mail" library. Probably this should # have the same check as for liblockfile below. AC_CHECK_LIB(mail, maillock, have_mail=yes, have_mail=no) @@ -3803,7 +3789,7 @@ AC_CHECK_FUNCS(accept4 fchdir gethostname \ getrusage get_current_dir_name \ lrand48 random rint \ select getpagesize setlocale newlocale \ -getrlimit setrlimit shutdown getaddrinfo \ +getrlimit setrlimit shutdown \ pthread_sigmask strsignal setitimer \ sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \ gai_strerror sync \ diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 79cebaa..8d3df55 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -2128,7 +2128,8 @@ associated with any buffer. The arguments @var{host} and @var{service} specify where to connect to; @var{host} is the host name (a string), and @var{service} is the name of -a defined network service (a string) or a port number (an integer). +a defined network service (a string) or a port number (an integer like +@code{80} or an integer string like @code{"80"}). The remaining arguments @var{parameters} are keyword/argument pairs that are mainly relevant to encrypted connections: @@ -2352,8 +2353,9 @@ connecting to that address will be accepted. @item :service @var{service} @var{service} specifies a port number to connect to; or, for a server, -the port number to listen on. It should be a service name that -translates to a port number, or an integer specifying the port number +the port number to listen on. It should be a service name like +@samp{"http"} that translates to a port number, or an integer like @samp{80} +or an integer string like @samp{"80"} that specifies the port number directly. For a server, it can also be @code{t}, which means to let the system select an unused port number. diff --git a/etc/NEWS b/etc/NEWS index 4328761..b651b9e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -74,11 +74,10 @@ to deal with asynchronous sockets is to avoid interacting with them until they have changed status to "run". This is most easily done from a process sentinel. -** `make-network-stream' has always allowed :service to be specified -as a "number string" (i.e., :service "993") when using gethostbyname, -but has required using a real number (i.e., :service 993) on systems -without gethostbyname. This difference has now been eliminated, and -you can use "number strings" on all systems. +** ‘make-network-process’ and ‘open-network-stream’ sometimes allowed +:service to be an integer string (e.g., :service "993") and sometimes +required an integer (e.g., :service 993). This difference has been +eliminated, and integer strings work everywhere. ** It is possible to disable attempted recovery on fatal signals diff --git a/lib-src/pop.c b/lib-src/pop.c index 21d7215..9839934 100644 --- a/lib-src/pop.c +++ b/lib-src/pop.c @@ -102,12 +102,6 @@ extern char *krb_realmofhost (/* char * */); #endif /* ! KERBEROS5 */ #endif /* KERBEROS */ -#ifndef WINDOWSNT -#ifndef HAVE_H_ERRNO -extern int h_errno; -#endif -#endif - static int socket_connection (char *, int); static int pop_getline (popserver, char **); static int sendline (popserver, const char *); @@ -972,13 +966,9 @@ static int have_winsock = 0; static int socket_connection (char *host, int flags) { -#ifdef HAVE_GETADDRINFO struct addrinfo *res, *it; struct addrinfo hints; int ret; -#else /* !HAVE_GETADDRINFO */ - struct hostent *hostent; -#endif struct servent *servent; struct sockaddr_in addr; char found_port = 0; @@ -1065,7 +1055,6 @@ socket_connection (char *host, int flags) } -#ifdef HAVE_GETADDRINFO memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; @@ -1097,34 +1086,6 @@ socket_connection (char *host, int flags) } freeaddrinfo (res); -#else /* !HAVE_GETADDRINFO */ - do - { - hostent = gethostbyname (host); - try_count++; - if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5))) - { - strcpy (pop_error, "Could not determine POP server's address"); - return (-1); - } - } while (! hostent); - - while (*hostent->h_addr_list) - { - memcpy (&addr.sin_addr, *hostent->h_addr_list, hostent->h_length); - if (! connect (sock, (struct sockaddr *) &addr, sizeof (addr))) - break; - hostent->h_addr_list++; - } - connect_ok = *hostent->h_addr_list != NULL; - if (! connect_ok) - { - realhost = alloca (strlen (hostent->h_name) + 1); - strcpy (realhost, hostent->h_name); - } - -#endif /* !HAVE_GETADDRINFO */ - #define CONNECT_ERROR "Could not connect to POP server: " if (! connect_ok) diff --git a/lisp/mpc.el b/lisp/mpc.el index 20e4bc8..aa7fee6 100644 --- a/lisp/mpc.el +++ b/lisp/mpc.el @@ -265,10 +265,7 @@ defaults to 6600 and HOST defaults to localhost." (let ((v (match-string 3 host))) (setq host (match-string 2 host)) (when (and (stringp v) (not (string= "" v))) - (setq port - (if (string-match "[^[:digit:]]" v) - (string-to-number v) - v))))) + (setq port v)))) (when (file-name-absolute-p host) ;; Expand file name because `file-name-absolute-p' ;; considers paths beginning with "~" as absolute diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el index f919efb..5ddaef5 100644 --- a/lisp/net/network-stream.el +++ b/lisp/net/network-stream.el @@ -65,8 +65,8 @@ BUFFER is a buffer or buffer name to associate with the process. Process output goes at end of that buffer. BUFFER may be nil, meaning that the process is not associated with any buffer. HOST is the name or IP address of the host to connect to. -SERVICE is the name of the service desired, or an integer specifying - a port number to connect to. +SERVICE is the name of the service desired, or an integer or + integer string specifying a port number to connect to. The remaining PARAMETERS should be a sequence of keywords and values: diff --git a/src/process.c b/src/process.c index 69f5e1d..359cd21 100644 --- a/src/process.c +++ b/src/process.c @@ -3429,21 +3429,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) } -#ifndef HAVE_GETADDRINFO -static Lisp_Object -conv_numerical_to_lisp (unsigned char *number, int length, int port) -{ - Lisp_Object address = Fmake_vector (make_number (length + 1), Qnil); - struct Lisp_Vector *p = XVECTOR (address); - - p->contents[length] = make_number (port); - for (int i = 0; i < length; i++) - p->contents[i] = make_number (number[i]); - - return address; -} -#endif - /* Create a network stream/datagram client/server process. Treated exactly like a normal process when reading and writing. Primary differences are in status display and process deletion. A network @@ -3479,9 +3464,8 @@ host, and only clients connecting to that address will be accepted. :service SERVICE -- SERVICE is name of the service desired, or an integer specifying a port number to connect to. If SERVICE is t, -a random port number is selected for the server. (If Emacs was -compiled with getaddrinfo, a port number can also be specified as a -string, e.g. "80", as well as an integer. This is not portable.) +a random port number is selected for the server. A port number can +be specified as an integer string, e.g., "80", as well as an integer. :type TYPE -- TYPE is the type of connection. The default (nil) is a stream type connection, `datagram' creates a datagram type connection, @@ -3614,11 +3598,9 @@ usage: (make-network-process &rest ARGS) */) Lisp_Object proc; Lisp_Object contact; struct Lisp_Process *p; -#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A const char *portstring; ptrdiff_t portstringlen ATTRIBUTE_UNUSED; char portbuf[INT_BUFSIZE_BOUND (EMACS_INT)]; -#endif #ifdef HAVE_LOCAL_SOCKETS struct sockaddr_un address_un; #endif @@ -3689,7 +3671,7 @@ usage: (make-network-process &rest ARGS) */) tem = Fplist_get (contact, QCfamily); if (NILP (tem)) { -#if defined (HAVE_GETADDRINFO) && defined (AF_INET6) +#ifdef AF_INET6 family = AF_UNSPEC; #else family = AF_INET; @@ -3761,7 +3743,6 @@ usage: (make-network-process &rest ARGS) */) } #endif -#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A if (!NILP (host)) { /* SERVICE can either be a string or int. @@ -3783,7 +3764,6 @@ usage: (make-network-process &rest ARGS) */) portstringlen = SBYTES (service); } } -#endif #ifdef HAVE_GETADDRINFO_A if (!NILP (host) && !NILP (Fplist_get (contact, QCnowait))) @@ -3815,7 +3795,6 @@ usage: (make-network-process &rest ARGS) */) } #endif /* HAVE_GETADDRINFO_A */ -#ifdef HAVE_GETADDRINFO /* If we have a host, use getaddrinfo to resolve both host and service. Otherwise, use getservbyname to lookup the service. */ @@ -3855,10 +3834,8 @@ usage: (make-network-process &rest ARGS) */) goto open_socket; } -#endif /* HAVE_GETADDRINFO */ - /* We end up here if getaddrinfo is not defined, or in case no hostname - has been specified (e.g. for a local server process). */ + /* No hostname has been specified (e.g., a local server process). */ if (EQ (service, Qt)) port = 0; @@ -3894,43 +3871,6 @@ usage: (make-network-process &rest ARGS) */) xsignal1 (Qerror, CALLN (Fformat, unknown_service, service)); } -#ifndef HAVE_GETADDRINFO - if (!NILP (host)) - { - struct hostent *host_info_ptr; - unsigned char *addr; - int addrlen; - - /* gethostbyname may fail with TRY_AGAIN, but we don't honor that, - as it may `hang' Emacs for a very long time. */ - immediate_quit = 1; - QUIT; - - host_info_ptr = gethostbyname ((const char *) SDATA (host)); - immediate_quit = 0; - - if (host_info_ptr) - { - addr = (unsigned char *) host_info_ptr->h_addr; - addrlen = host_info_ptr->h_length; - } - else - /* Attempt to interpret host as numeric inet address. This - only works for IPv4 addresses. */ - { - unsigned long numeric_addr = inet_addr (SSDATA (host)); - - if (numeric_addr == -1) - error ("Unknown host \"%s\"", SDATA (host)); - - addr = (unsigned char *) &numeric_addr; - addrlen = 4; - } - - ip_addresses = list1 (conv_numerical_to_lisp (addr, addrlen, port)); - } -#endif /* not HAVE_GETADDRINFO */ - open_socket: if (!NILP (buffer)) commit 6bc8689c042830ae8c13e34af993e8f923e47c9d Author: Paul Eggert Date: Mon Mar 7 08:22:37 2016 -0800 Remove support for IRIX The IRIX port wasn’t really working anyway, and the code was getting in the way of other changes (e.g., getaddrinfo fixes). IRIX’s supplier dropped support for IRIX in 2013. * admin/CPP-DEFINES: * configure.ac (opsys): * doc/lispref/os.texi (System Environment): * etc/MACHINES, etc/PROBLEMS: * lisp/find-dired.el (find-grep-options): * lisp/lpr.el (lpr-lp-system): * lisp/ls-lisp.el (ls-lisp-emulation): * lisp/mail/rmail.el (rmail-spool-directory): * lisp/net/net-utils.el (ping-program-options): * lisp/progmodes/gud.el (gud-irix-p, gud-dbx-use-stopformat-p): * lisp/progmodes/ps-mode.el (ps-mode-print-function): * src/conf_post.h [IRIX6_5]: * src/emacs.c (Vsystem_type): * src/filelock.c (get_boot_time_1): * src/process.c (process_send_signal): * src/unexelf.c (unexec): Omit IRIX-specific code and/or documentation. * configure.ac (NON_GCC_TEST_OPTIONS, IRIX6_5, PREFER_VSUSP): Remove. All uses removed. * etc/NEWS: Document the change. diff --git a/admin/CPP-DEFINES b/admin/CPP-DEFINES index 86f2fa5..9064053 100644 --- a/admin/CPP-DEFINES +++ b/admin/CPP-DEFINES @@ -13,7 +13,6 @@ CYGWIN Compiling the Cygwin port. __CYGWIN__ Ditto GNU_LINUX HPUX -IRIX6_5 MSDOS Compiling the MS-DOS port. __MSDOS__ Ditto. __DJGPP_MINOR__ Minor version number of the DJGPP library; used only in msdos.c and dosfns.c. @@ -378,7 +377,6 @@ NSIG NSIG_MINIMUM NULL_DEVICE PAGESIZE -PREFER_VSUSP PTY_ITERATION PTY_NAME_SPRINTF PTY_OPEN diff --git a/configure.ac b/configure.ac index 0de6736..61287d7 100644 --- a/configure.ac +++ b/configure.ac @@ -615,12 +615,7 @@ case "${canonical}" in * ) unported=yes ;; esac opsys=darwin - ## Use fink packages if available. - ## FIXME find a better way to do this: http://debbugs.gnu.org/11507 -## if test -d /sw/include && test -d /sw/lib; then -## GCC_TEST_OPTIONS="-I/sw/include -L/sw/lib" -## NON_GCC_TEST_OPTIONS=${GCC_TEST_OPTIONS} -## fi + ## FIXME: Find a way to use Fink if available (Bug#11507). ;; ## Chromium Native Client @@ -656,16 +651,6 @@ case "${canonical}" in opsys=aix4-2 ;; - ## Silicon Graphics machines - ## Iris 4D - mips-sgi-irix6.5 ) - opsys=irix6-5 - # Without defining _LANGUAGE_C, things get masked out in the headers - # so that, for instance, grepping for 'free' in stdlib.h fails and - # AC_HEADER_STD_C fails. (MIPSPro 7.2.1.2m compilers, Irix 6.5.3m). - NON_GCC_TEST_OPTIONS="-D_LANGUAGE_C" - ;; - ## Suns *-sun-solaris* \ | i[3456]86-*-solaris2* | i[3456]86-*-sunos5* \ @@ -782,8 +767,6 @@ AM_PROG_CC_C_O if test x$GCC = xyes; then test "x$GCC_TEST_OPTIONS" != x && CC="$CC $GCC_TEST_OPTIONS" -else - test "x$NON_GCC_TEST_OPTIONS" != x && CC="$CC $NON_GCC_TEST_OPTIONS" fi dnl This is used in lib/Makefile.am to use nt/gnulib.mk, the @@ -1233,7 +1216,6 @@ fi dnl We need -znocombreloc if we're using a relatively recent GNU ld. dnl If we can link with the flag, it shouldn't do any harm anyhow. -dnl (Don't use '-z nocombreloc' as -z takes no arg on Irix.) dnl Treat GCC specially since it just gives a non-fatal 'unrecognized option' dnl if not built to support GNU ld. @@ -1462,7 +1444,7 @@ LIBS=$OLD_LIBS dnl Current possibilities handled by sed (aix4-2 -> aix, dnl gnu-linux -> gnu/linux, etc.): -dnl gnu, gnu/linux, gnu/kfreebsd, aix, cygwin, darwin, hpux, irix. +dnl gnu, gnu/linux, gnu/kfreebsd, aix, cygwin, darwin, hpux. dnl And special cases: berkeley-unix, usg-unix-v, ms-dos, windows-nt. SYSTEM_TYPE=`echo $opsys | sed -e 's/[[0-9]].*//' -e 's|-|/|'` @@ -2199,7 +2181,7 @@ fi use_mmap_for_buffers=no case "$opsys" in - cygwin|mingw32|irix6-5) use_mmap_for_buffers=yes ;; + cygwin|mingw32) use_mmap_for_buffers=yes ;; esac AC_FUNC_MMAP @@ -3776,7 +3758,7 @@ mail_lock=no case "$opsys" in aix4-2) mail_lock="lockf" ;; - gnu|freebsd|dragonfly|netbsd|openbsd|darwin|irix6-5) mail_lock="flock" ;; + gnu|freebsd|dragonfly|netbsd|openbsd|darwin) mail_lock="flock" ;; ## On GNU/Linux systems, both methods are used by various mail programs. ## I assume most people are using newer mailers that have heard of flock. @@ -4286,7 +4268,7 @@ esac case $opsys in - irix6-5 | sol2* | unixware ) + sol2* | unixware ) dnl Some SVr4s don't define NSIG in sys/signal.h for ANSI environments; dnl instead, there's a system variable _sys_nsig. Unfortunately, we dnl need the constant to dimension an array. So wire in the appropriate @@ -4300,7 +4282,7 @@ emacs_broken_SIGIO=no case $opsys in dnl SIGIO exists, but the feature doesn't work in the way Emacs needs. dnl See eg . - hpux* | irix6-5 | nacl | openbsd | sol2* | unixware ) + hpux* | nacl | openbsd | sol2* | unixware ) emacs_broken_SIGIO=yes ;; @@ -4408,7 +4390,7 @@ dnl generated in the Makefile generated by 'xmkmf'. If we don't define dnl NARROWPROTO, we will see the wrong function prototypes for X functions dnl taking float or double parameters. case $opsys in - cygwin|gnu|gnu-linux|gnu-kfreebsd|irix6-5|freebsd|netbsd|openbsd) + cygwin|gnu|gnu-linux|gnu-kfreebsd|freebsd|netbsd|openbsd) AC_DEFINE(NARROWPROTO, 1, [Define if system's imake configuration file defines 'NeedWidePrototypes' as 'NO'.]) ;; @@ -4416,7 +4398,6 @@ esac dnl Used in process.c, this must be a loop, even if it only runs once. -dnl (Except on SGI; see below. Take that, clarity and consistency!) AH_TEMPLATE(PTY_ITERATION, [How to iterate over PTYs.]) dnl Only used if !PTY_ITERATION. Iterate from FIRST_PTY_LETTER to z, dnl trying suffixes 0-16. @@ -4479,27 +4460,6 @@ case $opsys in AC_DEFINE(PTY_TTY_NAME_SPRINTF, [sprintf (pty_name, "/dev/pty/tty%c%x", c, i);]) ;; - irix6-5 ) - dnl It looks like this cannot be right, because it is not a loop. - dnl However, process.c actually does this: - dnl # ifndef __sgi - dnl continue; - dnl # else - dnl return -1; - dnl # endif - dnl which presumably makes it OK, since irix == sgi (?). - dnl FIXME it seems like this special treatment is unnecessary? - dnl Why can't irix use a single-trip loop like eg cygwin? - AC_DEFINE(PTY_ITERATION, []) - dnl Not used, because PTY_ITERATION is defined. - AC_DEFINE(FIRST_PTY_LETTER, ['q']) - AC_DEFINE(PTY_OPEN, [ { struct sigaction ocstat, cstat; struct stat stb; char * name; sigemptyset(&cstat.sa_mask); cstat.sa_handler = SIG_DFL; cstat.sa_flags = 0; sigaction(SIGCHLD, &cstat, &ocstat); name = _getpty (&fd, O_RDWR | O_NDELAY, 0600, 0); sigaction(SIGCHLD, &ocstat, (struct sigaction *)0); if (name == 0) return -1; if (fd < 0) return -1; if (fstat (fd, &stb) < 0) return -1; strcpy (pty_name, name); }]) - dnl No need to get the pty name at all. - AC_DEFINE(PTY_NAME_SPRINTF, []) - dnl No need to use sprintf to get the tty name--we get that from _getpty. - AC_DEFINE(PTY_TTY_NAME_SPRINTF, []) - ;; - sol2* ) dnl On SysVr4, grantpt(3) forks a subprocess, so do not use dnl O_CLOEXEC when opening the pty, and keep the SIGCHLD handler @@ -4534,8 +4494,7 @@ AH_TEMPLATE(SIGNALS_VIA_CHARACTERS, [Make process_send_signal work by case $opsys in dnl Perry Smith says this is correct for AIX. - dnl thomas@mathematik.uni-bremen.de says this is needed for IRIX. - aix4-2 | cygwin | gnu | irix6-5 | dragonfly | freebsd | netbsd | openbsd | darwin ) + aix4-2 | cygwin | gnu | dragonfly | freebsd | netbsd | openbsd | darwin ) AC_DEFINE(SIGNALS_VIA_CHARACTERS, 1) ;; @@ -4615,8 +4574,7 @@ if test x$GCC = xyes; then AC_DEFINE(GC_SETJMP_WORKS, 1) else case $opsys in - dnl irix: Tested on Irix 6.5. SCM worked on earlier versions. - aix* | dragonfly | freebsd | netbsd | openbsd | irix6-5 | sol2* ) + aix* | dragonfly | freebsd | netbsd | openbsd | sol2* ) AC_DEFINE(GC_SETJMP_WORKS, 1) ;; esac @@ -4720,12 +4678,6 @@ case $opsys in AC_DEFINE(HPUX, [], [Define if the system is HPUX.]) ;; - irix6-5) - AC_DEFINE(USG, []) - AC_DEFINE(USG5_4, []) - AC_DEFINE(IRIX6_5, [], [Define if the system is IRIX.]) - ;; - mingw32) AC_DEFINE(DOS_NT, []) AC_DEFINE(WINDOWSNT, 1, [Define if compiling for native MS Windows.]) @@ -4799,11 +4751,6 @@ case $opsys in reopen it in the child.]) ;; - irix6-5) - AC_DEFINE(PREFER_VSUSP, 1, [Define if process_send_signal should - use VSUSP instead of VSWTCH.]) - ;; - sol2-10) AC_DEFINE(_STRUCTURED_PROC, 1, [Needed for system_process_attributes on Solaris.]) diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index d57cbcf..3428c29 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -899,9 +899,6 @@ A GNU (glibc-based) system with a FreeBSD kernel. @item hpux Hewlett-Packard HPUX operating system. -@item irix -Silicon Graphics Irix system. - @item nacl Google Native Client (@acronym{NaCl}) sandboxing system. diff --git a/etc/MACHINES b/etc/MACHINES index 085f169..5562dc2 100644 --- a/etc/MACHINES +++ b/etc/MACHINES @@ -105,12 +105,10 @@ the list at the end of this file. Emacs versions later than 24.4 will not compile on Irix by default. (Note that SGI stopped supporting Irix in December 2013.) - You should be able to work around the problem either by porting the - Emacs undumping code to GCC under Irix, or by configuring --with-wide-int. Older versions of Emacs 24 (and 23?) also had problems on Irix. It *may* be possible to build Emacs <= 24.4 on Irix 6.5 with an old version (3.1) of gcc. Newer versions of gcc may not work. - See . + See . * Obsolete platforms diff --git a/etc/NEWS b/etc/NEWS index 92d69d2..4328761 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -34,6 +34,9 @@ emacs-version and erc-cmd-SV functions, and the leave the following variables nil: emacs-build-system, emacs-build-time, erc-emacs-build-time. +** Emacs no longer works on IRIX. We expect that Emacs users are not +affected by this, as SGI stopped supporting IRIX in December 2013. + * Startup Changes in Emacs 25.2 diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 7d78037..f61921a 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -544,26 +544,6 @@ Other systems allow to set LD_RUN_PATH in a similar way, but before Emacs is linked. With LD_RUN_PATH set, the linker will include a specified run-time search path in the executable. -On some systems, Emacs can crash due to problems with dynamic -linking. Specifically, on SGI Irix 6.5, crashes were reported with -backtraces like this: - - (dbx) where - 0 strcmp(0xf49239d, 0x4031184, 0x40302b4, 0x12, 0xf0000000, 0xf4923aa, 0x0, 0x492ddb2) ["/xlv22/ficus-jan23/work/irix/lib/libc/libc_n32_M3_ns/strings/strcmp.s":35, 0xfb7e480] - 1 general_find_symbol(0xf49239d, 0x0, 0x0, 0x0, 0xf0000000, 0xf4923aa, 0x0, 0x492ddb2) - ["/comp2/mtibuild/v73/workarea/v7.3/rld/rld.c":2140, 0xfb65a98] - 2 resolve_symbol(0xf49239d, 0x4031184, 0x0, 0xfbdd438, 0x0, 0xf4923aa, 0x0, 0x492ddb2) - ["/comp2/mtibuild/v73/workarea/v7.3/rld/rld.c":1947, 0xfb657e4] - 3 lazy_text_resolve(0xd18, 0x1a3, 0x40302b4, 0x12, 0xf0000000, 0xf4923aa, 0x0, 0x492ddb2) - ["/comp2/mtibuild/v73/workarea/v7.3/rld/rld.c":997, 0xfb64d44] - 4 _rld_text_resolve(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) - ["/comp2/mtibuild/v73/workarea/v7.3/rld/rld_bridge.s":175, 0xfb6032c] - -('rld' is the dynamic linker.) We don't know why this -happens, but setting the environment variable LD_BIND_NOW to 1 (which -forces the dynamic linker to bind all shared objects early on) seems -to work around the problem. - Please refer to the documentation of your dynamic linker for details. *** When you run Ispell from Emacs, it reports a "misalignment" error. @@ -1931,14 +1911,6 @@ This seems to be a GCC optimization bug that occurs for GCC 4.1.2 (-g and -g -O2) and GCC 4.2.3 (-g -O and -g -O2). You can fix this by compiling with GCC 4.2.3 or CC 5.7, with no optimizations. -** Irix - -*** Irix: Trouble using ptys, or running out of ptys. - -The program mkpts (which may be in '/usr/adm' or '/usr/sbin') needs to -be set-UID to root, or non-root programs like Emacs will not be able -to allocate ptys reliably. - * Runtime problems specific to MS-Windows ** Emacs on Windows 9X requires UNICOWS.DLL diff --git a/lisp/find-dired.el b/lisp/find-dired.el index 7bfdbe7..b1b33ac 100644 --- a/lisp/find-dired.el +++ b/lisp/find-dired.el @@ -97,7 +97,7 @@ them for `find-ls-option'." (defcustom find-grep-options (if (or (eq system-type 'berkeley-unix) - (string-match "solaris2\\|irix" system-configuration)) + (string-match "solaris2" system-configuration)) "-s" "-q") "Option to grep to be as silent as possible. On Berkeley systems, this is `-s'; on Posix, and with GNU grep, `-q' does it. diff --git a/lisp/lpr.el b/lisp/lpr.el index 04e3b38..2fe32c7 100644 --- a/lisp/lpr.el +++ b/lisp/lpr.el @@ -36,7 +36,7 @@ ;;;###autoload (defvar lpr-lp-system - (memq system-type '(usg-unix-v hpux irix)) + (memq system-type '(usg-unix-v hpux)) "Non-nil if running on a system type that uses the \"lp\" command.") diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el index 85e91cd..11cbea0 100644 --- a/lisp/ls-lisp.el +++ b/lisp/ls-lisp.el @@ -72,7 +72,7 @@ (defcustom ls-lisp-emulation (cond ;; ((eq system-type 'windows-nt) 'MS-Windows) - ((memq system-type '(hpux usg-unix-v irix berkeley-unix)) + ((memq system-type '(hpux usg-unix-v berkeley-unix)) 'UNIX)) ; very similar to GNU ;; Anything else defaults to nil, meaning GNU. "Platform to emulate: GNU (default), MacOS, MS-Windows, UNIX. diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index 5464c38..2790c89 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -163,7 +163,7 @@ its character representation and its display representation.") (put 'rmail-spool-directory 'standard-value '((cond ((file-exists-p "/var/mail") "/var/mail/") ((file-exists-p "/var/spool/mail") "/var/spool/mail/") - ((memq system-type '(hpux usg-unix-v irix)) "/usr/mail/") + ((memq system-type '(hpux usg-unix-v)) "/usr/mail/") (t "/usr/spool/mail/")))) ;;;###autoload @@ -176,7 +176,7 @@ its character representation and its display representation.") "/var/mail/") ;; Many GNU/Linux systems use this name. ((file-exists-p "/var/spool/mail") "/var/spool/mail/") - ((memq system-type '(hpux usg-unix-v irix)) "/usr/mail/") + ((memq system-type '(hpux usg-unix-v)) "/usr/mail/") (t "/usr/spool/mail/"))) "Name of directory used by system mailer for delivering new mail. Its name should end with a slash." diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index 8029e2c..b13bece 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -79,7 +79,7 @@ ;; On GNU/Linux and Irix, the system's ping program seems to send packets ;; indefinitely unless told otherwise (defcustom ping-program-options - (and (memq system-type '(gnu/linux irix)) + (and (eq system-type 'gnu/linux) (list "-c" "4")) "Options for the ping program. These options can be used to limit how many ICMP packets are emitted." diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index 356cd3e..9bf7394 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -1182,36 +1182,30 @@ containing the executable being debugged." ;; correct line number, but life's too short. ;; d.love@dl.ac.uk (Dave Love) can be blamed for this -(defvar gud-irix-p - (and (string-match "^mips-[^-]*-irix" system-configuration) - (not (string-match "irix[6-9]\\.[1-9]" system-configuration))) +(defvar gud-irix-p nil "Non-nil to assume the interface appropriate for IRIX dbx. This works in IRIX 4, 5 and 6, but `gud-dbx-use-stopformat-p' provides a better solution in 6.1 upwards.") -(defvar gud-dbx-use-stopformat-p - (string-match "irix[6-9]\\.[1-9]" system-configuration) +(defvar gud-dbx-use-stopformat-p nil "Non-nil to use the dbx feature present at least from Irix 6.1 whereby $stopformat=1 produces an output format compatible with `gud-dbx-marker-filter'.") -;; [Irix dbx seems to be a moving target. The dbx output changed +;; [Irix dbx seemed to be a moving target. The dbx output changed ;; subtly sometime between OS v4.0.5 and v5.2 so that, for instance, ;; the output from `up' is no longer spotted by gud (and it's probably ;; not distinctive enough to try to match it -- use C-<, C-> ;; exclusively) . For 5.3 and 6.0, the $curline variable changed to ;; `long long'(why?!), so the printf stuff needed changing. The line ;; number was cast to `long' as a compromise between the new `long -;; long' and the original `int'. This is reported not to work in 6.2, +;; long' and the original `int'. This was reported not to work in 6.2, ;; so it's changed back to int -- don't make your sources too long. -;; From Irix6.1 (but not 6.0?) dbx supports an undocumented feature +;; From Irix6.1 (but not 6.0?) dbx supported an undocumented feature ;; whereby `set $stopformat=1' reportedly produces output compatible ;; with `gud-dbx-marker-filter', which we prefer. ;; The process filter is also somewhat ;; unreliable, sometimes not spotting the markers; I don't know -;; whether there's anything that can be done about that. It would be -;; much better if SGI could be persuaded to (re?)instate the MIPS -;; -emacs flag for gdb-like output (which ought to be possible as most -;; of the communication I've had over it has been from sgi.com).] +;; whether there's anything that can be done about that.] ;; this filter is influenced by the xdb one rather than the gdb one (defun gud-irixdbx-marker-filter (string) diff --git a/lisp/progmodes/ps-mode.el b/lisp/progmodes/ps-mode.el index 79c32c6..c929905 100644 --- a/lisp/progmodes/ps-mode.el +++ b/lisp/progmodes/ps-mode.el @@ -113,7 +113,7 @@ When the figure is finished these values should be replaced." (defcustom ps-mode-print-function (lambda () (let ((lpr-switches nil) - (lpr-command (if (memq system-type '(usg-unix-v hpux irix)) + (lpr-command (if (memq system-type '(usg-unix-v hpux)) "lp" "lpr"))) (lpr-buffer))) "Lisp function to print current buffer as PostScript." diff --git a/src/conf_post.h b/src/conf_post.h index 2788abf..11dbb6e 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -117,14 +117,6 @@ typedef bool bool_bf; #undef HAVE_RINT #endif /* HPUX */ -#ifdef IRIX6_5 -#ifdef emacs -char *_getpty(); -#endif -#define INET6 /* Needed for struct sockaddr_in6. */ -#undef HAVE_GETADDRINFO /* IRIX has getaddrinfo but not struct addrinfo. */ -#endif /* IRIX6_5 */ - #ifdef MSDOS #ifndef __DJGPP__ You lose; /* Emacs for DOS must be compiled with DJGPP */ diff --git a/src/emacs.c b/src/emacs.c index a381da4..cdc4ebb 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -2419,8 +2419,8 @@ Special values: `ms-dos' compiled as an MS-DOS application. `windows-nt' compiled as a native W32 application. `cygwin' compiled using the Cygwin library. -Anything else (in Emacs 24.1, the possibilities are: aix, berkeley-unix, -hpux, irix, usg-unix-v) indicates some sort of Unix system. */); +Anything else (in Emacs 26, the possibilities are: aix, berkeley-unix, +hpux, usg-unix-v) indicates some sort of Unix system. */); Vsystem_type = intern_c_string (SYSTEM_TYPE); /* See configure.ac for the possible SYSTEM_TYPEs. */ diff --git a/src/filelock.c b/src/filelock.c index 1b32b93..57e3990 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -253,14 +253,7 @@ get_boot_time_1 (const char *filename, bool newest) struct utmp ut, *utp; if (filename) - { - /* On some versions of IRIX, opening a nonexistent file name - is likely to crash in the utmp routines. */ - if (faccessat (AT_FDCWD, filename, R_OK, AT_EACCESS) != 0) - return; - - utmpname (filename); - } + utmpname (filename); setutent (); diff --git a/src/process.c b/src/process.c index 4359f68..69f5e1d 100644 --- a/src/process.c +++ b/src/process.c @@ -6464,7 +6464,7 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, break; case SIGTSTP: -#if defined (VSWTCH) && !defined (PREFER_VSUSP) +#ifdef VSWTCH sig_char = &t.c_cc[VSWTCH]; #else sig_char = &t.c_cc[VSUSP]; diff --git a/src/unexelf.c b/src/unexelf.c index e901994..6343207 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -461,29 +461,6 @@ unexec (const char *new_name, const char *old_name) || !strcmp (old_section_names + new_shdr->sh_name, ".sdata") || !strcmp (old_section_names + new_shdr->sh_name, ".lit4") || !strcmp (old_section_names + new_shdr->sh_name, ".lit8") - /* The conditional bit below was in Oliva's original code - (1999-08-25) and seems to have been dropped by mistake - subsequently. It prevents a crash at startup under X in - `IRIX64 6.5 6.5.17m', whether compiled on that release or - an earlier one. It causes no trouble on the other ELF - platforms I could test (Irix 6.5.15m, Solaris 8, Debian - Potato x86, Debian Woody SPARC); however, it's reported - to cause crashes under some version of GNU/Linux. It's - not yet clear what's changed in that Irix version to - cause the problem, or why the fix sometimes fails under - GNU/Linux. There's probably no good reason to have - something Irix-specific here, but this will have to do - for now. IRIX6_5 is the most specific macro we have to - test. -- fx 2002-10-01 - - The issue _looks_ as though it's gone away on 6.5.18m, - but maybe it's still lurking, to be triggered by some - change in the binary. It appears to concern the dynamic - loader, but I never got anywhere with an SGI support call - seeking clues. -- fx 2002-11-29. */ -#ifdef IRIX6_5 - || !strcmp (old_section_names + new_shdr->sh_name, ".got") -#endif || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1") || !strcmp (old_section_names + new_shdr->sh_name, ".data1")) src = (caddr_t) old_shdr->sh_addr; @@ -665,9 +642,6 @@ unexec (const char *new_name, const char *old_name) || !strcmp (old_section_names + shdr->sh_name, ".sdata") || !strcmp (old_section_names + shdr->sh_name, ".lit4") || !strcmp (old_section_names + shdr->sh_name, ".lit8") -#ifdef IRIX6_5 /* see above */ - || !strcmp (old_section_names + shdr->sh_name, ".got") -#endif || !strcmp (old_section_names + shdr->sh_name, ".sdata1") || !strcmp (old_section_names + shdr->sh_name, ".data1")) {