⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gros2pm.c

📁 Demo for Free type 2.2.1
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "grobjs.h"
#include "grdevice.h"

#define INCL_DOS
#define INCL_WIN
#define INCL_GPI
#define INCL_SUB

#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#define  DEBUGxxx

#ifdef DEBUG
#define LOG(x)  LogMessage##x
#else
#define LOG(x)  /* rien */
#endif

#ifdef DEBUG
  static void  LogMessage( const char*  fmt, ... )
  {
    va_list  ap;

    va_start( ap, fmt );
    vfprintf( stderr, fmt, ap );
    va_end( ap );
  }
#endif

  typedef struct Translator
  {
    ULONG   os2key;
    grKey   grkey;

  } Translator;


  static
  Translator  key_translators[] =
  {
    { VK_BACKSPACE, grKeyBackSpace },
    { VK_TAB,       grKeyTab       },
    { VK_ENTER,     grKeyReturn    },
    { VK_ESC,       grKeyEsc       },
    { VK_HOME,      grKeyHome      },
    { VK_LEFT,      grKeyLeft      },
    { VK_UP,        grKeyUp        },
    { VK_RIGHT,     grKeyRight     },
    { VK_DOWN,      grKeyDown      },
    { VK_PAGEUP,    grKeyPageUp    },
    { VK_PAGEDOWN,  grKeyPageDown  },
    { VK_END,       grKeyEnd       },
    { VK_F1,        grKeyF1        },
    { VK_F2,        grKeyF2        },
    { VK_F3,        grKeyF3        },
    { VK_F4,        grKeyF4        },
    { VK_F5,        grKeyF5        },
    { VK_F6,        grKeyF6        },
    { VK_F7,        grKeyF7        },
    { VK_F8,        grKeyF8        },
    { VK_F9,        grKeyF9        },
    { VK_F10,       grKeyF10       },
    { VK_F11,       grKeyF11       },
    { VK_F12,       grKeyF12       }
  };


#define MAX_PIXEL_MODES  32

  static  HAB   gr_anchor;   /* device anchor block */

  typedef POINTL  PMBlitPoints[4];

  typedef struct grPMSurface_
  {
    grSurface  root;
    grBitmap   image;

    HAB        anchor;         /* handle to anchor block for surface's window */
    HWND       frame_window;   /* handle to window's frame                    */
    HWND       client_window;  /* handle to window's client                   */
    HWND       title_window;   /* handle to window's title bar                */

    HPS        image_ps;       /* memory presentation space used to hold */
                               /* the surface's content under PM         */
    HDC        image_dc;       /* memory device context for the image    */

    HEV        event_lock;     /* semaphore used in listen_surface   */
    HMTX       image_lock;     /* a mutex used to synchronise access */
                               /* to the memory presentation space   */
                               /* used to hold the surface           */

    TID        message_thread; /* thread used to process this surface's */
                               /* messages..                            */

    PBITMAPINFO2 bitmap_header;/* os/2 bitmap descriptor                   */
    HBITMAP      os2_bitmap;   /* Handle to OS/2 bitmap contained in image */
    BOOL         ready;        /* ??? */

    long         shades[256];  /* indices of gray levels in pixel_mode_gray */

    POINTL       surface_blit[4];  /* surface blitting table   */
    POINTL       magnify_blit[4];  /* magnifier blitting table */
    int          magnification;    /* level of magnification   */
    POINTL       magnify_center;
    SIZEL        magnify_size;

    grEvent      event;

    PMBlitPoints blit_points;

  } grPMSurface;

  /* we use a static variable to pass a pointer to the PM Surface  */
  /* to the client window. This is a bit ugly, but it makes things */
  /* a lot more simple..                                           */
  static  grPMSurface*  the_surface;

  static
  void  enable_os2_iostreams( void )
  {
    PTIB  thread_block;
    PPIB  process_block;

    /* XXX : This is a very nasty hack, it fools OS/2 and let the program */
    /*       call PM functions, even though stdin/stdout/stderr are still */
    /*       directed to the standard i/o streams..                       */
    /*       The program must be compiled with WINDOWCOMPAT               */
    /*                                                                    */
    /*   Credits go to Michal for finding this !!                         */
    /*                                                                    */
    DosGetInfoBlocks( &thread_block, &process_block );
    process_block->pib_ultype = 3;
  }



  static
  int  init_device( void )
  {
    enable_os2_iostreams();

    /* create an anchor block. This will allow this thread (i.e. the */
    /* main one) to call Gpi functions..                             */
    gr_anchor = WinInitialize(0);
    if (!gr_anchor)
    {
      /* could not initialise Presentation Manager */
      return -1;
    }

    return 0;
  }



  static
  void  done_device( void )
  {
    /* Indicates that we do not use the Presentation Manager, this */
    /* will also release all associated resources..                */
    WinTerminate( gr_anchor );
  }



  /* close a given window */
  static
  void  done_surface( grPMSurface*  surface )
  {
    LOG(( "Os2PM: done_surface(%08lx)\n", (long)surface ));

    if ( surface->frame_window )
      WinDestroyWindow( surface->frame_window );

    WinReleasePS( surface->image_ps );

    grDoneBitmap( &surface->image );
    grDoneBitmap( &surface->root.bitmap );
  }


#define LOCK(x)    DosRequestMutexSem( x, SEM_INDEFINITE_WAIT )
#define UNLOCK(x)  DosReleaseMutexSem( x )

  static
  const int  pixel_mode_bit_count[] =
  {
    0,
    1,   /* mono  */
    4,   /* pal4  */
    8,   /* pal8  */
    8,   /* grays */
    15,  /* rgb15 */
    16,  /* rgb16 */
    24,  /* rgb24 */
    32   /* rgb32 */
  };


 /************************************************************************
  *
  * Technical note : how the OS/2 Presntation Manager driver works
  *
  * PM is, in my opinion, a bloated and over-engineered graphics
  * sub-system, even though it has lots of nice features. Here are
  * a few tidbits about it :
  *
  *
  * - under PM, a "bitmap" is a device-specific object whose bits are
  *   not directly accessible to the client application. This means
  *   that we must use a scheme like the following to display our
  *   surfaces :
  *
  *     - hold, for each surface, its own bitmap buffer where the
  *       rest of the graph library writes directly.
  *
  *     - create a PM bitmap object with the same dimensions (and
  *       possibly format).
  *
  *     - copy the content of each updated rectangle into the
  *       PM bitmap with the function 'GpiSetBitmapBits'.
  *
  *     - finally, "blit" the PM bitmap to the screen calling
  *       'GpiBlitBlt'
  *
  * - but there is more : you cannot directly blit a PM bitmap to the
  *   screen with PM. The 'GpiBlitBlt' only works with presentation
  *   spaces. This means that we also need to create, for each surface :
  *
  *     - a memory presentation space, used to hold the PM bitmap
  *     - a "memory device context" for the presentation space
  *
  *   The blit is then performed from the memory presentation space
  *   to the screen's presentation space..
  *
  *
  * - because each surface creates its own event-handling thread,
  *   we must protect the surface's presentation space from concurrent
  *   accesses (i.e. calls to 'GpiSetBitmapBits' when drawing to the
  *   surface, and calls to 'GpiBlitBlt' when drawing it on the screen
  *   are performed in two different threads).
  *
  *   we use a simple mutex to do this.
  *
  *
  * - we also use a semaphore to perform a rendez-vous between the
  *   main and event-handling threads (needed in "listen_event").
  *
  ************************************************************************/

  static
  void  RunPMWindow( grPMSurface*  surface );




  static
  void  refresh_rectangle( grPMSurface* surface,
                           int          x,
                           int          y,
                           int          w,
                           int          h )
  {
    LOG(( "Os2PM: refresh_rectangle( %08lx, %d, %d, %d, %d )\n",
          (long)surface, x, y, w, h ));

    (void)x;
    (void)y;
    (void)w;
    (void)h;

    /*
    convert_rectangle( surface, x, y, w, h );
    */
    LOCK( surface->image_lock );
    GpiSetBitmapBits( surface->image_ps,
                      0,
                      surface->root.bitmap.rows,
                      surface->root.bitmap.buffer,
                      surface->bitmap_header );
    UNLOCK( surface->image_lock );

    WinInvalidateRect( surface->client_window, NULL, FALSE );
    WinUpdateWindow( surface->frame_window );
  }


  static
  void  set_title( grPMSurface* surface,
                   const char*  title )
  {
    ULONG  rc;

#if 1
    LOG(( "Os2PM: set_title( %08lx == %08lx, %s )\n",
             (long)surface, surface->client_window, title ));
#endif
    LOG(( "      -- frame         = %08lx\n",
          (long)surface->frame_window ));
    LOG(( "      -- client parent = %08lx\n",
          (long)WinQueryWindow( surface->client_window, QW_PARENT ) ));
    rc = WinSetWindowText( surface->client_window, (PSZ)title );
    LOG(( "      -- returned rc = %ld\n",rc ));
  }



  static
  void  listen_event( grPMSurface* surface,
                      int          event_mask,
                      grEvent*     grevent )
  {
    ULONG  ulRequestCount;

    (void) event_mask;   /* ignored for now */

    /* the listen_event function blocks until there is an event to process */
    DosWaitEventSem( surface->event_lock, SEM_INDEFINITE_WAIT );
    DosQueryEventSem( surface->event_lock, &ulRequestCount );
    *grevent = surface->event;
    DosResetEventSem( surface->event_lock, &ulRequestCount );

    return;
  }


  static
  grPMSurface*  init_surface( grPMSurface*  surface,
                              grBitmap*     bitmap )
  {
    PBITMAPINFO2  bit;
    SIZEL         sizl = { 0, 0 };
    LONG          palette[256];
    LOG(( "Os2PM: init_surface( %08lx, %08lx )\n",
          (long)surface, (long)bitmap ));

    LOG(( "       -- input bitmap =\n" ));
    LOG(( "       --   mode   = %d\n", bitmap->mode ));
    LOG(( "       --   grays  = %d\n", bitmap->grays ));
    LOG(( "       --   width  = %d\n", bitmap->width ));
    LOG(( "       --   height = %d\n", bitmap->rows ));

    /* create the bitmap - under OS/2, we support all modes as PM */
    /* handles all conversions automatically..                    */
    if ( grNewBitmap( bitmap->mode,
                      bitmap->grays,
                      bitmap->width,
                      bitmap->rows,
                      bitmap ) )
      return 0;

    LOG(( "       -- output bitmap =\n" ));
    LOG(( "       --   mode   = %d\n", bitmap->mode ));
    LOG(( "       --   grays  = %d\n", bitmap->grays ));
    LOG(( "       --   width  = %d\n", bitmap->width ));
    LOG(( "       --   height = %d\n", bitmap->rows ));

    bitmap->pitch = -bitmap->pitch;
    surface->root.bitmap = *bitmap;

    /* create the image and event lock */
    DosCreateEventSem( NULL, &surface->event_lock, 0, TRUE  );
    DosCreateMutexSem( NULL, &surface->image_lock, 0, FALSE );

    /* create the image's presentation space */
    surface->image_dc = DevOpenDC( gr_anchor,
                                   OD_MEMORY, (PSZ)"*", 0L, 0L, 0L );

    surface->image_ps = GpiCreatePS( gr_anchor,
                                     surface->image_dc,
                                     &sizl,
                                     PU_PELS    | GPIT_MICRO |

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -