Intereting Posts

как я могу написать буфер экрана консоли ANSI C?

Я работаю над созданием ASCII-игры, и везде, где я смотрю, люди говорят, что используют Console.Write () из MSDN, что является dandy и все, если вы используете Windows, но я нет.

И, таким образом, я пытаюсь написать функцию или группу функций в C, которые могут чередоваться между двумя экранными буферами, и записывать их на экран, аналогично тем, какими будут страницы man, а также pico, vim и Emacs.

У меня работает буфер, и я нашел старую ASCII-игру для linux под названием 0verkill, которая использует C и putchar () для размещения каждого символа на экране, но все мои попытки воссоздать это, приводят к непрерывному streamу текста, а не панель размера статического текста. Я действительно не хочу использовать какие-либо внешние библиотеки, такие как проклятия (потому что это снизит переносимость) и хотелось бы придерживаться стандартов ansi, если это вообще возможно.

Спасибо!

    Я действительно не хочу использовать какие-либо внешние библиотеки, такие как проклятия (потому что это уменьшит переносимость)

    Какие? Библиотеки, такие как проклятия и ncurses, предназначены для того, чтобы сделать этот вид более переносимым, потому что …

    и хотел бы придерживаться стандартов ansi, если это вообще возможно.

    … нет стандарта ANSI (по крайней мере для C) для того, что вы хотите. Каждая операционная система реализует такое поведение по-разному, поэтому, если вам нужен переносной способ сделать это, вам нужно использовать библиотеку. Честно говоря, мне бы не хотелось разрабатывать систему, в которой не было ncurses, перенесенных на нее. Представьте себе все программы, которые вы не сможете использовать без него.

    Я думаю, что вы ищете управляющий символ ANSI ESC[2J который очищает экран. Вы бы назвали это после любого изменения состояния, чтобы «обновить» экран консоли.

    Посмотрите эту страницу, чтобы узнать о других. Используя эти коды, вы можете определять цвета и форматирование (расстояние, выравнивание, отступы и т. Д.) На консоли.

    Существует стандарт ANSI X3.64, также ISO / IEC 6429, который описывает терминал DEC VT100. В стандарте описаны некоторые escape-последовательности для определения цвета и курсора, которые распознает совместимый эмулятор терминала, который будет в основном всех X-терминалов, но в Windows не обязательно (возможно, вам нужен пользователь для загрузки ansi.sys ). Именно эта последняя уродливая несогласованность иллюстрирует, почему вы должны использовать ncurses, который абстрагирует эту информацию.

    Пример заголовка и исходного файла, иллюстрирующий способ абстрагирования проклятий из приложения. Собирать пыль; написал его более 15 лет назад. Пусть покупатель будет бдителен.

    cursemu.h

     /*************************************************************************** * * DO NOT CHANGE ANYTHING BETWEEN THIS LINE AND THE NEXT LINE THAT HAS THE * WORDS "KLAATU BARRATA NIKTO" ON IT * ***************************************************************************/ #ifndef X__CURSEMU__H #define X__CURSEMU__H #include  #ifdef linux #define _POSIX_VERSION #endif #ifndef _POSIX_VERSION #include  #define USE_OLD_TTY #include  #undef USE_OLD_TTY #ifndef CBREAK #define CBREAK RAW #endif #if !defined(sun) && !defined(sequent) && !defined(hpux) && \ !defined(_AIX) && !defined(aix) #include  #define strchr index #else #include  #endif #else #include  #include  #endif #include  #include  #include  #include  #include  #include  #include  #include  #include  /* Keep looking ... */ int _tty_ch; #ifdef _POSIX_VERSION struct termios _tty; tcflag_t _res_iflg, _res_lflg; #define cbreak()(_tty.c_lflag&=~ICANON, \ tcsetattr( _tty_ch, TCSANOW, &_tty )) #define noecho()(_tty.c_lflag &= ~(ECHO|ICRNL), \ tcsetattr( _tty_ch, TCSADRAIN, &_tty )) #define savetty()((void) tcgetattr(_tty_ch, &_tty), \ _res_iflg = _tty.c_iflag, _res_lflg = _tty.c_lflag ) #define resetty()(_tty.c_iflag = _res_iflg, _tty.c_lflag = _res_lflg,\ (void) tcsetattr(_tty_ch, TCSADRAIN, &_tty)) #define erasechar()(_tty.c_cc[VERASE]) #else struct sgttyb _tty; int _res_flg; #define cbreak()(_tty.sg_flags|=CBREAK, ioctl(_tty_ch, TIOCSETP, &_tty)) #define noecho()(_tty.sg_flags &= ~(ECHO|CRMOD), \ ioctl( _tty_ch, TIOCSETP, &_tty )) #define savetty()((void) ioctl(_tty_ch, TIOCGETP, &_tty), \ _res_flg = _tty.sg_flags ) #define resetty()(_tty.sg_flags = _res_flg, \ (void) ioctl(_tty_ch, TIOCSETP, &_tty)) #define erasechar()(_tty.sg_erase) #endif /* KLAATU BARRATA NIKTO */ #define TERMCAP_LENGTH 1024 struct CtrlSeq { char termcap[ TERMCAP_LENGTH ]; int numRows, numCols; /* These pointers are indexes into the termcap buffer, and represent the * control sequences neccessary to send to the terminal window to perform * their appropriately named feature. */ char *highlight, *endMode, /* End highlight mode, and other modes. */ *clearScr, *clearEol, *scrollRegion, *moveCursor, *deleteRow, *insertRow, *saveCursor, /* Save the current cursor position */ *restoreCursor; /* Restore the saved cursor position */ int dumbTerm, /* 1 if the terminal is a dumb terminal */ flush; /* 1 if the emulation should flush stdout */ }; struct CtrlSeq ctrlSeq; #define DEFAULT_COLS 80 #define DEFAULT_ROWS 24 void ce_flush( int toSet ); void ce_puts( char *str ); void ce_gotoRowCol( int row, int col ); void ce_writeStrRowCol( char *theText, int row, int col ); void ce_writeStr( char *theText ); void ce_writeCharRowCol( char theChar, int row, int col ); void ce_writeChar( char theChar ); void ce_clearScreen( void ); void ce_clearEol( void ); void ce_highlight( int on ); void ce_scrollRegion( int row1, int row2 ); void ce_deleteRow( int row ); void ce_insertRow( int row ); void ce_saveCursor( void ); void ce_restoreCursor( void ); int ce_getRows( void ); int ce_getCols( void ); #endif 

    cursemu.c

     #include "cursemu.h" int putchar_x( int c ) { return( putchar( c ) ); } /* Returns 0 on success, -1 on error */ int ce_startCurses( void ) { char *ptr, tempBuff[ 1024 ]; int result = 0; if( (ptr = (char *)getenv( "TERM" )) != NULL ) result = tgetent( tempBuff, ptr ); else result = tgetent( tempBuff, "vt100" ); if( result < 1 ) { perror( "FATAL Error: No termcap entry found (even tried vt100)!\n" ); return( -1 ); } ptr = ctrlSeq.termcap; if( (ctrlSeq.numCols = tgetnum( "co" )) == -1 ) ctrlSeq.numCols = DEFAULT_COLS; if( (ctrlSeq.numRows = tgetnum( "li" )) == -1 ) ctrlSeq.numRows = DEFAULT_ROWS; if( (ctrlSeq.moveCursor = (char *)tgetstr( "cm", &ptr )) == NULL ) ctrlSeq.moveCursor = (char *)tgetstr( "cl", &ptr ); if( (ctrlSeq.highlight = (char *)tgetstr( "mr", &ptr )) == NULL ) ctrlSeq.highlight = (char *)tgetstr( "md", &ptr ); ctrlSeq.endMode = (char *)tgetstr( "me", &ptr ); ctrlSeq.clearEol = (char *)tgetstr( "ce", &ptr ); ctrlSeq.clearScr = (char *)tgetstr( "cl", &ptr ); ctrlSeq.scrollRegion = (char *)tgetstr( "cs", &ptr ); ctrlSeq.deleteRow = (char *)tgetstr( "dl", &ptr ); ctrlSeq.insertRow = (char *)tgetstr( "al", &ptr ); ctrlSeq.saveCursor = (char *)tgetstr( "sc", &ptr ); ctrlSeq.restoreCursor = (char *)tgetstr( "rc", &ptr ); ctrlSeq.dumbTerm = (ctrlSeq.moveCursor == NULL) || (ctrlSeq.scrollRegion == NULL) || (ctrlSeq.saveCursor == NULL) || (ctrlSeq.restoreCursor == NULL) || (ctrlSeq.clearEol == NULL); ctrlSeq.flush = 1; if( !ctrlSeq.dumbTerm ) { if( (_tty_ch = open( "/dev/tty", O_RDWR, 0 ) ) == -1 ) _tty_ch = 0; savetty(); cbreak(); noecho(); return( 0 ); } return( -1 ); } int ce_endCurses( void ) { ce_scrollRegion( -1, -1 ); ce_gotoRowCol( ce_getRows() - 1, 0 ); resetty(); } void ce_flush( int toSet ) { ctrlSeq.flush = toSet; if( toSet == 1 ) fflush( stdout ); } void ce_puts( char *str ) { tputs( str, 0, putchar_x ); if( ctrlSeq.flush ) fflush( stdout ); } void ce_gotoRowCol( int row, int col ) { if( row > ctrlSeq.numRows ) row = ctrlSeq.numRows; if( col > ctrlSeq.numCols ) col = ctrlSeq.numCols; ce_puts( (char *)tgoto( ctrlSeq.moveCursor, col, row ) ); } void ce_writeStrRowCol( char *theText, int row, int col ) { ce_flush( 0 ); ce_gotoRowCol( row, col ); ce_writeStr( theText ); ce_flush( 1 ); } void ce_writeStr( char *theText ) { ce_flush( 0 ); printf( "%s", theText ); ce_flush( 1 ); } void ce_writeCharRowCol( char theChar, int row, int col ) { ce_flush( 0 ); ce_gotoRowCol( row, col ); ce_writeChar( theChar ); ce_flush( 1 ); } void ce_writeChar( char theChar ) { ce_flush( 0 ); printf( "%c", theChar ); ce_flush( 1 ); } void ce_clearScreen( void ) { ce_puts( ctrlSeq.clearScr ); } void ce_clearEol( void ) { ce_puts( ctrlSeq.clearEol ); } void ce_highlight( int on ) { if( on == 0 ) ce_puts( ctrlSeq.endMode ); else ce_puts( ctrlSeq.highlight ); } void ce_scrollRegion( int row1, int row2 ) { ce_puts( (char *)tgoto( ctrlSeq.scrollRegion, row1, row2 ) ); } void ce_deleteRow( int row ) { ce_gotoRowCol( row, 0 ); ce_puts( ctrlSeq.deleteRow ); } void ce_insertRow( int row ) { ce_gotoRowCol( row, 0 ); ce_puts( ctrlSeq.insertRow ); } void ce_saveCursor( void ) { ce_puts( ctrlSeq.saveCursor ); } void ce_restoreCursor( void ) { ce_puts( ctrlSeq.restoreCursor ); } int ce_getRows( void ) { return( ctrlSeq.numRows ); } int ce_getCols( void ) { return( ctrlSeq.numCols ); } 

    составление

    Требуется:

     gcc -o cursemu.o -lcurses -ltermcap