|
|
1.1 root 1: /****************************************************************************
2:
3: MANDEL.C --
4:
5: Main code for the Windows Mandelbrot Set distributed drawing program.
6:
1.1.1.2 root 7: Copyright (C) 1990, 1992 Microsoft Corporation.
1.1 root 8:
9: This code sample is provided for demonstration purposes only.
10: Microsoft makes no warranty, either express or implied,
11: as to its usability in any given situation.
12:
13: ****************************************************************************/
14:
15: #include <sys\types.h>
16: #include <sys\stat.h>
17: #include <direct.h>
18: #include <dos.h>
19: #include <string.h>
20: #include <ctype.h>
21: #include <malloc.h> // malloc, free
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <time.h>
25:
26: #ifdef RPC
1.1.1.2 root 27: #include <rpc.h> // RPC data and API function prototypes
28: #include "mdlrpc.h" // header file generated by the MIDL compiler
1.1 root 29: #endif
30:
31: #include <windows.h> /* Required for all Windows applications */
1.1.1.3 ! root 32: #include <windowsx.h> /* Allow portability from Win16, Win32 */
1.1 root 33: #include "mandel.h" /* Specific to this program */
34:
35: #ifdef RPC
36: char szTitle[] = "Mandelbrot RPC";
37: #else
38: char szTitle[] = "Mandelbrot Standalone";
39: #endif
40:
41: char szBitmap[] = "Mandel";
42:
43: CPOINT cptUL = { (double) -2.05, (double) 1.4 };
44: double dPrec = (double) .01;
45:
46: void PaintLine( HWND, svr_table *, HDC, int);
47: COLORREF MapColor( DWORD, DWORD );
48: void DrawRect( HWND, PRECT, BOOL, HDC);
49: long get_drivemap(void);
50: void set_dlgitems(HWND, char *, long);
51: BOOL update_curdir(HWND, char *, long);
52: char * getdcwd( int, char *, unsigned);
53: void set_filename( HWND );
54: BOOL munge_path( char *);
55:
56: HANDLE hInst; /* current instance */
57:
58: int iLines = LINES;
59: svr_table SvrTable[20];
60: int SvrTableSz = 0;
61:
62: #define NCOLORS 11
63: int fContinueZoom = TRUE;
64: int fZoomIn = TRUE;
65: int Histogram[4][4][NCOLORS+1] = {0}; /* split current picture into 16 regions */
66: /* zoom on most complex region; region with most colors represented */
67: int ColorCount[4][4] = {0};
68: int Max[4][4] = { 0 };
69: int iHistMaxI = 2;
70: int iHistMaxJ = 3;
71: RECT rcZoom;
72: BOOL fRectDefined = FALSE;
1.1.1.3 ! root 73: #ifdef RPC
! 74: int fBound = FALSE; /* flag indicates whether bound to svr */
! 75: RPC_STATUS status; // returned by RPC API function
! 76: unsigned char * pszUuid = NULL;
! 77: unsigned char * pszProtocolSequence = "ncacn_np";
! 78: unsigned char * pszEndpoint = "\\pipe\\mandel";
! 79: unsigned char * pszOptions = NULL;
! 80: unsigned char * pszStringBinding;
! 81: unsigned char szNetworkAddress[UNCLEN+1] = {'\0'};
! 82: #endif
1.1 root 83:
84: /*
85: *
86: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
87: *
88: * PURPOSE: Calls initialization function, processes message loop
89: *
90: * COMMENTS:
91: *
92: * Windows recognizes this function by name as the initial entry point
93: * for the program. This function calls the application initialization
94: * routine, if no other instance of the program is running, and always
95: * calls the instance initialization routine. It then executes a message
96: * retrieval and dispatch loop that is the top-level control structure
97: * for the remainder of execution. The loop is terminated when a WM_QUIT
98: * message is received, at which time this function exits the application
99: * instance by returning the value passed by PostQuitMessage().
100: *
101: * If this function must abort before entering the message loop, it
102: * returns the conventional value NULL.
103: *
104: */
105:
106: int APIENTRY WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
107: HANDLE hInstance; /* current instance */
108: HANDLE hPrevInstance; /* previous instance */
109: LPSTR lpCmdLine; /* command line */
110: int nCmdShow; /* show-window type (open/icon) */
111: {
112: MSG msg; /* message */
113:
1.1.1.3 ! root 114: #ifdef RPC
! 115: unsigned long ulRpcException;
! 116: #endif
1.1 root 117:
1.1.1.3 ! root 118: #ifdef RPC
1.1 root 119: // add a runtime exception handler for RPC version
120: // see below for additional exception handling code
121: RpcTryExcept {
122: #endif
123:
1.1.1.3 ! root 124: UNREFERENCED_PARAMETER(lpCmdLine);
! 125:
! 126:
1.1 root 127: if (!hPrevInstance) /* Other instances of app running? */
128: if (!InitApplication(hInstance)) /* Initialize shared things */
129: return (FALSE); /* Exits if unable to initialize */
130:
131: /* Perform initializations that apply to a specific instance */
132:
133: if (!InitInstance(hInstance, nCmdShow))
134: return (FALSE);
135:
136: /* Acquire and dispatch messages until a WM_QUIT message is received. */
137:
138: while (GetMessage(&msg, /* message structure */
1.1.1.3 ! root 139: (HWND)NULL, /* handle of window receiving the message */
1.1 root 140: 0, /* lowest message to examine */
141: 0)) /* highest message to examine */
142: {
143: TranslateMessage(&msg); /* Translates virtual key codes */
144: DispatchMessage(&msg); /* Dispatches message to window */
145: }
146:
147: // add a runtime exception handler for RPC version
148: // see above for additional exception handling code
149: #ifdef RPC
150: } // end of RpcTryExcept statements
151: RpcExcept(1) {
1.1.1.3 ! root 152: ulRpcException = RpcExceptionCode();
! 153: sprintf(pszFail, "Runtime exception 0x%lx = %ld\n", ulRpcException, ulRpcException);
! 154: MessageBox(msg.hwnd, pszFail, "RPC Sample Application",
! 155: MB_ICONINFORMATION | MB_SYSTEMMODAL);
1.1 root 156: }
157: RpcEndExcept
158: #endif
159:
1.1.1.3 ! root 160: return (msg.wParam); /* Returns the value from PostQuitMessage */
1.1 root 161: } // end WinMain
162:
163: /*
164: * FUNCTION: InitApplication(HANDLE)
165: *
166: * PURPOSE: Initializes window data and registers window class
167: *
168: * COMMENTS:
169: *
170: * This function is called at initialization time only if no other
171: * instances of the application are running. This function performs
172: * initialization tasks that can be done once for any number of running
173: * instances.
174: *
175: * In this case, we initialize a window class by filling out a data
176: * structure of type WNDCLASS and calling the Windows RegisterClass()
177: * function. Since all instances of this application use the same window
178: * class, we only need to do this when the first instance is initialized.
179: */
180:
181: BOOL InitApplication(hInstance)
182: HANDLE hInstance; /* current instance */
183: {
184: WNDCLASS wc;
185:
186: /* Fill in window class structure with parameters that describe the */
187: /* main window. */
188:
189: wc.style = 0; /* Class style(s). */
190: wc.lpfnWndProc = (WNDPROC)MainWndProc; /* Function to retrieve messages for */
191: /* windows of this class. */
192: wc.cbClsExtra = 0; /* No per-class extra data. */
193: wc.cbWndExtra = 0; /* No per-window extra data. */
194: wc.hInstance = hInstance; /* Application that owns the class. */
195: wc.hIcon = LoadIcon(hInstance, "RPC_ICON");
196: wc.hbrBackground = GetStockObject(WHITE_BRUSH);
197: wc.lpszMenuName = MENUNAME; /* Name of menu resource in .RC file. */
198: wc.lpszClassName = CLASSNAME; /* Name used in call to CreateWindow. */
199:
200: /* Register the window class and return success/failure code. */
201: return (RegisterClass(&wc));
202:
203: }
204:
205: /*
206: * FUNCTION: InitInstance(HANDLE, int)
207: *
208: * PURPOSE: Saves instance handle and creates main window.
209: *
210: * COMMENTS:
211: *
212: * This function is called at initialization time for every instance of
213: * this application. This function performs initialization tasks that
214: * cannot be shared by multiple instances.
215: *
216: * In this case, we save the instance handle in a static variable and
217: * create and display the main program window.
218: */
219:
220: BOOL InitInstance(hInstance, nCmdShow)
221: HANDLE hInstance; /* Current instance identifier. */
222: int nCmdShow; /* Param for first ShowWindow() call. */
223: {
224: HWND hWnd; /* Main window handle. */
225: RECT rc;
1.1.1.3 ! root 226: HMENU hMenu;
1.1 root 227:
228: /* Save the instance handle in static variable, which will be used in */
229: /* many subsequence calls from this application to Windows. */
230:
231: hInst = hInstance;
232:
233: /* Create a main window for this application instance. */
234:
235: hWnd = CreateWindow(
236: CLASSNAME, /* See RegisterClass() call. */
237: szTitle, /* Text for window title bar. */
238: WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX,
239: CW_USEDEFAULT, /* Default horizontal position. */
240: CW_USEDEFAULT, /* Default vertical position. */
241: WIDTH, /* Default width. */
242: HEIGHT, /* Default height. */
1.1.1.3 ! root 243: (HWND)NULL, /* Overlapped windows have no parent. */
! 244: (HMENU)NULL, /* Use the window class menu. */
1.1 root 245: hInstance, /* This instance owns this window. */
1.1.1.3 ! root 246: (void FAR *)NULL /* Pointer not needed. */
1.1 root 247: );
248:
249: /* If window could not be created, return "failure" */
250:
251: if (!hWnd)
1.1.1.3 ! root 252: return (FALSE);
1.1 root 253:
254: /* Make the window visible; update its client area; and return "success" */
255:
256: ShowWindow(hWnd, nCmdShow); /* Show the window */
1.1.1.3 ! root 257: UpdateWindow(hWnd); /* Sends WM_PAINT message */
1.1 root 258: rc.top = rc.left = 0;
259: rc.bottom = HEIGHT-1;
260: rc.right = WIDTH-1;
261:
262: SetNewCalc(cptUL, dPrec, rc);
1.1.1.3 ! root 263: hMenu = GetMenu(hWnd);
! 264:
! 265: #ifndef RPC
! 266: EnableMenuItem(hMenu, IDM_SERVER, MF_GRAYED); /* disable option */
! 267: #endif
1.1 root 268:
269: return (TRUE); /* Returns the value from PostQuitMessage */
270: }
271:
272:
273:
274: /*
275: * FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
276: *
277: * PURPOSE: Processes messages
278: *
279: * MESSAGES:
280: *
1.1.1.3 ! root 281: * WM_COMMAND - application menu
1.1 root 282: * WM_DESTROY - destroy window
283: *
284: * COMMENTS:
285: *
286: */
287:
288: LONG APIENTRY MainWndProc(
289: HWND hWnd, /* window handle */
290: UINT message, /* type of message */
291: UINT wParam, /* additional information */
292: LONG lParam) /* additional information */
293: {
1.1.1.3 ! root 294: DLGPROC lpProc; /* pointer to the dialog box function */
1.1 root 295: PAINTSTRUCT ps;
296: HDC hdc;
297: static HDC hdcMem;
298: static HBITMAP hbmMem;
299: static int width;
300: static int height;
301: RECT rc;
302: static BOOL fButtonDown = FALSE;
303: static POINT pSelected;
304: POINT pMove;
305: int iWidthNew;
306: int iHeightNew;
307: static int miOldLines;
308: double scaling;
309:
310: switch (message)
311: {
312:
313: case WM_CREATE:
1.1.1.3 ! root 314: #ifdef WIN16
! 315: PostMessage(hWnd, WM_COMMAND, IDM_SERVER, 0L); /* force server spec */
! 316: #else
! 317: PostMessage(hWnd, WM_COMMAND, IDM_BIND, 0L); /* bind to server */
! 318: #endif
! 319: if (!InitRemote(hWnd))
1.1 root 320: return FALSE;
321:
322: InitHistogram();
323:
324: hdc = GetDC(hWnd);
325: hdcMem = CreateCompatibleDC(hdc);
326: GetWindowRect(hWnd, &rc);
327: width = rc.right - rc.left;
328: height = rc.bottom - rc.top;
329: hbmMem = CreateCompatibleBitmap(hdc, width, height);
330: SelectObject(hdcMem, hbmMem);
331:
332: ReleaseDC(hWnd,hdc);
333:
334: rc.left = rc.top = 0;
335: rc.right = width+1;
336: rc.bottom = height + 1;
337: FillRect(hdcMem, &rc, GetStockObject(WHITE_BRUSH));
338:
339: SetTimer(hWnd, 1, POLL_TIME, NULL); // set timer for polls
340:
341: CheckMenuItem(GetMenu(hWnd), IDM_4LINES, MF_CHECKED);
342: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_CHECKED);
343: miOldLines = IDM_4LINES; // save to uncheck
1.1.1.3 ! root 344: break;
1.1 root 345:
346: case WM_PAINT:
347: hdc = BeginPaint(hWnd, &ps);
348: BitBlt(hdc, ps.rcPaint.left,
349: ps.rcPaint.top,
350: ps.rcPaint.right - ps.rcPaint.left,
351: ps.rcPaint.bottom - ps.rcPaint.top,
352: hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
353: EndPaint(hWnd, &ps);
354: break;
355:
356: case WM_COMMAND: /* message: command from application menu */
357: switch(wParam)
358: {
1.1.1.3 ! root 359: case IDM_BIND:
! 360: #ifdef RPC
! 361: if (Bind(hWnd))
! 362: PostMessage(hWnd, WM_DESTROY, 0, 0L);
! 363: #endif
! 364: break;
1.1 root 365:
366: case IDM_ABOUT:
1.1.1.3 ! root 367: lpProc = MakeProcInstance(About, hInst);
1.1 root 368:
1.1.1.2 root 369: DialogBox(hInst, /* current instance */
370: ABOUTBOX, /* resource to use */
371: hWnd, /* parent handle */
1.1.1.3 ! root 372: lpProc); /* About() instance address */
1.1 root 373:
1.1.1.3 ! root 374: FreeProcInstance(lpProc);
1.1 root 375: break;
376:
377: case IDM_ZOOMOUT:
378: if (dPrec > (double)MAXPREC) // don't allow the zoom out
379: break;
380: rcZoom.left = WIDTH/4 + (WIDTH/8); // center square
381: rcZoom.top = HEIGHT/4 + (HEIGHT/8);
382: rcZoom.right = rcZoom.left + (WIDTH/4);
383: rcZoom.bottom = rcZoom.top + (HEIGHT/4);
384:
385: cptUL.real -= (rcZoom.left * dPrec); // inverse of zoom in
386: cptUL.imag += (rcZoom.top * dPrec);
387: iWidthNew = (rcZoom.right - rcZoom.left + 1);
388: iHeightNew = (rcZoom.bottom - rcZoom.top + 1);
389: scaling =
390: ( (double) ((iWidthNew > iHeightNew) ? iWidthNew : iHeightNew)
391: / (double)width);
392: dPrec /= scaling;
393:
394: rc.left = rc.top = 0;
395: rc.bottom = height - 1;
396: rc.right = width - 1;
397:
398: SetNewCalc(cptUL, dPrec, rc);
399: fRectDefined = FALSE;
400: DoSomeWork(hWnd, FALSE);
401: break;
402:
403: case IDM_ZOOMIN: // zoom in on selected rectangle
404: // if no rectangle, don't zoom in
405: if (!fRectDefined)
406: break;
407: if (dPrec < (double)MINPREC) // don't allow zoom in
408: break;
409: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); // draw new rect
410:
411: // calculate new upper-left
412: cptUL.real += (rcZoom.left * dPrec);
413: cptUL.imag -= (rcZoom.top * dPrec);
414:
415: iWidthNew = (rcZoom.right - rcZoom.left + 1);
416: iHeightNew = (rcZoom.bottom - rcZoom.top + 1);
417: scaling =
418: ( (double) ((iWidthNew > iHeightNew) ? iWidthNew : iHeightNew)
419: / (double)width);
420:
421: dPrec *= scaling;
422:
423: rc.left = rc.top = 0;
424: rc.bottom = height - 1;
425: rc.right = width - 1;
426:
427: SetNewCalc( cptUL, dPrec, rc);
428: IncPictureID();
429:
430: fRectDefined = FALSE;
431: DoSomeWork(hWnd, FALSE);
432: break;
433:
434: case IDM_CONTINUOUS: // continuous zoom in
435: if (fContinueZoom == TRUE) {
436: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_UNCHECKED);
437: fContinueZoom = FALSE;
438: }
439: else {
440: CheckMenuItem(GetMenu(hWnd), IDM_CONTINUOUS, MF_CHECKED);
441: fContinueZoom = TRUE;
442: }
443: break;
444:
445: case IDM_REDRAW:
446: if (fContinueZoom == TRUE)
447: InitHistogram();
448: rc.left = rc.top = 0;
449: rc.right = width+1;
450: rc.bottom = height + 1;
451: FillRect(hdcMem, &rc, GetStockObject(WHITE_BRUSH));
452: InvalidateRect(hWnd, NULL, TRUE);
453:
454: rc.left = rc.top = 0;
455: rc.bottom = height - 1;
456: rc.right = width - 1;
457: SetNewCalc( cptUL, dPrec, rc);
458:
459: fRectDefined = FALSE;
460: DoSomeWork(hWnd, FALSE);
461: break;
462:
1.1.1.3 ! root 463: case IDM_EXIT:
1.1 root 464: DestroyWindow(hWnd);
465: break;
466:
467: case IDM_TOP:
468: cptUL.real = (double) -2.05;
469: cptUL.imag = (double) 1.4;
470: dPrec = .01;
471:
472: rc.left = rc.top = 0;
473: rc.bottom = height - 1;
474: rc.right = width - 1;
475: SetNewCalc( cptUL, dPrec, rc);
476: cPictureID = 0; // incremented past original
477:
478: fRectDefined = FALSE;
479: DoSomeWork(hWnd, FALSE);
480: break;
481:
482: case IDM_1LINE:
483: case IDM_2LINES:
484: case IDM_4LINES:
485:
486: CheckMenuItem(GetMenu(hWnd), miOldLines, MF_UNCHECKED);
487: miOldLines = wParam;
488: switch(wParam)
489: {
490: case IDM_1LINE:
491: iLines = 1;
492: break;
493: case IDM_2LINES:
494: iLines = 2;
495: break;
496: case IDM_4LINES:
497: iLines = 4;
498: break;
499: }
500:
501: CheckMenuItem(GetMenu(hWnd), miOldLines, MF_CHECKED);
1.1.1.3 ! root 502: break;
1.1 root 503:
1.1.1.3 ! root 504: #ifdef RPC
! 505: case IDM_SERVER:
! 506: lpProc = MakeProcInstance(Server, hInst);
! 507: DialogBox(hInst, /* current instance */
! 508: "ServerBox", /* resource to use */
! 509: hWnd, /* parent handle */
! 510: lpProc); /* Server instance address */
! 511: FreeProcInstance(lpProc);
! 512: break;
! 513: #endif
1.1 root 514:
515: default: /* Lets Windows process it */
516: return (DefWindowProc(hWnd, message, wParam, lParam));
517: }
518: break;
519: case WM_DESTROY: /* message: window being destroyed */
520: PostQuitMessage(0);
521: DeleteDC(hdcMem);
522: DeleteObject(hbmMem);
523: break;
524:
525: case WM_DOSOMEWORK:
526: // do another slice of calculation work
527: DoSomeWork(hWnd, FALSE);
528: break;
529:
530: case WM_PAINTLINE:
531: // The shared buffer contains a line of data; draw it
532: PaintLine(hWnd,
533: (svr_table *)&SvrTable[(signed int)wParam],
534: hdcMem,
535: height);
536: break;
537:
538: case WM_TIMER:
539: // timer means we should do another slice of work
540: DoSomeWork(hWnd, TRUE);
541: break;
542:
543: case WM_LBUTTONDOWN:
544: // left button down; start to define a zoom rectangle
545:
546: if (fRectDefined)
547: DrawRect(hWnd, &rcZoom, FALSE, hdcMem); // undraw old rectangle
548:
549: // initialize rectangle
550: rcZoom.left = rcZoom.right = pSelected.x = LOWORD(lParam);
551: rcZoom.top = rcZoom.bottom = pSelected.y = HIWORD(lParam);
552:
553: // draw the new rectangle
554: DrawRect(hWnd, &rcZoom, TRUE, hdcMem);
555:
556: fRectDefined = TRUE;
557: fButtonDown = TRUE;
558: SetCapture(hWnd); // capture all mouse events
559: break;
560:
561: case WM_MOUSEMOVE:
562:
563: // mouse move -- if the button is down, change the rect
564: if (!fButtonDown)
565: break;
566:
567: DrawRect(hWnd, &rcZoom, FALSE, hdcMem); // undraw old rect
568:
569: pMove.x = LOWORD(lParam);
570: pMove.y = HIWORD(lParam);
571:
572: // update the selection rectangle
573: if (pMove.x <= pSelected.x)
574: rcZoom.left = pMove.x;
575: if (pMove.x >= pSelected.x)
576: rcZoom.right = pMove.x;
577: if (pMove.y <= pSelected.y)
578: rcZoom.top = pMove.y;
579: if (pMove.y >= pSelected.y)
580: rcZoom.bottom = pMove.y;
581:
582: DrawRect(hWnd, &rcZoom, TRUE, hdcMem); // draw new rect
583: break;
584:
585: case WM_LBUTTONUP:
586: // button up; end selection
587: fButtonDown = FALSE;
588: ReleaseCapture();
589: break;
590:
591: default: /* Passes it on if unproccessed */
592: return (DefWindowProc(hWnd, message, wParam, lParam));
593: }
594: return (0L);
595: }
596:
597:
598:
599: /*
600: * FUNCTION: About(HWND, unsigned, WORD, LONG)
601: *
602: * PURPOSE: Processes messages for "About" dialog box
603: *
604: * MESSAGES:
605: *
606: * WM_INITDIALOG - initialize dialog box
607: * WM_COMMAND - Input received
608: *
609: * COMMENTS:
610: *
611: * No initialization is needed for this particular dialog box, but TRUE
612: * must be returned to Windows.
613: *
614: * Wait for user to click on "Ok" button, then close the dialog box.
615: */
616:
617: BOOL APIENTRY About(
618: HWND hDlg, /* window handle of the dialog box */
619: UINT message, /* type of message */
620: UINT wParam, /* message-specific information */
621: LONG lParam)
622: {
623: UNREFERENCED_PARAMETER(lParam);
624:
625: switch (message)
626: {
627: case WM_INITDIALOG: /* message: initialize dialog box */
628:
629: return (TRUE);
630:
631: case WM_COMMAND: /* message: received a command */
632: if (wParam == IDOK /* "OK" box selected? */
633: || wParam == IDCANCEL) /* System menu close command? */
634: {
635: EndDialog(hDlg, TRUE); /* Exits the dialog box */
636: return (TRUE);
637: }
638: break;
639: }
640: return (FALSE); /* Didn't process a message */
641: }
642:
643:
644:
645:
646: /*
647: * DoSomeWork --
648: *
649: * This function does our work for us. It does it in little pieces, and
650: * will schedule itself as it sees fit.
651: */
652:
653: void
654: DoSomeWork( HWND hwnd,
655: BOOL fTimer)
656: {
657:
658: static WORD wIteration = 0;
659:
660: if (fTimer) {
661: wIteration++;
662:
663: // on every nth tick, we send out a poll
664: if (wIteration == 120) { // tune this?
665: wIteration = 0;
666: return;
667: }
668:
669: // on the half-poll, we check for responses
670: if ((wIteration == 2) || (wIteration == 10)) {
671: return;
672: }
673:
674: }
675:
676: if (CheckDrawStatus(hwnd))
677: SendMessage(hwnd, WM_DOSOMEWORK, 0, 0L);
678:
679: return;
680: }
681:
682:
683:
684: /*
685: * DrawRect --
686: *
687: * This function draws (or undraws) the zoom rectangle.
688: */
689:
690: void
691: DrawRect( HWND hwnd,
692: PRECT prc,
693: BOOL fDrawIt,
694: HDC hdcBM)
695: {
696:
697: HDC hdc;
698: DWORD dwRop;
699:
700: hdc = GetDC(hwnd);
701:
702: if (fDrawIt)
703: dwRop = NOTSRCCOPY;
704: else
705: dwRop = SRCCOPY;
706:
707:
708: // top side
709: BitBlt(hdc, prc->left, prc->top, (prc->right - prc->left) + 1,
710: 1, hdcBM, prc->left, prc->top, dwRop);
711:
712: // bottom side
713: BitBlt(hdc, prc->left, prc->bottom, (prc->right - prc->left) + 1,
714: 1, hdcBM, prc->left, prc->bottom, dwRop);
715:
716: // left side
717: BitBlt(hdc,prc->left, prc->top, 1, (prc->bottom - prc->top) + 1,
718: hdcBM, prc->left, prc->top, dwRop);
719:
720: // right side
721: BitBlt(hdc,prc->right, prc->top, 1, (prc->bottom - prc->top) + 1,
722: hdcBM, prc->right, prc->top, dwRop);
723:
724: ReleaseDC(hwnd, hdc);
725: }
726:
727:
728:
729: /*
730: * PaintLine --
731: *
732: * This function paints a buffer of data into the bitmap.
733: */
734:
735: void
736: PaintLine( HWND hwnd,
737: svr_table * pst,
738: HDC hdcBM,
739: int cHeight)
740: {
741:
742: PWORD pwDrawData;
743: int y;
744: int x;
745: DWORD dwThreshold;
746: RECT rc;
747: WORD lines;
748:
749: lines = (WORD) pst->cLines;
750:
751: // picture ID had better match, or else we skip it
752: if (CheckDrawingID(pst->cPicture))
753: {
754: // figure out our threshold
755: dwThreshold = QueryThreshold();
756:
757: // get a pointer to the draw buffer
758: pwDrawData = (PWORD)GetDrawBuffer();
759: if (pwDrawData == NULL) {
760: ReturnDrawBuffer();
761: return;
762: }
763:
764: // starting x coordinate
765: x = (int) pst->dwLine;
766:
767: // now loop through the rectangle
768: while (lines-- > 0)
769: {
770: // bottom to top, since that's the order of the data in the buffer
771: y = (int) cHeight-1;
772:
773:
774: while (y >= 0) {
775: // draw a pixel
776: SetPixel(hdcBM, x,y, MapColor((DWORD)*pwDrawData, dwThreshold));
777: if (fContinueZoom == TRUE)
778: CalcHistogram(x, y, (DWORD)*pwDrawData, dwThreshold);
779: // now increment buffer pointer and y coord
780: y--;
781: pwDrawData++;
782: }
783: x++; // increment X coordinate
784: }
785:
786: // figure out the rectangle to invalidate
787: rc.top = 0;
788: rc.bottom = cHeight;
789: rc.left = (int)(pst->dwLine);
790: rc.right = (int)(pst->dwLine) + pst->cLines;
791:
792: FreeDrawBuffer();
793:
794: // and invalidate it on the screen so we redraw it
795: InvalidateRect(hwnd, &rc, FALSE);
796: }
797:
798: // free this for someone else to use
799: ReturnDrawBuffer();
800:
801: // and change the pipe state, if necessary
802: if (pst->iStatus == SS_PAINTING)
803: pst->iStatus = SS_IDLE;
804:
805: }
806:
807:
808: #define CLR_BLACK RGB(0,0,0)
809: #define CLR_DARKBLUE RGB(0,0,127)
810: #define CLR_BLUE RGB(0,0,255)
811: #define CLR_CYAN RGB(0,255,255)
812: #define CLR_DARKGREEN RGB(0,127,0)
813: #define CLR_GREEN RGB(0,255,0)
814: #define CLR_YELLOW RGB(255,255,0)
815: #define CLR_RED RGB(255,0,0)
816: #define CLR_DARKRED RGB(127,0,0)
817: #define CLR_WHITE RGB(255,255,255)
818: #define CLR_PALEGRAY RGB(194,194,194)
819: #define CLR_DARKGRAY RGB(127,127,127)
820:
821:
822: static COLORREF ColorMapTable[] = { // size = NCOLORS
823: CLR_DARKBLUE,
824: CLR_BLUE,
825: CLR_CYAN,
826: CLR_DARKGREEN,
827: CLR_GREEN,
828: CLR_YELLOW,
829: CLR_RED,
830: CLR_DARKRED,
831: CLR_WHITE,
832: CLR_PALEGRAY,
833: CLR_DARKGRAY};
834:
835:
836: /*
837: * MapColor --
838: *
839: * This function maps an iteration count into a corresponding RGB color.
840: */
841:
842: COLORREF
843: MapColor(DWORD dwIter,
844: DWORD dwThreshold)
845: {
846:
847: // if it's beyond the threshold, call it black
848: if (dwIter >= dwThreshold) {
849: return CLR_BLACK;
850: }
851:
852: // get a modulus based on the number of colors
853: dwIter = (dwIter / 3) % NCOLORS; // 11;
854:
855: // and return the appropriate color
856: return ColorMapTable[dwIter];
857:
858: }
859: /* CalcHistogram
860: * This function is used to select the region that is the
861: * most complex and will be used to zoom in for the next picture;
862: * it contains the most colors. The number of colors are counted.
863: */
864:
865: void
866: CalcHistogram(int x,
867: int y,
868: DWORD dwIter,
869: DWORD dwThreshold)
870: {
871:
872: // if it's beyond the threshold, call it black
873: if (dwIter >= dwThreshold) {
874: Histogram[x/(WIDTH/4)][y/(HEIGHT/4)][NCOLORS]++;
875: return;
876: }
877: // get a modulus based on the number of colors
878: dwIter = (dwIter / 3) % NCOLORS; // 11;
879:
880: // and bump the count for the appropriate color
881: Histogram[x/(WIDTH/4)][y/(HEIGHT/4)][dwIter]++; // region of map
882:
883: return;
884:
885: }
886:
887:
888: /* InitHistogram
889: * This function initializes the histogram data structures.
890: */
891:
892: void InitHistogram(void)
893: {
894: int i, j, k;
895:
896: for (i = 0; i < 4; i++)
897: for (j = 0; j < 4; j++)
898: for (k = 0; k <= NCOLORS; k++)
899: Histogram[i][j][k] = 0; /* count of colors */
900: }
901:
902: /* CountHistogram
903: * This function determines the number of colors represented
904: * within a region. The region with the most colors is
905: * selected using the maxi and maxj values. X and Y coordinates
906: * corresponding to these regions are stored in the HistRegion
907: * table and are used for the next picture.
908: */
909:
910: void CountHistogram(void)
911: {
912: int i, j, k;
913: /* count the number of colors in each region */
914: /* find the color that dominates each region */
915: for (i = 0; i < 4; i++) {
916: for (j = 0; j < 4; j++) {
917: ColorCount[i][j] = 0;
918: Max[i][j] = 0;
919: for (k = 0; k <= NCOLORS; k++) {
920: if (Histogram[i][j][k] > Max[i][j])
921: Max[i][j] = Histogram[i][j][k];
922: if (Histogram[i][j][k] != 0) /* count of colors */
923: ColorCount[i][j]++;
924: }
925:
926: }
927: }
928: iHistMaxI = 0;
929: iHistMaxJ = 0;
930: /* if several regions have the same number of colors, */
931: /* select the region with the most variety: the smallest max */
932: for (i = 0; i < 4; i++) {
933: for (j = 0; j < 4; j++) {
934: if ( (ColorCount[i][j] >= ColorCount[iHistMaxI][iHistMaxJ])
935: && (Max[i][j] < Max[iHistMaxI][iHistMaxJ]) ) {
936: iHistMaxI = i;
937: iHistMaxJ = j;
938: }
939: }
940: }
941: InitHistogram(); /* initialize for next time */
942:
943: }
1.1.1.2 root 944:
945: /* need this function to link properly; ndrlib needs it */
946: void * MIDL_user_allocate(size_t len)
947: {
948: UNREFERENCED_PARAMETER(len);
949: return(NULL);
950: }
1.1.1.3 ! root 951:
! 952: /****************************************************************************
! 953:
! 954: FUNCTION: Server(HWND, unsigned, WORD, LONG)
! 955:
! 956: PURPOSE: Processes messages for "Server" dialog box
! 957:
! 958: MESSAGES:
! 959:
! 960: WM_INITDIALOG - initialize dialog box
! 961: WM_COMMAND - Input received
! 962:
! 963: COMMENTS:
! 964:
! 965: No initialization is needed for this particular dialog box, but TRUE
! 966: must be returned to Windows.
! 967:
! 968: Wait for user to click on "Ok" button, then close the dialog box.
! 969:
! 970: ****************************************************************************/
! 971: BOOL APIENTRY Server(
! 972: HWND hDlg, /* window handle of the dialog box */
! 973: UINT message, /* type of message */
! 974: UINT wParam, /* message-specific information */
! 975: LONG lParam)
! 976: {
! 977: UNREFERENCED_PARAMETER(lParam);
! 978:
! 979: #ifdef RPC
! 980: switch (message) {
! 981:
! 982: case WM_INITDIALOG: /* message: initialize dialog box */
! 983: SetDlgItemText( hDlg, IDD_SERVERNAME, szNetworkAddress);
! 984: return (TRUE);
! 985:
! 986: case WM_COMMAND: /* message: received a command */
! 987: switch(wParam) {
! 988: case IDCANCEL: /* System menu close command? */
! 989: EndDialog( hDlg, FALSE );
! 990: return( TRUE );
! 991: case IDOK: /* "OK" box selected? */
! 992: GetDlgItemText( hDlg, IDD_SERVERNAME, szNetworkAddress, UNCLEN);
! 993: if (Bind(hDlg) != RPC_S_OK) {
! 994: EndDialog(hDlg, FALSE);
! 995: return(FALSE);
! 996: }
! 997: EndDialog(hDlg, TRUE);
! 998: return(TRUE);
! 999: } /* end switch wParam */
! 1000:
! 1001: } /* end switch message */
! 1002: return (FALSE); /* Didn't process a message */
! 1003: #endif
! 1004: }
! 1005:
! 1006: /****************************************************************************
! 1007:
! 1008: FUNCTION: Bind(HWND)
! 1009:
! 1010: PURPOSE: Make RPC API calls to bind to the server application
! 1011:
! 1012: COMMENTS:
! 1013:
! 1014: The binding calls are made from InitInstance() and whenever
! 1015: the user changes the server name or endpoint. If the bind
! 1016: operation is successful, the global flag fBound is set to TRUE.
! 1017:
! 1018: The global flag fBound is used to determine whether to call
! 1019: the RPC API function RpcBindingFree.
! 1020:
! 1021: ****************************************************************************/
! 1022:
! 1023: #ifdef RPC
! 1024: RPC_STATUS Bind(HWND hWnd)
! 1025: {
! 1026: RPC_STATUS status;
! 1027:
! 1028: if (fBound == TRUE) { /* unbind only if bound */
! 1029: fBound = FALSE;
! 1030: status = RpcBindingFree(&hMandel); // remote calls done; unbind
! 1031: sprintf(pszFail, "RpcBindingFree returned 0x%x", status);
! 1032: MessageBox(hWnd, pszFail, "RPC Sample Application", MB_ICONINFORMATION);
! 1033: if (status)
! 1034: return(status);
! 1035: }
! 1036: status = RpcStringBindingCompose(pszUuid,
! 1037: pszProtocolSequence,
! 1038: szNetworkAddress,
! 1039: pszEndpoint,
! 1040: pszOptions,
! 1041: &pszStringBinding);
! 1042: sprintf(pszFail, "RpcStringBindingCompose returned: (0x%x)\nNetwork Address = %s\n",
! 1043: status, szNetworkAddress);
! 1044: MessageBox(hWnd, pszFail, "RPC Sample Application", MB_ICONINFORMATION);
! 1045:
! 1046: if (status)
! 1047: return(status);
! 1048:
! 1049: status = RpcBindingFromStringBinding(pszStringBinding,
! 1050: &hMandel);
! 1051:
! 1052: sprintf(pszFail, "RpcBindingFromStringBinding returned: (0x%x)\nString = %s\n",
! 1053: status, pszStringBinding);
! 1054: MessageBox(hWnd, pszFail, "RPC Sample Application", MB_ICONINFORMATION);
! 1055:
! 1056: if (status)
! 1057: return(status);
! 1058:
! 1059: fBound = TRUE; /* bind successful; reset flag */
! 1060: return(status);
! 1061: }
! 1062: #endif
! 1063:
! 1064: /* end mandel.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.