qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs qe.h qe.c


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs qe.h qe.c
Date: Mon, 26 Dec 2016 08:57:36 -0500 (EST)

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        16/12/26 08:57:36

Modified files:
        .              : qe.h qe.c 

Log message:
        display: improve handling of very long lines
        - simplify the code
        - fix display of continuation lines when line numbers are visible

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.229&r2=1.230
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.c?cvsroot=qemacs&r1=1.238&r2=1.239

Patches:
Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.229
retrieving revision 1.230
diff -u -b -r1.229 -r1.230
--- qe.h        25 Dec 2016 10:51:14 -0000      1.229
+++ qe.h        26 Dec 2016 13:57:36 -0000      1.230
@@ -1142,10 +1142,10 @@
 /* contains all the information necessary to uniquely identify a line,
    to avoid displaying it */
 typedef struct QELineShadow {
-    short x_start;
+    unsigned int crc;
+    int x;
     short y;
     short height;
-    unsigned int crc;
 } QELineShadow;
 
 enum WrapType {
@@ -1609,9 +1609,9 @@
     short ascent;
     short descent;
     short style;      /* style index */
-    short line_index; /* index in line_buf */
+    short line_index; /* index into line_buf */
     short len;   /* number of glyphs */
-    short dummy;  /* align, must be assigned for CRC */
+    short dummy;      /* alignment, must be set for CRC */
 } TextFragment;
 
 #ifdef CONFIG_TINY
@@ -1637,11 +1637,14 @@
     int space_width;    /* width of space character */
     int tab_width;      /* width of tabulation */
     int x_disp;         /* starting x display */
+    int x_start;        /* start_x adjusted for RTL */
+    int x_line;         /* updated x position for line */
     int x;              /* current x position */
     int y;              /* current y position */
     int line_num;       /* current text line number */
     int cur_hex_mode;   /* true if current char is in hex mode */
     int hex_mode;       /* hex mode from edit_state, -1 if all chars wanted */
+    int line_numbers;   /* display line numbers if enough space */
     void *cursor_opaque;
     int (*cursor_func)(struct DisplayState *,
                        int offset1, int offset2, int line_num,

Index: qe.c
===================================================================
RCS file: /sources/qemacs/qemacs/qe.c,v
retrieving revision 1.238
retrieving revision 1.239
diff -u -b -r1.238 -r1.239
--- qe.c        26 Dec 2016 09:28:36 -0000      1.238
+++ qe.c        26 Dec 2016 13:57:36 -0000      1.239
@@ -943,6 +943,7 @@
     MoveContext *m = ds->cursor_opaque;
 
     if (line_num == m->yd) {
+        if (offset1 >= 0) {
         if (w < 0) {  /* for RTL glyphs */
             x += w;
             w = -w;
@@ -953,6 +954,7 @@
             m->xdmin = d;
             m->offsetd = offset1;
         }
+        }
         return 0;
     } else if (line_num > m->yd) {
         /* no need to explore more chars */
@@ -2924,6 +2926,13 @@
 {
     s->base = base;
     s->x = s->x_disp = s->edit_state->x_disp[base];
+    if (s->base == DIR_RTL) {
+        /* XXX: probably broken. bidir handling needs fixing */
+        s->x_start = s->edit_state->width - s->x;
+    } else {
+        s->x_start = s->x;
+    }
+    s->x_line = s->x_start;
     s->style = 0;
     s->last_style = 0;
     s->fragment_index = 0;
@@ -2960,10 +2969,10 @@
     /* select default values */
     get_style(e, &style, e->default_style);
     font = select_font(e->screen, style.font_style, style.font_size);
-    s->eol_width = max(glyph_width(e->screen, font, '/'),
-                       glyph_width(e->screen, font, '\\'));
-    s->eol_width = max(s->eol_width, glyph_width(e->screen, font, '$'));
     s->default_line_height = font->ascent + font->descent;
+    s->eol_width = max3(glyph_width(e->screen, font, '/'),
+                        glyph_width(e->screen, font, '\\'),
+                        glyph_width(e->screen, font, '$'));
     s->space_width = glyph_width(e->screen, font, ' ');
     s->tab_width = s->space_width * e->b->tab_width;
     s->width = e->width - s->eol_width;
@@ -2972,6 +2981,9 @@
     s->cur_hex_mode = 0;
     s->y = e->y_disp;
     s->line_num = 0;
+    s->line_numbers = e->line_numbers * s->space_width * 8;
+    if (s->line_numbers > s->width / 2)
+        s->line_numbers = 0;
     s->eol_reached = 0;
     s->eod = 0;
     display_bol(s);
@@ -3031,7 +3043,7 @@
 {
     EditState *e = s->edit_state;
     QEditScreen *screen = e->screen;
-    int level, pos, p, i, x_start, x, x1, y, baseline, line_height, 
max_descent;
+    int level, pos, p, i, x, x1, y, baseline, line_height, max_descent;
     TextFragment *frag;
     QEFont *font;
 
@@ -3039,10 +3051,11 @@
     baseline = 0;
     max_descent = 0;
     for (i = 0; i < nb_fragments; i++) {
-        if (fragments[i].ascent > baseline)
-            baseline = fragments[i].ascent;
-        if (fragments[i].descent > max_descent)
-            max_descent = fragments[i].descent;
+        frag = &fragments[i];
+        if (frag->ascent > baseline)
+            baseline = frag->ascent;
+        if (frag->descent > max_descent)
+            max_descent = frag->descent;
     }
     if (nb_fragments == 0) {
         /* if empty line, still needs a non zero line height */
@@ -3057,7 +3070,8 @@
         while (pos < nb_fragments) {
             if (fragments[pos].embedding_level >= level) {
                 /* find all chars >= level */
-                for (p = pos + 1; p < nb_fragments && 
fragments[p].embedding_level >= level; p++);
+                for (p = pos + 1; p < nb_fragments && 
fragments[p].embedding_level >= level; p++)
+                    continue;
                 reverse_fragments(fragments + pos, p - pos);
                 pos = p + 1;
             } else {
@@ -3066,12 +3080,6 @@
         }
     }
 
-    if (s->base == DIR_RTL) {
-        x_start = e->width - s->x;
-    } else {
-        x_start = s->x_disp;
-    }
-
     /* draw everything */
     if (s->do_disp == DISP_PRINT) {
         QEStyleDef style, default_style;
@@ -3091,39 +3099,35 @@
             memset(&e->line_shadow[n], 0xff,
                    LINE_SHADOW_INCR * sizeof(QELineShadow));
         }
-        /* XXX: incorrect for very long lines */
+        /* Use checksum based line cache to improve speed in graphics mode.
+         * XXX: overlong lines will fail the cache test
+         */
         ls = &e->line_shadow[s->line_num];
-        if (ls->y == s->y &&
-            ls->x_start == x_start &&
-            ls->height == line_height &&
-            ls->crc == crc) {
-            /* no display needed */
-        } else {
-#if 0
-            printf("old=%d %d %d %d\n",
-                   ls->y, ls->x_start, ls->height, ls->crc);
-            printf("cur=%d %d %d %d\n",
-                   s->y, x_start, line_height, crc);
-#endif
-            /* init line shadow */
+        if (ls->y != s->y || ls->x != s->x_line
+        ||  ls->height != line_height || ls->crc != crc) {
+            /* update values for the line cache */
             ls->y = s->y;
-            ls->x_start = x_start;
+            ls->x = s->x_line;
             ls->height = line_height;
             ls->crc = crc;
 
-            /* display ! */
-
+            /* display */
             get_style(e, &default_style, 0);
             x = e->xleft;
             y = e->ytop + s->y;
 
             /* first display background rectangles */
-            if (x_start > 0) {
-                fill_rectangle(screen, x, y,
-                               x_start, line_height,
+            /* XXX: should coalesce rectangles with identical style */
+            /* XXX: test is incorrect for subsequent flushes of very long 
lines */
+            if (s->x_line > 0) {
+                /* erase space before the line display, 
+                 * for example the column for line numbers 
+                 * on continuation lines.
+                 */
+                fill_rectangle(screen, x, y, s->x_line, line_height,
                                default_style.bg_color);
             }
-            x += x_start;
+            x += s->x_line;
             for (i = 0; i < nb_fragments; i++) {
                 frag = &fragments[i];
                 get_style(e, &style, frag->style);
@@ -3132,66 +3136,57 @@
                 x += frag->width;
             }
             x1 = e->xleft + s->width + s->eol_width;
-            if (x < x1) {
+            if (x < x1 && last != -1) {
                 fill_rectangle(screen, x, y, x1 - x, line_height,
                                default_style.bg_color);
             }
 
             /* then display text */
-            x = e->xleft;
-            if (x_start > 0) {
-                /* RTL eol mark */
-                if (last == 0 && s->base == DIR_RTL) {
-                    unsigned int markbuf[1] = { '/' };
+            x = e->xleft + s->x_line;
+            y += baseline;
 
-                    /* XXX: potential font metrics mismatch */
-                    font = select_font(screen,
-                                       default_style.font_style,
-                                       default_style.font_size);
-                    draw_text(screen, font, x, y + font->ascent,
-                              markbuf, 1, default_style.fg_color);
-                    release_font(screen, font);
-                }
-            }
-            x += x_start;
             for (i = 0; i < nb_fragments; i++) {
                 frag = &fragments[i];
                 get_style(e, &style, frag->style);
                 font = select_font(screen,
                                    style.font_style, style.font_size);
-                draw_text(screen, font, x, y + baseline,
+                draw_text(screen, font, x, y,
                           s->line_chars + frag->line_index,
                           frag->len, style.fg_color);
                 release_font(screen, font);
                 x += frag->width;
             }
-            x1 = e->xleft + s->width + s->eol_width;
-            if (x < x1) {
-                /* LTR eol mark */
-                if (last == 0 && s->base == DIR_LTR) {
-                    unsigned int markbuf[1] = { '\\' };
 
-                    /* XXX: potential font metrics mismatch */
+            if (last == 0) {
+                /* draw eol mark */
+                unsigned int markbuf[1];
+
+                markbuf[0] = '/';        /* RTL eol mark */
+                x = e->xleft;            /* displayed at the left border */
+                if (s->base == DIR_LTR) {
+                    markbuf[0] = '\\';   /* LTR eol mark */
+                    x += s->width;       /* displayed at the right border */
+                }
                     font = select_font(screen,
                                        default_style.font_style,
                                        default_style.font_size);
-                    draw_text(screen, font,
-                              e->xleft + s->width, y + font->ascent,
+                draw_text(screen, font, x, y,
                               markbuf, 1, default_style.fg_color);
                     release_font(screen, font);
                 }
             }
         }
-    }
 
     /* call cursor callback */
     if (s->cursor_func) {
-        x = x_start;
+        x = s->x_line;
+        y = s->y;
+
         /* RTL eol cursor check (probably incorrect) */
         if (offset1 >= 0 && offset2 >= 0 &&
             s->base == DIR_RTL &&
             s->cursor_func(s, offset1, offset2, s->line_num,
-                           x, s->y, -s->eol_width, line_height, e->hex_mode)) {
+                           x, y, -s->eol_width, line_height, e->hex_mode)) {
             s->eod = 1;
         }
 
@@ -3209,11 +3204,11 @@
                     _offset1 >= 0 && _offset2 >= 0) {
                     if (s->base == DIR_RTL) {
                         if (s->cursor_func(s, _offset1, _offset2, s->line_num,
-                                           x + w, s->y, -w, line_height, 
hex_mode))
+                                           x + w, y, -w, line_height, 
hex_mode))
                             s->eod = 1;
                     } else {
                         if (s->cursor_func(s, _offset1, _offset2, s->line_num,
-                                           x, s->y, w, line_height, hex_mode))
+                                           x, y, w, line_height, hex_mode))
                             s->eod = 1;
                     }
                 }
@@ -3225,16 +3220,21 @@
         if (offset1 >= 0 && offset2 >= 0 &&
             s->base == DIR_LTR &&
             s->cursor_func(s, offset1, offset2, s->line_num,
-                           x, s->y, s->eol_width, line_height, e->hex_mode)) {
+                           x, y, s->eol_width, line_height, e->hex_mode)) {
             s->eod = 1;
         }
+        s->x_line = x;
     }
 #if 0
     printf("y=%d line_num=%d line_height=%d baseline=%d\n",
            s->y, s->line_num, line_height, baseline);
 #endif
+    if (last != -1) {
+        /* bump to next line */
+        s->x_line = s->x_start;
     s->y += line_height;
     s->line_num++;
+    }
 }
 
 /* keep 'n' line chars at the start of the line */
@@ -3286,8 +3286,13 @@
         return;
 
     if (s->nb_fragments >= MAX_SCREEN_WIDTH ||
-        s->line_index + s->fragment_index > MAX_SCREEN_WIDTH)
-        goto the_end;
+        s->line_index + s->fragment_index > MAX_SCREEN_WIDTH) {
+        /* too many fragments on the same line, flush and stay on the line */
+        flush_line(s, s->fragments, s->nb_fragments, -1, -1, -1);
+        s->nb_fragments = 0;
+        s->line_index = 0;
+        s->word_index = 0;
+    }
 
     /* update word start index if needed */
     if (s->nb_fragments >= 1 && s->last_word_space != s->last_space) {
@@ -3415,10 +3420,11 @@
             /* move the remaining fragment to next line */
             s->nb_fragments = 0;
             s->x = 0;
-            if (s->edit_state->line_numbers) {
-                /* should skip line number column if present */
-                //s->x = s->space_width * 8;
-            }
+
+            /* skip line number column if present */
+            s->x += s->line_numbers;
+            s->x_line += s->line_numbers;
+
             if (len1 > 0) {
                 memmove(s->fragments, frag, sizeof(TextFragment));
                 frag = s->fragments;
@@ -3444,10 +3450,11 @@
                     (s->nb_fragments - s->word_index) * sizeof(TextFragment));
             s->nb_fragments -= s->word_index;
             s->x = 0;
-            if (s->edit_state->line_numbers) {
-                /* should skip line number column if present */
-                //s->x = s->space_width * 8;
-            }
+
+            /* skip line number column if present */
+            s->x += s->line_numbers;
+            s->x_line += s->line_numbers;
+
             for (i = 0; i < s->nb_fragments; i++) {
                 s->fragments[i].line_index -= index;
                 s->x += s->fragments[i].width;
@@ -3457,7 +3464,6 @@
         }
         break;
     }
- the_end:
     s->fragment_index = 0;
 }
 
@@ -3916,7 +3922,7 @@
     display_bol_bidir(ds, base, embedding_max_level);
 
     /* line numbers */
-    if (s->line_numbers) {
+    if (ds->line_numbers) {
         ds->style = QE_STYLE_COMMENT;
         display_printf(ds, -1, -1, "%6d  ", line_num + 1);
         ds->style = 0;
@@ -4029,6 +4035,8 @@
                 display_char_bidir(ds, offset0, offset, embedding_level, c);
             }
             char_index++;
+            //if (ds->y >= s->height && ds->eod)  //@@@ causes bug
+            //    break;
         }
     }
     return offset;
@@ -4041,10 +4049,16 @@
     DisplayState ds1, *ds = &ds1;
     int x1, xc, yc, offset, bottom = -1;
 
+    if (s->offset == 0) {
+        s->offset_top = s->y_disp = s->x_disp[0] = s->x_disp[1] = 0;
+    }
+
     /* if the cursor is before the top of the display zone, we must
        resync backward */
     if (s->offset < s->offset_top) {
         s->offset_top = s->mode->backward_offset(s, s->offset);
+        ///XXXX probably too strong, should keep cursor close to top
+        //s->y_disp = 0;  //@@@?
     }
 
     if (s->display_invalid) {
@@ -4100,12 +4114,12 @@
         s->offset_top = offset;
         s->offset_bottom = bottom;
         /* adjust y_disp so that the cursor is at the bottom of the screen */
-        s->y_disp = s->height - ds->y;
+        s->y_disp = min(s->height - ds->y, 0);
         display_close(ds);
     } else {
         yc = m->yc;
         if (yc < 0) {
-            s->y_disp -= yc;
+            s->y_disp += -yc;
         } else
         if ((yc + m->cursor_height) > s->height) {
             s->y_disp += s->height - (yc + m->cursor_height);
@@ -4116,6 +4130,32 @@
        between rtl and ltr margins. We try to have x_disp == 0 as much
        as possible */
     if (s->wrap == WRAP_TRUNCATE) {
+#if 1  //@@@?
+        //put_status(s, "|xc=%d x_disp+%d", m->xc, s->x_disp[m->basec]);
+        if (m->xc != NO_CURSOR) {
+            xc = m->xc;
+            x1 = xc - s->x_disp[m->basec];
+            // Do not snap x_disp to 0 to allow scroll_left()
+            //if (x1 >= 0 && x1 < ds->width) {
+            //    s->x_disp[m->basec] = 0;
+            //} else
+            if (xc < 0) {
+                /* XXX: refering to ds after display_close(ds) */
+                if (x1 >= 0 && x1 < ds->width) {
+                    /* snap back to left margin */
+                    s->x_disp[m->basec] = 0;
+                } else {
+                    /* XXX: should center screen horizontally? */
+                    /* XXX: maybe scroll horizontally by a quarter screen? */
+                    s->x_disp[m->basec] += -xc;
+                }
+            } else
+            if (xc + m->cursor_width >= ds->width) {
+                /* XXX: maybe scroll horizontally by a quarter screen? */
+                s->x_disp[m->basec] += ds->width - (xc + m->cursor_width);
+            }
+        }
+#else
         xc = m->xc;
         x1 = xc - s->x_disp[m->basec];
         if (x1 >= 0 && x1 < ds->width - ds->eol_width) {
@@ -4127,6 +4167,7 @@
         if (xc >= ds->width) {
             s->x_disp[m->basec] += ds->width - xc - ds->eol_width;
         }
+#endif
     } else {
         s->x_disp[0] = 0;
         s->x_disp[1] = 0;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]