Я только что закончил работать с кодом программы CLI, преобразовав его в программу TUI с помощью ncurses.
Он проверяет пользователя по набору вопросов и ответов в виде флеш-карты.
Все прошло относительно гладко, за исключением того, что я заменил многие вызовы printf()
функцией popupinfo(int colour,char * title, char * body)
для всплывающего окна.
Эта функция использует следующие функции:
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)
чтобы вычислить размер окна, прежде чем использовать wprintw()
для печати в этом окне.
Моя проблема заключается в том, что когда длина строки, отличной от последней строки, точно равна ширине окна (или кратна ширине окна), одна или несколько строк текста будут исключены из окна.
Например:
Answer:
Foobarbaz.
будет печатать правильно, но в:
Answer:
Foo.
«Фу». не печатается.
Я полагаю, это связано с тем, что функция wprintw()
перемещает курсор на новую строку после печати (window_width)
символов, но затем встречает символ новой строки, который был в конце только что напечатанной строки.
Кто-нибудь знает способ (за исключением написания целой функции для обработки вывода самостоятельно), чтобы остановить это?
Полезные детали:
Я заменяю:
printf("\nSorry, the correct answer is:\n\n\t%s\n\n",currententry->answer);
с участием:
sprintf(passingstring,"The correct answer is:\n\n%s",currententry->answer);
popupinfo(3,"Sorry!",passingstring);
всплывающая информация определяется как:
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();
}
Также полезно:
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;
}
а также
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;
}
Другие функции:
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)
Для получения дополнительной информации см. полный исходный код версий CLI и ncurses, который можно найти по адресу http://github.com/megamasha