patch 9.0.0438: cannot put virtual text above a line v9.0.0438
authorBram Moolenaar <Bram@vim.org>
Sat, 10 Sep 2022 19:00:56 +0000 (20:00 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 10 Sep 2022 19:00:56 +0000 (20:00 +0100)
Problem:    Cannot put virtual text above a line.
Solution:   Add the "above" value for "text_align".

runtime/doc/textprop.txt
src/charset.c
src/drawline.c
src/misc2.c
src/move.c
src/proto/charset.pro
src/structs.h
src/testdir/dumps/Test_prop_with_text_above_1.dump [new file with mode: 0644]
src/testdir/test_textprop.vim
src/textprop.c
src/version.c

index 996cdd19786d13fcc21d38ce8666f177ade9b49e..8d7c0ecf3994fc0d953b518481f200dad060dcf5 100644 (file)
@@ -153,6 +153,7 @@ prop_add({lnum}, {col}, {props})
                                           the text wraps to the next screen
                                           line)
                                   below   in the next screen line
+                                  above   just above the line
                                When omitted "after" is used.  Only one
                                "right" property can fit in each line, if
                                there are two ore more these will go in a
index d26a696c740a04b94c7f976d8aa2b2bd74db48e6..acf60999db91ee26b00a44fd50bd71507dd8102a 100644 (file)
@@ -1069,40 +1069,6 @@ lbr_chartabsize_adv(chartabsize_T *cts)
     return retval;
 }
 
-#if defined(FEAT_PROP_POPUP) || defined(PROTO)
-/*
- * Return the cell size of virtual text after truncation.
- */
-    int
-textprop_size_after_trunc(
-       win_T   *wp,
-       int     below,
-       int     added,
-       char_u  *text,
-       int     *n_used_ptr)
-{
-    int        space = below ? wp->w_width : added;
-    int len = (int)STRLEN(text);
-    int strsize = 0;
-    int n_used;
-
-    // if the remaining size is to small wrap
-    // anyway and use the next line
-    if (space < PROP_TEXT_MIN_CELLS)
-       space += wp->w_width;
-    for (n_used = 0; n_used < len; n_used += (*mb_ptr2len)(text + n_used))
-    {
-       int clen = ptr2cells(text + n_used);
-
-       if (strsize + clen > space)
-           break;
-       strsize += clen;
-    }
-    *n_used_ptr = n_used;
-    return strsize;
-}
-#endif
-
 /*
  * Return the screen size of the character indicated by "cts".
  * "cts->cts_cur_text_width" is set to the extra size for a text property that
@@ -1142,6 +1108,7 @@ win_lbr_chartabsize(
 
 #if defined(FEAT_PROP_POPUP)
     cts->cts_cur_text_width = 0;
+    cts->cts_first_char = 0;
 #endif
 
 #if defined(FEAT_LINEBREAK) || defined(FEAT_PROP_POPUP)
@@ -1194,9 +1161,12 @@ win_lbr_chartabsize(
            if (tp->tp_id < 0
                    && ((tp->tp_col - 1 >= col
                                             && tp->tp_col - 1 < col + charlen)
-                      || (tp->tp_col == MAXCOL && (s[0] == NUL || s[1] == NUL)
-                                                  && cts->cts_with_trailing))
-                   && -tp->tp_id - 1 < gap->ga_len)
+                      || (tp->tp_col == MAXCOL
+                          && ((tp->tp_flags & TP_FLAG_ALIGN_ABOVE)
+                               ? col == 0
+                               : (s[0] == NUL || s[1] == NUL)
+                                                 && cts->cts_with_trailing)))
+                   && tp->tp_id - 1 < gap->ga_len)
            {
                char_u *p = ((char_u **)gap->ga_data)[-tp->tp_id - 1];
 
@@ -1218,6 +1188,8 @@ win_lbr_chartabsize(
                    else
                        cells = vim_strsize(p);
                    cts->cts_cur_text_width += cells;
+                   if (tp->tp_flags & TP_FLAG_ALIGN_ABOVE)
+                       cts->cts_first_char += cells;
                    cts->cts_start_incl = tp->tp_flags & TP_FLAG_START_INCL;
                    size += cells;
                    if (*s == TAB)
@@ -1564,6 +1536,11 @@ getvcol(
 #endif
                break;
            }
+#ifdef FEAT_PROP_POPUP
+           if (cursor == &wp->w_virtcol && cts.cts_ptr == cts.cts_line)
+               // do not count the virtual text above for w_curswant
+               wp->w_virtcol_first_char = cts.cts_first_char;
+#endif
 
            if (posptr != NULL && cts.cts_ptr >= posptr)
                // character at pos->col
index 6c298b6f481562ceea8febe8eb1a47854147839e..56d42e2a7fb838c17e21913b6002580f69f97f39 100644 (file)
@@ -278,6 +278,38 @@ get_sign_display_info(
 #endif
 
 #if defined(FEAT_PROP_POPUP) || defined(PROTO)
+/*
+ * Return the cell size of virtual text after truncation.
+ */
+    static int
+textprop_size_after_trunc(
+       win_T   *wp,
+       int     flags,      // TP_FLAG_ALIGN_*
+       int     added,
+       char_u  *text,
+       int     *n_used_ptr)
+{
+    int        space = (flags & (TP_FLAG_ALIGN_BELOW | TP_FLAG_ALIGN_ABOVE))
+                                                        ? wp->w_width : added;
+    int len = (int)STRLEN(text);
+    int strsize = 0;
+    int n_used;
+
+    // if the remaining size is to small wrap anyway and use the next line
+    if (space < PROP_TEXT_MIN_CELLS)
+       space += wp->w_width;
+    for (n_used = 0; n_used < len; n_used += (*mb_ptr2len)(text + n_used))
+    {
+       int clen = ptr2cells(text + n_used);
+
+       if (strsize + clen > space)
+           break;
+       strsize += clen;
+    }
+    *n_used_ptr = n_used;
+    return strsize;
+}
+
 /*
  * Take care of padding, right-align and truncation of virtual text after a
  * line.
@@ -297,6 +329,7 @@ text_prop_position(
        int         *n_attr_skip)   // cells to skip attr, NULL if not used
 {
     int            right = (tp->tp_flags & TP_FLAG_ALIGN_RIGHT);
+    int            above = (tp->tp_flags & TP_FLAG_ALIGN_ABOVE);
     int            below = (tp->tp_flags & TP_FLAG_ALIGN_BELOW);
     int            wrap = (tp->tp_flags & TP_FLAG_WRAP);
     int            padding = tp->tp_col == MAXCOL && tp->tp_len > 1
@@ -304,36 +337,45 @@ text_prop_position(
     int            col_with_padding = vcol + (below ? 0 : padding);
     int            col_off = 0;
     int            room = wp->w_width - col_with_padding;
-    int            added = room;
+    int            before = room;      // spaces before the text
+    int            after = 0;          // spaces after the text
     int            n_used = *n_extra;
     char_u  *l = NULL;
     int            strsize = vim_strsize(*p_extra);
-    int            cells = wrap ? strsize
-             : textprop_size_after_trunc(wp, below, added, *p_extra, &n_used);
+    int            cells = wrap ? strsize : textprop_size_after_trunc(wp,
+                                     tp->tp_flags, before, *p_extra, &n_used);
 
-    if (wrap || right || below || padding > 0 || n_used < *n_extra)
+    if (wrap || right || above || below || padding > 0 || n_used < *n_extra)
     {
-       // Right-align: fill with spaces
-       if (right)
-           added -= cells;
-       if (added < 0
-               || !(right || below)
-               || (below
-                   ? (col_with_padding == 0 || !wp->w_p_wrap)
-                   : (n_used < *n_extra)))
+       if (above)
        {
-           if (right && (wrap || room < PROP_TEXT_MIN_CELLS))
-           {
-               // right-align on next line instead of wrapping if possible
-               col_off = win_col_off(wp) + win_col_off2(wp);
-               added = wp->w_width - col_off - strsize + room;
-               if (added < 0)
-                   added = 0;
+           before = 0;
+           after = wp->w_width - cells;
+       }
+       else
+       {
+           // Right-align: fill with before
+           if (right)
+               before -= cells;
+           if (before < 0
+                   || !(right || below)
+                   || (below
+                       ? (col_with_padding == 0 || !wp->w_p_wrap)
+                       : (n_used < *n_extra)))
+           {
+               if (right && (wrap || room < PROP_TEXT_MIN_CELLS))
+               {
+                   // right-align on next line instead of wrapping if possible
+                   col_off = win_col_off(wp) + win_col_off2(wp);
+                   before = wp->w_width - col_off - strsize + room;
+                   if (before < 0)
+                       before = 0;
+                   else
+                       n_used = *n_extra;
+               }
                else
-                   n_used = *n_extra;
+                   before = 0;
            }
-           else
-               added = 0;
        }
 
        // With 'nowrap' add one to show the "extends" character if needed (it
@@ -346,15 +388,15 @@ text_prop_position(
 
        // add 1 for NUL, 2 for when '…' is used
        if (n_attr != NULL)
-           l = alloc(n_used + added + padding + 3);
+           l = alloc(n_used + before + after + padding + 3);
        if (n_attr == NULL || l != NULL)
        {
            int off = 0;
 
            if (n_attr != NULL)
            {
-               vim_memset(l, ' ', added);
-               off += added;
+               vim_memset(l, ' ', before);
+               off += before;
                if (padding > 0)
                {
                    vim_memset(l + off, ' ', padding);
@@ -365,8 +407,8 @@ text_prop_position(
            }
            else
            {
-               off = added + padding + n_used;
-               cells += added + padding;
+               off = before + after + padding + n_used;
+               cells += before + after + padding;
            }
            if (n_attr != NULL)
            {
@@ -385,10 +427,16 @@ text_prop_position(
                        // change last character to '>'
                        *lp = '>';
                }
+               else if (after > 0)
+               {
+                   vim_memset(l + off, ' ', after);
+                   l[off + after] = NUL;
+               }
+
                *p_extra = l;
-               *n_extra = n_used + added + padding;
+               *n_extra = n_used + before + after + padding;
                *n_attr = mb_charlen(*p_extra);
-               *n_attr_skip = added + padding + col_off;
+               *n_attr_skip = before + padding + col_off;
            }
        }
     }
@@ -1694,11 +1742,14 @@ win_line(
                // text prop can show.
                while (text_prop_next < text_prop_count
                           && (text_props[text_prop_next].tp_col == MAXCOL
-                             ? (*ptr == NUL
+                             ? ((*ptr == NUL
                                  && (wp->w_p_wrap
                                      || wlv.row == startrow
                                      || (text_props[text_prop_next].tp_flags
                                                       & TP_FLAG_ALIGN_BELOW)))
+                              || (bcol == 0 &&
+                                     (text_props[text_prop_next].tp_flags
+                                                      & TP_FLAG_ALIGN_ABOVE)))
                              : bcol >= text_props[text_prop_next].tp_col - 1))
                {
                    if (text_props[text_prop_next].tp_col == MAXCOL
@@ -1773,6 +1824,8 @@ win_line(
                        {
                            int     right = (tp->tp_flags
                                                        & TP_FLAG_ALIGN_RIGHT);
+                           int     above = (tp->tp_flags
+                                                       & TP_FLAG_ALIGN_ABOVE);
                            int     below = (tp->tp_flags
                                                        & TP_FLAG_ALIGN_BELOW);
                            int     wrap = (tp->tp_flags & TP_FLAG_WRAP);
@@ -1797,18 +1850,15 @@ win_line(
                                // don't combine char attr after EOL
                                text_prop_flags &= ~PT_FLAG_COMBINE;
 #ifdef FEAT_LINEBREAK
-                           if (below || right || !wrap)
+                           if (above || below || right || !wrap)
                            {
                                // no 'showbreak' before "below" text property
-                               // or after "right" text property
+                               // or after "above" or "right" text property
                                need_showbreak = FALSE;
                                dont_use_showbreak = TRUE;
                            }
 #endif
-                           // Keep in sync with where
-                           // textprop_size_after_trunc() is called in
-                           // win_lbr_chartabsize().
-                           if ((right || below || !wrap || padding > 0)
+                           if ((right || above || below || !wrap || padding > 0)
                                                            && wp->w_width > 2)
                            {
                                char_u  *prev_p_extra = wlv.p_extra;
index 84adafab664cbc5444719761d7625e284a52ced7..165a08080c075531a24d0fc218baabfb351e3780 100644 (file)
@@ -85,7 +85,7 @@ getviscol2(colnr_T col, colnr_T coladd UNUSED)
 }
 
 /*
- * Try to advance the Cursor to the specified screen column.
+ * Try to advance the Cursor to the specified screen column "wantcol".
  * If virtual editing: fine tune the cursor position.
  * Note that all virtual positions off the end of a line should share
  * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
@@ -94,29 +94,30 @@ getviscol2(colnr_T col, colnr_T coladd UNUSED)
  * return OK if desired column is reached, FAIL if not
  */
     int
-coladvance(colnr_T wcol)
+coladvance(colnr_T wantcol)
 {
-    int rc = getvpos(&curwin->w_cursor, wcol);
+    int rc = getvpos(&curwin->w_cursor, wantcol);
 
-    if (wcol == MAXCOL || rc == FAIL)
+    if (wantcol == MAXCOL || rc == FAIL)
        curwin->w_valid &= ~VALID_VIRTCOL;
     else if (*ml_get_cursor() != TAB)
     {
        // Virtcol is valid when not on a TAB
        curwin->w_valid |= VALID_VIRTCOL;
-       curwin->w_virtcol = wcol;
+       curwin->w_virtcol = wantcol;
     }
     return rc;
 }
 
 /*
- * Return in "pos" the position of the cursor advanced to screen column "wcol".
+ * Return in "pos" the position of the cursor advanced to screen column
+ * "wantcol".
  * return OK if desired column is reached, FAIL if not
  */
     int
-getvpos(pos_T *pos, colnr_T wcol)
+getvpos(pos_T *pos, colnr_T wantcol)
 {
-    return coladvance2(pos, FALSE, virtual_active(), wcol);
+    return coladvance2(pos, FALSE, virtual_active(), wantcol);
 }
 
     static int
@@ -156,8 +157,8 @@ coladvance2(
     }
     else
     {
-       int width = curwin->w_width - win_col_off(curwin);
-       chartabsize_T cts;
+       int             width = curwin->w_width - win_col_off(curwin);
+       chartabsize_T   cts;
 
        if (finetune
                && curwin->w_p_wrap
@@ -183,6 +184,9 @@ coladvance2(
        init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
        while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL)
        {
+#ifdef FEAT_PROP_POPUP
+           int at_start = cts.cts_ptr == cts.cts_line;
+#endif
            // Count a tab for what it's worth (if list mode not on)
 #ifdef FEAT_LINEBREAK
            csize = win_lbr_chartabsize(&cts, &head);
@@ -191,6 +195,11 @@ coladvance2(
            csize = lbr_chartabsize_adv(&cts);
 #endif
            cts.cts_vcol += csize;
+#ifdef FEAT_PROP_POPUP
+           if (at_start)
+               // do not count the columns for virtual text above
+               cts.cts_vcol -= cts.cts_first_char;
+#endif
        }
        col = cts.cts_vcol;
        idx = (int)(cts.cts_ptr - line);
@@ -2400,7 +2409,7 @@ update_mouseshape(int shape_idx)
 
 /*
  * Change directory to "new_dir".  Search 'cdpath' for relative directory
- * names, otherwise just mch_chdir().
+ * names.
  */
     int
 vim_chdir(char_u *new_dir)
index 089ffca39934d995f3e291d16efb246e6442b9e7..9ec7798b9f2ef529c5ef994ba07ee6c8d82c7873 100644 (file)
@@ -476,7 +476,11 @@ update_curswant(void)
     if (curwin->w_set_curswant)
     {
        validate_virtcol();
-       curwin->w_curswant = curwin->w_virtcol;
+       curwin->w_curswant = curwin->w_virtcol
+#ifdef FEAT_PROP_POPUP
+                               - curwin->w_virtcol_first_char
+#endif
+                               ;
        curwin->w_set_curswant = FALSE;
     }
 }
@@ -835,6 +839,9 @@ validate_virtcol_win(win_T *wp)
     check_cursor_moved(wp);
     if (!(wp->w_valid & VALID_VIRTCOL))
     {
+#ifdef FEAT_PROP_POPUP
+       wp->w_virtcol_first_char = 0;
+#endif
        getvvcol(wp, &wp->w_cursor, NULL, &(wp->w_virtcol), NULL);
 #ifdef FEAT_SYN_HL
        redraw_for_cursorcolumn(wp);
@@ -982,6 +989,11 @@ curs_columns(
     if (!(curwin->w_valid & VALID_CROW))
        curs_rows(curwin);
 
+#ifdef FEAT_PROP_POPUP
+    // will be set by getvvcol() but not reset
+    curwin->w_virtcol_first_char = 0;
+#endif
+
     /*
      * Compute the number of virtual columns.
      */
index 6bc8eab990f5f1668224ec0d1c81365dc550a01c..c7d5767954bab1ab93ad3ec8bc79085f25defe04 100644 (file)
@@ -34,7 +34,6 @@ void init_chartabsize_arg(chartabsize_T *cts, win_T *wp, linenr_T lnum, colnr_T
 void clear_chartabsize_arg(chartabsize_T *cts);
 int lbr_chartabsize(chartabsize_T *cts);
 int lbr_chartabsize_adv(chartabsize_T *cts);
-int textprop_size_after_trunc(win_T *wp, int below, int added, char_u *text, int *n_used_ptr);
 int win_lbr_chartabsize(chartabsize_T *cts, int *headp);
 void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
 colnr_T getvcol_nolist(pos_T *posp);
index 6e29785d3d0ddcb511e4cc84db08f7202e18aa4f..c12f8e45af64591e00d19578aebabceb0b6e6555 100644 (file)
@@ -813,12 +813,13 @@ typedef struct textprop_S
 #define TP_FLAG_CONT_PREV      0x2     // property was continued from prev line
 
 // without these text is placed after the end of the line
-#define TP_FLAG_ALIGN_RIGHT    0x10    // virtual text is right-aligned
-#define TP_FLAG_ALIGN_BELOW    0x20    // virtual text on next screen line
+#define TP_FLAG_ALIGN_RIGHT    0x010   // virtual text is right-aligned
+#define TP_FLAG_ALIGN_ABOVE    0x020   // virtual text above the line
+#define TP_FLAG_ALIGN_BELOW    0x040   // virtual text on next screen line
 
-#define TP_FLAG_WRAP           0x40    // virtual text wraps - when missing
+#define TP_FLAG_WRAP           0x080   // virtual text wraps - when missing
                                        // text is truncated
-#define TP_FLAG_START_INCL     0x80    // "start_incl" copied from proptype
+#define TP_FLAG_START_INCL     0x100   // "start_incl" copied from proptype
 
 #define PROP_TEXT_MIN_CELLS    4       // minimun number of cells to use for
                                        // the text, even when truncating
@@ -3678,6 +3679,11 @@ struct window_S
                                    // more than one screen line or when
                                    // w_leftcol is non-zero
 
+#ifdef FEAT_PROP_POPUP
+    colnr_T    w_virtcol_first_char;   // offset for w_virtcol when there are
+                                       // virtual text properties above the
+                                       // line
+#endif
     /*
      * w_wrow and w_wcol specify the cursor position in the window.
      * This is related to positions in the window, not in the display or
@@ -4607,6 +4613,7 @@ typedef struct {
     textprop_T *cts_text_props;        // text props (allocated)
     char       cts_has_prop_with_text; // TRUE if if a property inserts text
     int         cts_cur_text_width;     // width of current inserted text
+    int         cts_first_char;                // width text props above the line
     int                cts_with_trailing;      // include size of trailing props with
                                        // last character
     int                cts_start_incl;         // prop has true "start_incl" arg
diff --git a/src/testdir/dumps/Test_prop_with_text_above_1.dump b/src/testdir/dumps/Test_prop_with_text_above_1.dump
new file mode 100644 (file)
index 0000000..cc68f5e
--- /dev/null
@@ -0,0 +1,9 @@
+|f+0&#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| @42
+|s+0&#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| @41
+|o+0&#ffffff0|n|e| |t|w|o| @52
+|t|h|r>e@1| |f|o|u|r| @49
+|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| @46
+|f+0&#ffffff0|i|v|e| |s|i|x| @51
+|~+0#4040ff13&| @58
+|~| @58
+| +0#0000000&@41|2|,|4| @10|A|l@1| 
index 21d751fb14fbbc56495ec2d015e23601d66593f1..d89f84cedda347df30aebd88e288e2389fdc0c42 100644 (file)
@@ -2848,6 +2848,26 @@ func Test_props_with_text_below_nowrap()
   call delete('XscriptPropsBelowNowrap')
 endfunc
 
+func Test_props_with_text_above()
+  CheckRunVimInTerminal
+
+  let lines =<< trim END
+      call setline(1, ['one two', 'three four', 'five six'])
+      call prop_type_add('above1', #{highlight: 'Search'})
+      call prop_type_add('above2', #{highlight: 'DiffChange'})
+      call prop_add(1, 0, #{type: 'above1', text: 'first thing above', text_align: 'above'})
+      call prop_add(1, 0, #{type: 'above2', text: 'second thing above', text_align: 'above'})
+      call prop_add(3, 0, #{type: 'above1', text: 'another thing', text_align: 'above'})
+
+      normal gglllj
+  END
+  call writefile(lines, 'XscriptPropsWithTextAbove', 'D')
+  let buf = RunVimInTerminal('-S XscriptPropsWithTextAbove', #{rows: 9, cols: 60})
+  call VerifyScreenDump(buf, 'Test_prop_with_text_above_1', {})
+
+  call StopVimInTerminal(buf)
+endfunc
+
 func Test_props_with_text_override()
   CheckRunVimInTerminal
 
index 5f5c6a2aa23e57cfdd05dc2cb0ef46705120fb53..ff96833f6c000a7fd673b4d9724f076c30cef76a 100644 (file)
@@ -497,6 +497,8 @@ prop_add_common(
            }
            if (STRCMP(p, "right") == 0)
                flags |= TP_FLAG_ALIGN_RIGHT;
+           else if (STRCMP(p, "above") == 0)
+               flags |= TP_FLAG_ALIGN_ABOVE;
            else if (STRCMP(p, "below") == 0)
                flags |= TP_FLAG_ALIGN_BELOW;
            else if (STRCMP(p, "after") != 0)
@@ -673,6 +675,21 @@ count_props(linenr_T lnum, int only_starting, int last_line)
 static textprop_T      *text_prop_compare_props;
 static buf_T           *text_prop_compare_buf;
 
+/* Score for sorting on position of the text property: 0: above,
+ * 1: after (default), 2: right, 3: below (comes last)
+ */
+    static int
+text_prop_order(int flags)
+{
+    if (flags & TP_FLAG_ALIGN_ABOVE)
+       return 0;
+    if (flags & TP_FLAG_ALIGN_RIGHT)
+       return 2;
+    if (flags & TP_FLAG_ALIGN_BELOW)
+       return 3;
+    return 1;
+}
+
 /*
  * Function passed to qsort() to sort text properties.
  * Return 1 if "s1" has priority over "s2", -1 if the other way around, zero if
@@ -694,21 +711,13 @@ text_prop_compare(const void *s1, const void *s2)
     col2 = tp2->tp_col;
     if (col1 == MAXCOL && col2 == MAXCOL)
     {
-       int flags1 = 0;
-       int flags2 = 0;
-
-       // both props add text are after the line, order on 0: after (default),
-       // 1: right, 2: below (comes last)
-       if (tp1->tp_flags & TP_FLAG_ALIGN_RIGHT)
-           flags1 = 1;
-       if (tp1->tp_flags & TP_FLAG_ALIGN_BELOW)
-           flags1 = 2;
-       if (tp2->tp_flags & TP_FLAG_ALIGN_RIGHT)
-           flags2 = 1;
-       if (tp2->tp_flags & TP_FLAG_ALIGN_BELOW)
-           flags2 = 2;
-       if (flags1 != flags2)
-           return flags1 < flags2 ? 1 : -1;
+       int order1 = text_prop_order(tp1->tp_flags);
+       int order2 = text_prop_order(tp2->tp_flags);
+
+       // both props add text before or after the line, sort on order where it
+       // is added
+       if (order1 != order2)
+           return order1 < order2 ? 1 : -1;
     }
 
     // property that inserts text has priority over one that doesn't
index 2d9b3ad208c1229f3bd19b8e15cdddb0111cfc4f..ac89e77c08da95460920420c142d54273ed88fdb 100644 (file)
@@ -703,6 +703,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    438,
 /**/
     437,
 /**/