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