У меня есть эта функция, которая обрабатывает написание текста в поле сообщения, которое я написал с нуля, потому что 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);
//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 = wgetch(win);
if( ch == ERR ){
if( !printDebug ){
// fprintf(stderr, ... );
printDebug = true;
}
return "";
}
else if( ch == '\n' ){
chx = x1; chy = x1;
max_x[0] = x1;
for( int i = 0; i < height; i++ ) max_x[i] = 0;
break;
}
else if( (ch >= 32 && ch = x2 ){ chx = x1; chy++; }
if( chy > y2 ) continue;
max_x[chy - y1]++;
wmove(win, chy, chx);
printDebug = false;
}
else if( ch == KEY_BACKSPACE ){
if( line.length() > 0 && (width)){
if( chx >= x1 ) chx--;
if( chy > y1 ){ chy--; chx = x2-1; }
int rel_x = chx - x1;
int rel_y = chy - y1;
int index = rel_y * width + rel_x;
if( index < 0 ) continue;
line.erase(index, 1);
for( int i = index; i < width*height; i++){
int x = x1 + i % width;
int y = y1 + i / width;
if (i < line.length()) mvwaddch(win, y, x, line[i]);
else mvwaddch(win, y, x, ' ');
}
wmove(win, chy, chx);
max_x[chy - y1]--;
printDebug = false;
}
}
else if( ch == KEY_RIGHT ){
int newchx = chx + 1;
if( newchx >= x2 ){
if( chy < y2 ){
newchx = x1 + 1;
chy++;
} else newchx = chx;
}
else if( newchx > max_x[chy - y1] ) newchx = max_x[chy - y1];
chx = newchx;
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;
}
}
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); //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 = wgetch(win); if( ch == ERR ){ if( !printDebug ){ // fprintf(stderr, ... ); printDebug = true; } return ""; } else if( ch == '\n' ){ chx = x1; chy = x1; max_x[0] = x1; for( int i = 0; i < height; i++ ) max_x[i] = 0; break; } else if( (ch >= 32 && ch = x2 ){ chx = x1; chy++; } if( chy > y2 ) continue; max_x[chy - y1]++; wmove(win, chy, chx); printDebug = false; } else if( ch == KEY_BACKSPACE ){ if( line.length() > 0 && (width)){ if( chx >= x1 ) chx--; if( chy > y1 ){ chy--; chx = x2-1; } int rel_x = chx - x1; int rel_y = chy - y1; int index = rel_y * width + rel_x; if( index < 0 ) continue; line.erase(index, 1); for( int i = index; i < width*height; i++){ int x = x1 + i % width; int y = y1 + i / width; if (i < line.length()) mvwaddch(win, y, x, line[i]); else mvwaddch(win, y, x, ' '); } wmove(win, chy, chx); max_x[chy - y1]--; printDebug = false; } } else if( ch == KEY_RIGHT ){ int newchx = chx + 1; if( newchx >= x2 ){ if( chy < y2 ){ newchx = x1 + 1; chy++; } else newchx = chx; } else if( newchx > max_x[chy - y1] ) newchx = max_x[chy - y1]; chx = newchx; 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; } } 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 () , но, как ни странно, было написано, и я буквально не имею подсказки.>