home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / imagedit / util.c < prev    next >
Text File  |  1996-06-12  |  14KB  |  474 lines

  1.     /****************************************************************************/
  2.     /*                                                                          */
  3.     /*                 Copyright (C) 1987-1996 Microsoft Corp.                */
  4.     /*                           All Rights Reserved                            */
  5.     /*                                                                          */
  6.     /****************************************************************************/
  7.     /****************************** Module Header *******************************
  8.     * Module Name: util.c
  9.     *
  10.     * Contains miscellaneous utility functions for ImagEdit.
  11.     *
  12.     * History:
  13.     *
  14.     ****************************************************************************/
  15.     
  16.     #include "imagedit.h"
  17.     
  18.     #include <stdio.h>
  19.     #include <stdarg.h>
  20.     
  21.     #define CBOVERHEAD      (sizeof(INT)+sizeof(INT)+sizeof(INT))
  22.     #define MEMSIGHEAD      0x1234
  23.     #define MEMSIGTAIL      0x5678
  24.     
  25.     
  26.     
  27.     /****************************************************************************
  28.     * MyAlloc
  29.     *
  30.     *
  31.     *
  32.     * History:
  33.     *  25-Jul-1989   - Created
  34.     ****************************************************************************/
  35.     
  36.     VOID *MyAlloc(
  37.         INT cbAlloc)
  38.     {
  39.         register HANDLE hMem;
  40.     
  41.         if (hMem = LocalAlloc(LMEM_FIXED, cbAlloc)) {
  42.             return (VOID *)hMem;
  43.         }
  44.         else {
  45.             MessageBeep(0);
  46.             Message(MSG_OUTOFMEMORY);
  47.     
  48.             return NULL;
  49.         }
  50.     }
  51.     
  52.     
  53.     
  54.     /****************************************************************************
  55.     * MyRealloc
  56.     *
  57.     *
  58.     *
  59.     * History:
  60.     *  25-Jul-1989   - Created
  61.     ****************************************************************************/
  62.     
  63.     VOID *MyRealloc(
  64.         VOID *npMem,
  65.         INT cbNewAlloc)
  66.     {
  67.         npMem = (VOID *)LocalReAlloc((HANDLE)npMem, cbNewAlloc, LMEM_MOVEABLE);
  68.     
  69.         if (!npMem) {
  70.             MessageBeep(0);
  71.             Message(MSG_OUTOFMEMORY);
  72.     
  73.             return NULL;
  74.         }
  75.     
  76.         return npMem;
  77.     }
  78.     
  79.     
  80.     
  81.     /****************************************************************************
  82.     * MyFree
  83.     *
  84.     *
  85.     * History:
  86.     *  25-Jul-1989   - Created
  87.     ****************************************************************************/
  88.     
  89.     VOID *MyFree(
  90.         VOID *npMem)
  91.     {
  92.         if (LocalFree((HANDLE)npMem)) {
  93.             MessageBeep(0);
  94.             Message(MSG_MEMERROR);
  95.     
  96.             return npMem;
  97.         }
  98.     
  99.         return NULL;
  100.     }
  101.     
  102.     
  103.     
  104.     /************************************************************************
  105.     * Message
  106.     *
  107.     * This function puts up a message box.  The message is described in
  108.     * the gamdMessages table.
  109.     *
  110.     * Arguments:
  111.     *   UINT idMsg - Index to the message.
  112.     *   ...        - Optional arguments.
  113.     *
  114.     * Returns:
  115.     *     What MessageBox returns.
  116.     *
  117.     ************************************************************************/
  118.     
  119.     INT Message(
  120.         UINT idMsg,
  121.         ...)
  122.     {
  123.         va_list marker;
  124.         INT RetCode;
  125.         CHAR szT[CCHTEXTMAX];
  126.     
  127.         va_start(marker, idMsg);
  128.         vsprintf(szT, ids(gamdMessages[idMsg].ids), marker);
  129.     
  130.         RetCode = MessageBox(NULL, szT, ids(IDS_PGMTITLE),
  131.                 gamdMessages[idMsg].fMessageBox | MB_TASKMODAL);
  132.     
  133.         va_end(marker);
  134.     
  135.         return RetCode;
  136.     }
  137.     
  138.     
  139.     
  140.     /************************************************************************
  141.     * CenterWindow
  142.     *
  143.     * This function centers the given window over its owner.  It ensures
  144.     * that the window is entirely within the visible screen, however.
  145.     * If the window does not have an owner, it is centered over the
  146.     * desktop.
  147.     *
  148.     * Arguments:
  149.     *   HWND hwnd - The window to center.
  150.     *
  151.     * History:
  152.     *
  153.     ************************************************************************/
  154.     
  155.     VOID CenterWindow(
  156.         HWND hwnd)
  157.     {
  158.         RECT rc;
  159.         RECT rcOwner;
  160.         RECT rcCenter;
  161.         HWND hwndOwner;
  162.     
  163.         GetWindowRect(hwnd, &rc);
  164.     
  165.         if (!(hwndOwner = GetWindow(hwnd, GW_OWNER)))
  166.             hwndOwner = GetDesktopWindow();
  167.     
  168.         GetWindowRect(hwndOwner, &rcOwner);
  169.     
  170.         /*
  171.          *  Calculate the starting x,y for the new
  172.          *  window so that it would be centered.
  173.          */
  174.         rcCenter.left = rcOwner.left +
  175.                 (((rcOwner.right - rcOwner.left) -
  176.                 (rc.right - rc.left))
  177.                 / 2);
  178.     
  179.         rcCenter.top = rcOwner.top +
  180.                 (((rcOwner.bottom - rcOwner.top) -
  181.                 (rc.bottom - rc.top))
  182.                 / 2);
  183.     
  184.         rcCenter.right = rcCenter.left + (rc.right - rc.left);
  185.         rcCenter.bottom = rcCenter.top + (rc.bottom - rc.top);
  186.     
  187.         FitRectToScreen(&rcCenter);
  188.     
  189.         SetWindowPos(hwnd, NULL, rcCenter.left, rcCenter.top, 0, 0,
  190.                 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  191.     }
  192.     
  193.     
  194.     
  195.     /************************************************************************
  196.     * FitRectToScreen
  197.     *
  198.     * This function ensures that the given rectangle is entirely within
  199.     * the visible screen, adjusting it if necessary.
  200.     *
  201.     * Arguments:
  202.     *   PRECT prc - The rectangle.
  203.     *
  204.     * History:
  205.     *
  206.     ************************************************************************/
  207.     
  208.     VOID FitRectToScreen(
  209.         PRECT prc)
  210.     {
  211.         INT cxScreen;
  212.         INT cyScreen;
  213.         INT delta;
  214.     
  215.         cxScreen = GetSystemMetrics(SM_CXSCREEN);
  216.         cyScreen = GetSystemMetrics(SM_CYSCREEN);
  217.     
  218.         if (prc->right > cxScreen) {
  219.             delta = prc->right - prc->left;
  220.             prc->right = cxScreen;
  221.             prc->left = prc->right - delta;
  222.         }
  223.     
  224.         if (prc->left < 0) {
  225.             delta = prc->right - prc->left;
  226.             prc->left = 0;
  227.             prc->right = prc->left + delta;
  228.         }
  229.     
  230.         if (prc->bottom > cyScreen) {
  231.             delta = prc->bottom - prc->top;
  232.             prc->bottom = cyScreen;
  233.             prc->top = prc->bottom - delta;
  234.         }
  235.     
  236.         if (prc->top < 0) {
  237.             delta = prc->bottom - prc->top;
  238.             prc->top = 0;
  239.             prc->bottom = prc->top + delta;
  240.         }
  241.     }
  242.     
  243.     
  244.     
  245.     /************************************************************************
  246.     * ids
  247.     *
  248.     * This function will return a string, given the string id.  If this is
  249.     * the first time that the string has been retrieved, memory will be
  250.     * allocated for it and it will be loaded.  After it is loaded once, it
  251.     * is then cached in a PSTR array and is available for later without
  252.     * having to load it again.
  253.     *
  254.     * Arguments:
  255.     *   UINT idString - String ID of the string to retrieve.
  256.     *
  257.     * History:
  258.     *
  259.     ************************************************************************/
  260.     
  261.     PSTR ids(
  262.         UINT idString)
  263.     {
  264.         static PSTR apstr[CSTRINGS];        // String resource array cache.
  265.         PSTR pstr;
  266.         INT cch;
  267.     
  268.         if (apstr[idString])
  269.             return apstr[idString];
  270.     
  271.         if (!(pstr = MyAlloc(CCHTEXTMAX)))
  272.             return "";
  273.     
  274.         if (!(cch = LoadString(ghInst, idString, pstr, CCHTEXTMAX))) {
  275.             MyFree(pstr);
  276.             return "";
  277.         }
  278.     
  279.         apstr[idString] = pstr = MyRealloc(pstr, cch + 1);
  280.     
  281.         return (pstr ? pstr : "");
  282.     }
  283.     
  284.     
  285.     
  286.     /************************************************************************
  287.     * MyCreateBitmap
  288.     *
  289.     *
  290.     *
  291.     * Arguments:
  292.     *
  293.     * History:
  294.     *
  295.     ************************************************************************/
  296.     
  297.     HBITMAP MyCreateBitmap(
  298.         HDC hdc,
  299.         INT cx,
  300.         INT cy,
  301.         INT nColors)
  302.     {
  303.         BITMAPINFOHEADER bmih;
  304.     
  305.         if (nColors == 2) {
  306.             return CreateBitmap(cx, cy, 1, 1, NULL);
  307.         }
  308.         else {
  309.             bmih.biSize = sizeof(BITMAPINFOHEADER);
  310.             bmih.biWidth = cx;
  311.             bmih.biHeight = cy;
  312.             bmih.biPlanes = 1;              // 1 plane, 4 bpp is
  313.             bmih.biBitCount = 4;            // 16 colors.
  314.     
  315.             bmih.biCompression =
  316.             bmih.biSizeImage =
  317.             bmih.biXPelsPerMeter =
  318.             bmih.biYPelsPerMeter =
  319.             bmih.biClrUsed =
  320.             bmih.biClrImportant = 0;
  321.     
  322.             return CreateDIBitmap(hdc, &bmih, 0L, NULL, NULL, 0);
  323.         }
  324.     }
  325.     
  326.     
  327.     
  328.     #if defined(DBG) && defined(WIN16)
  329.     /****************************************************************************
  330.     * DBGStackReport
  331.     *
  332.     * This debugging function reports how much stack is used by a program.
  333.     * To use it, call it with fInit == TRUE right at the beginning of the
  334.     * program and then with fInit == FALSE just before the program exits.
  335.     * The stack space used during the current run of the program will be
  336.     * displayed on the debug terminal.
  337.     *
  338.     * It is implemented by filling the stack with a certain value down to
  339.     * the bottom of the stack (if fInit is TRUE).  When it is called with
  340.     * fInit == FALSE, it starts at the bottom of the stack and looks for
  341.     * where this "signature" value has been overwritten with data, then
  342.     * does a little math to compute the used stack.
  343.     *
  344.     * Arguments:
  345.     *   BOOL fInit - TRUE if the stack should be initialized, FALSE to
  346.     *                print out the report.
  347.     *
  348.     * History:
  349.     *  28-Aug-1990  - Created
  350.     ****************************************************************************/
  351.     
  352.     /*
  353.      * This signature byte will be used to fill the stack.
  354.      */
  355.     #define STACKSIG    'A'
  356.     
  357.     /*
  358.      * This is a C runtime global that is always at the very end of the
  359.      * global data.  Taking its address is a way that the "bottom" of the
  360.      * stack can be found.
  361.      */
  362.     extern CHAR end;
  363.     
  364.     VOID DBGStackReport(
  365.         BOOL fInit)
  366.     {
  367.         static PBYTE pbStackTop;
  368.         PBYTE pb;
  369.         BYTE bDummy;
  370.     
  371.         if (fInit) {
  372.             /*
  373.              * The address of one of this functions local variables is
  374.              * taken and considered the "top" of the stack.  This means
  375.              * that it will work best when it is called first thing in
  376.              * the program.
  377.              */
  378.             pbStackTop = pb = &bDummy;
  379.     
  380.             /*
  381.              * Fill the stack up.
  382.              */
  383.             while (pb > &end)
  384.                 *pb-- = STACKSIG;
  385.         }
  386.         else {
  387.             /*
  388.              * Start at the bottom of the stack and search upwards.
  389.              */
  390.             pb = &end;
  391.             while (*(++pb) == STACKSIG && pb < pbStackTop)
  392.                 ;
  393.     
  394.             /*
  395.              * Display the results.
  396.              */
  397.             DBGprintf("ImagEdit stack used: %d bytes.", pbStackTop - pb);
  398.         }
  399.     }
  400.     #endif
  401.     
  402.     
  403.     
  404.     #ifdef DBG
  405.     /****************************************************************************
  406.     * DBGBltImage
  407.     *
  408.     * This debugging function blits out the given image in the specified
  409.     * DC to the screen.  Every time that it is called, it will blit the
  410.     * image to the right of the last one, starting at the top of the
  411.     * screen.  It assumes that each image is 32x32 pixels.
  412.     *
  413.     * Arguments:
  414.     *   HDC hdc - The DC with the image to blit.  If this is NULL, the
  415.     *             current XOR and AND images are blit'd, with the AND
  416.     *             image below the XOR image.
  417.     *
  418.     * History:
  419.     *  16-Sep-1991  - Created
  420.     ****************************************************************************/
  421.     
  422.     VOID DBGBltImage(
  423.         HDC hdc)
  424.     {
  425.         static INT x;
  426.         HDC hdcScreen;
  427.     
  428.         hdcScreen = GetDC(NULL);
  429.     
  430.         if (hdc) {
  431.             BitBlt(hdcScreen, x, 0, 32, 32, hdc, 0, 0, SRCCOPY);
  432.         }
  433.         else {
  434.             BitBlt(hdcScreen, x, 0, 32, 32, ghdcImage, 0, 0, SRCCOPY);
  435.             BitBlt(hdcScreen, x, 32 + 1, 32, 32, ghdcANDMask, 0, 0, SRCCOPY);
  436.         }
  437.     
  438.         ReleaseDC(NULL, hdcScreen);
  439.         x += 32 + 1;
  440.     }
  441.     
  442.     
  443.     
  444.     /****************************************************************************
  445.     * DBGprintf
  446.     *
  447.     * This debugging function prints out a string to the debug output.
  448.     * An optional set of substitutional parameters can be specified,
  449.     * and the final output will be the processed result of these combined
  450.     * with the format string, just like printf.  A newline is always
  451.     * output after every call to this function.
  452.     *
  453.     * Arguments:
  454.     *   PSTR fmt - Format string (printf style).
  455.     *   ...      - Variable number of arguments.
  456.     *
  457.     * History:
  458.     *  28-Aug-1990  - Created
  459.     ****************************************************************************/
  460.     
  461.     VOID DBGprintf(PSTR fmt, ...)
  462.     {
  463.         va_list marker;
  464.         CHAR szBuf[CCHTEXTMAX];
  465.     
  466.         va_start(marker, fmt);
  467.         vsprintf(szBuf, fmt, marker);
  468.         va_end(marker);
  469.     
  470.         OutputDebugString(szBuf);
  471.         OutputDebugString("\r\n");
  472.     }
  473.     #endif
  474.