wprintw: In ncurses, when writing a newline-terminated line of exactly the same width as the window, two newlines are printed
I've just finished working through the code of a CLI program, converting it into a TUI program using ncurses.
It tests the user on a collection of questions and answers in a flash card-like way.
All went relatively smoothly except that I have replaced many printf()
calls with a popupinfo(int colour,char * title, char * body)
function to pop up a window.
int textwidth (char * text);//returns the width of a given string (which may include newlines) in chars when displayed without wrapping (for purposes of determining optimum window width)
int textheight (char * text, int width);//returns the height of a given string (which may include newlines) in lines when displayed wrapped to the given width (for purposes of determining optimum window width)
to calculate the size of the window before using wprintw()
to print to that window.
The problem I have is that when the length of a line other than the last line is exactly equal to the window width (or a multiple of the window width), one or more lines of text will be omitted from the window.
For example:
Answer:
Foobarbaz.
will print correctly, but in:
Answer:
Foo.
The 'Foo.' is not printed.
I believe this is because the wprintw()
function moves the 开发者_StackOverflow社区cursor to a new line after printing (window_width)
chars, but then encounters the newline character that was at the end of the line it just printed as well.
Does anyone know of a way (short of writing an entire function to handle output myself) to stop this happening?
Useful details:
I'm replacing:
printf("\nSorry, the correct answer is:\n\n\t%s\n\n",currententry->answer);
with:
sprintf(passingstring,"The correct answer is:\n\n%s",currententry->answer);
popupinfo(3,"Sorry!",passingstring);
popupinfo is defined as:
void popupinfo(int colour,char * title,char * message)//pops up a window with the given colour, title and text
{
WINDOW * wbpopup = NULL, * wpopup = NULL;
PANEL * ppopup = NULL;
int width, height;
width=textwidth(message);
getmaxyx(stdscr,nlines,ncols);
if (width>ncols-16)width=ncols-16;
height=textheight(message,width)+4;
width+=8;
if (!(wbpopup = newwin(height,width,(nlines-height)/2,(ncols-width)/2))) outofmemory();
ppopup = new_panel(wbpopup);
wattrset(wbpopup,COLOR_PAIR(colour));
werase(wbpopup);
wbkgd(wbpopup,COLOR_PAIR(colour));
box(wbpopup,0,0);
windowtitle(wbpopup,title);
wpopup = innerwindow(wbpopup);
wprintw(wpopup,message);
update_panels();
doupdate();
wgetch(wpopup);
delwin(wpopup);
del_panel(ppopup);
delwin(wbpopup);
update_panels();
doupdate();
}
Also useful:
int textwidth (char * text)//returns the width of a given string (which may include newlines) in chars when displayed without wrapping (for purposes of determining optimum window width)
{
int i=0,j=0,k=0;
while (text[i]!='\0')
{
if (text[i]=='\n')
{
k=j>k?j:k;
j=0;
}
else j++;
i++;
}
k=j>k?j:k;
return k;
}
and
int textheight (char * text, int width)//returns the height of a given string (which may include newlines) in lines when displayed wrapped to the given width (for purposes of determining optimum window width)
{
int i=0,j=0,k=1;
while (text[i]!='\0')
{
if (text[i]=='\n')
{
k++;
j=0;
}
else j++;
if (j>width)
{
k++;
j=1;
}
i++;
}
return k;
}
Other functions:
WINDOW * innerwindow(WINDOW * outerwindow);//creates an area within another window for purposes of displaying text with a margin
void windowtitle(WINDOW * window, char * title);//writes the given string to the given window (top centre)
For anything further, see full source for the CLI and ncurses versions, which can be found at http://github.com/megamasha
You are absolutely right when you say:
I believe this is because the wprintw() function moves the cursor to a new line after printing (window_width) chars, but then encounters the newline character that was at the end of the line it just printed as well.
Regarding your question
Does anyone know of a way (short of writing an entire function to handle output myself) to stop this happening?
- there is no such way, because what you observe is how line wrapping works in ncurses.
What you could do is making the popup window one character wider, thus avoiding the wrapping that is due to reaching the width of the window, for example by changing the line width+=8;
to width+=8+1;
in popupinfo
.
精彩评论