Example #1
0
static void refreshLine(const char *prompt, struct current *current)
{
    int plen;
    int pchars;
    int backup = 0;
    int i;
    const char *buf = current->buf;
    int chars = current->chars;
    int pos = current->pos;
    int b;
    int ch;
    int n;
    int width;
    int bufwidth;

    /* Should intercept SIGWINCH. For now, just get the size every time */
    getWindowSize(current);

    plen = strlen(prompt);
    pchars = utf8_strwidth(prompt, utf8_strlen(prompt, plen));

    /* Scan the prompt for embedded ansi color control sequences and
     * discount them as characters/columns.
     */
    pchars -= countColorControlChars(prompt);

    /* Account for a line which is too long to fit in the window.
     * Note that control chars require an extra column
     */

    /* How many cols are required to the left of 'pos'?
     * The prompt, plus one extra for each control char
     */
    n = pchars + utf8_strwidth(buf, utf8_strlen(buf, current->len));
    b = 0;
    for (i = 0; i < pos; i++) {
        b += utf8_tounicode(buf + b, &ch);
        if (ch < ' ') {
            n++;
        }
    }

    /* Pluse one if the current char is a control character */
    if (current->pos < current->chars && get_char(current, current->pos) < ' ') {
        n++;
    }

    /* If too many are needed, strip chars off the front of 'buf'
     * until it fits. Note that if the current char is a control character,
     * we need one extra col.
     */
    while (n >= current->cols && pos > 0) {
        b = utf8_tounicode(buf, &ch);
        if (ch < ' ') {
            n--;
        }
        n -= utf8_width(ch);
        buf += b;
        pos--;
        chars--;
    }

    /* Cursor to left edge, then the prompt */
    cursorToLeft(current);
    outputChars(current, prompt, plen);

    /* Now the current buffer content */

    /* Need special handling for control characters.
     * If we hit 'cols', stop.
     */
    b = 0; /* unwritted bytes */
    n = 0; /* How many control chars were written */
    width = 0; /* current display width */
    bufwidth = utf8_strwidth(buf, pos);

    for (i = 0; i < chars; i++) {
        int ch;
        int w = utf8_tounicode(buf + b, &ch);
        if (ch < ' ') {
            n++;
        }

        width += utf8_width(ch);

        if (pchars + width + n >= current->cols) {
            break;
        }
        if (ch < ' ') {
            /* A control character, so write the buffer so far */
            outputChars(current, buf, b);
            buf += b + w;
            b = 0;
            outputControlChar(current, ch + '@');
            if (i < pos) {
                backup++;
            }
        }
        else {
            b += w;
        }
    }
    outputChars(current, buf, b);

    /* Erase to right, move cursor to original position */
    eraseEol(current);
    setCursorPos(current, bufwidth + pchars + backup);
}
Example #2
0
static void refreshLine(const char *prompt, struct current *current)
{
    int plen;
    int pchars;
    int backup = 0;
    int i;
    const char *buf = current->buf;
    int chars = current->chars;
    int pos = current->pos;
    int b;
    int ch;
    int n;

    /* Should intercept SIGWINCH. For now, just get the size every time */
    getWindowSize(current);

    plen = strlen(prompt);
    pchars = utf8_strlen(prompt, plen);

    /* Scan the prompt for embedded ansi color control sequences and
     * discount them as characters/columns.
     */
    pchars -= countColorControlChars(prompt);

    /* Account for a line which is too long to fit in the window.
     * Note that control chars require an extra column
     */

    /* How many cols are required to the left of 'pos'?
     * The prompt, plus one extra for each control char
     */
    n = pchars + utf8_strlen(buf, current->len);
    b = 0;
    for (i = 0; i < pos; i++) {
        b += utf8_tounicode(buf + b, &ch);
        if (ch < ' ') {
            n++;
        }
    }

    /* If too many are needed, strip chars off the front of 'buf'
     * until it fits. Note that if the current char is a control character,
     * we need one extra col.
     */
    if (current->pos < current->chars && get_char(current, current->pos) < ' ') {
        n++;
    }

    while (n >= current->cols && pos > 0) {
        b = utf8_tounicode(buf, &ch);
        if (ch < ' ') {
            n--;
        }
        n--;
        buf += b;
        pos--;
        chars--;
    }

    /* Cursor to left edge, then the prompt */
    cursorToLeft(current);
    outputChars(current, prompt, plen);

    /* Now the current buffer content, but only if not fully hidden */

    if (is_hidden != LN_HIDDEN_ALL) {
        /* Need special handling for control characters.
	 * If we hit 'cols', stop.
	 */
        b = 0; /* unwritted bytes */
	n = 0; /* How many control chars were written */
	for (i = 0; i < chars; i++) {
	    int ch;
	    int w = utf8_tounicode(buf + b, &ch);
	    if (!is_hidden && ch < ' ') {
	        n++;
	    }
	    if (pchars + i + n >= current->cols) {
	        break;
	    }
	    if (is_hidden == LN_HIDDEN_STAR) {
	        /* In hidden/star mode all user-entered characters are
		 * shown as astericks ('*'). This is like control chars,
		 * except for a different translation. */
	        /* assert (b == 0) */
	        outputChars(current, "*", 1);
		buf += w;
		/* keep b = 0; */
	    }
	    else if (ch < ' ') {
	        /* A control character, so write the buffer so far */
	        outputChars(current, buf, b);
		buf += b + w;
		b = 0;
		outputControlChar(current, ch + '@');
		if (i < pos) {
		    backup++;
		}
	    }
	    else {
	        b += w;
	    }
	}

	/* if (is_hidden) assert (b==0) */
	outputChars(current, buf, b);

	/* Erase to right, move cursor to original position */
	eraseEol(current);
	setCursorPos(current, pos + pchars + backup);
    }
}