/**[txh]******************************************************************** Copyright (c) 2002 by Salvador E. Tropea (SET) Based on code contributed by Anatoli Soltan. Description: WinNT Screen routines. The original implementation was done by Anatoli, I removed some code, added some routines and adapted it to the new architecture. ToDo: Set UseScreenSaver when we are in full screen. Configuration variables: ScreenWidth ScreenHeight AppCP ScrCP InpCP Notes: 1) I saw a problem in W98SE, it looks like a bug in Windows: If I suspend to a shell and the resume doing window size changes at exit the screen seems to be partially restored. But if you force windows to redraw it (minimize/maximize for example) things gets right. This is problem only affects the cursor when using USE_NEW_BUFFER. 2) The USE_NEW_BUFFER mode is something I (SET) found in the Win32 API docs that's much cleaver than saving/restoring the screen contents. When defined I just create a new screen buffer and use it. To restore the screen you just need to set the original STDOUT handle as the active. It makes the code easier and exposes less Windows problems (bugs?). The only bizarre thing I observe is "invisible cursor", but this is just Windows forgets to update, as soon as the window needs a redraw the cursor gets visible again. 3) Anatoli left commented: hIn=CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); hOut=CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); I think they aren't useful but I left it here in case I need this example. ***************************************************************************/ #include #define Uses_stdlib #define Uses_TScreen #define Uses_TEvent #define Uses_TGKey #define Uses_TVCodePage #define Uses_unistd #include #include // I delay the check to generate as much dependencies as possible #ifdef TVOS_Win32 #define WIN32_LEAN_AND_MEAN #include #include #include #include //#define DEBUG #ifdef DEBUG #define DBPr1(a) fputs(a,stderr) #define DBPr2(a,b) fprintf(stderr,a,b) #define DBPr3(a,b,c) fprintf(stderr,a,b,c) #else #define DBPr1(a) #define DBPr2(a,b) #define DBPr3(a,b,c) #endif #define TV_CONSOLE_MODE (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT) #ifndef USE_NEW_BUFFER ushort *TScreenWinNT::saveScreenBuf; unsigned TScreenWinNT::saveScreenSize; unsigned TScreenWinNT::saveScreenCursorStart, TScreenWinNT::saveScreenCursorEnd; unsigned TScreenWinNT::saveScreenCursorX, TScreenWinNT::saveScreenCursorY; #else #define SaveScreenReleaseMemory() #endif DWORD TScreenWinNT::saveScreenConsoleMode; unsigned TScreenWinNT::saveScreenWidth, TScreenWinNT::saveScreenHeight; // Buffer used to arrange the data as needed by Win32 API CHAR *TScreenWinNT::outBuf; WORD *TScreenWinNT::outBufAttr; CHAR_INFO *TScreenWinNT::outBufCI; unsigned TScreenWinNT::outBufCapacity; void TScreenWinNT::ensureOutBufCapacity(unsigned count) { count=(count+1) & 0xFFFFFFFE; if (outBufCapacity>8); COORD dwBufferSize={1,1}; COORD dwBufferCoord={0,0}; SMALL_RECT rcWriteRegion={coord.X, coord.Y, coord.X, coord.Y}; WriteConsoleOutput(hOut,outBufCI,dwBufferSize,dwBufferCoord,&rcWriteRegion); //FillConsoleOutputCharacter(hOut,(CHAR)(value & 0xFF),1,coord,&cWritten); //FillConsoleOutputAttribute(hOut,(WORD)(value >> 8),1,coord,&cWritten); } void TScreenWinNT::SetCharacters(unsigned offset, ushort *values, unsigned count) { ensureOutBufCapacity(count); COORD coord; coord.Y=(SHORT)((offset)/screenWidth); coord.X=(SHORT)((offset)%screenWidth); unsigned i; for (i=0; i>8); } COORD dwBufferSize={count,1}; COORD dwBufferCoord={0, 0}; SMALL_RECT rcWriteRegion={coord.X, coord.Y, coord.X+count-1, coord.Y}; WriteConsoleOutput(hOut,outBufCI,dwBufferSize,dwBufferCoord,&rcWriteRegion); } #ifndef USE_NEW_BUFFER void TScreenWinNT::SaveScreen() { unsigned rows=GetRows(); unsigned cols=GetCols(); saveScreenSize=rows*cols; free(saveScreenBuf); saveScreenBuf=(ushort *)malloc(saveScreenSize*sizeof(ushort)); // Temporarily set these variables to let getCharacter work properly uchar screenWidthSave=screenWidth; uchar screenHeightSave=screenHeight; screenWidth=(uchar)cols; screenHeight=(uchar)rows; unsigned row, ofs; for (row=0, ofs=0; rowmax.X) newSize.X=max.X; if (newSize.Y>max.Y) newSize.Y=max.Y; // The buffer must be large enough to hold both modes (current and new) COORD newBufSize=newSize; if (info.dwMaximumWindowSize.X>newBufSize.X) newBufSize.X=info.dwMaximumWindowSize.X; if (info.dwMaximumWindowSize.Y>newBufSize.Y) newBufSize.Y=info.dwMaximumWindowSize.Y; // Enlarge the buffer size. It fails if not windowed. if (!SetConsoleScreenBufferSize(hCurrentOut,newBufSize)) return 0; // Resize the window. SMALL_RECT r={0,0,newSize.X-1,newSize.Y-1}; if (!SetConsoleWindowInfo(hCurrentOut,TRUE,&r)) {// Revert buffer size newSize.X=info.dwMaximumWindowSize.X; newSize.Y=info.dwMaximumWindowSize.Y; SetConsoleScreenBufferSize(hCurrentOut,newSize); return 0; } // Now we can shrink the buffer to the needed size SetConsoleScreenBufferSize(hCurrentOut,newSize); // This is something silly TV code spects: after a video mode change the // cursor should go to the "default" state. setCursorType(cursorLines); // Ok! we did it. return fW!=-1 || fH!=-1 || newSize.X!=(int)w || newSize.Y!=(int)h ? 2 : 1; } #else #include #include #include #endif // TVOSf_WIN32 /* Win32 API reference names 45 code pages. Only 20 of them are supported. Code page identifiers: *037 EBCDIC 437 MS-DOS United States * *500 EBCDIC "500V1" *708 Arabic (ASMO 708) *709 Arabic (ASMO 449+, BCON V4) *710 Arabic (Transparent Arabic) *720 Arabic (Transparent ASMO) 737 Greek (formerly 437G) * 775 Baltic * 850 MS-DOS Multilingual (Latin I) * 852 MS-DOS Slavic (Latin II) * 855 IBM Cyrillic (primarily Russian* 857 IBM Turkish * 860 MS-DOS Portuguese 861 MS-DOS Icelandic *862 Hebrew 863 MS-DOS Canadian-French *864 Arabic 865 MS-DOS Nordic 866 MS-DOS Russian * 869 IBM Modern Greek * *874 Thai *875 EBCDIC *932 Japan *936 Chinese (PRC, Singapore) *949 Korean *950 Chinese (Taiwan, Hong Kong) *1026 EBCDIC *1200 Unicode (BMP of ISO 10646) 1250 Windows 3.1 Eastern European * 1251 Windows 3.1 Cyrillic * 1252 Windows 3.1 US (ANSI) * 1253 Windows 3.1 Greek * 1254 Windows 3.1 Turkish * *1255 Hebrew *1256 Arabic 1257 Baltic * *1361 Korean (Johab) *10000 Macintosh Roman *10001 Macintosh Japanese *10006 Macintosh Greek I 10007 Macintosh Cyrillic *10029 Macintosh Latin 2 *10079 Macintosh Icelandic *10081 Macintosh Turkish ----------------- My registry also says: 20866 28591 28592 28595 28597 As a Windows 9x is shipped working with only one code page I can't test what a hell are these code pages. They seems to be some variant of 866 and some kind of ISO cp, just a guess. */