Search code examples
cncursescursespdcurses

printw() won't print a single character from a uint8_t array


Here is my main() code:

#include <stdio.h>
#include <stdlib.h>
#ifdef __gnu_linux__
    #include <ncurses.h>
#endif
#ifdef _WIN32
    #include <curses.h>
#endif
#include "terminal_info.h"
#include "interface.h"
int main()
{
    initscr();
    setvbuf(stdout, NULL, _IONBF, 0);
    testForUI();
    readUIFile();
    continuouslyUpdateInfo();
    refresh();
    printDocument();
    getch();
    endwin();
    clearAll();
    return 0;
}

The problem I'm having occurs in printDocument():

void printDocument()
{
    int counter = 0;
    printw("Document Size: %d\n", documentSize);
    for(counter = 0; counter < documentSize; counter++)
    {
        printw("%c",(char)document[counter]);
        refresh();
    }

}

At the start of the for loop, gdb says the contents of document are as follows:

$1 = (uint8_t *) 0x3e32c0 "<Root>\r\n    <Hello>World</Hello>\r\n    <This>\r\n
<Is>:-)</Is>\r\n        <An>:-O</An>\r\n        <Example>:-D</Example>\r\n    </This>\r\n</Root>\r\n««««««««_î_î_"

But the program only prints:

Document Size: 123

However, if I change the printw statement to:

printw("%c - %d",(char)document[counter], document[counter]);

I get this:

Document Size: 123

 - 13
 - 10  - 32  - 32  - 32  - 32< - 60H - 72e - 101l - 108l - 108o - 111> - 62W - 8
7o - 111r - 114l - 108d - 100< - 60/ - 47H - 72e - 101l - 108l - 108o - 111> - 6
 - 13
 - 13
 - 10    - 9< - 60I - 73s - 115> - 62: - 58- - 45) - 41< - 60/ - 47I - 73s - 115
 - 13
 - 10    - 9< - 60A - 65n - 110> - 62: - 58- - 45O - 79< - 60/ - 47A - 65n - 110
 - 13
 - 10    - 9< - 60E - 69x - 120a - 97m - 109p - 112l - 108e - 101> - 62: - 58- -
 - 13
 - 13
 - 13
 - 10

I tried disabling buffering in main() with setvbuf(), but it hasn't done me any good at all.

Here is the document that is read and printed, if it may help:

<Root>
    <Hello>World</Hello>
    <This>
    <Is>:-)</Is>
    <An>:-O</An>
    <Example>:-D</Example>
    </This>
</Root>

Declaration of document: extern uint8_t * document;


Solution

  • You need to get rid of the carriage return (CR) characters (\r).

    When you output a CR, ncurses resets the cursor to the first column in the same row. Then when you output a NL (\n), ncurses erases from the cursor position to the end of the row before advancing the cursor to the next row. That effectively deletes the entire row that was just printed.

    This behaviour is documented, for what it's worth. From man waddch (emphasis added):

    If ch is a tab, newline, or backspace, the cursor is moved appropriately within the window. Backspace moves the cursor one character left; at the left edge of a window it does nothing. Newline does a clrtoeol, then moves the cursor to the window left margin on the next line, scrolling the window if on the last line. Tabs are considered to be at every eighth column. The tab interval may be altered by setting the TABSIZE variable.

    The response to a carriage return is documented in the ncurses waddch manpage, at the end of the PORTABILITY section:

    If ch is a carriage return, the cursor is moved to the beginning of the current row of the window. This is true of other implementations, but is not documented.

    (Thanks to Thomas Dickey for pointing to the PORTABILITY section.)