Mercurial > hg > xemacs-beta
diff src/redisplay.c @ 819:6504113e7c2d
[xemacs-hg @ 2002-04-25 18:03:23 by andyp]
sync up windows branch from 21.4
author | andyp |
---|---|
date | Thu, 25 Apr 2002 18:04:24 +0000 |
parents | a5954632b187 |
children | 6728e641994e |
line wrap: on
line diff
--- a/src/redisplay.c Thu Apr 25 06:09:18 2002 +0000 +++ b/src/redisplay.c Thu Apr 25 18:04:24 2002 +0000 @@ -145,9 +145,9 @@ to be skipped before anything is displayed. */ Bytebpos bi_start_col_enabled; int start_col_xoffset; /* Number of pixels that still need to - be skipped. This is used for - horizontal scrolling of glyphs, where we want - to be able to scroll over part of the glyph. */ + be skipped. This is used for + horizontal scrolling of glyphs, where we want + to be able to scroll over part of the glyph. */ int hscroll_glyph_width_adjust; /* how much the width of the hscroll glyph differs from space_width (w). @@ -161,18 +161,20 @@ struct extent_fragment *ef; face_index findex; - /* The height of a pixmap may either be predetermined if the user - has set a baseline value, or it may be dependent on whatever the - line ascent and descent values end up being, based just on font - information. In the first case we can immediately update the - values, thus their inclusion here. In the last case we cannot - determine the actual contribution to the line height until we - have finished laying out all text on the line. Thus we propagate - the max height of such pixmaps and do a final calculation after - all text has been added to the line. */ + /* The height of a pixmap may either be predetermined if the user has set a + baseline value, or it may be dependent on whatever the line ascent and + descent values end up being, based just on font and pixmap-ascent + information. In the first case we can immediately update the values, thus + their inclusion here. In the last case we cannot determine the actual + contribution to the line height until we have finished laying out all text + on the line. Thus we propagate the max height of such pixmaps and do a + final calculation (in calculate_baseline()) after all text has been added + to the line. */ int new_ascent; int new_descent; int max_pixmap_height; + int need_baseline_computation; + int end_glyph_width; /* Well, it is the kitchen sink after all ... */ Lisp_Object result_str; /* String where we put the result of generating a formatted string in the modeline. */ @@ -190,15 +192,24 @@ PROP_STRING, PROP_CHAR, PROP_MINIBUF_PROMPT, - PROP_BLANK + PROP_BLANK, + PROP_GLYPH }; /* Data that should be propagated to the next line. Either a single - Emchar or a string of Intbyte's. + Emchar, a string of Intbyte's or a glyph. The actual data that is propagated ends up as a Dynarr of these blocks. + prop_blocks are used to indicate that data that was supposed to go + on the previous line couldn't actually be displayed. Generally this + shouldn't happen if we are clipping the end of lines. If we are + wrapping then we need to display the propagation data before moving + on. Its questionable whether we should wrap or clip glyphs in this + instance. Most e-lisp relies on clipping so we preserve this + behavior. + #### It's unclean that both Emchars and Intbytes are here. */ @@ -227,6 +238,14 @@ int width; face_index findex; } p_blank; + + struct + { + /* Not used as yet, but could be used to wrap rather than clip glyphs. */ + int width; + Lisp_Object glyph; + } p_glyph; + } data; }; @@ -263,6 +282,9 @@ static void update_line_start_cache (struct window *w, Charbpos from, Charbpos to, Charbpos point, int no_regen); static int point_visible (struct window *w, Charbpos point, int type); +static void calculate_yoffset (struct display_line *dl, + struct display_block *fixup); +static void calculate_baseline (pos_data *data); static void sledgehammer_check_redisplay_structs (void); @@ -680,6 +702,108 @@ return bounds; } +/* This takes a display_block and its containing line and corrects the yoffset + of each glyph in the block to cater for the ascent of the line as a + whole. Must be called *after* the line-ascent is known! */ + +static void +calculate_yoffset (struct display_line *dl, struct display_block *fixup) +{ + int i; + for (i=0; i<Dynarr_length (fixup->runes); i++) + { + struct rune *r = Dynarr_atp (fixup->runes,i); + if (r->type == RUNE_DGLYPH) + { + if (r->object.dglyph.ascent < dl->ascent) + r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + + r->object.dglyph.descent; + } + } +} + +/* Calculate the textual baseline (the ascent and descent values for the + display_line as a whole). + + If the baseline is completely blank, or contains no manually positioned + glyphs, then the textual baseline is simply the baseline of the default font. + (The `contains no manually positioned glyphs' part is actually done for + us by `add_emchar_rune'.) + + If the baseline contains pixmaps, and they're all manually positioned, then + the textual baseline location is constrained that way, and we need do no + work. + + If the baseline contains pixmaps, and at least one is automatically + positioned, then the textual ascent is the largest ascent on the line, and + the textual descent is the largest descent (which is how things are set up at + entry to this function anyway): except that if the max_ascent + max_descent + is too small for the height of the line (say you've adjusted the baseline of + a short glyph, and there's a tall one next to it), then take the ascent and + descent for the line individually from the largest of the explicitly set + ascent/descent, and the rescaled ascent/descent of the default font, scaled + such that the largest glyph will fit. + + This means that if you have a short glyph (but taller than the default + font's descent) forced right under the baseline, and a really tall + automatically positioned glyph, that the descent for the line is just big + enough for the manually positioned short glyph, and the tall one uses as + much of that space as the default font would were it as tall as the tall + glyph; but that the ascent is big enough for the tall glyph to fit. + + This behaviour means that under no circumstances will changing the baseline + of a short glyph cause a tall glyph to move around; nor will it move the + textual baseline more than necessary. (Changing a tall glyph's baseline + might move the text's baseline arbitrarily, of course.) */ + +static void +calculate_baseline (pos_data *data) +{ + /* Blank line: baseline is default font's baseline. */ + + if (!data->new_ascent && !data->new_descent) + { + /* We've got a blank line so initialize these values from the default + face. */ + default_face_font_info (data->window, &data->new_ascent, + &data->new_descent, 0, 0, 0); + } + + /* No automatically positioned glyphs? Return at once. */ + if (!data->need_baseline_computation) + return; + + /* Is the tallest glyph on the line automatically positioned? + If it's manually positioned, or it's automatically positioned + and there's enough room for it anyway, we need do no more work. */ + if (data->max_pixmap_height > data->new_ascent + data->new_descent) + { + int default_font_ascent, default_font_descent, default_font_height; + int scaled_default_font_ascent, scaled_default_font_descent; + + default_face_font_info (data->window, &default_font_ascent, + &default_font_descent, &default_font_height, + 0, 0); + + scaled_default_font_ascent = data->max_pixmap_height * + default_font_ascent / default_font_height; + + data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); + + /* The ascent may have expanded now. Do we still need to grow the descent, + or are things big enough? + + The +1 caters for the baseline row itself. */ + if (data->max_pixmap_height > data->new_ascent + data->new_descent) + { + scaled_default_font_descent = (data->max_pixmap_height * + default_font_descent / default_font_height) + 1; + + data->new_descent = max (data->new_descent, scaled_default_font_descent); + } + } +} + /* Given a display line and a starting position, ensure that the contents of the display line accurately represent the visual representation of the buffer contents starting from the given @@ -875,11 +999,13 @@ } else data->last_char_width = -1; + if (!no_contribute_to_line_height) { data->new_ascent = max (data->new_ascent, (int) fi->ascent); data->new_descent = max (data->new_descent, (int) fi->descent); } + data->last_charset = charset; data->last_findex = data->findex; } @@ -1130,12 +1256,11 @@ static prop_block_dynarr * add_octal_runes (pos_data *data) { - prop_block_dynarr *prop, *add_failed; + prop_block_dynarr *add_failed, *prop = 0; Emchar orig_char = data->ch; int orig_cursor_type = data->cursor_type; /* Initialize */ - prop = NULL; add_failed = NULL; if (data->start_col) @@ -1195,7 +1320,7 @@ ADD_NEXT_OCTAL_RUNE_CHAR; data->cursor_type = orig_cursor_type; - return prop; + return NULL; } #undef ADD_NEXT_OCTAL_RUNE_CHAR @@ -1568,6 +1693,7 @@ Lisp_Object face; Lisp_Object instance; face_index findex; + prop_block_dynarr *retval = 0; if (cachel) width = cachel->width; @@ -1579,7 +1705,6 @@ if (data->start_col || data->start_col_xoffset) { - prop_block_dynarr *retval; int glyph_char_width = width / space_width (w); /* If we still have not fully scrolled horizontally after @@ -1615,17 +1740,41 @@ if (data->pixpos + width > data->max_pixpos) { /* If this is the first object we are attempting to add to - the line then we ignore the horizontal_clip threshold. - Otherwise we will loop until the bottom of the window - continually failing to add this glyph because it is wider - than the window. We could alternatively just completely - ignore the glyph and proceed from there but I think that - this is a better solution. */ + the line then we ignore the horizontal_clip threshold. + Otherwise we will loop until the bottom of the window + continually failing to add this glyph because it is wider + than the window. We could alternatively just completely + ignore the glyph and proceed from there but I think that + this is a better solution. + + This does, however, create a different problem in that we + can end up adding the object to every single line, never + getting any further - for instance an extent with a long + start-glyph that covers multitple following + characters. */ if (Dynarr_length (data->db->runes) && data->max_pixpos - data->pixpos < horizontal_clip) return ADD_FAILED; - else + else { + struct prop_block pb; + + /* We need to account for the width of the end-of-line + glyph if there is nothing more in the line to display, + since we will not display it in this instance. It seems + kind of gross doing it here, but otherwise we have to + search the runes in create_text_block(). */ + if (data->ch == '\n') + data->max_pixpos += data->end_glyph_width; width = data->max_pixpos - data->pixpos; + /* Add the glyph we are displaying, but clipping, to the + propagation data so that we don't try and do it + again. */ + retval = Dynarr_new (prop_block); + pb.type = PROP_GLYPH; + pb.data.p_glyph.glyph = gb->glyph; + pb.data.p_glyph.width = width; + Dynarr_add (retval, pb); + } } if (cachel) @@ -1641,6 +1790,8 @@ baseline = glyph_baseline (gb->glyph, data->window); + rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ + if (glyph_contrib_p (gb->glyph, data->window)) { /* A pixmap that has not had a baseline explicitly set. Its @@ -1648,6 +1799,7 @@ if (NILP (baseline)) { int height = ascent + descent; + data->need_baseline_computation = 1; data->max_pixmap_height = max (data->max_pixmap_height, height); } @@ -1670,6 +1822,9 @@ data->new_ascent = max (data->new_ascent, pix_ascent); data->new_descent = max (data->new_descent, pix_descent); + data->max_pixmap_height = max (data->max_pixmap_height, height); + + rb.object.dglyph.descent = pix_descent; } /* Otherwise something is screwed up. */ @@ -1701,7 +1856,7 @@ data->findex = orig_findex; data->bi_charbpos = orig_charbpos; data->bi_start_col_enabled = orig_start_col_enabled; - return NULL; + return retval; } rb.findex = findex; @@ -1718,6 +1873,9 @@ rb.object.dglyph.glyph = gb->glyph; rb.object.dglyph.extent = gb->extent; rb.object.dglyph.xoffset = xoffset; + rb.object.dglyph.ascent = ascent; + rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has + a normal (textual) baseline. */ if (allow_cursor) { @@ -1753,7 +1911,7 @@ Dynarr_add (data->db->runes, rb); data->pixpos += width; - return NULL; + return retval; } else { @@ -1782,7 +1940,7 @@ abort (); /* there are no unknown types */ } - return NULL; /* shut up compiler */ + return NULL; } /* Add all glyphs at position POS_TYPE that are contained in the given @@ -1842,7 +2000,6 @@ is_surrogate_for_selected_frame (f)); int truncate_win = window_truncation_on (w); - int end_glyph_width; /* If the buffer's value of selective_display is an integer then only lines that start with less than selective_display columns of @@ -1940,10 +2097,10 @@ glyph. Save the width of the end glyph for later use. */ data.max_pixpos = dl->bounds.right_in; if (truncate_win) - end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); + data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); else - end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); - data.max_pixpos -= end_glyph_width; + data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); + data.max_pixpos -= data.end_glyph_width; if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) { @@ -2036,10 +2193,25 @@ /* Check for face changes. */ if (initial || (!no_more_frags && data.bi_charbpos == data.ef->end)) { + Lisp_Object last_glyph = Qnil; + + /* Deal with glyphs that we have already displayed. The + theory is that if we end up with a PROP_GLYPH in the + propagation data then we are clipping the glyph and there + can be no propagation data before that point. The theory + works because we always recalculate the extent-fragments + for propagated data, we never actually propagate the + fragments that still need to be displayed. */ + if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) + { + last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph; + Dynarr_free (*prop); + *prop = 0; + } /* Now compute the face and begin/end-glyph information. */ data.findex = /* Remember that the extent-fragment routines deal in Bytebpos's. */ - extent_fragment_update (w, data.ef, data.bi_charbpos); + extent_fragment_update (w, data.ef, data.bi_charbpos, last_glyph); get_display_tables (w, data.findex, &face_dt, &window_dt); @@ -2109,9 +2281,9 @@ } /* If there is propagation data, then it represents the current - buffer position being displayed. Add them and advance the - position counter. This might also add the minibuffer - prompt. */ + buffer position being displayed. Add them and advance the + position counter. This might also add the minibuffer + prompt. */ else if (*prop) { dl->used_prop_data = 1; @@ -2133,19 +2305,59 @@ here rather than doing them at the end of handling the previous run so that glyphs at the beginning and end of a line are handled correctly. */ - else if (Dynarr_length (data.ef->end_glyphs) > 0) - { - *prop = add_glyph_runes (&data, END_GLYPHS); - if (*prop) - goto done; - } - - /* If there are begin glyphs, add them to the line. */ - else if (Dynarr_length (data.ef->begin_glyphs) > 0) - { - *prop = add_glyph_runes (&data, BEGIN_GLYPHS); - if (*prop) - goto done; + else if (Dynarr_length (data.ef->end_glyphs) > 0 + || Dynarr_length (data.ef->begin_glyphs) > 0) + { + glyph_block_dynarr* tmpglyphs = 0; + /* #### I think this is safe, but could be wrong. */ + data.ch = BI_BUF_FETCH_CHAR (b, data.bi_charbpos); + + if (Dynarr_length (data.ef->end_glyphs) > 0) + { + *prop = add_glyph_runes (&data, END_GLYPHS); + tmpglyphs = data.ef->end_glyphs; + } + + /* If there are begin glyphs, add them to the line. */ + if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) + { + *prop = add_glyph_runes (&data, BEGIN_GLYPHS); + tmpglyphs = data.ef->begin_glyphs; + } + + if (*prop) + { + /* If we just clipped a glyph and we are at the end of a + line and there are more glyphs to display then do + appropriate processing to not get a continuation + glyph. */ + if (*prop != ADD_FAILED + && Dynarr_atp (*prop, 0)->type == PROP_GLYPH + && data.ch == '\n') + { + /* If there are no more glyphs then do the normal + processing. + + #### This doesn't actually work if the same glyph is + present more than once in the block. To solve + this we would have to carry the index around + which might be problematic since the fragment is + recalculated for each line. */ + if (EQ (Dynarr_end (tmpglyphs)->glyph, + Dynarr_atp (*prop, 0)->data.p_glyph.glyph)) + { + Dynarr_free (*prop); + *prop = 0; + } + else { + data.blank_width = DEVMETH (d, eol_cursor_width, ()); + add_emchar_rune (&data); /* discard prop data. */ + goto done; + } + } + else + goto done; + } } /* If at end-of-buffer, we've already processed begin and @@ -2179,7 +2391,7 @@ /* We aren't going to be adding an end glyph so give its space back in order to make sure that the cursor can fit. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; if (selective > 0 && (bi_spaces_at_point @@ -2260,7 +2472,7 @@ /* We won't be adding a truncation or continuation glyph so give up the room allocated for them. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; if (!NILP (b->selective_display_ellipses)) { @@ -2469,7 +2681,7 @@ for the next newline. We also add the end-of-line glyph which we know will fit because we adjusted the right border before we starting laying out the line. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; data.findex = DEFAULT_INDEX; gb.extent = Qnil; @@ -2604,26 +2816,7 @@ else db->end_pos = dl->bounds.right_white; - /* update line height parameters */ - if (!data.new_ascent && !data.new_descent) - { - /* We've got a blank line so initialize these values from the default - face. */ - default_face_font_info (data.window, &data.new_ascent, - &data.new_descent, 0, 0, 0); - } - - if (data.max_pixmap_height) - { - int height = data.new_ascent + data.new_descent; - int pix_ascent, pix_descent; - - pix_descent = data.max_pixmap_height * data.new_descent / height; - pix_ascent = data.max_pixmap_height - pix_descent; - - data.new_ascent = max (data.new_ascent, pix_ascent); - data.new_descent = max (data.new_descent, pix_descent); - } + calculate_baseline (&data); dl->ascent = data.new_ascent; dl->descent = data.new_descent; @@ -2641,6 +2834,8 @@ dl->descent = descent; } + calculate_yoffset (dl, db); + dl->cursor_elt = data.cursor_x; /* #### lossage lossage lossage! Fix this shit! */ if (data.bi_charbpos > BI_BUF_ZV (b)) @@ -2729,14 +2924,15 @@ gb.extent = Qnil; add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); } - + if (data.max_pixmap_height) { int height = data.new_ascent + data.new_descent; int pix_ascent, pix_descent; - + pix_descent = data.max_pixmap_height * data.new_descent / height; pix_ascent = data.max_pixmap_height - pix_descent; + calculate_baseline (&data); data.new_ascent = max (data.new_ascent, pix_ascent); data.new_descent = max (data.new_descent, pix_descent); @@ -2748,6 +2944,8 @@ data.db->start_pos = dl->bounds.left_in; data.db->end_pos = data.pixpos; + calculate_yoffset (dl, data.db); + return data.pixpos - dl->bounds.left_in; } @@ -2819,20 +3017,13 @@ (reverse ? elt-- : elt++); } - if (data.max_pixmap_height) - { - int height = data.new_ascent + data.new_descent; - int pix_ascent, pix_descent; - - pix_descent = data.max_pixmap_height * data.new_descent / height; - pix_ascent = data.max_pixmap_height - pix_descent; - data.new_ascent = max (data.new_ascent, pix_ascent); - data.new_descent = max (data.new_descent, pix_descent); - } + calculate_baseline (&data); dl->ascent = data.new_ascent; dl->descent = data.new_descent; + calculate_yoffset (dl, data.db); + return data.pixpos; } @@ -4269,9 +4460,9 @@ /***************************************************************************/ -/* */ -/* displayable string routines */ -/* */ +/* */ +/* displayable string routines */ +/* */ /***************************************************************************/ /* Given a position for a string in a window, ensure that the given @@ -4312,7 +4503,6 @@ pos_data data; int truncate_win = b ? window_truncation_on (w) : 0; - int end_glyph_width = 0; /* We're going to ditch selective display for static text, it's an FSF thing and invisible extents are the way to go here. @@ -4420,13 +4610,7 @@ /* Set the right boundary adjusting it to take into account any end glyph. Save the width of the end glyph for later use. */ data.max_pixpos = dl->bounds.right_in; -#if 0 - if (truncate_win) - end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); - else - end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); -#endif - data.max_pixpos -= end_glyph_width; + data.max_pixpos -= data.end_glyph_width; data.cursor_type = NO_CURSOR; data.cursor_x = -1; @@ -4482,11 +4666,19 @@ /* Check for face changes. */ if (initial || (!no_more_frags && data.bi_charbpos == data.ef->end)) { + Lisp_Object last_glyph = Qnil; + /* Deal with clipped glyphs that we have already displayed. */ + if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) + { + last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph; + Dynarr_free (*prop); + *prop = 0; + } /* Now compute the face and begin/end-glyph information. */ data.findex = /* Remember that the extent-fragment routines deal in Bytebpos's. */ - extent_fragment_update (w, data.ef, data.bi_charbpos); + extent_fragment_update (w, data.ef, data.bi_charbpos, last_glyph); /* This is somewhat cheesy but the alternative is to propagate default_face into extent_fragment_update. */ if (data.findex == DEFAULT_INDEX) @@ -4578,17 +4770,23 @@ a line are handled correctly. */ else if (Dynarr_length (data.ef->end_glyphs) > 0) { + data.ch = XSTRING_CHAR (disp_string, data.bi_charbpos); *prop = add_glyph_runes (&data, END_GLYPHS); - if (*prop) + + if (*prop) { goto done; + } } /* If there are begin glyphs, add them to the line. */ else if (Dynarr_length (data.ef->begin_glyphs) > 0) { + data.ch = XSTRING_CHAR (disp_string, data.bi_charbpos); *prop = add_glyph_runes (&data, BEGIN_GLYPHS); - if (*prop) + + if (*prop) { goto done; + } } /* If at end-of-buffer, we've already processed begin and @@ -4622,7 +4820,7 @@ /* We aren't going to be adding an end glyph so give its space back in order to make sure that the cursor can fit. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; goto done; } @@ -4664,7 +4862,7 @@ *prop = add_blank_rune (&data, w, char_tab_width); /* add_blank_rune is only supposed to be called with - sizes guaranteed to fit in the available space. */ + sizes guaranteed to fit in the available space. */ assert (!(*prop)); if (prop_width) @@ -4720,7 +4918,7 @@ } } -done: + done: /* Determine the starting point of the next line if we did not hit the end of the buffer. */ @@ -4753,7 +4951,7 @@ for the next newline. We also add the end-of-line glyph which we know will fit because we adjusted the right border before we starting laying out the line. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; data.findex = default_face; gb.extent = Qnil; @@ -4782,7 +4980,7 @@ cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); } - if (end_glyph_width) + if (data.end_glyph_width) add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); if (truncate_win && data.bi_charbpos == bi_string_zv) @@ -4862,26 +5060,7 @@ else db->end_pos = dl->bounds.right_white; - /* update line height parameters */ - if (!data.new_ascent && !data.new_descent) - { - /* We've got a blank line so initialize these values from the default - face. */ - default_face_font_info (data.window, &data.new_ascent, - &data.new_descent, 0, 0, 0); - } - - if (data.max_pixmap_height) - { - int height = data.new_ascent + data.new_descent; - int pix_ascent, pix_descent; - - pix_descent = data.max_pixmap_height * data.new_descent / height; - pix_ascent = data.max_pixmap_height - pix_descent; - - data.new_ascent = max (data.new_ascent, pix_ascent); - data.new_descent = max (data.new_descent, pix_descent); - } + calculate_baseline (&data); dl->ascent = data.new_ascent; dl->descent = data.new_descent; @@ -4899,6 +5078,8 @@ dl->descent = descent; } + calculate_yoffset (dl, db); + dl->cursor_elt = data.cursor_x; /* #### lossage lossage lossage! Fix this shit! */ if (data.bi_charbpos > bi_string_zv)