#include "commands.h"
#include "debug.h"
#include "device.h"
+#include "elhash.h"
#include "extents.h"
#include "faces.h"
#include "frame.h"
struct glyph_cachel *cachel);
static Bytind create_text_block (struct window *w, struct display_line *dl,
Bytind bi_start_pos, int start_col,
- prop_block_dynarr **prop, int type);
+ prop_block_dynarr **prop,
+ int type);
static int create_overlay_glyph_block (struct window *w,
struct display_line *dl);
static void create_left_glyph_block (struct window *w,
int glyphs_changed;
int glyphs_changed_set;
+/* non-zero if any displayed subwindow is in need of updating
+ somewhere. */
+int subwindows_changed;
+int subwindows_changed_set;
+
/* This variable is 1 if the icon has to be updated.
It is set to 1 when `frame-icon-glyph' changes. */
int icon_changed;
static Bufpos
generate_display_line (struct window *w, struct display_line *dl, int bounds,
Bufpos start_pos, int start_col,
- prop_block_dynarr **prop, int type)
+ prop_block_dynarr **prop,
+ int type)
{
Bufpos ret_bufpos;
int overlay_width;
}
}
-/* Given a display table entry, call the appropriate functions to
- display each element of the entry. */
-
static prop_block_dynarr *
-add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
+add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
{
prop_block_dynarr *prop = NULL;
- if (VECTORP (entry))
- {
- struct Lisp_Vector *de = XVECTOR (entry);
- long len = vector_length (de);
- int elt;
-
- for (elt = 0; elt < len; elt++)
- {
- if (NILP (de->contents[elt]))
- continue;
- else if (STRINGP (de->contents[elt]))
- {
- prop =
- add_bufbyte_string_runes
- (data,
- XSTRING_DATA (de->contents[elt]),
- XSTRING_LENGTH (de->contents[elt]),
- 0);
- }
- else if (GLYPHP (de->contents[elt]))
- {
- if (data->start_col)
- data->start_col--;
-
- if (!data->start_col && data->bi_start_col_enabled)
- {
- prop = add_hscroll_rune (data);
- }
- else
- {
- struct glyph_block gb;
-
- gb.glyph = de->contents[elt];
- gb.extent = Qnil;
- prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
- }
- }
- else if (CHAR_OR_CHAR_INTP (de->contents[elt]))
- {
- data->ch = XCHAR_OR_CHAR_INT (de->contents[elt]);
- prop = add_emchar_rune (data);
- }
- /* Else blow it off because someone added a bad entry and we
- don't have any safe way of signaling an error. */
-
- /* #### Still need to add any remaining elements to the
- propagation information. */
- if (prop)
- return prop;
- }
- }
- else if (STRINGP (entry))
+ if (STRINGP (entry))
{
prop = add_bufbyte_string_runes (data,
XSTRING_DATA (entry),
data->ch = XCHAR_OR_CHAR_INT (entry);
prop = add_emchar_rune (data);
}
+ else if (CONSP (entry))
+ {
+ if (EQ (XCAR (entry), Qformat)
+ && CONSP (XCDR (entry))
+ && STRINGP (XCAR (XCDR (entry))))
+ {
+ Lisp_Object format = XCAR (XCDR (entry));
+ Bytind len = XSTRING_LENGTH (format);
+ Bufbyte *src = XSTRING_DATA (format), *end = src + len;
+ Bufbyte *result = alloca_array (Bufbyte, len);
+ Bufbyte *dst = result;
+
+ while (src < end)
+ {
+ Emchar c = charptr_emchar (src);
+ INC_CHARPTR (src);
+ if (c != '%' || src == end)
+ dst += set_charptr_emchar (dst, c);
+ else
+ {
+ c = charptr_emchar (src);
+ INC_CHARPTR (src);
+ switch (c)
+ {
+ /*case 'x':
+ dst += long_to_string_base ((char *)dst, data->ch, 16);
+ break;*/
+ case '%':
+ dst += set_charptr_emchar (dst, '%');
+ break;
+ }
+ }
+ }
+ prop = add_bufbyte_string_runes (data, result, dst - result, 0);
+ }
+ }
/* Else blow it off because someone added a bad entry and we don't
- have any safe way of signaling an error. Hey, this comment
- sounds familiar. */
+ have any safe way of signaling an error. */
+ return prop;
+}
+
+/* Given a display table entry, call the appropriate functions to
+ display each element of the entry. */
+
+static prop_block_dynarr *
+add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
+{
+ prop_block_dynarr *prop = NULL;
+ if (VECTORP (entry))
+ {
+ struct Lisp_Vector *de = XVECTOR (entry);
+ EMACS_INT len = vector_length (de);
+ int elt;
+
+ for (elt = 0; elt < len; elt++)
+ {
+ if (NILP (vector_data (de)[elt]))
+ continue;
+ else
+ prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
+ /* Else blow it off because someone added a bad entry and we
+ don't have any safe way of signaling an error. Hey, this
+ comment sounds familiar. */
+
+ /* #### Still need to add any remaining elements to the
+ propagation information. */
+ if (prop)
+ return prop;
+ }
+ }
+ else
+ prop = add_disp_table_entry_runes_1 (data, entry);
return prop;
}
static Bytind
create_text_block (struct window *w, struct display_line *dl,
Bytind bi_start_pos, int start_col,
- prop_block_dynarr **prop, int type)
+ prop_block_dynarr **prop,
+ int type)
{
struct frame *f = XFRAME (w->frame);
struct buffer *b = XBUFFER (w->buffer);
struct device *d = XDEVICE (f->device);
pos_data data;
- struct Lisp_Vector *dt = 0;
/* Don't display anything in the minibuffer if this window is not on
a selected frame. We consider all other windows to be active
into a more general conversion mechanism. Ideally you
could specify a Lisp function that converts characters,
but this violates the Second Golden Rule and besides would
- make things way way way way slow. An idea I like is to
- be able to specify multiple display tables instead of just
- one. Each display table can specify conversions for some
- characters and leave others unchanged. The way the
- character gets displayed is determined by the first display
- table with a binding for that character. This way, you
- could call a function `enable-hex-display' that adds a
- pre-defined hex display-table (or maybe computes one if
- you give weird parameters to the function) and adds it
- to the list of display tables for the current buffer.
-
- Unfortunately there are still problems dealing with Mule
- characters. For example, maybe I want to specify that
- all extended characters (i.e. >= 256) are displayed in hex.
- It's not reasonable to create a mapping for all possible
- such characters, because there are about 2^19 of them.
- One way of dealing with this is to extend the concept
- of what a display table is. Currently it's only allowed
- to be a 256-entry vector. Instead, it should be something
- like:
-
- a) A 256-entry vector, for backward compatibility
- b) Some sort of hashtable, mapping characters to values
- c) A list that specifies a range of values and the
- mapping to provide for those values.
-
- Also, extend the concept of "mapping" to include a
- printf-like spec. Then, you could make all extended
- characters show up as hex with a display table like
-
- ((256 . 524288) . "%x")
+ make things way way way way slow.
+
+ So instead, we extend the display-table concept, which was
+ historically limited to 256-byte vectors, to one of the
+ following:
+
+ a) A 256-entry vector, for backward compatibility;
+ b) char-table, mapping characters to values;
+ c) range-table, mapping ranges of characters to values;
+ d) a list of the above.
+
+ The (d) option allows you to specify multiple display tables
+ instead of just one. Each display table can specify conversions
+ for some characters and leave others unchanged. The way the
+ character gets displayed is determined by the first display table
+ with a binding for that character. This way, you could call a
+ function `enable-hex-display' that adds a hex display-table to
+ the list of display tables for the current buffer.
+
+ #### ...not yet implemented... Also, we extend the concept of
+ "mapping" to include a printf-like spec. Thus you can make all
+ extended characters show up as hex with a display table like
+ this:
+
+ #s(range-table data ((256 524288) (format "%x")))
Since more than one display table is possible, you have
- great flexibility in mapping ranges of characters.
- */
+ great flexibility in mapping ranges of characters. */
Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
? XCHAR_OR_CHAR_INT (b->ctl_arrow)
: ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
? 255 : 160));
+ Lisp_Object face_dt, window_dt;
+
/* The text display block for this display line. */
struct display_block *db = get_display_block_from_line (dl, TEXT);
/* Remember that the extent-fragment routines deal in Bytind's. */
extent_fragment_update (w, data.ef, data.bi_bufpos);
+ get_display_tables (w, data.findex, &face_dt, &window_dt);
+
if (data.bi_bufpos == data.ef->end)
no_more_frags = 1;
-
- dt = get_display_table (w, data.findex);
}
initial = 0;
else
{
+ Lisp_Object entry = Qnil;
/* Get the character at the current buffer position. */
data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
+ if (!NILP (face_dt) || !NILP (window_dt))
+ entry = display_table_entry (data.ch, face_dt, window_dt);
/* If there is a display table entry for it, hand it off to
add_disp_table_entry_runes and let it worry about it. */
- if (dt && !NILP (DISP_CHAR_ENTRY (dt, data.ch)))
+ if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
{
- *prop =
- add_disp_table_entry_runes (&data,
- DISP_CHAR_ENTRY (dt, data.ch));
+ *prop = add_disp_table_entry_runes (&data, entry);
if (*prop)
goto done;
{
/* If data.start_col_enabled is still true, then the window is
scrolled far enough so that nothing on this line is visible.
- We need to stick a trunctation glyph at the beginning of the
+ We need to stick a truncation glyph at the beginning of the
line in that case unless the line is completely blank. */
if (data.bi_start_col_enabled)
{
they should start. The inside margin glyphs get whatever space
is left after the whitespace glyphs have been displayed. These
are tricky to calculate since if we decide to use the overflow
- area we basicaly have to start over. So for these we build up a
+ area we basically have to start over. So for these we build up a
list of just the inside margin glyphs and manipulate it to
determine the needed info. */
{
struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have beeb handled in add_glyph_rune */
+ abort (); /* these should have been handled in add_glyph_rune */
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_OUTSIDE_MARGIN)
they should start. The inside margin glyphs get whatever space
is left after the whitespace glyphs have been displayed. These
are tricky to calculate since if we decide to use the overflow
- area we basicaly have to start over. So for these we build up a
+ area we basically have to start over. So for these we build up a
list of just the inside margin glyphs and manipulate it to
determine the needed info. */
{
struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have beeb handled in add_glyph_rune */
+ abort (); /* these should have been handled in add_glyph_rune */
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
{
MODELINE_INDEX, min_pixpos, max_pixpos, type);
/* The modeline is at the bottom of the gutters. We have to wait to
- set this until we've generated teh modeline in order to account
+ set this until we've generated the modeline in order to account
for any embedded faces. */
dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
}
}
if (prop)
- Dynarr_free (prop);
+ Dynarr_free (prop);
/* #### More not quite right, but close enough. */
/* #### Ben sez: apparently window_end_pos[] is measured
/* If the changes are below the visible area then if point hasn't
moved return success otherwise fail in order to be safe. */
if (line > dla_end)
- {
- return regenerate_window_extents_only_changed (w, startp, pointm,
- extent_beg_unchanged,
- extent_end_unchanged);
- }
+ return regenerate_window_extents_only_changed (w, startp, pointm,
+ extent_beg_unchanged,
+ extent_end_unchanged);
else
/* At this point we know what line the changes first affect. We
now redraw that line. If the changes are contained within it
&& extent_end_unchanged != -1
&& ((extent_beg_unchanged < ddl->bufpos)
|| (extent_end_unchanged > ddl->end_bufpos)))
- {
- return
- regenerate_window_extents_only_changed (w, startp, pointm,
- extent_beg_unchanged,
- extent_end_unchanged);
- }
+ return regenerate_window_extents_only_changed (w, startp, pointm,
+ extent_beg_unchanged,
+ extent_end_unchanged);
else
return 1;
}
Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
the_buffer);
- /* #### BUFU amounts of overkil just to get the cursor
+ /* #### BUFU amounts of overkill just to get the cursor
location marked properly. FIX ME FIX ME FIX ME */
regenerate_window (w, startp, pointm, DESIRED_DISP);
}
temporary change to the echo area. */
&& !(MINI_WINDOW_P (w) && f->buffers_changed)
&& !f->frame_changed
- && !truncation_changed)
+ && !truncation_changed
+ /* check whether start is really at the begining of a line GE */
+ && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
+ )
{
/* Check if the cursor has actually moved. */
if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
&& !f->extents_changed
&& !f->faces_changed
&& !f->glyphs_changed
+ && !f->subwindows_changed
&& !f->point_changed
&& !f->windows_structure_changed)
{
&& !f->extents_changed
&& !f->faces_changed
&& !f->glyphs_changed
+ && !f->subwindows_changed
&& !f->windows_structure_changed)
{
if (point_visible (w, pointm, CURRENT_DISP)
&& !f->clip_changed
&& !f->faces_changed
&& !f->glyphs_changed
+ && !f->subwindows_changed
&& !f->windows_structure_changed
&& !f->frame_changed
&& !truncation_changed
Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
? BUF_ZV (b)
: BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
-
- update_line_start_cache (w, start, end, pointm, 1);
+ /* Don't pollute the cache if not sure if we are correct */
+ if (w->start_at_line_beg)
+ update_line_start_cache (w, start, end, pointm, 1);
redisplay_output_window (w);
/*
* If we just displayed the echo area, the line start cache is
- * no longer valid, because the minibuffer window is assocaited
+ * no longer valid, because the minibuffer window is associated
* with the window now.
*/
if (echo_active)
change_frame_size (f, f->new_height, f->new_width, 0);
/* If frame size might need to be changed, due to changed size
- of toolbars, scroolabrs etc, change it now */
+ of toolbars, scrollbars etc, change it now */
if (f->size_slipped)
{
adjust_frame_size (f);
assert (!f->size_slipped);
}
-
+
/* The menubar, toolbar, and icon updates must be done before
hold_frame_size_changes is called and we are officially
'in_display'. They may eval lisp code which may call Fsignal.
being handled. */
update_frame_menubars (f);
#endif /* HAVE_MENUBARS */
-
+ /* widgets are similar to menus in that they can call lisp to
+ determine activation etc. Therefore update them before we get
+ into redisplay. This is primarily for connected widgets such as
+ radio buttons. */
+ update_frame_subwindows (f);
#ifdef HAVE_TOOLBARS
/* Update the toolbars. */
update_frame_toolbars (f);
/* Erase the frame before outputting its contents. */
if (f->clear)
- DEVMETH (d, clear_frame, (f));
+ {
+ DEVMETH (d, clear_frame, (f));
+ }
+
+ /* invalidate the subwindow cache. we are going to reuse the glyphs
+ flag here to cause subwindows to get instantiated. This is
+ because subwindows changed is less strict - dealing with things
+ like the clicked state of button. */
+ if (!Dynarr_length (f->subwindow_cachels)
+ || f->glyphs_changed
+ || f->frame_changed)
+ reset_subwindow_cachels (f);
+ else
+ mark_subwindow_cachels_as_not_updated (f);
/* Do the selected window first. */
redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
f->faces_changed = 0;
f->frame_changed = 0;
f->glyphs_changed = 0;
+ f->subwindows_changed = 0;
f->icon_changed = 0;
f->menubar_changed = 0;
f->modeline_changed = 0;
f->faces_changed || f->frame_changed || f->menubar_changed ||
f->modeline_changed || f->point_changed || f->size_changed ||
f->toolbar_changed || f->windows_changed || f->size_slipped ||
- f->windows_structure_changed || f->glyphs_changed)
+ f->windows_structure_changed || f->glyphs_changed || f->subwindows_changed)
{
preempted = redisplay_frame (f, 0);
}
f->modeline_changed || f->point_changed || f->size_changed ||
f->toolbar_changed || f->windows_changed ||
f->windows_structure_changed ||
- f->glyphs_changed)
+ f->glyphs_changed || f->subwindows_changed)
{
preempted = redisplay_frame (f, 0);
}
d->faces_changed = 0;
d->frame_changed = 0;
d->glyphs_changed = 0;
+ d->subwindows_changed = 0;
d->icon_changed = 0;
d->menubar_changed = 0;
d->modeline_changed = 0;
!faces_changed && !frame_changed && !icon_changed &&
!menubar_changed && !modeline_changed && !point_changed &&
!size_changed && !toolbar_changed && !windows_changed &&
- !glyphs_changed &&
+ !glyphs_changed && !subwindows_changed &&
!windows_structure_changed && !disable_preemption &&
preemption_count < max_preempts)
goto done;
d->menubar_changed || d->modeline_changed || d->point_changed ||
d->size_changed || d->toolbar_changed || d->windows_changed ||
d->windows_structure_changed ||
- d->glyphs_changed)
+ d->glyphs_changed || d->subwindows_changed)
{
preempted = redisplay_device (d);
extents_changed = 0;
frame_changed = 0;
glyphs_changed = 0;
+ subwindows_changed = 0;
icon_changed = 0;
menubar_changed = 0;
modeline_changed = 0;
{
struct device *d = XDEVICE (XFRAME (w->frame)->device);
struct buffer *b = XBUFFER (w->buffer);
- /* Be careful in the order of these tests. The first clasue will
+ /* Be careful in the order of these tests. The first clause will
fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
- This can occur when the frame title is computed really early */
+ This can occur when the frame title is computed really early */
Bufpos pos =
((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
(w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
for (; gb < gb_last; gb++)
{
- if (!NILP (gb->glyph)) ((markobj) (gb->glyph));
- if (!NILP (gb->extent)) ((markobj) (gb->extent));
+ if (!NILP (gb->glyph))
+ markobj (gb->glyph);
+ if (!NILP (gb->extent))
+ markobj (gb->extent);
}
}
}
if (r->type == RUNE_DGLYPH)
{
if (!NILP (r->object.dglyph.glyph))
- ((markobj) (r->object.dglyph.glyph));
+ markobj (r->object.dglyph.glyph);
if (!NILP (r->object.dglyph.extent))
- ((markobj) (r->object.dglyph.extent));
+ markobj (r->object.dglyph.extent);
}
}
}
else
{
struct line_start_cache lsc;
-
+
lsc.start = dl->bufpos;
lsc.end = dl->end_bufpos;
lsc.height = dl->ascent + dl->descent;
size changes can cause text shifting. However, the extent
covering the region is constantly having its face set and
priority altered by the mouse code. This means that the line
- start cache is constanty being invalidated. This is bad
+ start cache is constantly being invalidated. This is bad
since the mouse code also triggers heavy usage of the cache.
Since it is an unlikely that f->extents being changed
indicates that the cache really needs to be updated and if it
/*
* Handle invisible text properly:
- * If the last line we're inserting has the same end as the
+ * If the last line we're inserting has the same end as the
* line before which it will be added, merge the two lines.
*/
if (Dynarr_length (cache) &&
d->pixel_to_glyph_cache.obj1 = *obj1; \
d->pixel_to_glyph_cache.obj2 = *obj2; \
d->pixel_to_glyph_cache.retval = position; \
- RETURN__ position; \
+ RETURN_SANS_WARNINGS position; \
} while (0)
/* Given x and y coordinates in pixels relative to a frame, return
{
if (WINDOWP (locale))
{
- struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (locale)));
- MARK_FRAME_GLYPHS_CHANGED (f);
+ MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
}
else if (FRAMEP (locale))
{
- struct frame *f = XFRAME (locale);
- MARK_FRAME_GLYPHS_CHANGED (f);
+ MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
}
else if (DEVICEP (locale))
{
Lisp_Object frmcons;
DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
- {
- struct frame *f = XFRAME (XCAR (frmcons));
- MARK_FRAME_GLYPHS_CHANGED (f);
- }
+ MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
}
else if (CONSOLEP (locale))
{
Lisp_Object frmcons, devcons;
CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
- {
- struct frame *f = XFRAME (XCAR (frmcons));
- MARK_FRAME_GLYPHS_CHANGED (f);
- }
+ MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
}
else /* global or buffer */
{
Lisp_Object frmcons, devcons, concons;
FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
- {
- struct frame *f = XFRAME (XCAR (frmcons));
- MARK_FRAME_GLYPHS_CHANGED (f);
- }
+ MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
}
}
Minimum pixel height for clipped bottom display line.
A clipped line shorter than this won't be displayed.
*/ ,
- redisplay_variable_changed);
+ redisplay_variable_changed);
vertical_clip = 5;
DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
Clipped glyphs shorter than this won't be displayed.
Only pixmap glyph instances are currently allowed to be clipped.
*/ ,
- redisplay_variable_changed);
+ redisplay_variable_changed);
horizontal_clip = 5;
DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
Marker for where to display an arrow on top of the buffer text.
This must be the beginning of a line in order to work.
See also `overlay-arrow-string'.
-*/ , redisplay_variable_changed);
+*/ ,
+ redisplay_variable_changed);
Voverlay_arrow_position = Qnil;
DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
String to display as an arrow. See also `overlay-arrow-position'.
*/ ,
- redisplay_variable_changed);
+ redisplay_variable_changed);
Voverlay_arrow_string = Qnil;
DEFVAR_INT ("scroll-step", &scroll_step /*
&truncate_partial_width_windows /*
*Non-nil means truncate lines in all windows less than full frame wide.
*/ ,
- redisplay_variable_changed);
+ redisplay_variable_changed);
truncate_partial_width_windows = 1;
DEFVAR_BOOL ("visible-bell", &visible_bell /*