X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/8d80e2275236bcfa3ef3f8cc011ecd2a1993f25c..e24c997dd3fad26308be1631ee6371cd33dacebd:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 88f9e9c55c..b78da7692a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -42,6 +42,8 @@ extern void set_frame_menubar (); extern int interrupt_input; extern int command_loop_level; +extern Lisp_Object Qface; + /* Nonzero means print newline before next minibuffer message. */ int noninteractive_need_newline; @@ -83,6 +85,10 @@ char *previous_echo_glyphs; /* Nonzero means truncate lines in all windows less wide than the frame */ int truncate_partial_width_windows; +/* Nonzero means we have more than one non-minibuffer-only frame. + Not guaranteed to be accurate except while parsing frame-title-format. */ +int multiple_frames; + Lisp_Object Vglobal_mode_string; /* Marker for where to display an arrow on top of the buffer text. */ @@ -91,6 +97,12 @@ Lisp_Object Voverlay_arrow_position; /* String to display for the arrow. */ Lisp_Object Voverlay_arrow_string; +/* Like mode-line-format, but for the titlebar on a visible frame. */ +Lisp_Object Vframe_title_format; + +/* Like mode-line-format, but for the titlebar on an iconified frame. */ +Lisp_Object Vicon_title_format; + /* Values of those variables at last redisplay. */ static Lisp_Object last_arrow_position, last_arrow_string; @@ -275,6 +287,7 @@ int message_buf_print; void message (m, a1, a2, a3) char *m; + EMACS_INT a1, a2, a3; { if (noninteractive) { @@ -311,7 +324,7 @@ message (m, a1, a2, a3) { int len; #ifdef NO_ARG_ARRAY - int a[3]; + EMACS_INT a[3]; a[0] = a1; a[1] = a2; a[2] = a3; @@ -335,6 +348,12 @@ message (m, a1, a2, a3) } } +void +update_echo_area () +{ + message2 (echo_area_glyphs, echo_area_glyphs_length); +} + static void echo_area_display () { @@ -392,32 +411,57 @@ echo_area_display () } #ifdef HAVE_X_WINDOWS -/* I'm trying this out because I saw Unimpress use it, but it's - possible that this may mess adversely with some window managers. -jla +static char frame_title_buf[512]; +static char *frame_title_ptr; - Wouldn't it be nice to use something like mode-line-format to - describe frame titles? -JimB */ +static int +store_frame_title (str, mincol, maxcol) + char *str; + int mincol, maxcol; +{ + char *limit; + if (maxcol < 0 || maxcol >= sizeof(frame_title_buf)) + maxcol = sizeof (frame_title_buf); + limit = &frame_title_buf[maxcol]; + while (*str != '\0' && frame_title_ptr < limit) + *frame_title_ptr++ = *str++; + while (frame_title_ptr < &frame_title_buf[mincol]) + *frame_title_ptr++ = ' '; + return frame_title_ptr - frame_title_buf; +} -/* Change the title of the frame to the name of the buffer displayed - in the currently selected window. Don't do this for minibuffer frames, - and don't do it when there's only one non-minibuffer frame. */ static void x_consider_frame_title (frame) Lisp_Object frame; { + Lisp_Object fmt; + struct buffer *obuf; + int len; FRAME_PTR f = XFRAME (frame); - if (FRAME_X_P (f) && ! FRAME_MINIBUF_ONLY_P (f)) - { - Lisp_Object title; - - title = Qnil; - if (! EQ (Fnext_frame (frame, Qnil), frame)) - title = XBUFFER (XWINDOW (f->selected_window)->buffer)->name; - - x_implicitly_set_name (f, title, Qnil); - } + if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name) + return; + multiple_frames = !EQ (Fnext_frame (frame, Qnil), frame); + obuf = current_buffer; + Fset_buffer (XWINDOW (f->selected_window)->buffer); + fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format); + frame_title_ptr = frame_title_buf; + len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0, + 0, sizeof (frame_title_buf), fmt); + frame_title_ptr = 0; + set_buffer_internal (obuf); + /* Set the name only if it's changed. This avoids consing + in the common case where it hasn't. (If it turns out that we've + already wasted too much time by walking through the list with + display_mode_element, then we might need to optimize at a higher + level than this.) */ + if (! STRINGP (f->name) || XSTRING (f->name)->size != len + || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0) + x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil); } +#else +#define frame_title_ptr ((char *)0) +#define store_frame_title(str, mincol, maxcol) 0 #endif /* Prepare for redisplay by updating menu-bar item lists when appropriate. @@ -594,7 +638,7 @@ redisplay () && GPT >= tlbufpos /* If selective display, can't optimize if the changes start at the beginning of the line. */ - && ((XTYPE (current_buffer->selective_display) == Lisp_Int + && ((INTEGERP (current_buffer->selective_display) && XINT (current_buffer->selective_display) > 0 ? (beg_unchanged >= tlbufpos && GPT > tlbufpos) @@ -746,7 +790,7 @@ update: { FRAME_PTR f; - if (XTYPE (XCONS (tail)->car) != Lisp_Frame) + if (!FRAMEP (XCONS (tail)->car)) continue; f = XFRAME (XCONS (tail)->car); @@ -884,7 +928,7 @@ mark_window_display_accurate (window, flag) for (;!NILP (window); window = w->next) { - if (XTYPE (window) != Lisp_Window) abort (); + if (!WINDOWP (window)) abort (); w = XWINDOW (window); if (!NILP (w->buffer)) @@ -1069,17 +1113,19 @@ redisplay_window (window, just_this_one) if (!EQ (window, selected_window)) { - SET_PT (marker_position (w->pointm)); - if (PT < BEGV) + int new_pt = marker_position (w->pointm); + if (new_pt < BEGV) { - SET_PT (BEGV); - Fset_marker (w->pointm, make_number (PT), Qnil); + new_pt = BEGV; + Fset_marker (w->pointm, make_number (new_pt), Qnil); } - else if (PT > (ZV - 1)) + else if (new_pt > (ZV - 1)) { - SET_PT (ZV); - Fset_marker (w->pointm, make_number (PT), Qnil); + new_pt = ZV; + Fset_marker (w->pointm, make_number (new_pt), Qnil); } + /* We don't use SET_PT so that the point-motion hooks don't run. */ + BUF_PT (current_buffer) = new_pt; } /* If window-start is screwed up, choose a new one. */ @@ -1112,7 +1158,7 @@ redisplay_window (window, just_this_one) ZV, height / 2, - (1 << (SHORTBITS - 1)), width, hscroll, pos_tab_offset (w, startp), w); - SET_PT (pos.bufpos); + BUF_PT (current_buffer) = pos.bufpos; if (w != XWINDOW (selected_window)) Fset_marker (w->pointm, make_number (PT), Qnil); else @@ -1175,7 +1221,7 @@ redisplay_window (window, just_this_one) /* If current starting point was originally the beginning of a line but no longer is, find a new starting point. */ else if (!NILP (w->start_at_line_beg) - && !(startp == BEGV + && !(startp <= BEGV || FETCH_CHAR (startp - 1) == '\n')) { goto recenter; @@ -1268,8 +1314,8 @@ recenter: try_window (window, pos.bufpos); startp = marker_position (w->start); - w->start_at_line_beg = - (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil; + w->start_at_line_beg + = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil; done: if ((!NILP (w->update_mode_line) @@ -1331,9 +1377,9 @@ done: (*redeem_scroll_bar_hook) (w); } - SET_PT (opoint); + BUF_PT (current_buffer) = opoint; current_buffer = old; - SET_PT (lpoint); + BUF_PT (current_buffer) = lpoint; } /* Do full redisplay on one window, starting at position `pos'. */ @@ -1417,10 +1463,9 @@ try_window_id (window) register int i, tem; int last_text_vpos = 0; int stop_vpos; - int selective - = XTYPE (current_buffer->selective_display) == Lisp_Int - ? XINT (current_buffer->selective_display) - : !NILP (current_buffer->selective_display) ? -1 : 0; + int selective = (INTEGERP (current_buffer->selective_display) + ? XINT (current_buffer->selective_display) + : !NILP (current_buffer->selective_display) ? -1 : 0); struct position val, bp, ep, xp, pp; int scroll_amount = 0; @@ -1987,10 +2032,9 @@ display_text_line (w, start, vpos, hpos, taboffset) = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active); int region_beg, region_end; - int selective - = XTYPE (current_buffer->selective_display) == Lisp_Int - ? XINT (current_buffer->selective_display) - : !NILP (current_buffer->selective_display) ? -1 : 0; + int selective = (INTEGERP (current_buffer->selective_display) + ? XINT (current_buffer->selective_display) + : !NILP (current_buffer->selective_display) ? -1 : 0); register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f); register struct Lisp_Vector *dp = window_display_table (w); @@ -1998,20 +2042,20 @@ display_text_line (w, start, vpos, hpos, taboffset) /* Nonzero means display something where there are invisible lines. The precise value is the number of glyphs to display. */ int selective_rlen - = (selective && dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector + = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp)) ? XVECTOR (DISP_INVIS_VECTOR (dp))->size : selective && !NILP (current_buffer->selective_display_ellipses) ? 3 : 0); /* This is the sequence of Lisp objects to display when there are invisible lines. */ Lisp_Object *invis_vector_contents - = (dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector + = (dp && VECTORP (DISP_INVIS_VECTOR (dp)) ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents : default_invis_vector); - GLYPH truncator = (dp == 0 || XTYPE (DISP_TRUNC_GLYPH (dp)) != Lisp_Int + GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp)) ? '$' : XINT (DISP_TRUNC_GLYPH (dp))); - GLYPH continuer = (dp == 0 || XTYPE (DISP_CONTINUE_GLYPH (dp)) != Lisp_Int + GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp)) ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp))); /* The next buffer location at which the face should change, due @@ -2185,7 +2229,7 @@ display_text_line (w, start, vpos, hpos, taboffset) } c = *p++; if (c >= 040 && c < 0177 - && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector)) + && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c)))) { if (p1 >= leftmargin) *p1 = MAKE_GLYPH (f, c, current_face); @@ -2261,7 +2305,7 @@ display_text_line (w, start, vpos, hpos, taboffset) #endif break; } - else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector) + else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) { p1 = copy_part_of_rope (f, p1, leftmargin, XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents, @@ -2271,7 +2315,7 @@ display_text_line (w, start, vpos, hpos, taboffset) else if (c < 0200 && ctl_arrow) { if (p1 >= leftmargin) - *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int + *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), current_face); p1++; @@ -2282,7 +2326,7 @@ display_text_line (w, start, vpos, hpos, taboffset) else { if (p1 >= leftmargin) - *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int + *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), current_face); p1++; @@ -2305,7 +2349,7 @@ display_text_line (w, start, vpos, hpos, taboffset) if (p1 != p1prev) { int *p2x = &charstart[p1prev - p1start]; - int *p2 = &charstart[p1 - p1start]; + int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start]; /* The window's left column should always contain a character position. @@ -2464,7 +2508,10 @@ display_text_line (w, start, vpos, hpos, taboffset) them when the scroll bar windows are flickering around to be reconfigured. */ *p1++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f) - ? ' ' : '|'); + ? ' ' + : (dp && INTEGERP (DISP_BORDER_GLYPH (dp)) + ? DISP_BORDER_GLYPH (dp) + : '|')); } desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos], p1 - desired_glyphs->glyphs[vpos]); @@ -2473,10 +2520,10 @@ display_text_line (w, start, vpos, hpos, taboffset) /* If the start of this line is the overlay arrow-position, then put the arrow string into the display-line. */ - if (XTYPE (Voverlay_arrow_position) == Lisp_Marker + if (MARKERP (Voverlay_arrow_position) && current_buffer == XMARKER (Voverlay_arrow_position)->buffer && start == marker_position (Voverlay_arrow_position) - && XTYPE (Voverlay_arrow_string) == Lisp_String + && STRINGP (Voverlay_arrow_string) && ! overlay_arrow_seen) { unsigned char *p = XSTRING (Voverlay_arrow_string)->data; @@ -2486,8 +2533,28 @@ display_text_line (w, start, vpos, hpos, taboffset) if (len > width) len = width; - for (i = 0; i < len; i++) - leftmargin[i] = p[i]; +#ifdef HAVE_X_WINDOWS + if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals)) + { + /* If the arrow string has text props, obey them when displaying. */ + for (i = 0; i < len; i++) + { + int c = p[i]; + Lisp_Object face, ilisp; + int newface; + + XFASTINT (ilisp) = i; + face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string); + newface = compute_glyph_face_1 (f, face, 0); + leftmargin[i] = FAST_MAKE_GLYPH (c, newface); + } + } + else +#endif /* HAVE_X_WINDOWS */ + { + for (i = 0; i < len; i++) + leftmargin[i] = p[i]; + } /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */ arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len; @@ -2657,8 +2724,11 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) if (this - 1 != last) { register int lim = --this - last + hpos; - hpos = display_string (w, vpos, last, -1, hpos, 0, 1, - hpos, min (lim, maxendcol)); + if (frame_title_ptr) + hpos = store_frame_title (last, hpos, min (lim, maxendcol)); + else + hpos = display_string (w, vpos, last, -1, hpos, 0, 1, + hpos, min (lim, maxendcol)); } else /* c == '%' */ { @@ -2683,11 +2753,15 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) spec_width, maxendcol, Vglobal_mode_string); else if (c != 0) - hpos = display_string (w, vpos, - decode_mode_spec (w, c, - maxendcol - hpos), - -1, - hpos, 0, 1, spec_width, maxendcol); + { + char *spec = decode_mode_spec (w, c, maxendcol - hpos); + if (frame_title_ptr) + hpos = store_frame_title (spec, spec_width, maxendcol); + else + hpos = display_string (w, vpos, spec, -1, + hpos, 0, 1, + spec_width, maxendcol); + } } } } @@ -2706,10 +2780,16 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) tem = Fsymbol_value (elt); /* If value is a string, output that string literally: don't check for % within it. */ - if (XTYPE (tem) == Lisp_String) - hpos = display_string (w, vpos, XSTRING (tem)->data, - XSTRING (tem)->size, - hpos, 0, 1, minendcol, maxendcol); + if (STRINGP (tem)) + { + if (frame_title_ptr) + hpos = store_frame_title (XSTRING (tem)->data, + minendcol, maxendcol); + else + hpos = display_string (w, vpos, XSTRING (tem)->data, + XSTRING (tem)->size, + hpos, 0, 1, minendcol, maxendcol); + } /* Give up right away for nil or t. */ else if (!EQ (tem, elt)) { elt = tem; goto tail_recurse; } @@ -2730,11 +2810,11 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) If first element is a symbol, process the cadr or caddr recursively according to whether the symbol's value is non-nil or nil. */ car = XCONS (elt)->car; - if (XTYPE (car) == Lisp_Symbol) + if (SYMBOLP (car)) { tem = Fboundp (car); elt = XCONS (elt)->cdr; - if (XTYPE (elt) != Lisp_Cons) + if (!CONSP (elt)) goto invalid; /* elt is now the cdr, and we know it is a cons cell. Use its car if CAR has a non-nil value. */ @@ -2750,12 +2830,12 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) elt = XCONS (elt)->cdr; if (NILP (elt)) break; - else if (XTYPE (elt) != Lisp_Cons) + else if (!CONSP (elt)) goto invalid; elt = XCONS (elt)->car; goto tail_recurse; } - else if (XTYPE (car) == Lisp_Int) + else if (INTEGERP (car)) { register int lim = XINT (car); elt = XCONS (elt)->cdr; @@ -2780,11 +2860,11 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) } goto tail_recurse; } - else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons) + else if (STRINGP (car) || CONSP (car)) { register int limit = 50; /* LIMIT is to protect against circular lists. */ - while (XTYPE (elt) == Lisp_Cons && --limit > 0 + while (CONSP (elt) && --limit > 0 && hpos < maxendcol) { hpos = display_mode_element (w, vpos, hpos, depth, @@ -2798,13 +2878,19 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) default: invalid: - return (display_string (w, vpos, "*invalid*", -1, hpos, 0, 1, - minendcol, maxendcol)); + if (frame_title_ptr) + hpos = store_frame_title ("*invalid*", minendcol, maxendcol); + else + hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1, + minendcol, maxendcol); + return hpos; } - end: if (minendcol > hpos) - hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol); + if (frame_title_ptr) + hpos = store_frame_title ("", minendcol, maxendcol); + else + hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol); return hpos; } @@ -2822,6 +2908,7 @@ decode_mode_spec (w, c, maxwidth) Lisp_Object obj; FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents; + struct buffer *b = XBUFFER (w->buffer); obj = Qnil; if (maxwidth > FRAME_WIDTH (f)) @@ -2830,7 +2917,7 @@ decode_mode_spec (w, c, maxwidth) switch (c) { case 'b': - obj = current_buffer->name; + obj = b->name; #if 0 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth) { @@ -2843,11 +2930,11 @@ decode_mode_spec (w, c, maxwidth) break; case 'f': - obj = current_buffer->filename; + obj = b->filename; #if 0 if (NILP (obj)) return "[none]"; - else if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth) + else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth) { bcopy ("...", decode_mode_spec_buf, 3); bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3, @@ -2871,7 +2958,7 @@ decode_mode_spec (w, c, maxwidth) return "??"; /* If the buffer is very big, don't waste time. */ - if (ZV - BEGV > line_number_display_limit) + if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit) { w->base_line_pos = Qnil; w->base_line_number = Qnil; @@ -2888,7 +2975,7 @@ decode_mode_spec (w, c, maxwidth) else { line = 1; - linepos = BEGV; + linepos = BUF_BEGV (b); } /* Count lines from base line to window start position. */ @@ -2900,15 +2987,15 @@ decode_mode_spec (w, c, maxwidth) or too far away, or if we did not have one. "Too close" means it's plausible a scroll-down would go back past it. */ - if (startpos == BEGV) + if (startpos == BUF_BEGV (b)) { XFASTINT (w->base_line_number) = topline; - XFASTINT (w->base_line_pos) = BEGV; + XFASTINT (w->base_line_pos) = BUF_BEGV (b); } else if (nlines < height + 25 || nlines > height * 3 + 50 - || linepos == BEGV) + || linepos == BUF_BEGV (b)) { - int limit = BEGV; + int limit = BUF_BEGV (b); int position; int distance = (height * 2 + 30) * 200; @@ -2945,32 +3032,38 @@ decode_mode_spec (w, c, maxwidth) break; case 'm': - obj = current_buffer->mode_name; + obj = b->mode_name; break; case 'n': - if (BEGV > BEG || ZV < Z) + if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b)) return " Narrow"; break; case '*': - if (!NILP (current_buffer->read_only)) + if (!NILP (b->read_only)) return "%"; - if (MODIFF > current_buffer->save_modified) + if (BUF_MODIFF (b) > b->save_modified) return "*"; return "-"; case '+': /* This differs from %* only for a modified read-only buffer. */ - if (MODIFF > current_buffer->save_modified) + if (BUF_MODIFF (b) > b->save_modified) return "*"; - if (!NILP (current_buffer->read_only)) + if (!NILP (b->read_only)) return "%"; return "-"; + case '&': + /* This differs from %* in ignoring read-only-ness. */ + if (BUF_MODIFF (b) > b->save_modified) + return "*"; + return "-"; + case 's': /* status of process */ - obj = Fget_buffer_process (Fcurrent_buffer ()); + obj = Fget_buffer_process (w->buffer); if (NILP (obj)) return "no process"; #ifdef subprocesses @@ -2979,29 +3072,29 @@ decode_mode_spec (w, c, maxwidth) break; case 't': /* indicate TEXT or BINARY */ -#ifdef MSDOS - return NILP (current_buffer->buffer_file_type) ? "T" : "B"; -#else /* not MSDOS */ +#ifdef MODE_LINE_BINARY_TEXT + return MODE_LINE_BINARY_TEXT (b); +#else return "T"; -#endif /* not MSDOS */ +#endif case 'p': { int pos = marker_position (w->start); - int total = ZV - BEGV; + int total = BUF_ZV (b) - BUF_BEGV (b); - if (XFASTINT (w->window_end_pos) <= Z - ZV) + if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b)) { - if (pos <= BEGV) + if (pos <= BUF_BEGV (b)) return "All"; else return "Bottom"; } - else if (pos <= BEGV) + else if (pos <= BUF_BEGV (b)) return "Top"; else { - total = ((pos - BEGV) * 100 + total - 1) / total; + total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; /* We can't normally display a 3-digit number, so get us a 2-digit number that is close. */ if (total == 100) @@ -3015,24 +3108,24 @@ decode_mode_spec (w, c, maxwidth) case 'P': { int toppos = marker_position (w->start); - int botpos = Z - XFASTINT (w->window_end_pos); - int total = ZV - BEGV; + int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos); + int total = BUF_ZV (b) - BUF_BEGV (b); - if (botpos >= ZV) + if (botpos >= BUF_ZV (b)) { - if (toppos <= BEGV) + if (toppos <= BUF_BEGV (b)) return "All"; else return "Bottom"; } else { - total = ((botpos - BEGV) * 100 + total - 1) / total; + total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; /* We can't normally display a 3-digit number, so get us a 2-digit number that is close. */ if (total == 100) total = 99; - if (toppos <= BEGV) + if (toppos <= BUF_BEGV (b)) sprintf (decode_mode_spec_buf, "Top%2d%%", total); else sprintf (decode_mode_spec_buf, "%2d%%", total); @@ -3070,7 +3163,7 @@ decode_mode_spec (w, c, maxwidth) *p = 0; return decode_mode_spec_buf; } - + case '-': { register char *p; @@ -3087,12 +3180,113 @@ decode_mode_spec (w, c, maxwidth) return decode_mode_spec_buf; } } - - if (XTYPE (obj) == Lisp_String) + + if (STRINGP (obj)) return (char *) XSTRING (obj)->data; else return ""; } + +/* Search for COUNT instances of a line boundary, which means either a + newline or (if selective display enabled) a carriage return. + Start at START. If COUNT is negative, search backwards. + + If we find COUNT instances, set *SHORTAGE to zero, and return the + position after the COUNTth match. Note that for reverse motion + this is not the same as the usual convention for Emacs motion commands. + + If we don't find COUNT instances before reaching the end of the + buffer (or the beginning, if scanning backwards), set *SHORTAGE to + the number of line boundaries left unfound, and return the end of the + buffer we bumped up against. */ + +static int +display_scan_buffer (start, count, shortage) + int *shortage, start; + register int count; +{ + int limit = ((count > 0) ? ZV - 1 : BEGV); + int direction = ((count > 0) ? 1 : -1); + + register unsigned char *cursor; + unsigned char *base; + + register int ceiling; + register unsigned char *ceiling_addr; + + /* If we are not in selective display mode, + check only for newlines. */ + if (! (!NILP (current_buffer->selective_display) + && !INTEGERP (current_buffer->selective_display))) + return scan_buffer ('\n', start, count, shortage, 0); + + /* The code that follows is like scan_buffer + but checks for either newline or carriage return. */ + + if (shortage != 0) + *shortage = 0; + + if (count > 0) + while (start != limit + 1) + { + ceiling = BUFFER_CEILING_OF (start); + ceiling = min (limit, ceiling); + ceiling_addr = &FETCH_CHAR (ceiling) + 1; + base = (cursor = &FETCH_CHAR (start)); + while (1) + { + while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr) + ; + if (cursor != ceiling_addr) + { + if (--count == 0) + { + immediate_quit = 0; + return (start + cursor - base + 1); + } + else + if (++cursor == ceiling_addr) + break; + } + else + break; + } + start += cursor - base; + } + else + { + start--; /* first character we scan */ + while (start > limit - 1) + { /* we WILL scan under start */ + ceiling = BUFFER_FLOOR_OF (start); + ceiling = max (limit, ceiling); + ceiling_addr = &FETCH_CHAR (ceiling) - 1; + base = (cursor = &FETCH_CHAR (start)); + cursor++; + while (1) + { + while (--cursor != ceiling_addr + && *cursor != '\n' && *cursor != 015) + ; + if (cursor != ceiling_addr) + { + if (++count == 0) + { + immediate_quit = 0; + return (start + cursor - base + 1); + } + } + else + break; + } + start += cursor - base; + } + } + + if (shortage != 0) + *shortage = count * direction; + return (start + ((direction == 1 ? 0 : 1))); +} /* Count up to N lines starting from FROM. But don't go beyond LIMIT. @@ -3113,7 +3307,7 @@ display_count_lines (from, limit, n, pos_ptr) else ZV = limit; - *pos_ptr = scan_buffer ('\n', from, n, &shortage, 0); + *pos_ptr = display_scan_buffer (from, n, &shortage); ZV = oldzv; BEGV = oldbegv; @@ -3173,7 +3367,7 @@ display_string (w, vpos, string, length, hpos, truncate, register struct Lisp_Vector *dp = 0; int i; - if (XTYPE (Vstandard_display_table) == Lisp_Vector + if (VECTORP (Vstandard_display_table) && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE) dp = XVECTOR (Vstandard_display_table); @@ -3192,7 +3386,7 @@ display_string (w, vpos, string, length, hpos, truncate, { int i; - for (i = 0; i < VERTICAL_SCROLL_BAR_WIDTH; i++) + for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++) *end-- = ' '; } else @@ -3224,7 +3418,7 @@ display_string (w, vpos, string, length, hpos, truncate, break; if (c >= 040 && c < 0177 - && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector)) + && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c)))) { if (p1 >= start) *p1 = c; @@ -3240,7 +3434,7 @@ display_string (w, vpos, string, length, hpos, truncate, } while ((p1 - start + hscroll - (hscroll > 0)) % tab_width); } - else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector) + else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) { p1 = copy_part_of_rope (f, p1, start, XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents, @@ -3250,7 +3444,7 @@ display_string (w, vpos, string, length, hpos, truncate, else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow)) { if (p1 >= start) - *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int + *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp)) ? XINT (DISP_CTRL_GLYPH (dp)) : '^'), 0); p1++; @@ -3261,7 +3455,7 @@ display_string (w, vpos, string, length, hpos, truncate, else { if (p1 >= start) - *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int + *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp)) ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'), 0); p1++; @@ -3348,6 +3542,33 @@ If this is zero, point is always centered after it moves off frame."); DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows, "*Non-nil means highlight region even in nonselected windows."); highlight_nonselected_windows = 1; + + DEFVAR_BOOL ("multiple-frames", &multiple_frames, + "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\ +Not guaranteed to be accurate except while parsing frame-title-format."); + + DEFVAR_LISP ("frame-title-format", &Vframe_title_format, + "Template for displaying the titlebar of visible frames.\n\ +\(Assuming the window manager supports this feature.)\n\ +This variable has the same structure as `mode-line-format' (which see),\n\ +and is used only on frames for which no explicit name has been set\n\ +\(see `modify-frame-parameters')."); + DEFVAR_LISP ("icon-title-format", &Vicon_title_format, + "Template for displaying the titlebar of an iconified frame.\n\ +\(Assuming the window manager supports this feature.)\n\ +This variable has the same structure as `mode-line-format' (which see),\n\ +and is used only on frames for which no explicit name has been set\n\ +\(see `modify-frame-parameters')."); + Vicon_title_format + = Vframe_title_format + = Fcons (intern ("multiple-frames"), + Fcons (build_string ("%b"), + Fcons (Fcons (build_string (""), + Fcons (intern ("invocation-name"), + Fcons (build_string ("@"), + Fcons (intern ("system-name"), + Qnil)))), + Qnil))); } /* initialize the window system */