/**[txh]******************************************************************** Copyright (c) 2002 by Jose Angel Sánchez Caso (JASC) Squeletons by Salvador E. Tropea (SET) Description: Windows Screen routines. ***************************************************************************/ #include #define Uses_string #define Uses_stdlib #define Uses_unistd #define Uses_AllocLocal #define Uses_TScreen #define Uses_TEvent #define Uses_TGKey #define Uses_TVCodePage #include #if defined(TVOS_Win32) && !defined(TV_Disable_WinGr_Driver) #define WIN32_LEAN_AND_MEAN #include #include #include #include /* Not always defined */ #ifndef IDC_ARROW #define IDC_ARROW MAKEINTRESOURCE(32512) #endif #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif #ifndef IDC_SIZENWSE #define IDC_SIZENWSE MAKEINTRESOURCE(32642) #endif const int cursorDelay= 300000; static char * className= "TVISION for windows"; /* Make the classname into a global variable */ /* ------------------------------------------------------------------------- */ VOID CALLBACK cursorProc( HWND hwnd // handle of window for timer messages , UINT uMsg // WM_TIMER message , UINT idEvent // timer identifier , DWORD /*dwTime*/ ) // current system time /* ------------------------------------------------------------------------- */ { if ( uMsg ) { TScreenWinGr::zPos ^= 0x80; /* Toggle phase (turn 180 degrees) */ if ( TScreenWinGr::xPos >= 0 ) TScreenWinGr::lowSetCursor( TScreenWinGr::xPos /* Show or hide cursor */ , TScreenWinGr::yPos , true ); } SetTimer( hwnd /* Reload timer */ , idEvent , cursorDelay / 1000 /* from usecs to msecs */ , cursorProc ); } /* ------------------------------------------------------------------------- */ TScreenWinGr::TScreenWinGr() /* ------------------------------------------------------------------------- */ { FreeConsole(); WNDCLASSEX wincl; /* Datastructure for the windowclass */ STARTUPINFO startinfo; HINSTANCE TvWinThisInstance= GetModuleHandle (NULL); GetStartupInfoA (&startinfo); /* Get the command line passed to the process. */ normCursor= LoadCursor(NULL, IDC_ARROW ); handCursor= LoadCursor(NULL, IDC_HAND ); /* Not available in 95 and NT */ if( handCursor==NULL ) { handCursor= LoadCursor(NULL, IDC_ARROW ); } sizeCursor= LoadCursor(NULL, IDC_SIZENWSE ); wincl.hIcon = LoadIcon( NULL /* Use default icon and mousepointer */ , IDI_APPLICATION); wincl.hIconSm = LoadIcon( NULL , IDI_APPLICATION); wincl.style = /* CS_DBLCLKS */ 0; /* don´t Catch double-clicks */ wincl.cbSize = sizeof(WNDCLASSEX); wincl.hCursor = normCursor; wincl.hInstance = TvWinThisInstance; wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.lpszMenuName = NULL; /* No menu */ wincl.lpszClassName= className; wincl.hbrBackground= NULL; if( !RegisterClassEx(&wincl) ) /* Register the window class, if fail quit the program */ { return; } /* The class is registered, lets create a program */ CreateWindow ( className /* Classname ("MyLittleWindow") */ , className /* Title Text */ , WS_CAPTION /* defaultwindow */ | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX , CW_USEDEFAULT /* Windows decides the position */ , CW_USEDEFAULT /* where the window end up on the screen */ , 800, 448 /* win size */ , HWND_DESKTOP /* The window is a childwindow to desktop */ , NULL /* No menu */ , TvWinThisInstance /* Program Instance handler */ , NULL ); /* No Window Creation data */ if ( ! hwnd ) { return; } initialized++ ; ShowWindow( hwnd /* Make the window visible on the screen */ , startinfo.dwFlags & STARTF_USESHOWWINDOW ? startinfo.wShowWindow : SW_SHOWDEFAULT ); for ( int col= 0 ; col<16 ; col++ ) { colorMap[ col ]= RGB( (col&4) ? (col&8) ? 0xFF:0x80:0 , (col&2) ? (col&8) ? 0xFF:0x80:0 , (col&1) ? (col&8) ? 0xFF:0x80:0 ); } flags0= CodePageVar | CursorShapes; screenMode= startupMode= getCrtMode(); cursorLines= startupCursor= getCursorType(); screenWidth= GetCols(); screenHeight= GetRows(); screenBuffer= ( ushort *) calloc( sizeof( ushort ) , screenHeight*screenWidth ); // This zeroes memory /* * Start cursor blinking handler */ cursorProc( hwnd // handle of window for timer messages , 0 // Don´t draw cursor , 0 // timer identifier , 0 ); } // current system time /* ------------------------------------------------------------------------- */ void TScreenWinGr::Init() /* ------------------------------------------------------------------------- */ { TScreen::System_p= System; TScreen::Resume= Resume; TScreen::Suspend= Suspend; TScreen::clearScreen= clearScreen; TScreen::setCharacter= setCharacter; TScreen::setCharacters= setCharacters; TScreen::setVideoMode= setVideoMode; TScreen::setVideoModeExt= setVideoModeExt; } /* ------------------------------------------------------------------------- */ void TScreenWinGr::Done() /* ------------------------------------------------------------------------- */ { } /* ------------------------------------------------------------------------- */ void TScreenWinGr::Resume() /* ------------------------------------------------------------------------- */ { SaveScreen(); } /* ------------------------------------------------------------------------- */ void TScreenWinGr::Suspend() /* ------------------------------------------------------------------------- */ { RestoreScreen(); } /* ------------------------------------------------------------------------- */ TScreenWinGr::~TScreenWinGr() /* ------------------------------------------------------------------------- */ { if (screenBuffer) { delete screenBuffer; screenBuffer= NULL; }} /* ------------------------------------------------------------------------- */ void TScreenWinGr::clearScreen() /* ------------------------------------------------------------------------- */ { } /* -------------------------------------------------------------------------- */ void TScreenWinGr::writeLine( unsigned x , unsigned y , int w , char * str , uchar color ) /* -------------------------------------------------------------------------- */ { if (w<=0) // Nothing to do { return; } SetBkColor ( hdc, colorMap[color>>4]); // Color de fondo SetTextColor( hdc, colorMap[color&15]); // Color de fondo TextOut( hdc // Output text , x * tm.tmMaxCharWidth , y * tm.tmHeight , str , w ); if ( y==yPos ) { if ( xPos >= x) { if ( xPos<= x+w ) { lowSetCursor( xPos , yPos , true ); }}}} /* ------------------------------------------------------ [ JASC jul/2002] -- */ void TScreenWinGr::setCharacters( unsigned offset , ushort * src , unsigned len ) /* -------------------------------------------------------------------------- */ { uchar letra; uchar color; int add ; int last ; ushort x= offset % screenWidth; // Regenerate cartesian coordinates ushort y= offset / screenWidth; ushort *old = screenBuffer + offset; ushort *old_right = old + len - 1; ushort *src_right = src + len - 1; char * dst; if (!len) { return; } if (!forceRedraw) { while (len > 0 && *old == *src) /* remove unchanged characters from left to right */ { x++; offset++; old++; src++; len--; } while (len > 0 && *old_right == *src_right) /* remove unchanged characters from right to left */ { old_right--; src_right--; len--; }} AllocLocalStr(tmp,len); /* write only middle changed characters */ dst= tmp; add= 0; last= -1; memcpy( old /* Copy to screen buffer */ , src , len*2 ); while(len--) /* Iterate */ { letra= attrChar(*src); /* JASC, are macros (endian dependent) */ color= attrColor(*src); if ( color != last ) { if (last>=0) { writeLine( x , y , add , tmp , last ); /* Print last same color block */ dst= tmp; x+= add; add= 0; } last= color; } *dst= letra; dst++; src++; add++; } if (!add) { return; } writeLine( x , y , add , tmp , last ); } /* Print last block */ /* ------------------------------------------------------------------------- */ void TScreenWinGr::setCharacter(unsigned offset, unsigned int value) /* ------------------------------------------------------------------------- */ { setCharacters( offset , reinterpret_cast(&value) , 1 ); } /* ------------------------------------------------------------------------- */ void TScreenWinGr::SaveScreen() /* ------------------------------------------------------------------------- */ { } /* ------------------------------------------------------------------------- */ void TScreenWinGr::RestoreScreen() /* ------------------------------------------------------------------------- */ { } /* ------------------------------------------------------------------------- */ void TScreenWinGr::SaveScreenReleaseMemory(void) /* ------------------------------------------------------------------------- */ {/* if (buffer) { delete buffer; } buffer = NULL; */ } /* ------------------------------------------------------------------------- */ void TScreenWinGr::setVideoMode( ushort mode ) /* ------------------------------------------------------------------------- */ { int sz= getRows()*getCols(); if (screenBuffer) { free( screenBuffer); screenBuffer= NULL; } screenBuffer= ( ushort *) calloc( sizeof(ushort) , sz ); // This zeroes memory setCrtMode( fixCrtMode( mode ) ); setCrtData(); } /* ------------------------------------------------------------------------- */ int TScreenWinGr::System( const char * command , pid_t * pidChild , int in , int out , int err) /* ------------------------------------------------------------------------- */ #ifndef TVCompf_Cygwin { if (pidChild) // fork mechanism not implemented, indicate the child finished { *pidChild=0; } // If the caller asks for redirection replace the requested handles if (in!=-1) dup2(in,STDIN_FILENO); if (out!=-1) dup2(out,STDOUT_FILENO); if (err!=-1) dup2(err,STDERR_FILENO); return system(command); } #else /* * fork mechanism is implemented in Cygwin, so linux code should work -- OH! * SET: Call to an external program, optionally forking */ { if (!pidChild) { // If the caller asks for redirection replace the requested handles if (in!=-1) dup2(in,STDIN_FILENO); if (out!=-1) dup2(out,STDOUT_FILENO); if (err!=-1) dup2(err,STDERR_FILENO); return system(command); } pid_t cpid=fork(); /* * Ok, we are the child * I'm not sure about it, but is the best I have right now. * Doing it we can kill this child and all the subprocesses * it creates by killing the group. It also have an interesting * effect that I must evaluate: By doing it this process lose * the controlling terminal and won't be able to read/write * to the parents console. I think that's good. */ if ( !cpid ) { if ( setsid()==-1 ) { _exit(127); } char *argv[4]; // If the caller asks for redirection replace the requested handles if (in!=-1) dup2(in,STDIN_FILENO); if (out!=-1) dup2(out,STDOUT_FILENO); if (err!=-1) dup2(err,STDERR_FILENO); argv[0]=getenv("SHELL"); if (!argv[0]) { argv[0]="/usr/bin/sh"; } argv[1]="-c"; argv[2]=(char *)command; argv[3]=0; execvp( argv[0] , argv ); _exit(127); } // We get here only if exec failed if (cpid==-1) // Fork failed do it manually { *pidChild=0; return system(command); } *pidChild=cpid; return(0); } #endif /* ------------------------------------------------------------------------- */ TScreen * TV_WinGrDriverCheck() /* ------------------------------------------------------------------------- */ { TScreenWinGr *drv=new TScreenWinGr(); if ( !TScreen::initialized ) { delete drv; drv= NULL; } TGKeyWinGr::init(); TScreenWinGr::Init(); TDisplayWinGr::Init(); THWMouseWinGr::init(); return(drv); } #else #include #include #include #endif // TVOS_Win32