|
|
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.