Jim Tcl
Check-in [e8aebbb399]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:linenoise: Update for optimised insert

Update to version: https://github.com/msteveb/linenoise/commit/d7bcf93d4de7581e043283ab461eca2310dd8fdc

Signed-off-by: Steve Bennett <steveb@workware.net.au>

Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e8aebbb3999267e10c5cd60f2c0b5d5cded9317b
User & Date: steveb@workware.net.au 2018-07-25 07:04:32
Context
2018-07-26
20:59
jim-interp.c: fix compile warning with GCC 8.1.1

GCC complains about possible truncation from snprintf() jim-interp.c: In function ‘JimInterpCommand’: jim-interp.c:164:46: warning: ‘%ld’ directive output may be truncated writing between 1 and 20 bytes into a region of size 19 [-Wformat-truncation=] snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); ^~~ jim-interp.c:164:32: note: directive argument in the range [-9223372036854775807, 9223372036854775807] snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); ^~~~~~~~~~~~~~~~~~ jim-interp.c:164:5: note: ‘snprintf’ output between 15 and 34 bytes into a destination of size 32 snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> check-in: 3bb8ebd082 user: borneo.antonio@gmail.com tags: trunk

2018-07-25
07:04
linenoise: Update for optimised insert

Update to version: https://github.com/msteveb/linenoise/commit/d7bcf93d4de7581e043283ab461eca2310dd8fdc

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: e8aebbb399 user: steveb@workware.net.au tags: trunk

05:30
Update autosetup to v0.6.8

autosetup changes: - The syntax for templates has changed slightly - Update config.guess and config.sub to 2018-03-08 - Add rpath support - Add --runstatedir

Also: - enable rpath when building libjim as shared - ensure that 'make test' works on MacOS when libjim is shared

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: ddb44ce9e6 user: steveb@workware.net.au tags: trunk

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to linenoise.c.

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
476
477
478
479
480
481
482

483
484
485
486
487
488
489
....
1242
1243
1244
1245
1246
1247
1248
1249



1250


1251
1252
1253
1254
1255


1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285


1286
1287
1288
1289
1290
1291
1292
....
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
....
1503
1504
1505
1506
1507
1508
1509
1510









1511
1512
1513
1514
1515
1516
1517
....
1575
1576
1577
1578
1579
1580
1581

1582
1583
1584
1585
1586










1587

1588
1589
1590
1591










1592
1593
1594
1595
1596
1597
1598
1599
....
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
....
1984
1985
1986
1987
1988
1989
1990

1991
1992
1993
1994
1995
1996
1997
void sb_append(stringbuf *sb, const char *str)
{
	sb_append_len(sb, str, strlen(str));
}

void sb_append_len(stringbuf *sb, const char *str, int len)
{
	int utf8_strlen(const char *str, int bytelen);
	if (sb->remaining < len + 1) {
		sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
	}
	memcpy(sb->data + sb->last, str, len);
	sb->data[sb->last + len] = 0;

	sb->last += len;
................................................................................
/* Structure to contain the status of the current (being edited) line */
struct current {
    stringbuf *buf; /* Current buffer. Always null terminated */
    int pos;    /* Cursor position, measured in chars */
    int cols;   /* Size of the window, in chars */
    int nrows;  /* How many rows are being used in multiline mode (>= 1) */
    int rpos;   /* The current row containing the cursor - multiline mode only */

    const char *prompt;
    stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
    stringbuf *output;  /* used only during refreshLine() - output accumulator */
#if defined(USE_TERMIOS)
    int fd;     /* Terminal fd */
#elif defined(USE_WINCONSOLE)
    HANDLE outh; /* Console output handle */
................................................................................

void linenoiseSetMultiLine(int enableml)
{
    mlmode = enableml;
}

/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
 * to the right of the prompt. */



static void refreshShowHints(struct current *current, const char *buf, int availcols) {


    if (showhints && hintsCallback && availcols > 0) {
        int bold = 0;
        int color = -1;
        char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
        if (hint) {


            const char *pt;
            if (bold == 1 && color == -1) color = 37;
            if (bold || color > 0) {
                int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
                setOutputHighlight(current, props, 3);
            }
            DRL("<hint bold=%d,color=%d>", bold, color);
            pt = hint;
            while (*pt) {
                int ch;
                int n = utf8_tounicode(pt, &ch);
                int width = char_display_width(ch);

                if (width >= availcols) {
                    DRL("<hinteol>");
                    break;
                }
                DRL_CHAR(ch);

                availcols -= width;
                outputChars(current, pt, n);
                pt += n;
            }
            if (bold || color > 0) {
                clearOutputHighlight(current);
            }
            /* Call the function to free the hint returned. */
            if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
        }
    }


}

#ifdef USE_TERMIOS
static void refreshStart(struct current *current)
{
    /* We accumulate all output here */
    assert(current->output == NULL);
................................................................................
    int displaycol;
    int displayrow;
    int visible;
    int currentpos;
    int notecursor;
    int cursorcol = 0;
    int cursorrow = 0;

    struct esc_parser parser;

#ifdef DEBUG_REFRESHLINE
    dfh = fopen("linenoise.debuglog", "a");
#endif

    /* Should intercept SIGWINCH. For now, just get the size every time */
................................................................................
        cursorcol = displaycol;
        cursorrow = displayrow;
    }

    DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n\n", displaycol, displayrow, cursorcol, cursorrow);

    /* (f) show hints */
    refreshShowHints(current, buf, current->cols - displaycol);










    refreshEndChars(current);

    /* (g) move the cursor to the correct place */
    cursorUp(current, displayrow - cursorrow);
    setCursorPos(current, cursorcol);

................................................................................
 */
static int insert_char(struct current *current, int pos, int ch)
{
    if (pos >= 0 && pos <= sb_chars(current->buf)) {
        char buf[MAX_UTF8_LEN + 1];
        int offset = utf8_index(sb_str(current->buf), pos);
        int n = utf8_getchars(buf, ch);


        /* null terminate since sb_insert() requires it */
        buf[n] = 0;

        /* Optimisation removed - see reason in remove_char() */












        sb_insert(current->buf, offset, buf);
        if (current->pos >= pos) {
            current->pos++;
        }










        return 1;
    }
    return 0;
}

/**
 * Captures up to 'n' characters starting at 'pos' for the cut buffer.
 *
................................................................................
 */
static void capture_chars(struct current *current, int pos, int nchars)
{
    if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
        int offset = utf8_index(sb_str(current->buf), pos);
        int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);

        if (nbytes) {
            if (current->capture) {
                sb_clear(current->capture);
            }
            else {
                current->capture = sb_alloc();
            }
            sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
................................................................................
    }
    return sb_len(current->buf);
}

int linenoiseColumns(void)
{
    struct current current;

    enableRawMode (&current);
    getWindowSize (&current);
    disableRawMode (&current);
    return current.cols;
}

/**







<







 







>







 







|
>
>
>
|
>
>





>
>
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
>
>







 







>







 







|
>
>
>
>
>
>
>
>
>







 







>




|
>
>
>
>
>
>
>
>
>
>
|
>




>
>
>
>
>
>
>
>
>
>
|







 







|







 







>







176
177
178
179
180
181
182

183
184
185
186
187
188
189
...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
....
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
....
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
....
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
....
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
....
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
....
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
void sb_append(stringbuf *sb, const char *str)
{
	sb_append_len(sb, str, strlen(str));
}

void sb_append_len(stringbuf *sb, const char *str, int len)
{

	if (sb->remaining < len + 1) {
		sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
	}
	memcpy(sb->data + sb->last, str, len);
	sb->data[sb->last + len] = 0;

	sb->last += len;
................................................................................
/* Structure to contain the status of the current (being edited) line */
struct current {
    stringbuf *buf; /* Current buffer. Always null terminated */
    int pos;    /* Cursor position, measured in chars */
    int cols;   /* Size of the window, in chars */
    int nrows;  /* How many rows are being used in multiline mode (>= 1) */
    int rpos;   /* The current row containing the cursor - multiline mode only */
    int availcols;  /* refreshLine() caches available cols after the prompt here */
    const char *prompt;
    stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
    stringbuf *output;  /* used only during refreshLine() - output accumulator */
#if defined(USE_TERMIOS)
    int fd;     /* Terminal fd */
#elif defined(USE_WINCONSOLE)
    HANDLE outh; /* Console output handle */
................................................................................

void linenoiseSetMultiLine(int enableml)
{
    mlmode = enableml;
}

/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
 * to the right of the prompt.
 * Returns 1 if a hint was shown, or 0 if not
 * If 'display' is 0, does no output. Just returns the appropriate return code.
 */
static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
{
    int rc = 0;
    if (showhints && hintsCallback && availcols > 0) {
        int bold = 0;
        int color = -1;
        char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
        if (hint) {
            rc = 1;
            if (display) {
                const char *pt;
                if (bold == 1 && color == -1) color = 37;
                if (bold || color > 0) {
                    int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
                    setOutputHighlight(current, props, 3);
                }
                DRL("<hint bold=%d,color=%d>", bold, color);
                pt = hint;
                while (*pt) {
                    int ch;
                    int n = utf8_tounicode(pt, &ch);
                    int width = char_display_width(ch);

                    if (width >= availcols) {
                        DRL("<hinteol>");
                        break;
                    }
                    DRL_CHAR(ch);

                    availcols -= width;
                    outputChars(current, pt, n);
                    pt += n;
                }
                if (bold || color > 0) {
                    clearOutputHighlight(current);
                }
                /* Call the function to free the hint returned. */
                if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
            }
        }
    }
    return rc;
}

#ifdef USE_TERMIOS
static void refreshStart(struct current *current)
{
    /* We accumulate all output here */
    assert(current->output == NULL);
................................................................................
    int displaycol;
    int displayrow;
    int visible;
    int currentpos;
    int notecursor;
    int cursorcol = 0;
    int cursorrow = 0;
    int hint;
    struct esc_parser parser;

#ifdef DEBUG_REFRESHLINE
    dfh = fopen("linenoise.debuglog", "a");
#endif

    /* Should intercept SIGWINCH. For now, just get the size every time */
................................................................................
        cursorcol = displaycol;
        cursorrow = displayrow;
    }

    DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n\n", displaycol, displayrow, cursorcol, cursorrow);

    /* (f) show hints */
    hint = refreshShowHints(current, buf, current->cols - displaycol, 1);

    /* Remember how many many cols are available for insert optimisation */
    if (prompt == current->prompt && hint == 0) {
        current->availcols = current->cols - displaycol;
    }
    else {
        /* Can't optimise */
        current->availcols = 0;
    }

    refreshEndChars(current);

    /* (g) move the cursor to the correct place */
    cursorUp(current, displayrow - cursorrow);
    setCursorPos(current, cursorcol);

................................................................................
 */
static int insert_char(struct current *current, int pos, int ch)
{
    if (pos >= 0 && pos <= sb_chars(current->buf)) {
        char buf[MAX_UTF8_LEN + 1];
        int offset = utf8_index(sb_str(current->buf), pos);
        int n = utf8_getchars(buf, ch);
        int rc = 1;

        /* null terminate since sb_insert() requires it */
        buf[n] = 0;

        /* Now we try to optimise in the simple but very common case that:
         * - we are inserting at EOL
         * - there are enough columns available
         * - no hints are being shown
         */
        if (pos == current->pos && pos == sb_chars(current->buf)) {
            int width = char_display_width(ch);
            if (current->availcols > width) {
                /* Yes, can optimise */
                current->availcols -= width;
                rc = 2;
            }
        }
        sb_insert(current->buf, offset, buf);
        if (current->pos >= pos) {
            current->pos++;
        }
        if (rc == 2) {
            if (refreshShowHints(current, sb_str(current->buf), current->availcols, 0)) {
                /* A hint needs to be shown, so can't optimise after all */
                rc = 1;
            }
            else {
                /* optimised output */
                outputChars(current, buf, n);
            }
        }
        return rc;
    }
    return 0;
}

/**
 * Captures up to 'n' characters starting at 'pos' for the cut buffer.
 *
................................................................................
 */
static void capture_chars(struct current *current, int pos, int nchars)
{
    if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
        int offset = utf8_index(sb_str(current->buf), pos);
        int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);

        if (nbytes > 0) {
            if (current->capture) {
                sb_clear(current->capture);
            }
            else {
                current->capture = sb_alloc();
            }
            sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
................................................................................
    }
    return sb_len(current->buf);
}

int linenoiseColumns(void)
{
    struct current current;
    current.output = NULL;
    enableRawMode (&current);
    getWindowSize (&current);
    disableRawMode (&current);
    return current.cols;
}

/**