X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/68e7476278a3dc4bd13dab63cc23bc0e671e5525..e2b6daf4193bcfd81d6dc67eeee3d50888710818:/src/dispnew.c diff --git a/src/dispnew.c b/src/dispnew.c index 284e1fde4b..e43a1a9869 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1,14 +1,14 @@ /* Updating of data structures for redisplay. Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ #include #include @@ -36,7 +34,7 @@ Boston, MA 02110-1301, USA. */ #include "dispextern.h" #include "cm.h" #include "buffer.h" -#include "charset.h" +#include "character.h" #include "keyboard.h" #include "frame.h" #include "termhooks.h" @@ -61,9 +59,9 @@ Boston, MA 02110-1301, USA. */ #include "w32term.h" #endif /* HAVE_NTGUI */ -#ifdef MAC_OS -#include "macterm.h" -#endif /* MAC_OS */ +#ifdef HAVE_NS +#include "nsterm.h" +#endif /* Include systime.h after xterm.h to avoid double inclusion of time.h. */ @@ -324,7 +322,9 @@ static struct frame *frame_matrix_frame; matrix adjustments. Redisplay must stop, and glyph matrices must be adjusted when this flag becomes non-zero during display. The reason fonts can be loaded so late is that fonts of fontsets are - loaded on demand. */ + loaded on demand. Another reason is that a line contains many + characters displayed by zero width or very narrow glyphs of + variable-width fonts. */ int fonts_changed_p; @@ -633,7 +633,7 @@ adjust_glyph_matrix (w, matrix, x, y, dim) int header_line_changed_p = 0; int header_line_p = 0; int left = -1, right = -1; - int window_width = -1, window_height; + int window_width = -1, window_height = -1; /* See if W had a header line that has disappeared now, or vice versa. Get W's size. */ @@ -1468,9 +1468,11 @@ line_draw_cost (matrix, vpos) len = 0; while (beg < end) { - GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg); + GLYPH g; + + SET_GLYPH_FROM_CHAR_GLYPH (g, *beg); - if (g < 0 + if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g)) len += 1; else @@ -2175,7 +2177,7 @@ showing_window_margins_p (w) else if (!NILP (w->left_margin_cols) || !NILP (w->right_margin_cols)) return 1; - + w = NILP (w->next) ? 0 : XWINDOW (w->next); } return 0; @@ -2740,7 +2742,9 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) struct glyph_matrix *window_matrix; int window_y, frame_y; /* If non-zero, a glyph to insert at the right border of W. */ - GLYPH right_border_glyph = 0; + GLYPH right_border_glyph; + + SET_GLYPH_FROM_CHAR (right_border_glyph, 0); /* Set window_matrix to the matrix we have to add to FRAME_MATRIX. */ if (w->must_be_updated_p) @@ -2751,15 +2755,19 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) if (!WINDOW_RIGHTMOST_P (w)) { struct Lisp_Char_Table *dp = window_display_table (w); + Lisp_Object gc; - right_border_glyph - = ((dp && INTEGERP (DISP_BORDER_GLYPH (dp))) - ? spec_glyph_lookup_face (w, XINT (DISP_BORDER_GLYPH (dp))) - : '|'); + SET_GLYPH_FROM_CHAR (right_border_glyph, '|'); + if (dp + && (gc = DISP_BORDER_GLYPH (dp), GLYPH_CODE_P (gc)) + && GLYPH_CODE_CHAR_VALID_P (gc)) + { + SET_GLYPH_FROM_GLYPH_CODE (right_border_glyph, gc); + spec_glyph_lookup_face (w, &right_border_glyph); + } - if (FAST_GLYPH_FACE (right_border_glyph) <= 0) - right_border_glyph - = FAST_MAKE_GLYPH (right_border_glyph, VERTICAL_BORDER_FACE_ID); + if (GLYPH_FACE (right_border_glyph) <= 0) + SET_GLYPH_FACE (right_border_glyph, VERTICAL_BORDER_FACE_ID); } } else @@ -2809,7 +2817,7 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) /* Maybe insert a vertical border between horizontally adjacent windows. */ - if (right_border_glyph) + if (GLYPH_CHAR (right_border_glyph) != 0) { struct glyph *border = window_row->glyphs[LAST_AREA] - 1; SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph); @@ -2845,21 +2853,19 @@ build_frame_matrix_from_leaf_window (frame_matrix, w) This is used for glyphs displayed specially and not part of the text; for instance, vertical separators, truncation markers, etc. */ -GLYPH +void spec_glyph_lookup_face (w, glyph) struct window *w; - GLYPH glyph; + GLYPH *glyph; { - int lface_id = FAST_GLYPH_FACE (glyph); + int lface_id = GLYPH_FACE (*glyph); /* Convert the glyph's specified face to a realized (cache) face. */ if (lface_id > 0) { int face_id = merge_faces (XFRAME (w->frame), Qt, lface_id, DEFAULT_FACE_ID); - glyph - = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), face_id); + SET_GLYPH_FACE (*glyph, face_id); } - return glyph; } /* Add spaces to a glyph row ROW in a window matrix. @@ -3384,7 +3390,7 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0, update_begin (f); #ifdef MSDOS if (FRAME_MSDOS_P (f)) - set_terminal_modes (FRAME_TERMINAL (f)); + FRAME_TERMINAL (f)->set_terminal_modes_hook (FRAME_TERMINAL (f)); #endif clear_frame (f); clear_current_matrices (f); @@ -3508,6 +3514,7 @@ direct_output_for_insert (g) || g == '\t' || g == '\n' || g == '\r' + || (g == ' ' && !NILP (current_buffer->word_wrap)) /* Give up if unable to display the cursor in the window. */ || w->cursor.vpos < 0 /* Give up if we are showing a message or just cleared the message @@ -3947,11 +3954,12 @@ update_frame (f, force_p, inhibit_hairy_id_p) paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p); update_end (f); - if (FRAME_TERMCAP_P (f)) + if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) { if (FRAME_TTY (f)->termscript) fflush (FRAME_TTY (f)->termscript); - fflush (FRAME_TTY (f)->output); + if (FRAME_TERMCAP_P (f)) + fflush (FRAME_TTY (f)->output); } /* Check window matrices for lost pointers. */ @@ -4058,7 +4066,7 @@ redraw_overlapped_rows (w, yb) { int i; struct frame *f = XFRAME (WINDOW_FRAME (w)); - + /* If rows overlapping others have been changed, the rows being overlapped have to be redrawn. This won't draw lines that have already been drawn in update_window_line because overlapped_p in @@ -4109,7 +4117,7 @@ redraw_overlapping_rows (w, yb) int i, bottom_y; struct glyph_row *row; struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); - + for (i = 0; i < w->current_matrix->nrows; ++i) { row = w->current_matrix->rows + i; @@ -4121,14 +4129,14 @@ redraw_overlapping_rows (w, yb) bottom_y = MATRIX_ROW_BOTTOM_Y (row); - if (row->overlapping_p && i > 0 && bottom_y < yb) + if (row->overlapping_p) { int overlaps = 0; - if (MATRIX_ROW_OVERLAPS_PRED_P (row) + if (MATRIX_ROW_OVERLAPS_PRED_P (row) && i > 0 && !MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p) overlaps |= OVERLAPS_PRED; - if (MATRIX_ROW_OVERLAPS_SUCC_P (row) + if (MATRIX_ROW_OVERLAPS_SUCC_P (row) && bottom_y < yb && !MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p) overlaps |= OVERLAPS_SUCC; @@ -4467,6 +4475,7 @@ update_text_area (w, vpos) struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA]; int overlapping_glyphs_p = current_row->contains_overlapping_glyphs_p; int desired_stop_pos = desired_row->used[TEXT_AREA]; + int abort_skipping = 0; /* If the desired row extends its face to the text area end, and unless the current row also does so at the same position, @@ -4486,7 +4495,7 @@ update_text_area (w, vpos) in common. */ while (i < stop) { - int can_skip_p = 1; + int can_skip_p = !abort_skipping; /* Skip over glyphs that both rows have in common. These don't have to be written. We can't skip if the last @@ -4503,11 +4512,13 @@ update_text_area (w, vpos) rif->get_glyph_overhangs (glyph, XFRAME (w->frame), &left, &right); - can_skip_p = right == 0; + can_skip_p = (right == 0 && !abort_skipping); } if (can_skip_p) { + int start_hpos = i; + while (i < stop && GLYPH_EQUAL_P (desired_glyph, current_glyph)) { @@ -4539,6 +4550,12 @@ update_text_area (w, vpos) x -= desired_glyph->pixel_width; left -= desired_glyph->pixel_width; } + + /* Abort the skipping algorithm if we end up before + our starting point, to avoid looping (bug#1070). + This can happen when the lbearing is larger than + the pixel width. */ + abort_skipping = (i < start_hpos); } } @@ -5296,22 +5313,26 @@ update_frame_1 (f, force_p, inhibit_id_p) Also flush out if likely to have more than 1k buffered otherwise. I'm told that some telnet connections get really screwed by more than 1k output at once. */ - int outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f)->output); - if (outq > 900 - || (outq > 20 && ((i - 1) % preempt_count == 0))) + FILE *display_output = FRAME_TTY (f)->output; + if (display_output) { - fflush (FRAME_TTY (f)->output); - if (preempt_count == 1) + int outq = PENDING_OUTPUT_COUNT (display_output); + if (outq > 900 + || (outq > 20 && ((i - 1) % preempt_count == 0))) { + fflush (display_output); + if (preempt_count == 1) + { #ifdef EMACS_OUTQSIZE - if (EMACS_OUTQSIZE (0, &outq) < 0) - /* Probably not a tty. Ignore the error and reset - the outq count. */ - outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output)); + if (EMACS_OUTQSIZE (0, &outq) < 0) + /* Probably not a tty. Ignore the error and reset + the outq count. */ + outq = PENDING_OUTPUT_COUNT (FRAME_TTY (f->output)); #endif - outq *= 10; - if (baud_rate <= outq && baud_rate > 0) - sleep (outq / baud_rate); + outq *= 10; + if (baud_rate <= outq && baud_rate > 0) + sleep (outq / baud_rate); + } } } } @@ -5912,7 +5933,7 @@ buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height) int *width, *height; { struct it it; - struct buffer *old_current_buffer = current_buffer; + Lisp_Object old_current_buffer = Fcurrent_buffer (); struct text_pos startp; Lisp_Object string; struct glyph_row *row; @@ -5921,7 +5942,9 @@ buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height) #endif int x0, x1; - current_buffer = XBUFFER (w->buffer); + /* We used to set current_buffer directly here, but that does the + wrong thing with `face-remapping-alist' (bug#2044). */ + Fset_buffer (w->buffer); SET_TEXT_POS_FROM_MARKER (startp, w->start); CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp))); BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp))); @@ -5931,7 +5954,7 @@ buffer_posn_from_coords (w, x, y, pos, object, dx, dy, width, height) move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1, MOVE_TO_X | MOVE_TO_Y); - current_buffer = old_current_buffer; + Fset_buffer (old_current_buffer); *dx = x0 + it.first_visible_x - it.current_x; *dy = *y - it.current_y; @@ -6195,11 +6218,16 @@ window_change_signal (signalnum) /* If we don't have an argument, */ if (! tty->term_initted) continue; + /* Suspended tty frames have tty->input == NULL avoid trying to + use it. */ + if (!tty->input) + continue; + get_tty_size (fileno (tty->input), &width, &height); - + if (width > 5 && height > 2) { Lisp_Object tail, frame; - + FOR_EACH_FRAME (tail, frame) if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty) /* Record the new sizes, but don't reallocate the data @@ -6208,7 +6236,7 @@ window_change_signal (signalnum) /* If we don't have an argument, */ change_frame_size (XFRAME (frame), height, width, 0, 1, 0); } } - + errno = old_errno; } #endif /* SIGWINCH */ @@ -6335,7 +6363,7 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe) (newheight - 1 - FRAME_TOP_MARGIN (f)), - 0); + 2); XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top_line, newheight - 1); set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0); @@ -6343,19 +6371,23 @@ change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe) else /* Frame has just one top-level window. */ set_window_height (FRAME_ROOT_WINDOW (f), - newheight - FRAME_TOP_MARGIN (f), 0); + newheight - FRAME_TOP_MARGIN (f), 2); - if (FRAME_TERMCAP_P (f) && !pretend) + /* MSDOS frames cannot PRETEND, as they change frame size by + manipulating video hardware. */ + if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) FrameRows (FRAME_TTY (f)) = newheight; } if (new_frame_total_cols != FRAME_TOTAL_COLS (f)) { - set_window_width (FRAME_ROOT_WINDOW (f), new_frame_total_cols, 0); + set_window_width (FRAME_ROOT_WINDOW (f), new_frame_total_cols, 2); if (FRAME_HAS_MINIBUF_P (f)) set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0); - if (FRAME_TERMCAP_P (f) && !pretend) + /* MSDOS frames cannot PRETEND, as they change frame size by + manipulating video hardware. */ + if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f)) FrameCols (FRAME_TTY (f)) = newwidth; if (WINDOWP (f->tool_bar_window)) @@ -6406,7 +6438,8 @@ FILE = nil means just close any termscript file currently open. */) { struct tty_display_info *tty; - if (! FRAME_TERMCAP_P (SELECTED_FRAME ())) + if (! FRAME_TERMCAP_P (SELECTED_FRAME ()) + && ! FRAME_MSDOS_P (SELECTED_FRAME ())) error ("Current frame is not on a tty device"); tty = CURTTY (); @@ -6436,14 +6469,15 @@ DEFUN ("send-string-to-terminal", Fsend_string_to_terminal, Control characters in STRING will have terminal-dependent effects. Optional parameter TERMINAL specifies the tty terminal device to use. -It may be a terminal id, a frame, or nil for the terminal used by the -currently selected frame. */) +It may be a terminal object, a frame, or nil for the terminal used by +the currently selected frame. In batch mode, STRING is sent to stdout +when TERMINAL is nil. */) (string, terminal) Lisp_Object string; Lisp_Object terminal; { - struct terminal *t = get_tty_terminal (terminal, 1); - struct tty_display_info *tty; + struct terminal *t = get_terminal (terminal, 1); + FILE *out; /* ??? Perhaps we should do something special for multibyte strings here. */ CHECK_STRING (string); @@ -6452,15 +6486,26 @@ currently selected frame. */) if (!t) error ("Unknown terminal device"); - tty = t->display_info.tty; - - if (tty->termscript) + if (t->type == output_initial) + out = stdout; + else if (t->type != output_termcap && t->type != output_msdos_raw) + error ("Device %d is not a termcap terminal device", t->id); + else { - fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); - fflush (tty->termscript); + struct tty_display_info *tty = t->display_info.tty; + + if (! tty->output) + error ("Terminal is currently suspended"); + + if (tty->termscript) + { + fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); + fflush (tty->termscript); + } + out = tty->output; } - fwrite (SDATA (string), 1, SBYTES (string), tty->output); - fflush (tty->output); + fwrite (SDATA (string), 1, SBYTES (string), out); + fflush (out); UNBLOCK_INPUT; return Qnil; } @@ -6792,7 +6837,7 @@ init_display () /* Construct the space glyph. */ space_glyph.type = CHAR_GLYPH; - SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' '); + SET_CHAR_GLYPH (space_glyph, ' ', DEFAULT_FACE_ID, 0); space_glyph.charpos = -1; inverse_video = 0; @@ -6813,6 +6858,10 @@ init_display () signal (SIGWINCH, window_change_signal); #endif /* SIGWINCH */ + /* If running as a daemon, no need to initialize any frames/terminal. */ + if (IS_DAEMON) + return; + /* If the user wants to use a window system, we shouldn't bother initializing the terminal. This is especially important when the terminal is so dumb that emacs gives up before and doesn't bother @@ -6825,12 +6874,7 @@ init_display () if (! inhibit_window_system && ! display_arg) { char *display; -#ifdef VMS - display = getenv ("DECW$DISPLAY"); -#else display = getenv ("DISPLAY"); -#endif - display_arg = (display != 0 && *display != 0); if (display_arg && !x_display_ok (display)) @@ -6847,11 +6891,9 @@ init_display () #endif ) { - Vinitial_window_system = intern ("x"); + Vinitial_window_system = Qx; #ifdef HAVE_X11 Vwindow_system_version = make_number (11); -#else - Vwindow_system_version = make_number (10); #endif #if defined (GNU_LINUX) && defined (HAVE_LIBNCURSES) /* In some versions of ncurses, @@ -6867,22 +6909,26 @@ init_display () #ifdef HAVE_NTGUI if (!inhibit_window_system) { - Vinitial_window_system = intern ("w32"); + Vinitial_window_system = Qw32; Vwindow_system_version = make_number (1); adjust_frame_glyphs_initially (); return; } #endif /* HAVE_NTGUI */ -#ifdef MAC_OS - if (!inhibit_window_system) +#ifdef HAVE_NS + if (!inhibit_window_system +#ifndef CANNOT_DUMP + && initialized +#endif + ) { - Vinitial_window_system = intern ("mac"); - Vwindow_system_version = make_number (1); + Vinitial_window_system = Qns; + Vwindow_system_version = make_number(10); adjust_frame_glyphs_initially (); return; } -#endif /* MAC_OS */ +#endif /* If no window system has been specified, try to use the terminal. */ if (! isatty (0)) @@ -6899,40 +6945,15 @@ init_display () #endif if (!terminal_type) { -#ifdef VMS - fprintf (stderr, "Please specify your terminal type.\n\ -For types defined in VMS, use set term /device=TYPE.\n\ -For types not defined in VMS, use define emacs_term \"TYPE\".\n\ -\(The quotation marks are necessary since terminal types are lower case.)\n"); -#else /* not VMS */ - #ifdef HAVE_WINDOW_SYSTEM if (! inhibit_window_system) fprintf (stderr, "Please set the environment variable DISPLAY or TERM (see `tset').\n"); else #endif /* HAVE_WINDOW_SYSTEM */ fprintf (stderr, "Please set the environment variable TERM; see `tset'.\n"); -#endif /* not VMS */ exit (1); } -#ifdef VMS - /* VMS DCL tends to up-case things, so down-case term type. - Hardly any uppercase letters in terminal types; should be none. */ - { - char *new = (char *) xmalloc (strlen (terminal_type) + 1); - char *p; - - strcpy (new, terminal_type); - - for (p = new; *p; p++) - if (isupper (*p)) - *p = tolower (*p); - - terminal_type = new; - } -#endif /* VMS */ - { struct terminal *t; struct frame *f = XFRAME (selected_frame); @@ -6961,9 +6982,15 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\ Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty_type, Ftty_type (selected_frame)), Qnil)); - Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty, Qnil), Qnil)); + if (t->display_info.tty->name) + Fmodify_frame_parameters (selected_frame, + Fcons (Fcons (Qtty, build_string (t->display_info.tty->name)), + Qnil)); + else + Fmodify_frame_parameters (selected_frame, Fcons (Fcons (Qtty, Qnil), + Qnil)); } - + { struct frame *sf = SELECTED_FRAME (); int width = FRAME_TOTAL_COLS (sf); @@ -6983,13 +7010,6 @@ For types not defined in VMS, use define emacs_term \"TYPE\".\n\ /* Set up faces of the initial terminal frame of a dumped Emacs. */ if (initialized && !noninteractive -#ifdef MSDOS - /* The MSDOS terminal turns on its ``window system'' relatively - late into the startup, so we cannot do the frame faces' - initialization just yet. It will be done later by pc-win.el - and internal_terminal_init. */ - && (strcmp (terminal_type, "internal") != 0 || inhibit_window_system) -#endif && NILP (Vinitial_window_system)) { /* For the initial frame, we don't have any way of knowing what @@ -7051,6 +7071,18 @@ WINDOW nil or omitted means report on the selected window. */) return w->cursor_off_p ? Qnil : Qt; } +DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame, + Slast_nonminibuf_frame, 0, 0, 0, + doc: /* Value is last nonminibuffer frame. */) + () +{ + Lisp_Object frame = Qnil; + + if (last_nonminibuf_frame) + XSETFRAME (frame, last_nonminibuf_frame); + + return frame; +} /*********************************************************************** Initialization @@ -7069,6 +7101,7 @@ syms_of_display () defsubr (&Ssend_string_to_terminal); defsubr (&Sinternal_show_cursor); defsubr (&Sinternal_show_cursor_p); + defsubr (&Slast_nonminibuf_frame); #if GLYPH_DEBUG defsubr (&Sdump_redisplay_history);