X.EXE's virtual keyboard.
Regarding the ExtTextOut() example I showed,
quoting from " www.Cotse.NET/users/jeffrelf/X.CPP "
( X.EXE's settings are at: " www.Cotse.NET/users/jeffrelf/X.TXT "
X.EXE is at: " www.Cotse.NET/users/jeffrelf/X.CPP " )...
I've changed that code quite a bit,
here are some highlights from it... The output looks like:
" www.Cotse.NET/users/jeffrelf/MinCho.PNG ".
if ( Eq ( Tb_Hit->Handler, L"UTF" ) ) {
// X.EXE's UTF button was hit,
// so give us a selection of glyphs ( i.e. a virtual keyboard ):
Log ( Begin_Log ); Dump = 1 ; int Chars = 0 ;
wchar_t Line[ 100 ], Bl[ 8 ], Init[ 8 ], Show [] = {
// Display these character ranges,
// covering 1.3 thousand glyphs.
// ( out of the million or so possible glyphs )
Lowest_Ascii + 1, Highest_Ascii
, L'??', L'??', L'??',L'??', L'??',L'??', L'???', L'???'
, L'???', L'???', L'???', L'???', L'???', L'???', L'???', L'???'
, L'???', L'???', L'???', L'???', L'???', L'???' };
LnP S = Show - 1 ;
Loop( sizeof Show / 2 / Sz_Char ) {
wchar_t est = * ++ S, EST = * ++ S ;
int Sz_Bl, Blanks = 0, BoSeg = 1
, EoSeg = 0, Col, ColsCh ; LnP P = Line - 1 ;
if ( ! J ) Col = * Init = 0 ;
// Put the UTF- hex number into Init,
// with control characters to color it:
else Col = -2 + Str( Init, L"%c%x%c ", Ch_New, est, Ch_Default );
// Display a rang of glyphs, from low-est to high-EST:
Loop( EST - est + 1 ) { ColsCh = _Gy( Ch = J + est )->ColsCh ;
// Toss ( and report on ) the glyphs that won't cache:
if ( ! ColsCh ) { Blanks ++ ; continue ; } Chars ++ ;
if ( ! Blanks ) Sz_Bl = * Bl = 0 ;
else Sz_Bl = Str( Bl, L" %d", Blanks ), Blanks = 0 ;
if ( ( Col += 1 + ColsCh + Sz_Bl ) < Col_Me ) {
// Insert a glyph ( and, maybe, a report ) into the line:
IncLin: if ( Sz_Bl ) Sz_Bl = 0, P += -1 + Str( ++ P, Bl );
* ++ P = Ch ; * ++ P = 32 ; continue ; }
// Display the line ( Init might have the UTF- hex number ):
EoSeg: * ++ P = 0 ; CPU_100( 0 );
Sh(L"%s%s", Init, Line ); if ( BoSeg ) * Init = 0 ;
Col = ColsCh + Sz_Bl, P = Line - 1 ; goto IncLin ; }
// Draw the last line of glyphs:
if ( ! EoSeg ) { EoSeg = 1 ; goto EoSeg ; } }
Sh(L"%s Chars", Prn( Chars ) ), Dump = 0 ;
Log ( End_Log ); goto Next_Event ; }
.................
#define Okay \
( rv >= 0 || rv == DDERR_WASSTILLDRAWING || rv == DDERR_SURFACELOST )
int Chk( int rv ) { if ( Okay ) return rv ;
LnP Err = LnP( DXGetErrorString8( rv ) );
return rv ;
// Note, the DDERR_CANTCREATEDC error happens
// when one attempts to create more than 20 thousand or so
// DirectDraw 7 surfaces... On Windows XP,
// _ All _ running programs together can't exceed this limit.
}
void Fast_Paint ( _SurT Sur_From, RECT FromR, RECT ToR ) {
if( ! Sur_From ) return; int X = ToR.left, Y = ToR.top;
long * P = Lng ToR - 1, * V = Lng Rec_Me;
Loop( 4 ) { int X= J & 1;
* P = Bound( * ++P, V[ X ? 1 : 0 ], V[ X ? 3 : 2 ]); }
P= Lng ToR; int W= P[2]-P[0], H= P[3]-P[1]; if( !W|| !H) return;
P= Lng FromR; if(X< 0) P[0]= P[2]- W; else P[2]= P[0]+ W;
if(Y< 0) P[1]= P[3]- H; else P[3]= P[1]+ H;
// BltFast() barfs if either the source or destination rectangles
// are out of bounds... " pois ?? ".
Chk( Sur_Draw->BltFast(
ToR.left, ToR.top, Sur_From, & FromR
, Sur_From != Cursor ? 0 : DDBLTFAST_SRCCOLORKEY ) ); }
_SurT ChFont( GyP P, const ulong * Hue );
const int Lowest_Ascii = 32, Highest_Ascii = 126 ;
GyP _Gy( wchar_t Ch ) { GyP P ; int Greater_Ch = 0 ;
if ( Ch >= Lowest_Ascii && Ch <= Highest_Ascii )
return Gy.BB [ Ch - Lowest_Ascii ];
GyA
BB = Gy.BB + ( Highest_Ascii - Lowest_Ascii + 1 )
, EE = Gy.PP + 1, PP = BB ;
// Look up the character, using this binary searh:
LOOP { PP = BB + ( EE - BB ) / 2 ;
if ( PP == Gy.PP + 1 ) { Greater_Ch = 0 ; break ; }
P = * PP ; Greater_Ch = Ch - P->Ch ;
if ( ! Greater_Ch ) return P ;
if ( Greater_Ch > 0 ) { if ( PP >= EE ) break ; BB = PP + 1 ; }
else { if ( PP <= BB ) break ; EE = PP - 1 ; } }
// Not found... insert it into the sorted list.
int _PP = PP - Gy.BB ; Inc( Gy );
EE = Gy.PP + 1, PP = Gy.BB + _PP ; int After = EE - PP - 1 ;
if ( Greater_Ch > 0 ) PP ++, -- After ;
if ( After > 0 ) memmove( PP + 1, PP, After * Sz_Ptr );
* PP = P = ( GyP ) Malloc ( sizeof * P ) ;
P->Ch = Ch, P->ColsCh = 1 ;
// Try to cache the glyph, using the default color:
ChFont( P, Is_Digit( Ch ) ? & Hues.Num_Color : & Hues.Default_Color );
return P ; }
NewSur( _SurT & Sur, int W, int H ) {
Z.dwWidth = W , Z.dwHeight = H , Z.ddsCaps.dwCaps = DDSCAPS_TEXTURE ;
Chk( Direct_Draw->CreateSurface( & Z, & Sur, 0 ) ); }
int I_Font = -1, W_, H_ ;
int Dump, C_I, MaxCol = 100 ; const int Max_W = 2 ;
#define NewFont \
I_Font = -1, NewSur( Font, MaxCol * W_, H_ );
_SurT ChFont( GyP P, const ulong * Hue ) {
CharSurT & C = P->CharSur [ Hue - ( ulong * ) & Hues ];
if ( ! P->ColsCh || C.Font ) return C_I = C.I, C.Font ;
wchar_t Ch = P->Ch ;
HDC DC ; Chk( Font->GetDC( & DC ) );
SetTextColor( DC, * Hue );
int Sym = Ch < Lowest_Ascii || Ch > Highest_Ascii, _Dump = Dump && Sym ;
SetTextAlign( DC , TA_LEFT | TA_TOP | TA_UPDATECP );
SetPtr( DC, Sym ? SymFnt : Fnt );
int _W = W_ * Max_W , X = ( C.I = ++ I_Font ) * W_ ;
RECT R = _R( X, 0, _W, H_ );
FillRect( DC, & R, Black );
// Cache the glyph and reject it if it didn't move the " cursor ":
SetBkMode( DC, OPAQUE ), SetBkColor( DC, 0 ), MvTo( X, 0 );
ExtTextOut( DC, X, 0, ETO_CLIPPED, & R, & Ch, 1, 0 );
MvTo( X, 0 ), _W = XY.x - X ;
if ( _W < W_ ) { Chk( Font->ReleaseDC( DC ) );
// Reject the glyph; it's too small and/or not monospaced:
P->ColsCh = 0 ; return I_Font --, C_I = C.I = 0, C.Font = 0 ; }
I_Font += (
P->ColsCh = ER( P->ColsCh, _W > W_ + 2 ? Max_W : 1 ) ) - 1 ;
if ( _Dump && P->ColsCh > 1 ) {
// The glyph is a double-wide, so use a special color:
SetTextColor( DC, RGB( 133, 99, 155 ) );
ExtTextOut( DC, X, 0, ETO_CLIPPED, & R, & Ch, 1, 0 ); }
Chk( Font->ReleaseDC( DC ) );
C.Font = Font ;
// If our surface of 100 monospaced characters is used up,
// create another surface ( surfaces are a very limited resource ):
if ( I_Font > MaxCol - 1 - Max_W ) NewFont
return C_I = C.I, C.Font ; }
int Col, Row ;
PrnChar ( const ulong * Hue, wchar_t Ch ) {
GyP P = _Gy( Ch ); int _W = W_ * P->ColsCh ;
// Get the glyph's surface and index into the surface:
_SurT Font = ChFont( P, Hue );
Fast_Paint ( Font, _R( C_I * W_, 0, _W, H_ )
, _R( Rnd( Col * W ), Row * H, _W, H_ ) ); Col += P->ColsCh ; }
// Maybe we'll paint the window... maybe we won't.
Paint_Maybe ( int Chillin ) {
static double Ready ; static int Was_Chillin ;
if ( Secs < Ready ) { static int Was, Is ;
if ( Tog && Chillin && ! Was_Chillin )
* Tog &= 0xDF, Paint_Req = Was = 1 ;
if ( Chillin )
// Nothing's going on, turn off once-per-second busy indicators
// and let the CPU rest for awhile:
Sleep( Was_Chillin = 8 );
else if ( Tog ) { Was_Chillin = 0 ;
if ( Was != ( Is = Secs ) )
Was = Is, Paint_Req = 1
, * Tog = * Tog & 0x20 ? * Tog & 0xDF : * Tog | 0x20 ; }
return; }
// This repaints the entire backbuffer up to 30 times a second,
// ( but only when reuired ):
Ready = _Secs + 1 / 30. ;
// X.EXE is " maximized "; so deal Win_XP's taskbar:
In_Taskbar();
if ( ! Paint_Req || ! ShowTime ) return;
// Blank the entire " maximized " window:
Sur_Draw->Blt( & Rec_Me, 0,0, DDBLT_COLORFILL, & ErBlack );
// Dx3D: WinSur->Clear( 0, 0, D3DCLEAR_TARGET, 0, 1, 0 );
// WinSur->BeginScene();
if ( Bar ) { // Show X.EXE's taskbar:
WriteLn ( Bar, 0 ) PrnChar( & Hues.Bar_Color, Ch ); }
if ( Ln.BB && VisLn >= 0 ) { LnA PP = Ln.BB + VisLn - 1 ;
// Display rows of monospaced text:
Loop( Row_Me ) { if ( ++ PP > Ln.PP ) break;
if ( ! * PP ) continue ;
Row = J + 1 , Col = 0 ; int Num = 1 ;
int Row_Selected = First_Sel && J == J_Sel - VisLn ;
const ulong * Color = & Hues.Default_Color ;
LnP P = * PP - 1 ;
Next_Ch: wchar_t Ch = * ++ P ;
switch ( Ch ) {
case 0: case 13: case 10: continue;
// Handle the control characters, used to change colors
// and/or to turn on and off the special coloring for digits:
case Ch_NoNum: Num = 0 ; goto Next_Ch ;
case Ch_Default:
Num = 1 , Color = & Hues.Default_Color ; goto Next_Ch ;
case Ch_New:
Num = 0 , Color = & Hues.New_Color ; goto Next_Ch ;
default:
PrnChar(
Ch < 32 || Ch == 127
? & Hues.Bin_Color
: Row_Selected && P >= BSel && P <= ESel
? & Hues.Sel_Color
: Num && Is_Digit( Ch )
? & Hues.Num_Color : Iden( Ch ) ? Color : & Hues.Bin_Color
, Ch );
goto Next_Ch ; } } }
if ( ! In_Taskbar() )
// Paint the cursor, it's an overlay ( a.k.a. " sprite " ):
Fast_Paint( Cursor, Rec_Cursor
, _R( X_Mouse - Left_Scr, Y_Mouse - Top_Scr, Cur_Pix, Cur_Pix ) );
// Dx3D's sprites work something like this,
// but it's amazingly Slo-o-ow... way too slow :
// Rec_Cursor = _R(
// X_Mouse - Left_Scr, Y_Mouse - Top_Scr, Cur_Pix, Cur_Pix )
// , CrsFnt->DrawText(
// Sur_Cursor, L"???", 1, & Rec_Cursor, 0, Hues.Sel_Color );
// Pump out the entire " maximized " window:
Sur_Scr->BltFast( Left_Scr, Top_Scr, Sur_Draw, 0, 0 );
// Dx3D: WinSur->EndScene(), WinSur->Present( 0, 0, 0, 0 );
Paint_Req = 0; }