У меня есть эта функция, которая обрабатывает написание текста в поле сообщения, которое я написал с нуля, потому что getstr () была слишком ограничена для меня. Проблема заключается в том, что сегодня я попытался сделать свой код более однопользованным безопасным, используя Wtimeout (Win, 0) до getch () , однако после этого появилось много ошибок, большинство из них нам достаточно легко исправить, кроме одного. Всякий раз, когда я достигаю правой границы с ящиком сообщений и должен обернуться влево и перейти по одной линии, текст продолжает писать, где изначально был курсор, и это вызывает много визуальных проблем. < /P>
Вот код: < /p>
std::string Handle_Messages(int y1, int x1, int y2, int x2){
//Show the cursor back.
curs_set(1);
//Puts the cursor on the message box's top left corner.
wmove(win, y1, x1);
//Allow writing.
echo();
//Enables special characters (like backspace!).
keypad(win, TRUE);
//Makes getch() non blocking, which is single-thread safe.
wtimeout(win, 0);
//Width and height.
const int width = x2 - x1;
const int height = y2 - y1;
//Initialize cursor positions if they haven't been initialized already.
if( chx == 0 ) chx = x1;
if( chy == 0 ) chy = y1;
//Initialize max_x if not already intialized.
if( !max_x ){
max_x = new int[height];
max_x[0] = x1;
//Set all indices (except the first one) to 0 to prevent undefined behavior.
for( int i = 1; i < height; i++ ){
max_x[ i ] = 0;
}
}
//The character read (int rather than char because special characters expect ints)
int ch;
//Have we cleared "Type Message"?
bool messageGone = false;
//Reading loop
while(1){
//Nothing is in the message box? Write "Type Message".
if( !line.length() ){
wattron(win, A_DIM);
mvwprintw(win, y1, x1, "Type Message...");
wattroff(win, A_DIM);
wmove(win, chy, chx);
messageGone = false;
}
//Clear "Type Message" if there is something in the message box
//and we haven't cleared it before.
if( line.length() > 0 && !messageGone ){
mvwprintw(win, y1, x1, " ");
mvwprintw(win, y1, x1, "%s", line.c_str());
wmove(win, chy, chx);
messageGone = true;
}
//Get a character.
ch = getch();
if( ch == ERR ){
if( !printDebug ){
// (for debugging).
// fprintf(stderr, ... );
printDebug = true;
}
return "";
}
//Pressed enter, meaning we're done.
else if( ch == '\n' ){
//Return the cursor to the top left.
chx = x1; chy = y1;
//Clear the maximum x values for each column.
max_x[0] = x1;
for( int i = 0; i < height; i++ ) max_x[i] = 0;
//Exit the loop, and return the line.
break;
}
//Printable character?
else if( (ch >= 32 && ch = x2 ){ chx = x1; chy++; }
//There's nowhere to write text anymore.
if( chy > y2 ) continue;
//Increase maximum x position.
max_x[chy - y1]++;
//Update cursor position.
wmove(win, chy, chx);
printDebug = false;
}
//Backspace.
else if( ch == KEY_BACKSPACE ){
//Only run if there is text.
if( line.length() > 0 ){
//Substract cursor position.
if( chx-1 >= x1 ) chx--;
//Wrap around if the cursor x position was gonna be negative.
else if( chy-1 >= y1 ){ chy--; chx = x2-1; }
//There's nothing to remove.
else continue;
//Calculate relative cursor positions to the box.
int rel_x = chx - x1;
int rel_y = chy - y1;
//Index.
int index = rel_y * width + rel_x;
//Don't allow negative indices.
if( index < 0 ) continue;
//Remove the character at the index.
line.erase(index, 1);
//Rewrites everything
for( int i = index; i < width*height; i++){
int x = x1 + i % width;
int y = y1 + i / width;
//If within text range, rewrite the text.
if (i < line.length()) mvwaddch(win, y, x, line[i]);
//If not remove the text.
else mvwaddch(win, y, x, ' ');
}
//Update cursor position.
wmove(win, chy, chx);
//Update maximum x position.
max_x[chy - y1]--;
printDebug = false;
}
}
//Cursor movement.
else if( ch == KEY_RIGHT ){
//Future character position.
int newchx = chx + 1;
//Wrap would be x position.
if( newchx >= x2 ){
//Can we get much lower?
if( chy+1 < y2 ){
newchx = x1 + 1;
chy++;
} else newchx = chx; //We can't
}
//Make the new position the maximum x position if we exceeded it.
if( newchx > max_x[chy - y1] ) newchx = max_x[chy - y1];
chx = newchx;
//Update cursor position
wmove(win, chy, chx);
printDebug = false;
}
else if( ch == KEY_LEFT ){
int newchx = chx - 1;
if( newchx < x1 ){
if( chy > y1 ){
newchx = x2 - 1;
chy--;
} else newchx = chx;
}
chx = newchx;
wmove(win, chy, chx);
printDebug = false;
}
}
//Hide cursor again.
curs_set(0);
return line;
< /code>
} < /p>
И вот как я использую его на main.cpp < /p>
while(1){
//Get the message.
std::string message = Handle_Messages(terminalHeight-4, 1,
terminalHeight-1, terminalWidth-18);
if( message != "" ) break;
//Present what we have written.
refresh();
}
Одна вещь, которую я попробовал, подумал, это использовал noecho () и удаление всех строк, которые использовали mvaddch () , но, как ни странно, было написано, и я буквально не имею подсказки.>
У меня есть эта функция, которая обрабатывает написание текста в поле сообщения, которое я написал с нуля, потому что getstr () была слишком ограничена для меня. Проблема заключается в том, что сегодня я попытался сделать свой код более однопользованным безопасным, используя Wtimeout (Win, 0) до getch () , однако после этого появилось много ошибок, большинство из них нам достаточно легко исправить, кроме одного. Всякий раз, когда я достигаю правой границы с ящиком сообщений и должен обернуться влево и перейти по одной линии, текст продолжает писать, где изначально был курсор, и это вызывает много визуальных проблем. < /P> Вот код: < /p> [code]std::string Handle_Messages(int y1, int x1, int y2, int x2){ //Show the cursor back. curs_set(1); //Puts the cursor on the message box's top left corner. wmove(win, y1, x1); //Allow writing. echo(); //Enables special characters (like backspace!). keypad(win, TRUE); //Makes getch() non blocking, which is single-thread safe. wtimeout(win, 0);
//Width and height. const int width = x2 - x1; const int height = y2 - y1;
//Initialize cursor positions if they haven't been initialized already. if( chx == 0 ) chx = x1; if( chy == 0 ) chy = y1; //Initialize max_x if not already intialized. if( !max_x ){ max_x = new int[height]; max_x[0] = x1; //Set all indices (except the first one) to 0 to prevent undefined behavior. for( int i = 1; i < height; i++ ){ max_x[ i ] = 0; } } //The character read (int rather than char because special characters expect ints) int ch; //Have we cleared "Type Message"? bool messageGone = false;
//Reading loop while(1){ //Nothing is in the message box? Write "Type Message". if( !line.length() ){ wattron(win, A_DIM); mvwprintw(win, y1, x1, "Type Message..."); wattroff(win, A_DIM); wmove(win, chy, chx); messageGone = false; } //Clear "Type Message" if there is something in the message box //and we haven't cleared it before. if( line.length() > 0 && !messageGone ){ mvwprintw(win, y1, x1, " "); mvwprintw(win, y1, x1, "%s", line.c_str()); wmove(win, chy, chx); messageGone = true; }
//Get a character. ch = getch(); if( ch == ERR ){ if( !printDebug ){ // (for debugging). // fprintf(stderr, ... ); printDebug = true; } return ""; } //Pressed enter, meaning we're done. else if( ch == '\n' ){ //Return the cursor to the top left. chx = x1; chy = y1; //Clear the maximum x values for each column. max_x[0] = x1; for( int i = 0; i < height; i++ ) max_x[i] = 0; //Exit the loop, and return the line. break; } //Printable character? else if( (ch >= 32 && ch = x2 ){ chx = x1; chy++; } //There's nowhere to write text anymore. if( chy > y2 ) continue; //Increase maximum x position. max_x[chy - y1]++; //Update cursor position. wmove(win, chy, chx); printDebug = false; } //Backspace. else if( ch == KEY_BACKSPACE ){ //Only run if there is text. if( line.length() > 0 ){ //Substract cursor position. if( chx-1 >= x1 ) chx--; //Wrap around if the cursor x position was gonna be negative. else if( chy-1 >= y1 ){ chy--; chx = x2-1; } //There's nothing to remove. else continue; //Calculate relative cursor positions to the box. int rel_x = chx - x1; int rel_y = chy - y1; //Index. int index = rel_y * width + rel_x; //Don't allow negative indices. if( index < 0 ) continue; //Remove the character at the index. line.erase(index, 1); //Rewrites everything for( int i = index; i < width*height; i++){ int x = x1 + i % width; int y = y1 + i / width; //If within text range, rewrite the text. if (i < line.length()) mvwaddch(win, y, x, line[i]); //If not remove the text. else mvwaddch(win, y, x, ' '); } //Update cursor position. wmove(win, chy, chx); //Update maximum x position. max_x[chy - y1]--; printDebug = false; } } //Cursor movement. else if( ch == KEY_RIGHT ){ //Future character position. int newchx = chx + 1; //Wrap would be x position. if( newchx >= x2 ){ //Can we get much lower? if( chy+1 < y2 ){ newchx = x1 + 1; chy++; } else newchx = chx; //We can't } //Make the new position the maximum x position if we exceeded it. if( newchx > max_x[chy - y1] ) newchx = max_x[chy - y1]; chx = newchx; //Update cursor position wmove(win, chy, chx); printDebug = false; } else if( ch == KEY_LEFT ){ int newchx = chx - 1; if( newchx < x1 ){ if( chy > y1 ){ newchx = x2 - 1; chy--; } else newchx = chx; } chx = newchx; wmove(win, chy, chx); printDebug = false; } } //Hide cursor again. curs_set(0); return line; < /code> } < /p> И вот как я использую его на main.cpp < /p> while(1){ //Get the message. std::string message = Handle_Messages(terminalHeight-4, 1, terminalHeight-1, terminalWidth-18); if( message != "" ) break; //Present what we have written. refresh(); } [/code] Одна вещь, которую я попробовал, подумал, это использовал noecho () и удаление всех строк, которые использовали mvaddch () , но, как ни странно, было написано, и я буквально не имею подсказки.>