Mercurial > hg > xemacs-beta
diff src/gutter.c @ 406:b8cc9ab3f761 r21-2-33
Import from CVS: tag r21-2-33
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:17:09 +0200 |
parents | 2f8bb876ab1d |
children | 501cfd01ee6d |
line wrap: on
line diff
--- a/src/gutter.c Mon Aug 13 11:16:09 2007 +0200 +++ b/src/gutter.c Mon Aug 13 11:17:09 2007 +0200 @@ -50,6 +50,9 @@ Lisp_Object Qgutter_visible; Lisp_Object Qdefault_gutter_position_changed_hook; +static void +update_gutter_geometry (struct frame *f, enum gutter_pos pos); + #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ do { \ switch (pos) \ @@ -85,6 +88,7 @@ return frame->right_gutter_was_visible; default: abort (); + return 0; /* To keep the compiler happy */ } } @@ -256,7 +260,7 @@ int line, border_width; face_index findex; display_line_dynarr* ddla, *cdla; - struct display_line *dl; + struct display_line *dl = 0; int cdla_len; if (!WINDOW_LIVE_P (w)) @@ -321,10 +325,38 @@ } /* grab coordinates of last line and blank after it. */ - dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); - ypos = dl->ypos + dl->descent - dl->clip; + if (Dynarr_length (ddla) > 0) + { + dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); + ypos = dl->ypos + dl->descent - dl->clip; + } + else + ypos = y; + redisplay_clear_region (window, findex, x + border_width , ypos, width - 2 * border_width, height - (ypos - y) - border_width); + /* If, for some reason, we have more to display than we have + room for, and we are allowed to resize the gutter, then make + sure this happens before the next time we try and + output. This can happen when face font sizes change. */ + if (dl && dl->clip > 0 && EQ (w->gutter_size[pos], Qautodetect)) + { + /* #### Ideally we would just mark the specifier as dirty + and everything else would "just work". Unfortunately we have + two problems with this. One is that the specifier cache + won't be recalculated unless the specifier code thinks the + cached value has actually changed, even though we have + marked the specifier as dirty. Additionally, although doing + this results in a gutter size change, we never seem to get + back into redisplay so that the frame size can be updated. I + think this is because we are already in redisplay and later + on the frame will be marked as clean. Thus we also have to + force a pending recalculation of the frame size. */ + w->gutter_size[pos] = Qnil; + Fset_specifier_dirty_flag (Vgutter_size[pos]); + update_gutter_geometry (f, pos); + } + /* bevel the gutter area if so desired */ if (border_width != 0) { @@ -468,6 +500,25 @@ /* We have to change the gutter geometry separately to the gutter update since it needs to occur outside of redisplay proper. */ +static void +update_gutter_geometry (struct frame *f, enum gutter_pos pos) +{ + /* If the gutter geometry has changed then re-layout the + frame. If we are in display there is almost no point in doing + anything else since the frame size changes will be delayed + until we are out of redisplay proper. */ + if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos]) + { + int width, height; + pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), + &width, &height); + change_frame_size (f, height, width, 0); + } + + /* Mark sizes as up-to-date. */ + f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); +} + void update_frame_gutter_geometry (struct frame *f) { @@ -481,20 +532,7 @@ until we are out of redisplay proper. */ GUTTER_POS_LOOP (pos) { - if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos]) - { - int width, height; - pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), - &width, &height); - change_frame_size (f, height, width, 0); - break; - } - } - - GUTTER_POS_LOOP (pos) - { - /* Mark sizes as up-to-date. */ - f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); + update_gutter_geometry (f, pos); } } } @@ -557,6 +595,10 @@ if (((x + width) < g_x) || (x > (g_x + g_width))) return; +#ifdef DEBUG_WIDGETS + printf ("redrawing gutter after expose %d+%d, %dx%d\n", + x, y, width, height); +#endif /* #### optimize this - redrawing the whole gutter for every expose is very expensive. We reset the current display lines because if they're being exposed they are no longer current. */ @@ -573,11 +615,16 @@ int height) { enum gutter_pos pos; + + /* We have to be "in display" when we output the gutter - make it + so. */ + hold_frame_size_changes (); GUTTER_POS_LOOP (pos) { if (FRAME_GUTTER_VISIBLE (f, pos)) redraw_exposed_gutter (f, pos, x, y, width, height); } + unhold_one_frame_size_changes (f); } void @@ -1047,8 +1094,8 @@ defsymbol (&Qgutter_size, "gutter-size"); defsymbol (&Qgutter_visible, "gutter-visible"); - defsymbol (&Qdefault_gutter_position_changed_hook, - "default-gutter-position-changed"); + defsymbol (&Qdefault_gutter_position_changed_hook, + "default-gutter-position-changed-hook"); } void