home *** CD-ROM | disk | FTP | other *** search
- /*=========================================================================*\
- * *
- * SORT.C - Multi-threaded PM sample. *
- * *
- * *
- * (C) Copyright IBM Corporation 1992. *
- * *
- * DISCLAIMER OF WARRANTIES. The following [enclosed] code is *
- * sample code created by IBM Corporation. This sample code is not *
- * part of any standard or IBM product and is provided to you solely *
- * for the purpose of assisting you in the development of your *
- * applications. The code is provided "AS IS", without *
- * warranty of any kind. IBM shall not be liable for any damages *
- * arising out of your use of the sample code, even if they have *
- * been advised of the possibility of such damages. *
- *-------------------------------------------------------------------------*
- *
- * This program demonstrates the use of many threads by doing
- * LISTCNT simultaneous sorts. Each sorting algorithm runs
- * from a separate thread, the routine which updates the display
- * is run from another thread, and the main thread is used to
- * handle the main window's messages. The display thread is
- * started when the program begins and is not terminated (allows
- * default cleanup to terminate thread) as the display routine
- * is used throughout the program's life.
- * This code was written to allow easy modification. To change
- * the number of simultaneous sorts, change the LISTCNT #define
- * and modify the global arrays which control the screen
- * drawing color, the sort each thread is to use, and the sort name.
- * Note: This program was not intended to infer the relative
- * speeds of the various sorting algorithms.
- *
- *---------------------------------------------------------------
- *
- * Procedures in this file:
- * main() Sets up the PM environment and calls
- * the main dialog procedure ClientWndProc
- * ClientWndProc() Handles the main window messages
- * CalcThread() Generic stub that sets up, executes, and
- * terminates each sort in an aux. thread
- * DispThread() Updates the display during the sorts
- * BubbleSort() Implements a bubble sort
- * InsertionSort() Implements an insertion sort
- * BatcherSort() Stub that calls recursive Batcher sort
- * BatcherSortR() Implements a Batcher sort
- * QuickSort() Stub that calls recursive Quick sort
- * QuickSortR() Implements a Quick sort
- * EnableMenuItem() Activates/deactivates a menu choice
- * EntryFldDlgProc() Handles the set number of disks dialog box
- * RandomizeData() Randomizes the data arrays for the sorts
- * FixSysMenu() Remove Restore, Size, Min, & Max from system menu
- *
- \*==============================================================*/
- /*--------------------------------------------------------------*\
- * Include files, macros, defined constants, and externs *
- \*--------------------------------------------------------------*/
- #define INCL_WIN
- #define INCL_WINHEAP
- #define INCL_HELP
- #define INCL_WINDIALOGS
- #define INCL_GPIPRIMITIVES
- #define INCL_GPIBITMAPS
- #define INCL_DOSPROCESS
- #define INCL_DOSSEMAPHORES
-
- #include <os2.h>
- #include <stdio.h>
- #include <string.h>
- #include <process.h>
- #include <stdlib.h>
- #include "sort.h"
-
- #ifdef RAND_MAX
- #undef RAND_MAX
- #define RAND_MAX 32767
- #endif
-
- /*--------------------------------------------------------------*\
- * Entry point declarations *
- \*--------------------------------------------------------------*/
-
- MRESULT EXPENTRY ClientWndProc (HWND, ULONG, MPARAM, MPARAM);
- MRESULT EXPENTRY EntryFldDlgProc(HWND, ULONG, MPARAM, MPARAM);
- MRESULT EXPENTRY AboutDlgProc(HWND, ULONG, MPARAM, MPARAM);
- LONG MessageBox(HWND, LONG, LONG, BOOL);
- VOID APIENTRY ExitProc(ULONG);
- BOOL Init(VOID);
-
- INT main(LONG ,CHAR **);
- VOID _Optlink CalcThread(PVOID);
- VOID _Optlink DispThread(PVOID);
-
- VOID EnableMenuItem(HWND, LONG, BOOL);
- VOID RandomizeData(ULONG);
- VOID BubbleSort(PCALCPARAM);
- VOID BatcherSort(PCALCPARAM);
- VOID BatcherSortR(PCALCPARAM, ULONG, ULONG, ULONG, BOOL);
- VOID QuickSort(PCALCPARAM);
- VOID QuickSortR(PCALCPARAM, LONG, LONG);
- VOID InsertionSort(PCALCPARAM);
- VOID FixSysMenu(HWND);
- VOID InitHelp(VOID);
- VOID HelpHelpForHelp(MPARAM);
- VOID HelpExtended(MPARAM);
- VOID HelpKeys(MPARAM);
- VOID HelpIndex(MPARAM);
- VOID HelpAbout(MPARAM);
- VOID DisplayHelpPanel(LONG);
- VOID DestroyHelpInstance(VOID);
- HEV hev;
- RECTL rcl; /* Rectangle struct for painting */
-
- /*--------------------------------------------------------------*\
- * Global variables *
- \*--------------------------------------------------------------*/
- CHAR szClientClass[40];
- USHORT Data[LISTCNT][MAX_ELEMS]; /* Array that contains the data to sort */
-
- /* Global data that defines each of the sort routines */
-
- /* Color of each of the LISTCNT data lists. */
- ULONG ulColors[LISTCNT] = { CLR_RED,CLR_BLUE,CLR_DARKGREEN,CLR_CYAN };
-
- /* List of sorts to be executed for each of the LISTCNT threads. */
- VOID (*pExecSub[LISTCNT])(PCALCPARAM)={BubbleSort,BatcherSort,QuickSort,
- InsertionSort};
- /* Ascii names of sorts */
- CHAR *szSubNames[LISTCNT]={"Bubble Sort",
- "Batcher Sort",
- "Quick Sort",
- "Insertion Sort"};
-
- HAB hab; /* Anchor block for the process */
- HMQ hmq;
- BOOL fHelpEnabled; /* flag to determine if help is enabled */
- CHAR szUntitled[MESSAGELEN]; /* buffer for "Untitled" string */
- HWND hwndFrame, hwndClient;
- static CHAR szLibName[HELPLIBRARYNAMELEN];
- static CHAR szWindowTitle[HELPLIBRARYNAMELEN];
- static HWND hwndHelpInstance;
- RECTL rectl;
-
- /****************************************************************\
- * Function name: main(LONG sArgc,CHAR **ppArgv)
- *
- * Parameters: NONE
- *
- * Returns: Always returns 0
- *
- * Purpose: Sets up the PM environment, calls the main window proc,
- * handles the window's messages then cleans up and exits.
- *
- * Usage:
- \****************************************************************/
- INT main(LONG sArgc,CHAR **ppArgv)
- {
- QMSG qmsg;
- CHAR *pszName = "SORT";
-
- ULONG flFrameFlags = FCF_STANDARD;
-
- strncpy(szClientClass,pszName,strlen(pszName) );
-
- /* These PM calls should be error checked */
- hab = WinInitialize(0);
- hmq = WinCreateMsgQueue(hab, 0);
-
- if(!Init())
- {
- MessageBox(HWND_DESKTOP,
- IDMSG_INITFAILED,
- MB_OK | MB_ERROR,
- TRUE);
- DosExit(EXIT_PROCESS,RETURN_ERROR);
- }
-
-
- hwndFrame = WinCreateStdWindow(HWND_DESKTOP,
- WS_VISIBLE,
- &flFrameFlags,
- szClientClass,
- NULL,
- 0L,
- (HMODULE)0,
- ID_RESOURCE,
- &hwndClient);
- if(hwndFrame == NULLHANDLE)
- {
- MessageBox(HWND_DESKTOP,
- IDMSG_MAINWINCREATEFAILED,
- MB_OK | MB_ERROR,
- TRUE);
- DosExit(EXIT_PROCESS,RETURN_ERROR);
- }
- InitHelp();
-
- while(WinGetMsg(hab,&qmsg,0,0,0)) /* Message loop */
- WinDispatchMsg(hab,&qmsg);
-
- /* destroy the help instance */
- DestroyHelpInstance();
-
- DosExit(EXIT_PROCESS,RETURN_SUCCESS);
- return 0L;
- }
-
- /****************************************************************\
- * Initialization routine
- *---------------------------------------------------------------
- *
- * Name: Init()
- *
- * Purpose: Performs initialization functions required before the main
- * window can be created.
- *
- * Usage: Called once before the main window is created.
- *
- * Method: - installs the routine ExitProc into the DosExitList chain
- * - registers all window classes
- * - performs any command line processing
- *
- *
- * Returns: TRUE - initialization is successful
- * FALSE - initialization failed
- \****************************************************************/
- BOOL Init(VOID)
- {
-
- /* Add ExitProc to the exit list to handle the exit processing. If
- * there is an error, then terminate the process since there have
- * not been any resources allocated yet */
-
- if(DosExitList(EXLST_ADD, ExitProc))
- {
- MessageBox(HWND_DESKTOP,
- IDMSG_CANNOTLOADEXITLIST,
- MB_OK | MB_ERROR,
- TRUE);
- DosExit(EXIT_PROCESS, RETURN_ERROR);
- }
-
- if(DosCreateEventSem(NULL,&hev,DC_SEM_SHARED,FALSE ) )
- {
- return(FALSE);
- }
-
- /* load application name from resource file */
- if(!WinLoadString(hab, 0, IDS_APPNAME, MAXNAMEL, szClientClass))
- return FALSE;
-
- /* load "untitled" string */
- if(!WinLoadString(hab, 0, IDS_UNTITLED, MESSAGELEN, szUntitled))
- return FALSE;
- /* register the main client window class */
- if(!WinRegisterClass(hab,
- (PSZ)szClientClass,
- (PFNWP)ClientWndProc,
- CS_SIZEREDRAW | CS_CLIPCHILDREN,
- 0))
- {
- return FALSE;
- }
- return( TRUE);
- } /* Init() */
-
- /****************************************************************\
- * Exit list processing procedure
- *--------------------------------------------------------------
- *
- * Name: ExitProc(usTermCode)
- *
- * Purpose: Cleans up certain resources when the application terminates
- *
- * Usage: Routine is called by DosExitList when the application exits
- *
- * Method: Global resources, such as the main window and message queue,
- * are destroyed and any system resources used are freed.
- *
- * Returns: Returns EXLST_EXIT to the DosExitList handler
- *
- \****************************************************************/
- VOID APIENTRY ExitProc(ULONG usTermCode)
- {
- /* destroy the main window if it exists */
- if(WinIsWindow(hab, hwndFrame)) {
- WinDestroyWindow(hwndFrame);
- }
-
- /*--------------------------------------------------*\
- * Any other system resources used *
- * (e.g. memory or files) should be freed here *
- \*--------------------------------------------------*/
-
- WinDestroyMsgQueue(hmq);
-
- WinTerminate(hab);
-
- DosExitList(EXLST_EXIT, 0L); /* termination complete */
- return;
- } /* ExitProc() */
-
- /****************************************************************\
- * Function name: ClientWndProc()
- *
- * Parameters: hwnd, msg, mp1, mp2. Standard PM Dialog Proc params.
- * No user data is expected in the WM_CREATE.
- *
- * Returns: Returns with WM_QUIT message
- *
- * Purpose: Handles all the messages associated with the main window
- * and calls the appropriate handling procedures.
- *
- * Usage : Called only by main()
- \****************************************************************/
- MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
- {
- HPS hps=0; /* Handle for painting */
- POINTL ptl; /* Point struct for painting */
- static CALCPARAM cp[LISTCNT]; /* Struct passed to sort threads */
- static TID tidCalc[LISTCNT]; /* Sort threads IDs */
- static CALCPARAM cpDisp; /* Struct passed to disp thread */
- static TID tidDisplay; /* Secondary display thread ID */
- static USHORT usWindowYCoord=1; /* Holds current client window ht */
- static BYTE cThreadCnt = 0; /* Count of sort threads running */
- static USHORT cSetSize=MAX_ELEMS; /* User sort set size */
- USHORT cnt,cnt2,usID; /* Utility counters */
- ULONG ulBlip; /* Holds the marker pos for Paint */
- MRESULT sRC;
-
- switch(msg)
- {
- case WM_CREATE:
- RandomizeData(cSetSize); /* Initially randomize data set */
- /* Start display thread */
- cpDisp.hwnd = hwnd;
- cpDisp.Array = &usWindowYCoord;
- cpDisp.pcThreadCnt = &cThreadCnt;
- cpDisp.pcSetSize = &cSetSize;
- if((tidDisplay = _beginthread(DispThread,
- #if __IBMC__
- NULL,
- #endif
- STACKSIZE,
- (PVOID) &cpDisp)) == (USHORT)-1)
- {
- WinAlarm(HWND_DESKTOP, WA_ERROR); /* can't start display thread */
- DosExit(EXIT_PROCESS,1);
- }
- /* Up the display priority an arbitrary amount to cause it to
- update more rapidly and to give it a higher priority than
- the sort threads.*/
- DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, 5, tidDisplay);
-
- return (MRESULT)0L;
-
- case WM_SIZE:
- WinInvalidateRect(hwnd,NULL,FALSE); /* Force a redraw */
- sRC = WinDefWindowProc(hwnd, msg, mp1, mp2);
- return sRC;
-
- case WM_PAINT:
- hps = WinBeginPaint(hwnd,0,0); /* Get paint handle */
- WinQueryWindowRect(hwnd,&rcl);
- if(NELEMS < MAX_ELEMS )
- {
- cSetSize = NELEMS;
- }
- else
- {
- cSetSize = MAX_ELEMS;
- }
- RandomizeData(cSetSize); /* Initially randomize data set */
- usWindowYCoord = rcl.yTop;
- /* Draw if screen */
- /* is big enough */
- if( (XOFFSET + (2 * COLUMNOFFSET))< (rcl.xRight-rcl.xLeft) &&
- (YOFFSET * ROWCNT) < (rcl.yTop-rcl.yBottom ) )
- {
- DrawRect(rcl.xLeft,rcl.yBottom, /* White out the screen */
- rcl.xRight,rcl.yTop,CLR_WHITE);
-
- DrawLine(XOFFSET, YOFFSET, /* Draw baseline */
- rcl.xRight,YOFFSET,CLR_BLACK);
-
- DrawLine(XOFFSET, YOFFSET, /* Draw vertical line */
- XOFFSET,rcl.yTop,CLR_BLACK);
-
- for(cnt=0;cnt<LISTCNT;cnt++) /* Draw data points */
- {
- for(cnt2=0;cnt2<cSetSize;cnt2++)
- {
- ulBlip = (rcl.yTop-YOFFSET-5) * Data[cnt][cnt2] / RAND_MAX
- + YOFFSET+1;
-
- Draw2Pel(XOFFSET+1 + cnt2, ulBlip, ulColors[cnt]);
- }
- }
- for(cnt=0,cnt2= 0;cnt<COLUMNCNT;cnt++) /* Do bottom legend */
- {
- if(cnt2 >= ROWCNT )
- {
- cnt2 = 0;
- }
- ptl.x = XOFFSET + cnt2++ *COLUMNOFFSET;
- /*
- *next row after the last column
- */
- if(cnt >= (COLUMNCNT / ROWCNT ) )
- {
- ptl.y = YOFFSET - ( 2 * ROWOFFSET);
- }
- else
- {
- ptl.y = YOFFSET - ROWOFFSET;
- }
- GpiSetColor(hps,ulColors[cnt]);
- GpiCharStringAt(hps,&ptl,
- (LONG) strlen(szSubNames[cnt]),
- szSubNames[cnt]);
- }
- }
-
- WinEndPaint(hps);
- return (MRESULT)0L;
-
- case WM_COMMAND:
- switch(SHORT1FROMMP(mp1))
- {
- case IDM_START:
-
- /*
- *clear the drawing semaphore
- */
- DosPostEventSem(hev);
- /* Try to get stack space */
- for(cnt=0;cnt<LISTCNT;cnt++)
- {
- cp[cnt].hwnd = hwnd; /* Set the static struct */
- cp[cnt].fContinueCalc = TRUE;
- cp[cnt].pFunc = pExecSub[cnt];
- cp[cnt].usID = cnt;
- cp[cnt].Array = Data[cnt];
- cp[cnt].cArray = cSetSize;
-
- /* Try to start the thread */
- if( (tidCalc[cnt] = _beginthread(CalcThread,
- #if __IBMC__
- NULL,
- #endif
- STACKSIZE,
- (PVOID)&cp[cnt])) == (USHORT)-1)
- {
- WinAlarm(HWND_DESKTOP, WA_ERROR);
- return (MRESULT)0L;
- }
- if(cThreadCnt++ == 0) /* When the first thread starts */
- {
- /* Disable Start, Set, and Randomize, enable Stop */
- EnableMenuItem(hwnd,IDM_START,FALSE);
- EnableMenuItem(hwnd,IDM_SET,FALSE);
- EnableMenuItem(hwnd,IDM_RANDOM,FALSE);
- EnableMenuItem(hwnd,IDM_STOP,TRUE);
- }
- }
- return (MRESULT)0L;
-
- case IDM_STOP:
- for(cnt=0;cnt<LISTCNT;cnt++)
- cp[cnt].fContinueCalc = FALSE; /* Notify thread to quit */
- return (MRESULT)0L;
-
- case IDM_RANDOM:
- RandomizeData(cSetSize); /* Randomize data */
- WinInvalidateRect(hwnd,NULL,FALSE); /* Force a redraw */
- return (MRESULT)0L;
-
- case IDM_SET:
- if(WinDlgBox(HWND_DESKTOP, hwnd, /* Pop up the query/set box */
- EntryFldDlgProc,(HMODULE)0,IDD_SETCOUNT,
- (VOID FAR *) &cSetSize))
- {
- WinInvalidateRect(hwnd,NULL,FALSE); /* Force a redraw */
- }
- return (MRESULT)0L;
-
- case IDM_GENERALHELP:
- HelpExtended(mp2);
- return (MRESULT)0L;
-
- case IDM_USINGHELP:
- HelpHelpForHelp(mp2);
- return (MRESULT)0L;
-
- case IDM_TUTORIAL:
- HelpKeys(mp2);
- return (MRESULT)0L;
-
- case IDM_HELPINDEX:
- HelpIndex(mp2);
- return (MRESULT)0L;
-
- case IDM_HELPPRODUCTINFO:
- HelpAbout(mp2);
- return (MRESULT)0L;
-
- default:
- sRC = WinDefWindowProc(hwnd, msg, mp1, mp2);
- return sRC;
- }
- break;
-
- case IDM_DONE:
- usID = SHORT1FROMMP(mp1); /* Get ID of quit thread */
-
- if(--cThreadCnt == 0) /* If all quit, enable menus */
- {
- EnableMenuItem(hwnd,IDM_START,TRUE);
- EnableMenuItem(hwnd,IDM_SET,TRUE);
- EnableMenuItem(hwnd,IDM_RANDOM,TRUE);
- EnableMenuItem(hwnd,IDM_STOP,FALSE);
- }
- return (MRESULT)0L;
-
- case HM_QUERY_KEYS_HELP:
- return ((MRESULT)PANEL_KEYSHELP);
-
- case WM_CLOSE:
-
- DosCloseEventSem(hev);
- for(cnt=0;cnt<LISTCNT;cnt++)
- {
- DosKillThread(tidCalc[cnt]);
- }
- DosKillThread(tidDisplay);
- WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
- return 0L;
-
- default:
- sRC = WinDefWindowProc(hwnd, msg, mp1, mp2);
- return sRC;
- }
-
- return (MRESULT)0L;
- }
-
- /****************************************************************\
- * Function name: CalcThread()
- *
- * Parameters: pcp is a struct which contains the hwnd handle, the
- * continue flag which is initially set to TRUE, the ID
- * which is the
- *
- * Returns: VOID
- *
- * Purpose: This generic stub calls the passed "sort" function with a pointer
- * to the data and an item count, then when the sort terminates, it
- * cleans up by Posting a done message, then terminating the thread.
- *
- * Usage : No DosExitCritSec() is called since _endthread()
- * clears the critical section when the thread is
- * terminated.
- *
- \****************************************************************/
- VOID CalcThread(PVOID pcp)
- {
- (*((PCALCPARAM)pcp)->pFunc)(pcp); /* Execute recurs routine */
- /* Set Crit so the IDM_DONE isn't processed */
- /* until this thread has completely terminated */
- DosEnterCritSec();
-
- WinPostMsg(((PCALCPARAM)pcp)->hwnd,IDM_DONE,
- MPFROMSHORT(((PCALCPARAM)pcp)->usID),NULL);/* Post done */
-
- /*
- *set the post count for each thread
- *that goes through
- */
- DosPostEventSem(hev);
-
- _endthread(); /* Terminate thread and exit crit sec */
- return;
- }
-
- /****************************************************************\
- * Function name: DispThread()
- *
- * Parameters: pcp is a struct which contains the hwnd handle, the
- * count of active threads, the ->Array element points to
- * the current height of the window which can be dynamically
- * resized by the user, the pcSetSize points to the current
- * set size which can be changed by the user only when the
- * sort is stopped.
- * None of the other pcp members are used.
- *
- * Returns: VOID
- *
- * Purpose: This routine is run as a secondary thread to update the screen
- * when the sort threads are running. It works by making passes
- * through the data lists and redrawing them. A DosSleep(0) is
- * called at the end of each pass to help sychronize things a bit.
- *
- * Usage : Note that this thread is started when the program is
- * initialized, and is never terminated. Note that
- * fDoUpdate is used in such a way that the screen is
- * ALWAYS updated once after all threads have terminated.
- * This avoids the possibility of the display not being
- * fully accurate when the sorts terminate.
- *
- \****************************************************************/
- VOID DispThread(PVOID pvData )
- {
- USHORT cnt,cnt2; /* Utility counters */
- HPS hps; /* Presentation space handle */
- POINTL ptl; /* Used for various drawing macros */
- ULONG ulBlip; /* Holds the Y offset for a given data point */
- PCALCPARAM pcp; /* after all sort threads terminate */
- USHORT *pusYCoord;
- ULONG ulPostCount;
-
- pcp = (PCALCPARAM) pvData;
- pusYCoord = pcp->Array;
- /* Points to location that always */
- /* contains current client wind hgt */
-
- hps = WinGetPS( pcp->hwnd);
-
- while(TRUE)
- {
- /*
- *sit and wait on the clearing of the semaphore
- */
- DosWaitEventSem(hev,SEM_INDEFINITE_WAIT);
- DosQueryEventSem(hev,&ulPostCount);
- /*
- *wait on all 4 threads + the post used to start
- *to post
- */
- if(ulPostCount == 5)
- {
- ulPostCount = 0;
- DosResetEventSem(hev,&ulPostCount);
- }
- for(cnt=0;cnt<*((PCALCPARAM)pcp)->pcSetSize;cnt++)/* Update data set */
- {
- DrawLine(XOFFSET+1 + cnt,YOFFSET+1, /* Erase vertical column */
- XOFFSET+1 + cnt,*pusYCoord, CLR_WHITE);
-
- for(cnt2=0;cnt2<LISTCNT;cnt2++) /* Draw each point */
- {
- ulBlip = (ULONG) (*pusYCoord-YOFFSET-5)*Data[cnt2][cnt] / RAND_MAX
- + YOFFSET+1;
- Draw2Pel(XOFFSET+1 + cnt, ulBlip, ulColors[cnt2]);
- }
- }
-
- }
-
- /* Note that these 3 lines NEVER get executed, but should the program be
- modified to end the thread, this is the appropriate termination code. */
- WinReleasePS(hps);
- _endthread();
- return;
- }
-
- /****************************************************************\
- * Function name: BubbleSort()
- *
- * Parameters: pcp is a struct which contains the hwnd handle, a
- * pointer to the data array, and a count of the items in
- * the data array.
- * None of the other pcp members are used.
- *
- * Returns: VOID
- *
- * Purpose: Implements a bubble sort which is an O(n^2) algorithm. It
- * works by repeatedly going through the data and comparing
- * consecutive elements and swapping them if they aren't in
- * the correct order. This guarantees that each pass will
- * place at least one additional item in its appropriate
- * place.
- *
- * Usage:
- \****************************************************************/
- VOID BubbleSort(PCALCPARAM pcp)
- {
- BOOL fModified = FALSE; /* Set whenever a swap is done, if an entire */
- /* pass doesn't set the flag, the we're done */
- INT cnt;
- INT cnt2; /* Counters used for the 2-level loops */
- USHORT usTemp; /* Used to hold a data item during a swap */
-
- for(cnt=(ULONG)(pcp->cArray-1);cnt>=0;cnt--) /*Set the max no. of passes*/
- {
- for(cnt2=0;cnt2<cnt;cnt2++) /* Only sort thru current cnt pass */
- {
- if(!pcp->fContinueCalc) /* User wishes to terminate the sort */
- return;
-
- if(pcp->Array[cnt2]>pcp->Array[cnt2+1]) /* Items need to swap */
- {
- fModified = TRUE;
-
- usTemp = pcp->Array[cnt2];
- pcp->Array[cnt2] = pcp->Array[cnt2+1];
- pcp->Array[cnt2+1]= usTemp;
- }
- }
- if(!fModified) /* Nothing changed during the entire pass */
- break;
- fModified = FALSE; /* Reset the modify flag */
- }
- return;
- }
-
- /****************************************************************\
- * Function name: InsertionSort()
- *
- * Parameters: pcp is a struct which contains the hwnd handle, a
- * pointer to the data array, and a count of the items in
- * the data array.
- * None of the other pcp members are used.
- *
- * Returns: VOID
- *
- * Purpose: Implements an insertion sort which is an O(n^2) algorithm.
- * This sort works much faster and does not require that much
- * additional code to implement. It works by setting a sorted
- * list to be just the first element, the working each
- * successive item into the already sorted list.
- *
- * Usage:
- \****************************************************************/
- VOID InsertionSort(PCALCPARAM pcp)
- {
- SHORT cnt,cnt2; /* Counters used for the 2-level loops */
- USHORT usTemp; /* Used to hold a data item during a swap */
-
- for(cnt=1;cnt<(LONG)pcp->cArray;cnt++) /* Insert each item in turn */
- {
- if(!pcp->fContinueCalc) /* User wishes to terminate the sort */
- return;
- usTemp=pcp->Array[cnt]; /* Hold value to insert */
- cnt2=(LONG)(cnt-1);
- while(pcp->Array[cnt2]>usTemp) /* Move items down to make room */
- {
- pcp->Array[cnt2+1]=pcp->Array[cnt2];
- cnt2--;
- if(cnt2<0)
- break;
- }
- pcp->Array[cnt2+1] = usTemp; /* Insert the item */
- }
- return;
- }
-
- /****************************************************************\
- * Function name: BatcherSort()
- *
- * Parameters: pcp is a struct which contains the continue flag,
- * a pointer to the data array, and a count of the items in
- * the data array.
- * None of the other pcp members are used.
- *
- * Returns: VOID
- *
- * Purpose: This routine is a stub that calls the recursive Batcher sort
- * with the proper initial arguments.
- *
- * Usage: It passes the pcp, the size of the array to be sorted,
- * the offset to start sorting at(0), the number number
- * of elements each item is from neighboring elements (1),
- * and Half flag to sort the halves (1=YES).
- \****************************************************************/
- VOID BatcherSort(PCALCPARAM pcp)
- {
- BatcherSortR(pcp,pcp->cArray,0,1,1);
- return;
- }
-
- /****************************************************************\
- * Function name: BatcherSortR()
- *
- * Parameters: pcp is a struct which contains the continue flag,
- * a pointer to the data array.
- * None of the other pcp members are used.
- * usArrSize is the number of elements in the current sort set.
- * usStart is the offset to the 1st element in the set.
- * usSkip is the spacing between consecutive elements.
- * fHalves sorts the 2 halves when set, otherwise skips the
- * 1st 2 of the 4 sub-sorts.
- *
- * Returns: VOID
- *
- * Purpose: Implements Batcher sort which is O(n lg n). The advantage
- * of the batcher sort is that the comparisons made do NOT
- * depend upon the outcome of previous comparisons. This makes
- * it a good algorithm for parallelism. The algorithm works as
- * follows: Sort the first half, sort the second half, sort the
- * odd elements, sort the even elements, then compare swap
- * elements 2/3, 4/5, ...
- *
- * Usage : There are several adaptations to the algorithm to
- * allow it to work with arbitrary sized data sets
- * (the original required a power of 2 sized data
- * set): if the set size is less than 2, the routine
- * returns, the first "half" is always the largest
- * possible power of two, and the top value for the
- * final compare/swap is adjusted to round up in
- * case of an odd data set.
- * Another optimization is that involving the fHalves
- * flag. This stems from the observation that when
- * the odd/even sort recurses, the first and second
- * halves are already sorted, thus the first 2
- * recursive calls are unnecessary in this case.
- *
- \****************************************************************/
- VOID BatcherSortR(PCALCPARAM pcp, ULONG usArrSize, ULONG usStart,
- ULONG usSkip, BOOL fHalves)
- {
- USHORT cnt,usUpper,usTemp; /* Utility variables */
-
- if(!pcp->fContinueCalc) /* User wishes to terminate the sort */
- return;
-
- if(usArrSize<2) /* No sorting needed if <2 items in the set */
- return;
-
- if(usArrSize==2) /* Do simple compare/swap if there are 2 elements */
- {
- if(pcp->Array[usStart]>pcp->Array[usStart+usSkip])
- {
- usTemp = pcp->Array[usStart];
- pcp->Array[usStart] = pcp->Array[usStart+usSkip];
- pcp->Array[usStart+usSkip]= usTemp;
- }
- return;
- }
-
- usTemp=1; /* usTemp ends up holding the smallest power */
- while(usTemp < usArrSize) /* of 2 that is at least as big as usArrSize */
- usTemp *= 2;
-
- if(fHalves) /* If the sort was NOT called by the odd/even recurses */
- {
- BatcherSortR(pcp,(ULONG)(usTemp/2),usStart,usSkip,(BOOL)1); /* Sort 1st half */
- BatcherSortR(pcp,(ULONG)(usArrSize-usTemp/2), /* Sort 2nd half */
- (ULONG)(usStart+usTemp/2*usSkip),usSkip,(BOOL)1);
- }
- BatcherSortR(pcp,(ULONG)(usArrSize-usArrSize/2),usStart,(ULONG)(usSkip*2),(BOOL)0); /* Sort evens */
- BatcherSortR(pcp,(ULONG)(usArrSize/2),(ULONG)(usStart+usSkip),(ULONG)(usSkip*2),(BOOL)0); /* Sort odds */
-
- if(!pcp->fContinueCalc) /* User wishes to terminate the sort */
- return;
-
- usUpper=(ULONG)(usStart+usSkip+(usArrSize-usArrSize/2-1)*2*usSkip);
- for(cnt=usStart+usSkip;cnt<usUpper;cnt+=usSkip*2) /* Do final compares */
- {
- if(pcp->Array[cnt]>pcp->Array[cnt+usSkip])
- {
- usTemp = pcp->Array[cnt];
- pcp->Array[cnt] = pcp->Array[cnt+usSkip];
- pcp->Array[cnt+usSkip]= usTemp;
- }
- if(!pcp->fContinueCalc) /* User wishes to terminate the sort */
- return;
- }
- return;
- }
-
-
- /****************************************************************\
- * Function name: QuickSort()
- *
- * Parameters: pcp is a struct which contains the continue flag,
- * a pointer to the data array, and a count of the items in
- * the data array.
- * None of the other pcp members are used.
- *
- * Returns: VOID
- *
- * Purpose: This routine is a stub that calls the recursive Quick sort
- * with the proper initial arguments.
- *
- * Usage : It passes the pcp (Which contains the array ptr),
- * the offset to start sorting at(0), and the offset to
- * finish sorting at (Array size-1).
- *
- \****************************************************************/
- VOID QuickSort(PCALCPARAM pcp)
- {
- QuickSortR(pcp,0,(pcp->cArray-1));
- return;
- }
-
-
- /****************************************************************\
- * Function name: QuickSortR()
- *
- * Parameters: pcp is a struct which contains the continue flag,
- * a pointer to the data array.
- * None of the other pcp members are used.
- * sLeft is the offset of the leftmost sort element (smallest).
- * sRight is the offset of rightmost sort element (largest).
- *
- * Returns: VOID
- *
- * Purpose: Implements Quick sort which is O(n lg n). Quick sort is a
- * good all-purpose sorting algorithm and is widely used. This
- * implementation works by placing the first element in the list
- * into its correct place, by moving all elements smaller to its
- * left, and all numbers larger to its right. The Quick sort
- * recurses on the smaller side of the properly placed element,
- * and loops back through the same routine for the larger side.
- *
- * NOTE: This routine does not recurse on both sides of the
- * partition element. It only recurses on the smaller
- * of the two sides. This was done in order to eliminate
- * the stack overrun when it tries to sort an already
- * sorted list.
- *
- * Usage:
- *
- \****************************************************************/
- VOID QuickSortR(PCALCPARAM pcp, LONG sLeft, LONG sRight)
- {
- SHORT sTempLeft = sLeft; /* Holds lower bound on split position */
- SHORT sTempRight = sRight; /* Holds upper bound on split position */
- SHORT sSplit; /* Used to hold offset of positioned elem */
- USHORT usTemp; /* Holds temp element during positioning */
-
- while(TRUE)
- {
- if(sLeft >= sRight) /* If there is <=1 element, return */
- return;
-
- if(!pcp->fContinueCalc) /* User wishes to terminate the sort */
- return;
-
- /* Split list, sSplit will contain the split element */
- usTemp = pcp->Array[sTempLeft];
-
- while(TRUE) /* Loop thru 2 cases until the split position is found */
- {
- while(pcp->Array[sTempRight] > usTemp && /* Skip elems on right side */
- sTempRight > sLeft) /* that are > the split elem */
- sTempRight--;
-
- if(sTempRight<=sTempLeft) /* Left and Right have met, split is found */
- {
- pcp->Array[sTempLeft]=usTemp; /* Place split elem at proper place */
- sSplit = sTempLeft;
- break;
- }
- pcp->Array[sTempLeft++] =
- pcp->Array[sTempRight]; /* Move small element to LHS */
-
- while(pcp->Array[sTempLeft] < usTemp && /* Skip elems on left side */
- sTempLeft < sRight) /* that are < the split elem */
- sTempLeft++;
-
- if(sTempRight<=sTempLeft) /* Left and Right have met, split is found */
- {
- pcp->Array[sTempRight]=usTemp; /* Place split elem at proper place */
- sSplit = sTempRight;
- break;
- }
- pcp->Array[sTempRight--] =
- pcp->Array[sTempLeft]; /* Move large element to RHS */
- }
-
- if ((sSplit - sLeft) > (sRight - sSplit)) {
- /* left half is larger than right half */
- QuickSortR(pcp, sSplit+1, sRight); /* Sort the 2nd half of the list */
- if(!pcp->fContinueCalc) /* User wishes to terminate sort */
- return;
- sTempLeft = sLeft; /* Set up to sort the 1st half */
- sTempRight = sRight = sSplit - 1;
- }
- else {
- /* right half is larger than left half */
- QuickSortR(pcp, sLeft, sSplit-1); /* Sort the 1st half of the list */
- if(!pcp->fContinueCalc) /* User wishes to terminate sort */
- return;
- sTempRight = sRight; /* Set up to sort the 2nd half */
- sTempLeft = sLeft = sSplit + 1;
- }
- }
- return;
- }
-
- /****************************************************************\
- * Function name: EnableMenuItem()
- *
- * Parameters: hwnd is a handle of the current window.
- * sMenuItem is the ID of the item to Enable/Disable.
- * fEnable will enable item if TRUE, otherwise disables it.
- *
- * Returns: VOID
- *
- * Purpose: This routine handles enabling/disabling of menu items. This
- * is done by getting Parent and Menu hwnd handles then sending
- * the appropriate message.
- *
- * Usage:
- *
- \****************************************************************/
- VOID EnableMenuItem(HWND hwnd, LONG sMenuItem, BOOL fEnable)
- {
- HWND hwndParent = WinQueryWindow(hwnd, QW_PARENT);
- HWND hwndMenu = WinWindowFromID(hwndParent, FID_MENU);
-
- WinSendMsg(hwndMenu, MM_SETITEMATTR,
- MPFROM2SHORT(sMenuItem, TRUE),
- MPFROM2SHORT(MIA_DISABLED, fEnable ? 0 : MIA_DISABLED));
- return;
- }
-
- /****************************************************************\
- * Function name: EntryFldDlgProc()
- *
- * Parameters: hwnd, msg, mp1, mp2. Standard PM Dialog Proc params.
- * A pointer to the current set size is passed in WM_INITDLG.
- *
- * Returns: Terminates with a TRUE iff a new valid data set size is entered.
- *
- * Purpose: Handles all the messages associated with the set entry field
- * and calls the appropriate handling procedures. The purpose
- * of this dialog box is to get a new data set size for the
- * sort routines.
- *
- *
- * Usage : If the value entered is valid, the proc will set the
- * variable passed in through the WM_INITDLG to the value.
- \****************************************************************/
- MRESULT EXPENTRY EntryFldDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
- {
- SHORT sNewSize=0; /* Holds new set set */
- static SHORT *pcSetSize; /* Set to point to user-passed set size */
- MRESULT sRC;
-
- switch(msg)
- {
- case WM_INITDLG:
- FixSysMenu(hwnd);
- pcSetSize=PVOIDFROMMP(mp2);
- WinSendDlgItemMsg(hwnd, IDD_ENTRYFLD,EM_SETTEXTLIMIT, /* Limit len */
- MPFROM2SHORT(4,0),NULL);
- WinSetDlgItemShort(hwnd, IDD_ENTRYFLD,
- *pcSetSize,TRUE);
- return (MRESULT)0L; /* Allow normal focus setting */
-
- case WM_COMMAND:
- switch(SHORT1FROMMP(mp1))
- {
- case DID_OK:
- WinQueryDlgItemShort(hwnd, IDD_ENTRYFLD,
- &sNewSize, TRUE); /* Get the short */
- if(sNewSize>0 && sNewSize<=MAX_ELEMS) /* Set new data set size */
- {
- *pcSetSize = sNewSize;
- WinDismissDlg(hwnd,TRUE);
- }
- else /* Invalid value */
- {
- MessageBox(hwnd, IDMSG_ERRORSIZE,
- MB_OK | MB_ERROR, TRUE);
- return (MRESULT)FALSE;
- }
- return (MRESULT)0L;
-
- case DID_CANCEL:
- WinDismissDlg(hwnd,FALSE);
- return (MRESULT)0L;
-
- default:
- sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
- return sRC;
- }
- break;
-
- default:
- sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
- return sRC;
- }
- return (MRESULT)0L;
- }
-
- /****************************************************************\
- * Function name: AboutDlgProc()
- *
- * Parameters: hwnd, msg, mp1, mp2. Standard PM Dialog Proc params.
- *
- * Returns:
- *
- * Purpose: Handles all the messages associated with the About dialog.
- *
- * Usage:
- *
- \****************************************************************/
- MRESULT EXPENTRY AboutDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
- {
- MRESULT sRC;
-
- switch(msg)
- {
- case WM_INITDLG:
- FixSysMenu(hwnd);
- return (MRESULT)0L;
-
- case WM_COMMAND:
- WinDismissDlg(hwnd, TRUE);
- return (MRESULT)0L;
-
- default:
- sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
- return sRC;
- }
- return (MRESULT)0L;
- }
-
- /****************************************************************\
- * Function name: RandomizeData()
- *
- * Parameters: cSetSize is the current size of the data set
- *
- * Returns: VOID
- *
- * Purpose: This routine randomizes the data arrays.
- *
- * Usage : This routine assumes that LISTCNT and NELEMS define
- * the dimensions of the global Data array which is
- * randomized.
- \****************************************************************/
- VOID RandomizeData(ULONG cSetSize)
- {
- USHORT cnt,cnt2;
-
- for(cnt=0;cnt<LISTCNT;cnt++)
- {
- for(cnt2=0;cnt2<cSetSize;cnt2++)
- Data[cnt][cnt2] = rand();
- }
- return;
- }
-
- /****************************************************************\
- * Function name: FixSysMenu()
- *
- * Parameters: hwndDlg - handle to calling dialog
- *
- * Returns: VOID
- *
- * Purpose: This routine removes the Restore, Size, Minimize, and
- * Maximize options from the system menu of a dialog.
- *
- * Usage : Called during the WM_INITDLG of a dialog procedure.
- *
- \****************************************************************/
- VOID FixSysMenu(HWND hwndDlg)
- {
- HWND hwndMenu; /* handle to system menu */
-
- hwndMenu = WinWindowFromID(hwndDlg, FID_SYSMENU);
-
- WinSendMsg(hwndMenu, /* delete Restore from the system menu */
- MM_DELETEITEM,
- MPFROM2SHORT(SC_RESTORE, TRUE),
- MPFROMP(NULL));
-
- WinSendMsg(hwndMenu, /* delete Size from the system menu */
- MM_DELETEITEM,
- MPFROM2SHORT(SC_SIZE, TRUE),
- MPFROMP(NULL));
-
- WinSendMsg(hwndMenu, /* delete Minimize from the system menu */
- MM_DELETEITEM,
- MPFROM2SHORT(SC_MINIMIZE, TRUE),
- MPFROMP(NULL));
-
- WinSendMsg(hwndMenu, /* delete Maximize from the system menu */
- MM_DELETEITEM,
- MPFROM2SHORT(SC_MAXIMIZE, TRUE),
- MPFROMP(NULL));
- return;
- }
-
- /****************************************************************\
- * Routine for initializing the help manager
- *--------------------------------------------------------------
- *
- * Name: InitHelp()
- *
- * Purpose: Initializes the IPF help facility
- *
- * Usage: Called once during initialization of the program
- *
- * Method: Initializes the HELPINIT structure and creates the help
- * instance. If successful, the help instance is associated
- * with the main window
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID InitHelp(VOID)
- {
- HELPINIT hini;
-
- /* If we return because of an error, Help will be disabled */
- fHelpEnabled = FALSE;
- /* Initialize help init structure */
- hini.cb = sizeof(HELPINIT);
- hini.ulReturnCode = 0;
- /* If tutorial added, add name here */
- hini.pszTutorialName = (PSZ)NULL;
-
- hini.phtHelpTable = (PHELPTABLE)MAKELONG(SORT_HELP_TABLE, 0xFFFF);
- hini.hmodHelpTableModule = 0;
- hini.hmodAccelActionBarModule = 0;
- hini.idAccelTable = 0;
- hini.idActionBar = 0;
-
- if(!WinLoadString(hab,
- 0,
- IDS_HELPWINDOWTITLE,
- HELPLIBRARYNAMELEN,
- (PSZ)szWindowTitle))
- {
- MessageBox(hwndClient, IDMSG_CANNOTLOADSTRING,
- MB_OK | MB_ERROR, FALSE);
- return;
- }
- hini.pszHelpWindowTitle = (PSZ)szWindowTitle;
-
- /* If debugging, show panel ids, else don't */
- #ifdef DEBUG
- hini.fShowPanelId = CMIC_SHOW_PANEL_ID;
- #else
- hini.fShowPanelId = CMIC_HIDE_PANEL_ID;
- #endif
-
- if(!WinLoadString(hab,
- 0,
- IDS_HELPLIBRARYNAME,
- HELPLIBRARYNAMELEN,
- (PSZ)szLibName))
- {
- MessageBox(hwndClient, IDMSG_CANNOTLOADSTRING,
- MB_OK | MB_ERROR, FALSE);
- return;
- }
- hini.pszHelpLibraryName = (PSZ)szLibName;
- /* Creating help instance */
- hwndHelpInstance = WinCreateHelpInstance(hab, &hini);
-
- if(hwndHelpInstance == 0 || hini.ulReturnCode)
- {
- MessageBox(hwndFrame, IDMSG_HELPLOADERROR, MB_OK | MB_ERROR, TRUE);
- return;
- }
- /* Associate help instance with main frame */
- if(!WinAssociateHelpInstance(hwndHelpInstance, hwndFrame))
- {
- MessageBox(hwndFrame, IDMSG_HELPLOADERROR,
- MB_OK | MB_ERROR, TRUE);
- return;
- }
- /* Help manager is successfully initialized so set flag to TRUE */
- fHelpEnabled = TRUE;
- return;
- } /* InitHelp() */
-
- /****************************************************************\
- * Processes the Help for Help command from the menu bar
- *--------------------------------------------------------------
- *
- * Name: HelpHelpForHelp(mp2)
- *
- * Purpose: Processes the WM_COMMAND message posted by the Help for
- * Help item of the Help menu
- *
- * Usage: Called from MainCommand when the Help for Help menu item
- * is selected
- *
- * Method: Sends an HM_DISPLAY_HELP message to the help instance so
- * that the default Help For Help is displayed.
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID HelpHelpForHelp(MPARAM mp2)
- {
- /* This just displays the system help for help panel */
- if(fHelpEnabled)
- if(WinSendMsg(hwndHelpInstance, HM_DISPLAY_HELP, NULL, NULL))
- MessageBox(hwndClient,
- IDMSG_HELPDISPLAYERROR,
- MB_OK | MB_ERROR,
- FALSE);
-
- /* This routine currently doesn't use the mp2 parameter but *\
- * it is referenced here to prevent an 'Unreferenced Parameter'
- \* warning at compile time. */
- return;
- } /* HelpHelpForHelp() */
-
- /****************************************************************\
- * Processes the Extended Help command from the menu bar
- *--------------------------------------------------------------
- *
- * Name: HelpExtended(mp2)
- *
- * Purpose: Processes the WM_COMMAND message posted by the Extended
- * Help item of the Help menu.
- *
- * Usage: Called from MainCommand when the Extended Help menu item
- * is selected.
- *
- * Method: Sends an HM_EXT_HELP message to the help instance so that
- * the default Extended Help is displayed.
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID HelpExtended(MPARAM mp2)
- {
- /* This just displays the system extended help panel */
- if(fHelpEnabled)
- if(WinSendMsg(hwndHelpInstance, HM_EXT_HELP, NULL, NULL))
- MessageBox(hwndClient,
- IDMSG_HELPDISPLAYERROR,
- MB_OK | MB_ERROR,
- FALSE);
-
- /* This routine currently doesn't use the mp2 parameter but *\
- * it is referenced here to prevent an 'Unreferenced Parameter'
- \* warning at compile time. */
- return;
- } /* HelpExtended() */
-
- /****************************************************************\
- * Processes the Keys Help command from the menu bar
- *--------------------------------------------------------------
- *
- * Name: HelpKeys(mp2)
- *
- * Purpose: Processes the WM_COMMAND message posted by the Keys Help
- * item of the Help menu.
- *
- * Usage: Called from MainCommand when the Keys Help menu item is
- * selected
- *
- * Method: Sends an HM_KEYS_HELP message to the help instance so that
- * the default Keys Help is displayed.
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID HelpKeys(MPARAM mp2)
- {
- /* This just displays the system keys help panel */
- if(fHelpEnabled)
- if(WinSendMsg(hwndHelpInstance, HM_KEYS_HELP, NULL, NULL))
- MessageBox(hwndClient,
- IDMSG_HELPDISPLAYERROR,
- MB_OK | MB_ERROR,
- FALSE);
-
- /* This routine currently doesn't use the mp2 parameter but *\
- * it is referenced here to prevent an 'Unreferenced Parameter'
- \* warning at compile time. */
- return;
- } /* HelpKeys() */
-
- /****************************************************************\
- * Processes the Index Help command from the menu bar
- *--------------------------------------------------------------
- *
- * Name: HelpIndex(mp2)
- *
- * Purpose: Processes the WM_COMMAND message posted by the Index Help
- * item of the Help menu
- *
- * Usage: Called from MainCommand when the Index Help menu item
- * is selected
- *
- * Method: Sends an HM_INDEX_HELP message to the help instance so
- * that the default Index Help is displayed.
- *
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID HelpIndex(MPARAM mp2)
- {
- /* This just displays the system help index panel */
- if(fHelpEnabled)
- if(WinSendMsg(hwndHelpInstance, HM_HELP_INDEX, NULL, NULL))
- MessageBox(hwndClient,
- IDMSG_HELPDISPLAYERROR,
- MB_OK | MB_ERROR,
- FALSE);
-
- /* This routine currently doesn't use the mp2 parameter but *\
- * it is referenced here to prevent an 'Unreferenced Parameter'
- \* warning at compile time. */
- return;
- } /* HelpIndex() */
-
- /****************************************************************\
- * Processes the About command from the Help menu
- *--------------------------------------------------------------
- *
- * Name: HelpAbout(mp2)
- *
- * Purpose: Processes the WM_COMMAND message posted by the About item
- * of the Help menu
- *
- * Usage: Called from MainCommand when the About menu item is selected
- *
- * Method: Calls WinDlgBox to display the about box dialog.
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID HelpAbout(MPARAM mp2)
- {
- /* Display the AboutBox dialog */
- WinDlgBox(HWND_DESKTOP,
- hwndClient,
- AboutDlgProc,
- (HMODULE)0,
- IDD_PRODUCTINFO,
- NULL);
-
- /* This routine currently doesn't use the mp2 parameter but *\
- * it is referenced here to prevent an 'Unreferenced Parameter'
- \* warning at compile time. */
- return;
- } /* HelpAbout() */
-
- /****************************************************************\
- * Displays the help panel indicated
- *--------------------------------------------------------------
- *
- * Name: DisplayHelpPanel(idPanel)
- *
- * Purpose: Displays the help panel whose id is given
- *
- * Usage: Called whenever a help panel is desired to be displayed,
- * usually from the WM_HELP processing of the dialog boxes
- *
- * Method: Sends HM_DISPLAY_HELP message to the help instance
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID DisplayHelpPanel(LONG idPanel)
- {
- if(fHelpEnabled)
- if(WinSendMsg(hwndHelpInstance,
- HM_DISPLAY_HELP,
- MPFROMLONG(MAKELONG(idPanel, NULL)),
- MPFROMSHORT(HM_RESOURCEID)))
-
- MessageBox(hwndFrame,
- IDMSG_HELPDISPLAYERROR,
- MB_OK | MB_ERROR,
- TRUE);
- return;
- } /* DisplayHelpPanel() */
-
- /****************************************************************\
- * Destroys the help instance
- *--------------------------------------------------------------
- *
- * Name: DestroyHelpInstance(VOID)
- *
- * Purpose: Destroys the help instance for the application
- *
- * Usage: Called after exit from message loop
- *
- * Method: Calls WinDestroyHelpInstance() to destroy the help instance
- *
- * Returns: VOID
- *
- \****************************************************************/
- VOID DestroyHelpInstance(VOID)
- {
- if(hwndHelpInstance != 0)
- {
- WinDestroyHelpInstance(hwndHelpInstance);
- }
- return;
- } /* DestroyHelpInstance() */
-
- /****************************************************************\
- * Message Box procedure
- *--------------------------------------------------------------
- *
- * Name: MessageBox(hwndOwner, nIdMsg, fsStyle, fBeep)
- *
- * Purpose: Displays the message box with the message given in idMsg
- * retrieved from the message table and using the style
- * flags in fsStyle
- *
- * Usage: Called whenever a MessageBox is to be displayed
- *
- * Method: - Message string is loaded from the process' message table
- * - Alarm beep is sounded if desired
- * - Message box with the message is displayed
- * - WinMessageBox return value is returned
- *
- * Returns: Return value from WinMessageBox()
- *
- \****************************************************************/
- LONG MessageBox(HWND hwndOwner, LONG idMsg, LONG fsStyle, BOOL fBeep)
- {
- CHAR szText[MESSAGELEN];
- LONG sRC;
-
- if(!WinLoadMessage(hab,
- (HMODULE)NULL,
- idMsg,
- MESSAGELEN,
- (PSZ)szText))
- {
- WinAlarm(HWND_DESKTOP, WA_ERROR);
- return RETURN_ERROR;
- }
-
- if(fBeep)
- WinAlarm(HWND_DESKTOP, WA_ERROR);
-
- sRC = WinMessageBox(HWND_DESKTOP,
- hwndOwner,
- szText,
- (PSZ)NULL,
- IDD_MSGBOX,
- fsStyle);
- return sRC;
- } /* MessageBox() */
-