PLplot  5.10.0
wingcc.c
Go to the documentation of this file.
00001 //      PLplot WIN32 under GCC device driver.
00002 //
00003 // Copyright (C) 2004  Andrew Roach
00004 //
00005 // This file is part of PLplot.
00006 //
00007 // PLplot is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU Library General Public License as published
00009 // by the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 //
00012 // PLplot is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU Library General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Library General Public License
00018 // along with PLplot; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020 //
00021 //
00022 #include "plDevs.h"
00023 
00024 #ifdef PLD_wingcc
00025 
00026 #include <string.h>
00027 #include <windows.h>
00028 #if !defined ( __CYGWIN__ )
00029 #include <tchar.h>
00030 #else
00031 #include <winnt.h>
00032 #define _T( a )    __TEXT( a )
00033 #endif
00034 #ifdef _WIN64
00035 #define GWL_USERDATA    GWLP_USERDATA
00036 #define GCL_HCURSOR     GCLP_HCURSOR
00037 #endif
00038 
00039 #include "plplotP.h"
00040 #include "drivers.h"
00041 #include "plevent.h"
00042 
00043 #ifdef PL_HAVE_FREETYPE
00044 
00045 //
00046 //  Freetype support has been added to the wingcc driver using the
00047 //  plfreetype.c module, and implemented as a driver-specific optional extra
00048 //  invoked via the -drvopt command line toggle. It uses the
00049 //  "PLESC_HAS_TEXT" command for rendering within the driver.
00050 //
00051 //  Freetype support is turned on/off at compile time by defining
00052 //  "PL_HAVE_FREETYPE".
00053 //
00054 //  To give the user some level of control over the fonts that are used,
00055 //  environmental variables can be set to over-ride the definitions used by
00056 //  the five default plplot fonts.
00057 //
00058 //  Freetype rendering is used with the command line "-drvopt text".
00059 //  Anti-aliased fonts can be used by issuing "-drvopt text,smooth"
00060 //
00061 
00062 #include "plfreetype.h"
00063 
00064 #ifndef max_number_of_grey_levels_used_in_text_smoothing
00065 #define max_number_of_grey_levels_used_in_text_smoothing    64
00066 #endif
00067 
00068 #endif
00069 
00070 
00071 // Device info
00072 
00073 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_wingcc = "wingcc:Win32 (GCC):1:wingcc:9:wingcc\n";
00074 
00075 // Struct to hold device-specific info.
00076 
00077 typedef struct
00078 {
00079     PLFLT        scale;              // scaling factor to "blow up" to the "virtual" page in removing hidden lines
00080     PLINT        width;              // Window width (which can change)
00081     PLINT        height;             // Window Height
00082 
00083     PLFLT        PRNT_scale;
00084     PLINT        PRNT_width;
00085     PLINT        PRNT_height;
00086 
00087     PLGraphicsIn gin;
00088 
00089     char         FT_smooth_text;
00090 //
00091 // WIN32 API variables
00092 //
00093 
00094     COLORREF          colour;                       // Current Colour
00095     COLORREF          oldcolour;                    // Used for high-speed background erasing
00096     MSG               msg;                          // A Win32 message structure.
00097     WNDCLASSEX        wndclass;                     // An extended window class structure.
00098     HWND              hwnd;                         // Handle for the main window.
00099     HPEN              pen;                          // Windows pen used for drawing
00100     HDC               hdc;                          // Driver Context
00101     HDC               hdc2;                         // Driver Context II - used for Blitting
00102     HDC               SCRN_hdc;                     // The screen's context
00103     HDC               PRNT_hdc;                     // used for printing
00104     PAINTSTRUCT       ps;                           // used to paint the client area of a window owned by that application
00105     RECT              rect;                         // defines the coordinates of the upper-left and lower-right corners of a rectangle
00106     RECT              oldrect;                      // used for re-sizing comparisons
00107     RECT              paintrect;                    // used for painting etc...
00108     HBRUSH            fillbrush;                    // brush used for fills
00109     HCURSOR           cursor;                       // Current windows cursor for this window
00110     HBITMAP           bitmap;                       // Bitmap of current display; used for fast redraws via blitting
00111     HGDIOBJ           oldobject;                    // Used for tracking objects probably not really needed but
00112     HMENU             PopupMenu;
00113 
00114     PLINT             draw_mode;
00115     char              truecolour;      // Flag to indicate 24 bit mode
00116     char              waiting;         // Flag to indicate drawing is done, and it is waiting;
00117                                        // we only do a windows redraw if plplot is plotting
00118     char              enterresize;     // Used to keep track of reszing messages from windows
00119     char              already_erased;  // Used to track first and only first backgroudn erases
00120 
00121     struct wingcc_Dev *push;           // A copy of the entire structure used when printing
00122                                        // We push and pop it off a virtual stack
00123 } wingcc_Dev;
00124 
00125 
00126 void plD_dispatch_init_wingcc( PLDispatchTable *pdt );
00127 
00128 void plD_init_wingcc( PLStream * );
00129 void plD_line_wingcc( PLStream *, short, short, short, short );
00130 void plD_polyline_wingcc( PLStream *, short *, short *, PLINT );
00131 void plD_eop_wingcc( PLStream * );
00132 void plD_bop_wingcc( PLStream * );
00133 void plD_tidy_wingcc( PLStream * );
00134 void plD_state_wingcc( PLStream *, PLINT );
00135 void plD_esc_wingcc( PLStream *, PLINT, void * );
00136 
00137 #ifdef PL_HAVE_FREETYPE
00138 
00139 static void plD_pixel_wingcc( PLStream *pls, short x, short y );
00140 static void plD_pixelV_wingcc( PLStream *pls, short x, short y );
00141 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y );
00142 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour );
00143 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour );
00144 static void init_freetype_lv1( PLStream *pls );
00145 static void init_freetype_lv2( PLStream *pls );
00146 
00147 #endif
00148 
00149 
00150 //--------------------------------------------------------------------------
00151 //  Local Function definitions and function-like defines
00152 //--------------------------------------------------------------------------
00153 
00154 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size );
00155 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size );
00156 static void Resize( PLStream *pls );
00157 static void plD_fill_polygon_wingcc( PLStream *pls );
00158 static void CopySCRtoBMP( PLStream *pls );
00159 static void PrintPage( PLStream *pls );
00160 static void UpdatePageMetrics( PLStream *pls, char flag );
00161 
00162 #define SetRegStringValue( a, b, c )       SetRegValue( a, b, c, REG_SZ, strlen( c ) + 1 )
00163 #define SetRegBinaryValue( a, b, c, d )    SetRegValue( a, b, (char *) c, REG_BINARY, d )
00164 #define SetRegIntValue( a, b, c )          SetRegValue( a, b, (char *) c, REG_DWORD, 4 )
00165 #define GetRegStringValue( a, b, c, d )    GetRegValue( a, b, c, d )
00166 #define GetRegIntValue( a, b, c )          GetRegValue( a, b, (char *) c, 4 )
00167 #define GetRegBinaryValue( a, b, c, d )    GetRegValue( a, b, (char *) c, d )
00168 
00169 //--------------------------------------------------------------------------
00170 //  Some debugging macros
00171 //--------------------------------------------------------------------------
00172 
00173 #if defined ( _MSC_VER )
00174   #define Debug( a )           do { if ( pls->debug ) { fprintf( stderr, ( a ) ); } } while ( 0 )
00175   #define Debug2( a, b )       do { if ( pls->debug ) { fprintf( stderr, ( a ), ( b ) ); } } while ( 0 )
00176   #define Debug3( a, b, c )    do { if ( pls->debug ) { fprintf( stderr, ( a ), ( b ), ( c ) ); } } while ( 0 )
00177 #elif defined ( __BORLANDC__ )
00178   #define Debug     if ( pls->debug ) printf
00179   #define Debug2    if ( pls->debug ) printf
00180   #define Debug3    if ( pls->debug ) printf
00181 #else
00182   #define Verbose( ... )     do { if ( pls->verbose ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
00183   #define Debug( ... )       do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
00184   #define Debug2( ... )      do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
00185   #define Debug3( ... )      do { if ( pls->debug ) { fprintf( stderr, __VA_ARGS__ ); } } while ( 0 )
00186 #endif
00187 
00188 #define ReportWinError()     do {                                                       \
00189         LPVOID lpMsgBuf;                                                                \
00190         FormatMessage(                                                                  \
00191             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,                \
00192             NULL, GetLastError(),                                                       \
00193             MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR) &lpMsgBuf, 0, NULL ); \
00194         MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK | MB_ICONINFORMATION );       \
00195         LocalFree( lpMsgBuf ); } while ( 0 )
00196 
00197 #define CrossHairCursor()    do {                                   \
00198         dev->cursor = LoadCursor( NULL, IDC_CROSS );                \
00199         SetClassLong( dev->hwnd, GCL_HCURSOR, (long) dev->cursor ); \
00200         SetCursor( dev->cursor ); } while ( 0 )
00201 
00202 #define NormalCursor()       do {                                          \
00203         dev->cursor = LoadCursor( NULL, IDC_ARROW );                       \
00204         SetClassLongPtr( dev->hwnd, GCL_HCURSOR, (LONG_PTR) dev->cursor ); \
00205         SetCursor( dev->cursor ); } while ( 0 )
00206 
00207 #define BusyCursor()         do {                                          \
00208         dev->cursor = LoadCursor( NULL, IDC_WAIT );                        \
00209         SetClassLongPtr( dev->hwnd, GCL_HCURSOR, (LONG_PTR) dev->cursor ); \
00210         SetCursor( dev->cursor ); } while ( 0 )
00211 
00212 #define PopupPrint       0x08A1
00213 #define PopupNextPage    0x08A2
00214 #define PopupQuit        0x08A3
00215 
00216 
00217 void plD_dispatch_init_wingcc( PLDispatchTable *pdt )
00218 {
00219 #ifndef ENABLE_DYNDRIVERS
00220     pdt->pl_MenuStr = "Win32 GCC device";
00221     pdt->pl_DevName = "wingcc";
00222 #endif
00223     pdt->pl_type     = plDevType_Interactive;
00224     pdt->pl_seq      = 9;
00225     pdt->pl_init     = (plD_init_fp) plD_init_wingcc;
00226     pdt->pl_line     = (plD_line_fp) plD_line_wingcc;
00227     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_wingcc;
00228     pdt->pl_eop      = (plD_eop_fp) plD_eop_wingcc;
00229     pdt->pl_bop      = (plD_bop_fp) plD_bop_wingcc;
00230     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_wingcc;
00231     pdt->pl_state    = (plD_state_fp) plD_state_wingcc;
00232     pdt->pl_esc      = (plD_esc_fp) plD_esc_wingcc;
00233 }
00234 
00235 static TCHAR* szWndClass = _T( "PlplotWin" );
00236 
00237 
00238 //--------------------------------------------------------------------------
00239 // This is the window function for the plot window. Whenever a message is
00240 // dispatched using DispatchMessage (or sent with SendMessage) this function
00241 // gets called with the contents of the message.
00242 //--------------------------------------------------------------------------
00243 
00244 LRESULT CALLBACK PlplotWndProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam )
00245 {
00246     PLStream   *pls = NULL;
00247     wingcc_Dev *dev = NULL;
00248 
00249 //
00250 // The window carries a 32bit user defined pointer which points to the
00251 // plplot stream (pls). This is used for tracking the window.
00252 // Unfortunately, this is "attached" to the window AFTER it is created
00253 // so we can not initialise PLStream or wingcc_Dev "blindly" because
00254 // they may not yet have been initialised.
00255 // WM_CREATE is called before we get to initialise those variables, so
00256 // we wont try to set them.
00257 //
00258 
00259     if ( nMsg == WM_CREATE )
00260     {
00261         return ( 0 );
00262     }
00263     else
00264     {
00265 #ifndef _WIN64
00266 #undef GetWindowLongPtr
00267 #define GetWindowLongPtr    GetWindowLong
00268 #endif
00269         pls = (PLStream *) GetWindowLongPtr( hwnd, GWL_USERDATA ); // Try to get the address to pls for this window
00270         if ( pls )                                                 // If we got it, then we will initialise this windows plplot private data area
00271         {
00272             dev = (wingcc_Dev *) pls->dev;
00273         }
00274     }
00275 
00276 //
00277 // Process the windows messages
00278 //
00279 // Everything except WM_CREATE is done here and it is generally hoped that
00280 // pls and dev are defined already by this stage.
00281 // That will be true MOST of the time. Some times WM_PAINT will be called
00282 // before we get to initialise the user data area of the window with the
00283 // pointer to the windows plplot stream
00284 //
00285 
00286     switch ( nMsg )
00287     {
00288     case WM_DESTROY:
00289         if ( dev )
00290             Debug( "WM_DESTROY\t" );
00291         PostQuitMessage( 0 );
00292         return ( 0 );
00293         break;
00294 
00295     case WM_PAINT:
00296         if ( dev )
00297         {
00298             Debug( "WM_PAINT\t" );
00299             if ( GetUpdateRect( dev->hwnd, &dev->paintrect, TRUE ) )
00300             {
00301                 BusyCursor();
00302                 BeginPaint( dev->hwnd, &dev->ps );
00303 
00304                 if ( ( dev->waiting == 1 ) && ( dev->already_erased == 1 ) )
00305                 {
00306                     Debug( "Remaking\t" );
00307 
00308                     if ( dev->ps.fErase )
00309                     {
00310                         dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) );
00311                         ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, _T( "" ), 0, 0 );
00312                         SetBkColor( dev->hdc, dev->oldcolour );
00313                     }
00314 
00315                     plRemakePlot( pls );
00316                     CopySCRtoBMP( pls );
00317                     dev->already_erased++;
00318                 }
00319                 else if ( ( dev->waiting == 1 ) && ( dev->already_erased == 2 ) )
00320                 {
00321                     dev->oldobject = SelectObject( dev->hdc2, dev->bitmap );
00322                     BitBlt( dev->hdc, dev->paintrect.left, dev->paintrect.top,
00323                         dev->paintrect.right, dev->paintrect.bottom,
00324                         dev->hdc2, dev->paintrect.left, dev->paintrect.top, SRCCOPY );
00325                     SelectObject( dev->hdc2, dev->oldobject );
00326                 }
00327 
00328                 EndPaint( dev->hwnd, &dev->ps );
00329                 NormalCursor();
00330                 return ( 0 );
00331             }
00332         }
00333         return ( 1 );
00334         break;
00335 
00336     case WM_SIZE:
00337         if ( dev )
00338         {
00339             Debug( "WM_SIZE\t" );
00340 
00341             if ( dev->enterresize == 0 )
00342                 Resize( pls );
00343         }
00344         return ( 0 );
00345         break;
00346 
00347     case WM_ENTERSIZEMOVE:
00348         if ( dev )
00349         {
00350             Debug( "WM_ENTERSIZEMOVE\t" );
00351             dev->enterresize = 1;
00352         }
00353         return ( 0 );
00354         break;
00355 
00356 
00357     case WM_EXITSIZEMOVE:
00358         if ( dev )
00359         {
00360             Debug( "WM_EXITSIZEMOVE\t" );
00361             Resize( pls );
00362             dev->enterresize = 0;     // Reset the variables that track sizing ops
00363         }
00364         return ( 0 );
00365         break;
00366 
00367     case WM_ERASEBKGND:
00368 
00369         if ( dev )
00370         {
00371             if ( dev->already_erased == 0 )
00372             {
00373                 Debug( "WM_ERASEBKGND\t" );
00374 
00375                 //
00376                 //    This is a new "High Speed" way of filling in the background.
00377                 //    supposidely this executes faster than creating a brush and
00378                 //    filling a rectangle - go figure ?
00379                 //
00380 
00381                 dev->oldcolour = SetBkColor( dev->hdc, RGB( pls->cmap0[0].r, pls->cmap0[0].g, pls->cmap0[0].b ) );
00382                 ExtTextOut( dev->hdc, 0, 0, ETO_OPAQUE, &dev->rect, _T( "" ), 0, 0 );
00383                 SetBkColor( dev->hdc, dev->oldcolour );
00384 
00385                 dev->already_erased = 1;
00386                 return ( 1 );
00387             }
00388         }
00389         return ( 0 );
00390         break;
00391 
00392     case WM_COMMAND:
00393         if ( dev )
00394             Debug( "WM_COMMAND\t" );
00395         return ( 0 );
00396         break;
00397     }
00398 
00399     // If we don't handle a message completely we hand it to the system
00400     // provided default window function.
00401     return DefWindowProc( hwnd, nMsg, wParam, lParam );
00402 }
00403 
00404 
00405 //--------------------------------------------------------------------------
00406 // plD_init_wingcc()
00407 //
00408 // Initialize device (terminal).
00409 //--------------------------------------------------------------------------
00410 
00411 void
00412 plD_init_wingcc( PLStream *pls )
00413 {
00414     wingcc_Dev *dev;
00415 
00416 #ifdef PL_HAVE_FREETYPE
00417     static int freetype    = 0;
00418     static int smooth_text = 0;
00419     static int save_reg    = 0;
00420     FT_Data    *FT;
00421 
00422 //
00423 //  Variables used for reading the registary keys
00424 //  might eventually add a user defined pallette here, but for now it just does freetype
00425 //
00426     TCHAR key_name[]       = _T( "Software\\PLplot\\wingcc" );
00427     TCHAR Keyword_text[]   = _T( "freetype" );
00428     TCHAR Keyword_smooth[] = _T( "smooth" );
00429 #endif
00430 
00431     DrvOpt wingcc_options[] = {
00432 #ifdef PL_HAVE_FREETYPE
00433         { "text",   DRV_INT, &freetype,    "Use driver text (FreeType)"            },
00434         { "smooth", DRV_INT, &smooth_text, "Turn text smoothing on (1) or off (0)" },
00435         { "save",   DRV_INT, &save_reg,    "Save defaults to registary"            },
00436 
00437 #endif
00438         { NULL,     DRV_INT, NULL,         NULL                                    }
00439     };
00440 
00441 //
00442 // Variable for storing the program name
00443 //
00444     TCHAR *program;
00445     int   programlength;
00446 
00447 // Allocate and initialize device-specific data
00448 
00449     if ( pls->dev != NULL )
00450         free( (void *) pls->dev );
00451 
00452     pls->dev = calloc( 1, (size_t) sizeof ( wingcc_Dev ) );
00453     if ( pls->dev == NULL )
00454         plexit( "plD_init_wingcc_Dev: Out of memory." );
00455 
00456     dev = (wingcc_Dev *) pls->dev;
00457 
00458     pls->icol0 = 1;                   // Set a fall back pen colour in case user doesn't
00459 
00460     pls->termin      = 1;             // interactive device
00461     pls->graphx      = GRAPHICS_MODE; //  No text mode for this driver (at least for now, might add a console window if I ever figure it out and have the inclination)
00462     pls->dev_fill0   = 1;             // driver can do solid area fills
00463     pls->dev_xor     = 1;             // driver supports xor mode
00464     pls->dev_clear   = 0;             // driver does not support clear - what is the proper API?
00465     pls->dev_dash    = 0;             // driver can not do dashed lines (yet)
00466     pls->plbuf_write = 1;             // driver uses the buffer for redraws
00467 
00468     if ( !pls->colorset )
00469         pls->color = 1;
00470 
00471 
00472 #ifdef PL_HAVE_FREETYPE
00473 
00474 //
00475 //  Read registry to see if the user has set up default values
00476 //  for text and smoothing. These will be overriden by anything that
00477 //  might be given on the command line, so we will load the
00478 //  values right into the same memory slots we pass to plParseDrvOpts
00479 //
00480 
00481     GetRegIntValue( key_name, Keyword_text, &freetype );
00482     GetRegIntValue( key_name, Keyword_smooth, &smooth_text );
00483 
00484 #endif
00485 
00486 // Check for and set up driver options
00487 
00488     plParseDrvOpts( wingcc_options );
00489 
00490 #ifdef PL_HAVE_FREETYPE
00491 
00492 //
00493 //  We will now save the settings to the registary if the user wants
00494 //
00495 
00496     if ( save_reg == 1 )
00497     {
00498         SetRegIntValue( key_name, Keyword_text, &freetype );
00499         SetRegIntValue( key_name, Keyword_smooth, &smooth_text );
00500     }
00501 
00502 #endif
00503 
00504 // Set up device parameters
00505 
00506     if ( pls->xlength <= 0 || pls->ylength <= 0 )
00507     {
00508         // use default width, height of 800x600 if not specifed by -geometry option
00509         // or plspage
00510         plspage( 0., 0., 800, 600, 0, 0 );
00511     }
00512 
00513     dev->width  = pls->xlength - 1;     // should I use -1 or not???
00514     dev->height = pls->ylength - 1;
00515 
00516 //
00517 // Begin initialising the window
00518 //
00519 
00520     // Initialize the entire structure to zero.
00521     memset( &dev->wndclass, 0, sizeof ( WNDCLASSEX ) );
00522 
00523     // This class is called WinTestWin
00524     dev->wndclass.lpszClassName = szWndClass;
00525 
00526     // cbSize gives the size of the structure for extensibility.
00527     dev->wndclass.cbSize = sizeof ( WNDCLASSEX );
00528 
00529     // All windows of this class redraw when resized.
00530     dev->wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC | CS_PARENTDC;
00531 
00532     // All windows of this class use the WndProc window function.
00533     dev->wndclass.lpfnWndProc = PlplotWndProc;
00534 
00535     // This class is used with the current program instance.
00536 
00537     dev->wndclass.hInstance = GetModuleHandle( NULL );
00538 
00539     // Use standard application icon and arrow cursor provided by the OS
00540     dev->wndclass.hIcon   = LoadIcon( NULL, IDI_APPLICATION );
00541     dev->wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
00542     dev->wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
00543     // Color the background white
00544     dev->wndclass.hbrBackground = NULL;
00545 
00546     dev->wndclass.cbWndExtra = sizeof ( pls );
00547 
00548 
00549     //
00550     // Now register the window class for use.
00551     //
00552 
00553     RegisterClassEx( &dev->wndclass );
00554 
00555     //
00556     //convert the program name to wide char if needed
00557     //
00558 
00559 #ifdef UNICODE
00560     printf( pls->program );
00561     programlength = strlen( pls->program ) + 1;
00562     program       = malloc( programlength * sizeof ( TCHAR ) );
00563     MultiByteToWideChar( CP_UTF8, 0, pls->program, programlength, program, programlength );
00564 #else
00565     program = pls->program;
00566 #endif
00567     //
00568     // Create our main window using that window class.
00569     //
00570     dev->hwnd = CreateWindowEx( WS_EX_WINDOWEDGE + WS_EX_LEFT,
00571         szWndClass,                                         // Class name
00572         program,                                            // Caption
00573         WS_OVERLAPPEDWINDOW,                                // Style
00574         pls->xoffset,                                       // Initial x (use default)
00575         pls->yoffset,                                       // Initial y (use default)
00576         pls->xlength,                                       // Initial x size (use default)
00577         pls->ylength,                                       // Initial y size (use default)
00578         NULL,                                               // No parent window
00579         NULL,                                               // No menu
00580         dev->wndclass.hInstance,                            // This program instance
00581         NULL                                                // Creation parameters
00582         );
00583 
00584 #ifdef UNICODE
00585     free( program );
00586 #endif
00587 
00588 //
00589 // Attach a pointer to the stream to the window's user area
00590 // this pointer will be used by the windows call back for
00591 // process this window
00592 //
00593 
00594 #ifdef _WIN64
00595     SetWindowLongPtr( dev->hwnd, GWL_USERDATA, (LONG_PTR) pls );
00596 #else
00597     SetWindowLong( dev->hwnd, GWL_USERDATA, (LONG) pls );
00598 #endif
00599 
00600     dev->SCRN_hdc = dev->hdc = GetDC( dev->hwnd );
00601 
00602 //
00603 //  Setup the popup menu
00604 //
00605 
00606     dev->PopupMenu = CreatePopupMenu();
00607     AppendMenu( dev->PopupMenu, MF_STRING, PopupPrint, _T( "Print" ) );
00608     AppendMenu( dev->PopupMenu, MF_STRING, PopupNextPage, _T( "Next Page" ) );
00609     AppendMenu( dev->PopupMenu, MF_STRING, PopupQuit, _T( "Quit" ) );
00610 
00611 #ifdef PL_HAVE_FREETYPE
00612 
00613     if ( freetype )
00614     {
00615         pls->dev_text    = 1; // want to draw text
00616         pls->dev_unicode = 1; // want unicode
00617         init_freetype_lv1( pls );
00618         FT = (FT_Data *) pls->FT;
00619         FT->want_smooth_text = smooth_text;
00620     }
00621 
00622 #endif
00623 
00624 
00625 
00626     plD_state_wingcc( pls, PLSTATE_COLOR0 );
00627     //
00628     // Display the window which we just created (using the nShow
00629     // passed by the OS, which allows for start minimized and that
00630     // sort of thing).
00631     //
00632     ShowWindow( dev->hwnd, SW_SHOWDEFAULT );
00633     SetForegroundWindow( dev->hwnd );
00634 
00635     //
00636     // Set up the DPI etc...
00637     //
00638 
00639 
00640     if ( pls->xdpi <= 0 ) // Get DPI from windows
00641     {
00642         plspage( GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4,
00643             GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4, 0, 0, 0, 0 );
00644     }
00645     else
00646     {
00647         pls->ydpi = pls->xdpi;        // Set X and Y dpi's to the same value
00648     }
00649 
00650 
00651 //
00652 //  Now we have to find out, from windows, just how big our drawing area is
00653 //  when we specified the page size earlier on, that includes the borders,
00654 //  title bar etc... so now that windows has done all its initialisations,
00655 //  we will ask how big the drawing area is, and tell plplot
00656 //
00657 
00658     GetClientRect( dev->hwnd, &dev->rect );
00659     dev->width  = dev->rect.right;
00660     dev->height = dev->rect.bottom;
00661 
00662     if ( dev->width > dev->height )           // Work out the scaling factor for the
00663     {                                         // "virtual" (oversized) page
00664         dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
00665     }
00666     else
00667     {
00668         dev->scale = (PLFLT) PIXELS_Y / dev->height;
00669     }
00670 
00671     Debug2( "Scale = %f (FLT)\n", dev->scale );
00672 
00673     plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
00674     plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) );
00675 
00676     // Set fill rule.
00677     if ( pls->dev_eofill )
00678         SetPolyFillMode( dev->hdc, ALTERNATE );
00679     else
00680         SetPolyFillMode( dev->hdc, WINDING );
00681 
00682 #ifdef PL_HAVE_FREETYPE
00683     if ( pls->dev_text )
00684     {
00685         init_freetype_lv2( pls );
00686     }
00687 #endif
00688 }
00689 
00690 //--------------------------------------------------------------------------
00691 // plD_line_wingcc()
00692 //
00693 // Draw a line in the current color from (x1,y1) to (x2,y2).
00694 //--------------------------------------------------------------------------
00695 
00696 void
00697 plD_line_wingcc( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
00698 {
00699     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00700     POINT      points[2];
00701 
00702 
00703     points[0].x = (LONG) ( x1a / dev->scale );
00704     points[1].x = (LONG) ( x2a / dev->scale );
00705     points[0].y = (LONG) ( dev->height - ( y1a / dev->scale ) );
00706     points[1].y = (LONG) ( dev->height - ( y2a / dev->scale ) );
00707 
00708     dev->oldobject = SelectObject( dev->hdc, dev->pen );
00709 
00710     if ( points[0].x != points[1].x || points[0].y != points[1].y )
00711     {
00712         Polyline( dev->hdc, points, 2 );
00713     }
00714     else
00715     {
00716         SetPixel( dev->hdc, points[0].x, points[0].y, dev->colour );
00717     }
00718     SelectObject( dev->hdc, dev->oldobject );
00719 }
00720 
00721 
00722 //--------------------------------------------------------------------------
00723 // plD_polyline_wingcc()
00724 //
00725 // Draw a polyline in the current color.
00726 //--------------------------------------------------------------------------
00727 
00728 void
00729 plD_polyline_wingcc( PLStream *pls, short *xa, short *ya, PLINT npts )
00730 {
00731     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00732     int        i;
00733     POINT      *points = NULL;
00734 
00735     if ( npts > 0 )
00736     {
00737         points = GlobalAlloc( GMEM_ZEROINIT | GMEM_FIXED, (size_t) npts * sizeof ( POINT ) );
00738         if ( points != NULL )
00739         {
00740             for ( i = 0; i < npts; i++ )
00741             {
00742                 points[i].x = (LONG) ( xa[i] / dev->scale );
00743                 points[i].y = (LONG) ( dev->height - ( ya[i] / dev->scale ) );
00744             }
00745             dev->oldobject = SelectObject( dev->hdc, dev->pen );
00746             Polyline( dev->hdc, points, npts );
00747             SelectObject( dev->hdc, dev->oldobject );
00748             GlobalFree( points );
00749         }
00750         else
00751         {
00752             plexit( "Could not allocate memory to \"plD_polyline_wingcc\"\n" );
00753         }
00754     }
00755 }
00756 
00757 //--------------------------------------------------------------------------
00758 // plD_fill_polygon_wingcc()
00759 //
00760 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00761 //--------------------------------------------------------------------------
00762 
00763 static void
00764 plD_fill_polygon_wingcc( PLStream *pls )
00765 {
00766     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00767     int        i;
00768     POINT      *points = NULL;
00769     HPEN       hpen, hpenOld;
00770 
00771     if ( pls->dev_npts > 0 )
00772     {
00773         points = GlobalAlloc( GMEM_ZEROINIT, (size_t) pls->dev_npts * sizeof ( POINT ) );
00774 
00775         if ( points == NULL )
00776             plexit( "Could not allocate memory to \"plD_fill_polygon_wingcc\"\n" );
00777 
00778         for ( i = 0; i < pls->dev_npts; i++ )
00779         {
00780             points[i].x = (PLINT) ( pls->dev_x[i] / dev->scale );
00781             points[i].y = (PLINT) ( dev->height - ( pls->dev_y[i] / dev->scale ) );
00782         }
00783 
00784         dev->fillbrush = CreateSolidBrush( dev->colour );
00785         hpen           = CreatePen( PS_SOLID, 1, dev->colour );
00786         dev->oldobject = SelectObject( dev->hdc, dev->fillbrush );
00787         hpenOld        = SelectObject( dev->hdc, hpen );
00788         Polygon( dev->hdc, points, pls->dev_npts );
00789         SelectObject( dev->hdc, dev->oldobject );
00790         DeleteObject( dev->fillbrush );
00791         SelectObject( dev->hdc, hpenOld );
00792         DeleteObject( hpen );
00793         GlobalFree( points );
00794     }
00795 }
00796 
00797 //--------------------------------------------------------------------------
00798 //    static void CopySCRtoBMP(PLStream *pls)
00799 //       Function copies the screen contents into a bitmap which is
00800 //       later used for fast redraws of the screen (when it gets corrupted)
00801 //       rather than remaking the plot from the plot buffer.
00802 //--------------------------------------------------------------------------
00803 
00804 static void CopySCRtoBMP( PLStream *pls )
00805 {
00806     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00807 
00808     //
00809     //   Clean up the old bitmap and DC
00810     //
00811 
00812     if ( dev->hdc2 != NULL )
00813         DeleteDC( dev->hdc2 );
00814     if ( dev->bitmap != NULL )
00815         DeleteObject( dev->bitmap );
00816 
00817     dev->hdc2 = CreateCompatibleDC( dev->hdc );
00818     GetClientRect( dev->hwnd, &dev->rect );
00819     dev->bitmap    = CreateCompatibleBitmap( dev->hdc, dev->rect.right, dev->rect.bottom );
00820     dev->oldobject = SelectObject( dev->hdc2, dev->bitmap );
00821     BitBlt( dev->hdc2, 0, 0, dev->rect.right, dev->rect.bottom, dev->hdc, 0, 0, SRCCOPY );
00822     SelectObject( dev->hdc2, dev->oldobject );
00823 }
00824 
00825 
00826 
00827 void
00828 plD_eop_wingcc( PLStream *pls )
00829 {
00830     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00831 
00832     Debug( "End of the page\n" );
00833     CopySCRtoBMP( pls );
00834     dev->already_erased = 2;
00835 
00836     NormalCursor();
00837 
00838     if ( !pls->nopause )
00839     {
00840         dev->waiting = 1;
00841         while ( GetMessage( &dev->msg, NULL, 0, 0 ) )
00842         {
00843             TranslateMessage( &dev->msg );
00844             switch ( (int) dev->msg.message )
00845             {
00846             case WM_CONTEXTMENU:
00847             case WM_RBUTTONDOWN:
00848                 TrackPopupMenu( dev->PopupMenu, TPM_CENTERALIGN | TPM_RIGHTBUTTON, LOWORD( dev->msg.lParam ),
00849                     HIWORD( dev->msg.lParam ), 0, dev->hwnd, NULL );
00850                 break;
00851 
00852             case WM_CHAR:
00853                 if ( ( (TCHAR) ( dev->msg.wParam ) == 32 ) ||
00854                      ( (TCHAR) ( dev->msg.wParam ) == 13 ) )
00855                 {
00856                     dev->waiting = 0;
00857                 }
00858                 else if ( ( (TCHAR) ( dev->msg.wParam ) == 27 ) ||
00859                           ( (TCHAR) ( dev->msg.wParam ) == 'q' ) ||
00860                           ( (TCHAR) ( dev->msg.wParam ) == 'Q' ) )
00861                 {
00862                     dev->waiting = 0;
00863                     PostQuitMessage( 0 );
00864                 }
00865                 break;
00866 
00867             case WM_LBUTTONDBLCLK:
00868                 Debug( "WM_LBUTTONDBLCLK\t" );
00869                 dev->waiting = 0;
00870                 break;
00871 
00872             case WM_COMMAND:
00873                 switch ( LOWORD( dev->msg.wParam ) )
00874                 {
00875                 case PopupPrint:
00876                     Debug( "PopupPrint" );
00877                     PrintPage( pls );
00878                     break;
00879                 case PopupNextPage:
00880                     Debug( "PopupNextPage" );
00881                     dev->waiting = 0;
00882                     break;
00883                 case PopupQuit:
00884                     Debug( "PopupQuit" );
00885                     dev->waiting = 0;
00886                     PostQuitMessage( 0 );
00887                     break;
00888                 }
00889                 break;
00890 
00891             default:
00892                 DispatchMessage( &dev->msg );
00893                 break;
00894             }
00895             if ( dev->waiting == 0 )
00896                 break;
00897         }
00898     }
00899 }
00900 
00901 //--------------------------------------------------------------------------
00902 //  Beginning of the new page
00903 //--------------------------------------------------------------------------
00904 void
00905 plD_bop_wingcc( PLStream *pls )
00906 {
00907     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00908 #ifdef PL_HAVE_FREETYPE
00909     FT_Data    *FT = (FT_Data *) pls->FT;
00910 #endif
00911     Debug( "Start of Page\t" );
00912 
00913 //
00914 //  Turn the cursor to a busy sign, clear the page by "invalidating" it
00915 //  then reset the colours and pen width
00916 //
00917 
00918     BusyCursor();
00919     dev->already_erased = 0;
00920     RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
00921 
00922     plD_state_wingcc( pls, PLSTATE_COLOR0 );
00923 }
00924 
00925 void
00926 plD_tidy_wingcc( PLStream *pls )
00927 {
00928     wingcc_Dev *dev = NULL;
00929 
00930 #ifdef PL_HAVE_FREETYPE
00931     if ( pls->dev_text )
00932     {
00933         FT_Data *FT = (FT_Data *) pls->FT;
00934         plscmap0n( FT->ncol0_org );
00935         plD_FreeType_Destroy( pls );
00936     }
00937 #endif
00938     Debug( "plD_tidy_wingcc" );
00939 
00940     if ( pls->dev != NULL )
00941     {
00942         dev = (wingcc_Dev *) pls->dev;
00943 
00944         DeleteMenu( dev->PopupMenu, PopupPrint, 0 );
00945         DeleteMenu( dev->PopupMenu, PopupNextPage, 0 );
00946         DeleteMenu( dev->PopupMenu, PopupQuit, 0 );
00947         DestroyMenu( dev->PopupMenu );
00948 
00949         if ( dev->hdc2 != NULL )
00950             DeleteDC( dev->hdc2 );
00951         if ( dev->hdc != NULL )
00952             ReleaseDC( dev->hwnd, dev->hdc );
00953         if ( dev->bitmap != NULL )
00954             DeleteObject( dev->bitmap );
00955 
00956         free_mem( pls->dev );
00957     }
00958 }
00959 
00960 
00961 
00962 
00963 //--------------------------------------------------------------------------
00964 // plD_state_png()
00965 //
00966 // Handle change in PLStream state (color, pen width, fill attribute, etc).
00967 //--------------------------------------------------------------------------
00968 
00969 void
00970 plD_state_wingcc( PLStream *pls, PLINT op )
00971 {
00972     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
00973 
00974     switch ( op )
00975     {
00976     case PLSTATE_COLOR0:
00977     case PLSTATE_COLOR1:
00978         dev->colour = RGB( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b );
00979         break;
00980 
00981     case PLSTATE_CMAP0:
00982     case PLSTATE_CMAP1:
00983         dev->colour = RGB( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b );
00984         break;
00985     }
00986 
00987     if ( dev->pen != NULL )
00988         DeleteObject( dev->pen );
00989     dev->pen = CreatePen( PS_SOLID, pls->width, dev->colour );
00990 }
00991 
00992 //--------------------------------------------------------------------------
00993 // GetCursorCmd()
00994 //
00995 // Handle events connected to selecting points (modelled after xwin)
00996 //--------------------------------------------------------------------------
00997 
00998 static void
00999 GetCursorCmd( PLStream *pls, PLGraphicsIn *gin )
01000 {
01001     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01002 
01003     HCURSOR    crosshair;
01004     HCURSOR    previous;
01005 
01006     plGinInit( gin );
01007 
01008     crosshair = LoadCursor( GetModuleHandle( NULL ), IDC_CROSS );
01009     previous  = SetCursor( crosshair );
01010 
01011     while ( gin->pX < 0 )
01012     {
01013         GetMessage( &dev->msg, NULL, 0, 0 );
01014         TranslateMessage( &dev->msg );
01015         switch ( (int) dev->msg.message )
01016         {
01017         case WM_LBUTTONDOWN:
01018             if ( dev->msg.wParam & MK_LBUTTON )
01019             {
01020                 gin->pX = dev->msg.pt.x;
01021                 gin->pY = dev->msg.pt.y;
01022                 gin->dX = (PLFLT) gin->pX / ( dev->width - 1 );
01023                 gin->dY = 1.0 - (PLFLT) gin->pY / ( dev->height - 1 );
01024 
01025                 gin->button = 1; // AM: there is no macro to indicate the pressed button!
01026                 gin->state  = 0; // AM: is there an equivalent under Windows?
01027                 gin->keysym = 0x20;
01028             }
01029             break;
01030         case WM_CHAR:
01031             gin->pX = dev->msg.pt.x;
01032             gin->pY = dev->msg.pt.y;
01033             gin->dX = (PLFLT) gin->pX / ( dev->width - 1 );
01034             gin->dY = 1.0 - (PLFLT) gin->pY / ( dev->height - 1 );
01035 
01036             gin->button = 0;
01037             gin->state  = 0;
01038             gin->keysym = dev->msg.wParam;
01039 
01040             break;
01041         }
01042     }
01043 
01044     // Restore the previous cursor
01045     SetCursor( previous );
01046 
01047 //    if ( GetCursorPos(&p) )
01048 //    {
01049 //        if ( ScreenToClient( dev->hwnd, &p ) )
01050 //        {
01051 //            // Fill the fields, but actually we need to run the event loop
01052 //            // We need to call GetMessage() in a loop. Unclear as yet to the
01053 //            // actual interface: key/button presses?
01054 //        }
01055 //    }
01056 }
01057 
01058 //--------------------------------------------------------------------------
01059 // plD_esc_wingcc()
01060 //
01061 // Handle PLplot escapes
01062 //--------------------------------------------------------------------------
01063 
01064 void
01065 plD_esc_wingcc( PLStream *pls, PLINT op, void *ptr )
01066 {
01067     wingcc_Dev   *dev = (wingcc_Dev *) pls->dev;
01068     PLGraphicsIn *gin = &( dev->gin );
01069 
01070 
01071     switch ( op )
01072     {
01073     case PLESC_GETC:
01074         GetCursorCmd( pls, (PLGraphicsIn *) ptr );
01075         break;
01076 
01077     case PLESC_FILL:
01078         plD_fill_polygon_wingcc( pls );
01079         break;
01080 
01081     case PLESC_DOUBLEBUFFERING:
01082         break;
01083 
01084     case PLESC_XORMOD:
01085         if ( *(PLINT *) ( ptr ) == 0 )
01086             SetROP2( dev->hdc, R2_COPYPEN );
01087         else
01088             SetROP2( dev->hdc, R2_XORPEN );
01089         break;
01090 
01091 #ifdef PL_HAVE_FREETYPE
01092     case PLESC_HAS_TEXT:
01093         plD_render_freetype_text( pls, (EscText *) ptr );
01094         break;
01095 
01096 //     case PLESC_LIKES_UNICODE:
01097 //      plD_render_freetype_sym(pls, (EscText *)ptr);
01098 //      break;
01099 
01100 #endif
01101     }
01102 }
01103 
01104 //--------------------------------------------------------------------------
01105 // static void Resize( PLStream *pls )
01106 //
01107 // This function calculates how to resize a window after a message has been
01108 // received from windows telling us the window has been changed.
01109 // It tries to recalculate the scale of the window so everything works out
01110 // just right.
01111 // The window is only resized if plplot has finished all of its plotting.
01112 // That means that if you resize while a picture is being plotted,
01113 // unpredictable results may result. The reason I do this is because the
01114 // resize function calls redraw window, which replays the whole plot.
01115 //--------------------------------------------------------------------------
01116 
01117 static void Resize( PLStream *pls )
01118 {
01119     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01120 #ifdef PL_HAVE_FREETYPE
01121     FT_Data    *FT = (FT_Data *) pls->FT;
01122 #endif
01123     Debug( "Resizing" );
01124 
01125     if ( dev->waiting == 1 )     // Only resize the window IF plplot has finished with it
01126     {
01127         memcpy( &dev->oldrect, &dev->rect, sizeof ( RECT ) );
01128         GetClientRect( dev->hwnd, &dev->rect );
01129         Debug3( "[%d %d]", dev->rect.right, dev->rect.bottom );
01130 
01131         if ( ( dev->rect.right > 0 ) && ( dev->rect.bottom > 0 ) )            // Check to make sure it isn't just minimised (i.e. zero size)
01132         {
01133             if ( memcmp( &dev->rect, &dev->oldrect, sizeof ( RECT ) ) != 0 )  // See if the window's changed size or not
01134             {
01135                 dev->already_erased = 0;
01136                 dev->width          = dev->rect.right;
01137                 dev->height         = dev->rect.bottom;
01138                 if ( dev->width > dev->height )     // Work out the scaling factor for the
01139                 {                                   // "virtual" (oversized) page
01140                     dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
01141                 }
01142                 else
01143                 {
01144                     dev->scale = (PLFLT) PIXELS_Y / dev->height;
01145                 }
01146 
01147 #ifdef PL_HAVE_FREETYPE
01148                 if ( FT )
01149                 {
01150                     FT->scale = dev->scale;
01151                     FT->ymax  = dev->height;
01152                 }
01153 #endif
01154             }
01155             RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
01156         }
01157         else
01158         {
01159             memcpy( &dev->rect, &dev->oldrect, sizeof ( RECT ) ); // restore the old size to current size since the window is minimised
01160         }
01161     }
01162 }
01163 
01164 
01165 //--------------------------------------------------------------------------
01166 // int SetRegValue(char *key_name, char *key_word, char *buffer,int dwType, int size)
01167 //
01168 //  Function set the registry; if registary entry does not exist, it is
01169 //  created. Actually, the key is created before it is set just to make sure
01170 //  that is is there !
01171 //--------------------------------------------------------------------------
01172 
01173 static int SetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int dwType, int size )
01174 {
01175     int   j = 0;
01176 
01177     DWORD lpdwDisposition;
01178     HKEY  hKey;
01179 
01180     j = RegCreateKeyEx(
01181         HKEY_CURRENT_USER,
01182         key_name,
01183         0,                                         // reserved
01184         NULL,                                      // address of class string
01185         REG_OPTION_NON_VOLATILE,                   // special options flag
01186         KEY_WRITE,                                 // desired security access
01187         NULL,                                      // address of key security structure
01188         &hKey,                                     // address of buffer for opened handle
01189         &lpdwDisposition                           // address of disposition value buffer
01190         );
01191 
01192     if ( j == ERROR_SUCCESS )
01193     {
01194         RegSetValueEx( hKey, key_word, 0, dwType, buffer, size );
01195         RegCloseKey( hKey );
01196     }
01197     return ( j );
01198 }
01199 
01200 //--------------------------------------------------------------------------
01201 // int GetRegValue(char *key_name, char *key_word, char *buffer, int size)
01202 //
01203 //  Function reads the registry and gets a string value from it
01204 //  buffer must be allocated by the caller, and the size is given in the size
01205 //  paramater.
01206 //  Return code is 1 for success, and 0 for failure.
01207 //--------------------------------------------------------------------------
01208 
01209 static int GetRegValue( TCHAR *key_name, TCHAR *key_word, char *buffer, int size )
01210 {
01211     int  ret = 0;
01212     HKEY hKey;
01213     int  dwType;
01214     int  dwSize = size;
01215 
01216     if ( RegOpenKeyEx( HKEY_CURRENT_USER, key_name, 0, KEY_READ, &hKey ) == ERROR_SUCCESS )
01217     {
01218         if ( RegQueryValueEx( hKey, key_word, 0, (LPDWORD) &dwType, buffer, (LPDWORD) &dwSize ) == ERROR_SUCCESS )
01219         {
01220             ret = 1;
01221         }
01222         RegCloseKey( hKey );
01223     }
01224     return ( ret );
01225 }
01226 
01227 #ifdef PL_HAVE_FREETYPE
01228 
01229 //--------------------------------------------------------------------------
01230 //  void plD_pixel_wingcc (PLStream *pls, short x, short y)
01231 //
01232 //  callback function, of type "plD_pixel_fp", which specifies how a single
01233 //  pixel is set in the current colour.
01234 //--------------------------------------------------------------------------
01235 
01236 static void plD_pixel_wingcc( PLStream *pls, short x, short y )
01237 {
01238     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01239 
01240     SetPixel( dev->hdc, x, y, dev->colour );
01241 }
01242 
01243 static void plD_pixelV_wingcc( PLStream *pls, short x, short y )
01244 {
01245     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01246 
01247     SetPixelV( dev->hdc, x, y, dev->colour );
01248 }
01249 
01250 //--------------------------------------------------------------------------
01251 //  void plD_set_pixelV_wingcc (PLStream *pls, short x, short y,PLINT colour)
01252 //
01253 //  callback function, of type "plD_set_pixel_fp", which specifies how a
01254 //  single pixel is set in the s[ecified colour. This colour
01255 //  by-passes plplot's internal table, and directly 'hits the hardware'.
01256 //--------------------------------------------------------------------------
01257 
01258 static void plD_set_pixel_wingcc( PLStream *pls, short x, short y, PLINT colour )
01259 {
01260     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01261 
01262     SetPixel( dev->hdc, x, y, colour );
01263 }
01264 
01265 static void plD_set_pixelV_wingcc( PLStream *pls, short x, short y, PLINT colour )
01266 {
01267     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01268 
01269     SetPixelV( dev->hdc, x, y, colour );
01270 }
01271 
01272 
01273 //--------------------------------------------------------------------------
01274 //  void plD_read_pixel_wingcc (PLStream *pls, short x, short y)
01275 //
01276 //  callback function, of type "plD_pixel_fp", which specifies how a single
01277 //  pixel is read.
01278 //--------------------------------------------------------------------------
01279 static PLINT plD_read_pixel_wingcc( PLStream *pls, short x, short y )
01280 {
01281     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01282 
01283     return ( GetPixel( dev->hdc, x, y ) );
01284 }
01285 
01286 
01287 //--------------------------------------------------------------------------
01288 //  void init_freetype_lv1 (PLStream *pls)
01289 //
01290 //  "level 1" initialisation of the freetype library.
01291 //  "Level 1" initialisation calls plD_FreeType_init(pls) which allocates
01292 //  memory to the pls->FT structure, then sets up the pixel callback
01293 //  function.
01294 //--------------------------------------------------------------------------
01295 
01296 static void init_freetype_lv1( PLStream *pls )
01297 {
01298     FT_Data    *FT;
01299     int        x;
01300     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01301 
01302     plD_FreeType_init( pls );
01303 
01304     FT = (FT_Data *) pls->FT;
01305 
01306 
01307 
01308 //
01309 //  Work out if our device support "fast" pixel setting
01310 //  and if so, use that instead of "slow" pixel setting
01311 //
01312 
01313     x = GetDeviceCaps( dev->hdc, RASTERCAPS );
01314 
01315     if ( x & RC_BITBLT )
01316         FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc;
01317     else
01318         FT->pixel = (plD_pixel_fp) plD_pixel_wingcc;
01319 
01320 //
01321 //  See if we have a 24 bit device (or better), in which case
01322 //  we can use the better antialaaising.
01323 //
01324 
01325     if ( GetDeviceCaps( dev->hdc, BITSPIXEL ) > 24 )
01326     {
01327         FT->BLENDED_ANTIALIASING = 1;
01328         FT->read_pixel           = (plD_read_pixel_fp) plD_read_pixel_wingcc;
01329 
01330         if ( x & RC_BITBLT )
01331             FT->set_pixel = (plD_set_pixel_fp) plD_set_pixelV_wingcc;
01332         else
01333             FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_wingcc;
01334     }
01335 }
01336 
01337 //--------------------------------------------------------------------------
01338 //  void init_freetype_lv2 (PLStream *pls)
01339 //
01340 //  "Level 2" initialisation of the freetype library.
01341 //  "Level 2" fills in a few setting that aren't public until after the
01342 //  graphics sub-system has been initialised.
01343 //  The "level 2" initialisation fills in a few things that are defined
01344 //  later in the initialisation process for the GD driver.
01345 //
01346 //  FT->scale is a scaling factor to convert co-ordinates. This is used by
01347 //  the GD and other drivers to scale back a larger virtual page and this
01348 //  eliminate the "hidden line removal bug". Set it to 1 if your device
01349 //  doesn't have scaling.
01350 //
01351 //  Some coordinate systems have zero on the bottom, others have zero on
01352 //  the top. Freetype does it one way, and most everything else does it the
01353 //  other. To make sure everything is working ok, we have to "flip" the
01354 //  coordinates, and to do this we need to know how big in the Y dimension
01355 //  the page is, and whether we have to invert the page or leave it alone.
01356 //
01357 //  FT->ymax specifies the size of the page FT->invert_y=1 tells us to
01358 //  invert the y-coordinates, FT->invert_y=0 will not invert the
01359 //  coordinates.
01360 //--------------------------------------------------------------------------
01361 
01362 static void init_freetype_lv2( PLStream *pls )
01363 {
01364     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01365     FT_Data    *FT  = (FT_Data *) pls->FT;
01366 
01367     FT->scale    = dev->scale;
01368     FT->ymax     = dev->height;
01369     FT->invert_y = 1;
01370 
01371     if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )           // do we want to at least *try* for smoothing ?
01372     {
01373         FT->ncol0_org   = pls->ncol0;                                                   // save a copy of the original size of ncol0
01374         FT->ncol0_xtra  = 16777216 - ( pls->ncol1 + pls->ncol0 );                       // work out how many free slots we have
01375         FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing;             // find out how many different shades of anti-aliasing we can do
01376         FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing;             // set a maximum number of shades
01377         plscmap0n( FT->ncol0_org + ( FT->ncol0_width * pls->ncol0 ) );                  // redefine the size of cmap0
01378 // the level manipulations are to turn off the plP_state(PLSTATE_CMAP0)
01379 // call in plscmap0 which (a) leads to segfaults since the GD image is
01380 // not defined at this point and (b) would be inefficient in any case since
01381 // setcmap is always called later (see plD_bop_png) to update the driver
01382 // color palette to be consistent with cmap0.
01383         {
01384             PLINT level_save;
01385             level_save = pls->level;
01386             pls->level = 0;
01387             pl_set_extended_cmap0( pls, FT->ncol0_width, FT->ncol0_org ); // call the function to add the extra cmap0 entries and calculate stuff
01388             pls->level = level_save;
01389         }
01390         FT->smooth_text = 1;                                                       // Yippee ! We had success setting up the extended cmap0
01391     }
01392     else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) ) // If we have a truecolour device, we wont even bother trying to change the palette
01393     {
01394         FT->smooth_text = 1;
01395     }
01396 }
01397 #endif
01398 
01399 //--------------------------------------------------------------------------
01400 //  static void UpdatePageMetrics ( PLStream *pls, char flag )
01401 //
01402 //      UpdatePageMetrics is a simple function which simply gets new vales for
01403 //      a changed DC, be it swapping from printer to screen or vice-versa.
01404 //      The flag variable is used to tell the function if it is updating
01405 //      from the printer (1) or screen (0).
01406 //--------------------------------------------------------------------------
01407 
01408 static void UpdatePageMetrics( PLStream *pls, char flag )
01409 {
01410     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01411   #ifdef PL_HAVE_FREETYPE
01412     FT_Data    *FT = (FT_Data *) pls->FT;
01413   #endif
01414 
01415     if ( flag == 1 )
01416     {
01417         dev->width  = GetDeviceCaps( dev->hdc, HORZRES ); // Get the page size from the printer
01418         dev->height = GetDeviceCaps( dev->hdc, VERTRES );
01419     }
01420     else
01421     {
01422         GetClientRect( dev->hwnd, &dev->rect );
01423         dev->width  = dev->rect.right;
01424         dev->height = dev->rect.bottom;
01425     }
01426 
01427     if ( dev->width > dev->height )     // Work out the scaling factor for the
01428     {                                   // "virtual" (oversized) page
01429         dev->scale = (PLFLT) ( PIXELS_X - 1 ) / dev->width;
01430     }
01431     else
01432     {
01433         dev->scale = (PLFLT) PIXELS_Y / dev->height;
01434     }
01435 
01436   #ifdef PL_HAVE_FREETYPE
01437     if ( FT )           // If we are using freetype, then set it up next
01438     {
01439         FT->scale = dev->scale;
01440         FT->ymax  = dev->height;
01441         if ( GetDeviceCaps( dev->hdc, RASTERCAPS ) & RC_BITBLT )
01442             FT->pixel = (plD_pixel_fp) plD_pixelV_wingcc;
01443         else
01444             FT->pixel = (plD_pixel_fp) plD_pixel_wingcc;
01445     }
01446   #endif
01447 
01448     pls->xdpi = GetDeviceCaps( dev->hdc, HORZRES ) / GetDeviceCaps( dev->hdc, HORZSIZE ) * 25.4;
01449     pls->ydpi = GetDeviceCaps( dev->hdc, VERTRES ) / GetDeviceCaps( dev->hdc, VERTSIZE ) * 25.4;
01450     plP_setpxl( dev->scale * pls->xdpi / 25.4, dev->scale * pls->ydpi / 25.4 );
01451     plP_setphy( 0, (PLINT) ( dev->scale * dev->width ), 0, (PLINT) ( dev->scale * dev->height ) );
01452 }
01453 
01454 //--------------------------------------------------------------------------
01455 //  static void PrintPage ( PLStream *pls )
01456 //
01457 //     Function brings up a standard printer dialog and, after the user
01458 //     has selected a printer, replots the current page to the windows
01459 //     printer.
01460 //--------------------------------------------------------------------------
01461 
01462 static void PrintPage( PLStream *pls )
01463 {
01464     wingcc_Dev *dev = (wingcc_Dev *) pls->dev;
01465   #ifdef PL_HAVE_FREETYPE
01466     FT_Data    *FT = (FT_Data *) pls->FT;
01467   #endif
01468     PRINTDLG   Printer;
01469     DOCINFO    docinfo;
01470 
01471     //
01472     //    Reset the docinfo structure to 0 and set it's fields up
01473     //    This structure is used to supply a name to the print queue
01474     //
01475 
01476     ZeroMemory( &docinfo, sizeof ( docinfo ) );
01477     docinfo.cbSize      = sizeof ( docinfo );
01478     docinfo.lpszDocName = _T( "Plplot Page" );
01479 
01480     //
01481     //   Reset out printer structure to zero and initialise it
01482     //
01483 
01484     ZeroMemory( &Printer, sizeof ( PRINTDLG ) );
01485     Printer.lStructSize = sizeof ( PRINTDLG );
01486     Printer.hwndOwner   = dev->hwnd;
01487     Printer.Flags       = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
01488     Printer.nCopies     = 1;
01489 
01490     //
01491     //   Call the printer dialog function.
01492     //   If the user has clicked on "Print", then we will continue
01493     //   processing and print out the page.
01494     //
01495 
01496     if ( PrintDlg( &Printer ) != 0 )
01497     {
01498         //
01499         //  Before doing anything, we will take some backup copies
01500         //  of the existing values for page size and the like, because
01501         //  all we are going to do is a quick and dirty modification
01502         //  of plplot's internals to match the new page size and hope
01503         //  it all works out ok. After that, we will manip the values,
01504         //  and when all is done, restore them.
01505         //
01506 
01507         if ( ( dev->push = GlobalAlloc( GMEM_ZEROINIT, sizeof ( wingcc_Dev ) ) ) != NULL )
01508         {
01509             BusyCursor();
01510             memcpy( dev->push, dev, sizeof ( wingcc_Dev ) );
01511 
01512             dev->hdc = dev->PRNT_hdc = Printer.hDC; // Copy the printer HDC
01513 
01514             UpdatePageMetrics( pls, 1 );
01515 
01516           #ifdef PL_HAVE_FREETYPE
01517             if ( FT )                                  // If we are using freetype, then set it up next
01518             {
01519                 dev->FT_smooth_text = FT->smooth_text; // When printing, we don't want smoothing
01520                 FT->smooth_text     = 0;
01521             }
01522           #endif
01523 
01524             //
01525             //   Now the stuff that actually does the printing !!
01526             //
01527 
01528             StartDoc( dev->hdc, &docinfo );
01529             plRemakePlot( pls );
01530             EndDoc( dev->hdc );
01531 
01532             //
01533             //  Now to undo everything back to what it was for the screen
01534             //
01535 
01536             dev->hdc = dev->SCRN_hdc;  // Reset the screen HDC to the default
01537             UpdatePageMetrics( pls, 0 );
01538 
01539           #ifdef PL_HAVE_FREETYPE
01540             if ( FT )           // If we are using freetype, then set it up next
01541             {
01542                 FT->smooth_text = dev->FT_smooth_text;
01543             }
01544           #endif
01545             memcpy( dev, dev->push, sizeof ( wingcc_Dev ) ); // POP our "stack" now to restore the values
01546 
01547             GlobalFree( dev->push );
01548             NormalCursor();
01549             RedrawWindow( dev->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW );
01550         }
01551     }
01552 }
01553 
01554 
01555 
01556 #else
01557 int
01558 pldummy_wingcc()
01559 {
01560     return ( 0 );
01561 }
01562 
01563 #endif                          // PLD_wingccdev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines