////////////////////////////////////////////////////////////////////////////////
//
//                                FileBar
//
//         OS/2 Application Launch Facility and WPS Shell Replacement
//
//                         Written By Eric A. Wolf
//                 Copyright (C) 1994 - All Rights Reserved
//
// This source code may be used for reference ONLY!  It is provided AS-IS and no
// guarantees are made as to its utility, functionality or correctness.  It is
// provided solely as a guide to aid aspiring OS/2 2.x Presentation Manager
// programmers in developing their own PM applications.  No modifications are
// to be made to this code for re-release as a same or different product.  This
// code must be distributed (in its original entirety) with the executable
// portion of this product.
//
//          -- Please register this shareware product for $10 today --
//                          See documentation for details
//
// Project Start Date:      December 26, 1993
// Project Completion Date: January   3, 1994
//
// Written using Borland C++ for OS/2, version 1.0, Borland Resource Workshop,
//               and the IBM OS/2 2.1 bitmap/icon editor
//
// File Last Modified:      July     8, 1994
//
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// set compile-time flags for what os/2 header information should be included
////////////////////////////////////////////////////////////////////////////////
#define INCL_PM
#define INCL_DOSSESMGR
#define INCL_DOSERRORS
#define INCL_DOSMISC
#define INCL_WINPOINTERS
#define INCL_WINPROGRAMLIST
#define INCL_WINSTDFILE
#define INCL_WINWORKPLACE
#define INCL_DOSPROCESS


////////////////////////////////////////////////////////////////////////////////
// include C, C++, OS/2, application and resource header files
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "filebar.h"
#include "dll/filebar.h"                      // include DLL function prototypes


////////////////////////////////////////////////////////////////////////////////
// MakeHourglassPointer - macro to make the mouse pointer the hourglass
////////////////////////////////////////////////////////////////////////////////
#define MakeHourglassPointer() {                                                               \
                                 HPOINTER pointer;                                             \
                                 pointer = WinQuerySysPointer( HWND_DESKTOP, SPTR_WAIT, FALSE);\
                                 WinSetPointer( HWND_DESKTOP, pointer );                       \
                               }


////////////////////////////////////////////////////////////////////////////////
// MakeArrowPointer - macro to make the mouse pointer the arrow
////////////////////////////////////////////////////////////////////////////////
#define MakeArrowPointer() {                                                                \
                             HPOINTER pointer;                                              \
                             pointer = WinQuerySysPointer( HWND_DESKTOP, SPTR_ARROW, FALSE);\
                             WinSetPointer( HWND_DESKTOP, pointer );                        \
                           }


////////////////////////////////////////////////////////////////////////////////
// define application constants
////////////////////////////////////////////////////////////////////////////////
#define PASSWORDLEN           8
#define NO                    'N'
#define YES                   'Y'
#define DEFAULTPASSWORD       "FILEBAR\0"
#define MAXCOUNT              250
#define TEMPSTRING            64
#define AT_TOP                TRUE
#define AT_BOTTOM             FALSE
#define TIMERID               1
#define MAXTASKS              30
#define MAXMENUS              8
#define MAXITEMS              40
#define MAXPATH               CCHMAXPATH
#define MAXACTIONSTRINGLENGTH MAXPATH
#define MAXITEMNAMELENGTH     24
#define MAXMENUNAMELENGTH     20
#define MAXARGSTRINGLENGTH    80
#define MAXDIRSTRINGLENGTH    MAXPATH
#define WINDOWED              1
#define FULLSCREEN            2
#define PM                    4
#define DOS                   8
#define OS2                   16
#define WINOS2                32
#define STARTMIN              64
#define STARTMAX              128
#define WPSFOLDER             256
#define STARTASWPS            512
#define SCALED                128
#define TILED                 64
#define OS2SHELL              "CMD.EXE"
#define OPTIONFILE            "FILEBAR.INI"
#define LAUNCHFILE            "STARTPRG.CMD"
#define LAUNCHINPUTS          "/C STARTPRG.CMD"
#define SEPARATOR             "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"
#define WPSDESKTOPNAME        "Desktop"
#define FILEBARMENUON         "~FileBar"
#define FILEBARMENUOFF        "\x04"
#define STARTINPUT            '['
#define ENDINPUT              ']'
#define BITMAPNAME            "\\FILEBAR.BMP\0"
#define CHIMESOUNDFILE        "\\CHIME.WAV\0"
#define NOCOLOR               1
#define MAXSTARTITEMS         10
#define WPSBUFFER             3084
#define MAXALARMS             32
#define SCHEDULE_EVERYHOUR    1
#define SCHEDULE_EVERYDAY     2
#define SCHEDULE_EVERYWEEK    4
#define SCHEDULE_EVERYMONTH   8
#define SCHEDULE_EVERYYEAR    16
#define SCHEDULE_USEWAVFILE   32
#define SCHEDULE_SOUNDONLY    64
#define SCHEDULE_LAUNCHAPP    128
#define BOOLEAN               INT
#define LAUNCHED              0
#define TERMCHAR              250
#define TASKMENUON            MSG71
#define TASKMENUOFF           MSG72


////////////////////////////////////////////////////////////////////////////////
// writeString - writes a string out with quotes on either side
////////////////////////////////////////////////////////////////////////////////
#define writeString(stream, string) fprintf(stream, "%c%s%c\n", TERMCHAR, string, TERMCHAR)


////////////////////////////////////////////////////////////////////////////////
// define function prototypes
////////////////////////////////////////////////////////////////////////////////
VOID validateTimeEntry( VOID );
VOID sortTimeEntries( INT );
VOID displayBackground( VOID );
VOID resizeMenu( VOID );
VOID readOptionFile( VOID );
VOID writeOptionFile( VOID );
VOID readString( FILE*, CHAR* );
VOID restartTimer( VOID );
VOID displayTimeDate( VOID );
VOID SwapTwoMenus( SHORT, SHORT );
VOID SwapTwoItems( SHORT, SHORT, SHORT );
VOID updateItemList( HWND );
VOID updateEditItemData( HWND hWnd );
VOID updateEditItemData( HWND hWnd );
VOID ExecuteStartUpList( VOID );
VOID updateCalendar( HWND );
VOID ringChime( CHAR* );
VOID checkAlarms( SHORT, SHORT, SHORT, SHORT, SHORT );
VOID updateTimeDisplay( HWND );
VOID reviseScheduledItem( INT );
VOID resetFileDialog( VOID );
VOID changePassword( CHAR* );
BYTE numberOfDaysInMonth( INT, INT );
SHORT startApplication( SHORT, SHORT );
MRESULT EXPENTRY ClientWndProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY GenericProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY TimeDateProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY EditMenuProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY AddAMenuProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY EditItemProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY EditItemDataProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY AddAnItemProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY menuHandler( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY EnterParamProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY backgroundProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY startupProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY schedulerProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY scheduleProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY reminderNoteProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY itemProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY showAllItemsProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY LaunchItemProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY popUpOptionsProc( HWND, ULONG, MPARAM, MPARAM );
MRESULT EXPENTRY globalPasswordProc( HWND, ULONG, MPARAM, MPARAM );

extern "C" {
    #define INCL_REXXSAA
    #include "rexxsaa.h"
    RexxStart rexxStart;
    }


////////////////////////////////////////////////////////////////////////////////
// define alarm/task scheduler item structure
////////////////////////////////////////////////////////////////////////////////
struct ALARMS {
    BYTE  AlarmYear;
    BYTE  AlarmMonth;
    BYTE  AlarmDay;
    BYTE  AlarmHour;
    BYTE  AlarmMinute;
    BYTE  options;
    CHAR  ReminderWAV[MAXACTIONSTRINGLENGTH];
    CHAR  ActionToDo[MAXACTIONSTRINGLENGTH];
};


////////////////////////////////////////////////////////////////////////////////
// define menu item structure
////////////////////////////////////////////////////////////////////////////////
struct USERMENUITEM {
    CHAR     ItemName[MAXITEMNAMELENGTH];
    CHAR     ActionToDo[MAXACTIONSTRINGLENGTH];
    CHAR     Directory[MAXDIRSTRINGLENGTH];
    CHAR     CmdLnArgs[MAXARGSTRINGLENGTH];
    SHORT    ProgType;
    CHAR     Password[PASSWORDLEN + 1];
    CHAR     PasswordEnabled;
};


////////////////////////////////////////////////////////////////////////////////
// define global variables
////////////////////////////////////////////////////////////////////////////////
const         BYTE daysInMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
USERMENUITEM* Menus[MAXMENUS][MAXITEMS];
ALARMS*       alarmPtr[MAXALARMS];
HAB      hab;
HMQ      hmq;
PID      TaskId[MAXTASKS];
PFNWP    menuMessageHandler;
FILEDLG  fileDlgInfo;
MENUITEM menuData[MAXMENUS];
LONG     oldNumItems;
LONG     ScreenSizeX   = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN) + 2;
LONG     ScreenSizeY   = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
LONG     MenuHeight    = WinQuerySysValue(HWND_DESKTOP, SV_CYMENU) + 2;
LONG     sysMenuHeight = WinQuerySysValue(HWND_DESKTOP, SV_CYMENU) + 2;
ULONG    popUpMessageID = WM_CHORD;
ULONG    noteTimerNumber;
ULONG    timerNumber;
ULONG    timeOption = TIMEANDDATE;
USHORT   year;
SHORT    startDay;
SHORT    ItemSelection;
SHORT    MenuSelection;
SHORT    oldProgType;
HWND     hwndClient;
HWND     hwndFrame;
HWND     hwndMenu;
HWND     TaskHandle[MAXTASKS];
HWND     popUpMenu = 0;
HWND     oldTaskHandles[MAXTASKS];
//CHAR*    settingsPath = 0;
CHAR     password[PASSWORDLEN + 1];
CHAR     oldPassword[PASSWORDLEN + 1];
CHAR     globalProtection = NO;
CHAR     oldPasswordEnabled;
CHAR     stringTerminator = '\0';
CHAR     MenuName[MAXMENUS][MAXMENUNAMELENGTH];
CHAR     backgroundBitmap[MAXACTIONSTRINGLENGTH];
CHAR     hourlyChimeWavFile[MAXACTIONSTRINGLENGTH];
CHAR     variableText[MAXARGSTRINGLENGTH-2];
CHAR     oldItemName[MAXITEMNAMELENGTH];
CHAR     oldDirectory[MAXACTIONSTRINGLENGTH];
CHAR     oldAction[MAXACTIONSTRINGLENGTH];
CHAR     oldCmdLn[MAXARGSTRINGLENGTH];
CHAR     parameterTitle[MAXITEMNAMELENGTH+8];
CHAR     tmpBuffer[MAXPATH*2];
INT      backgroundAttr = 3 + TILED;
INT      numAlarms = 0;
INT      numberOfAlarms;
INT      repeatTime = 60;
INT      EditItem;
INT      NumMenus;
INT      taskItemSelected;
INT      numStartItems = 0;
INT      StartUpMenu[MAXSTARTITEMS];
INT      StartUpItem[MAXSTARTITEMS];
INT      day;
INT      month;
PCHAR    ParameterTextPtr;
PCHAR    currentReminderWavFile;
BOOLEAN  alreadyChimed = FALSE;
BOOLEAN  BarPosition = AT_TOP;
BOOLEAN  HourlyChime = TRUE;
BOOLEAN  FileBarMenuOn = TRUE;
BOOLEAN  timeSync;
BOOLEAN  checkBeforeDelete = TRUE;
BOOLEAN  showBackground = FALSE;
BOOLEAN  isBackgroundDisplayed = FALSE;
BOOLEAN  startUp = TRUE;
BOOLEAN  DoStartUpList = FALSE;
BOOLEAN  allowPopUpMenu = TRUE;
BOOLEAN  maximizeDesktop = FALSE;
BOOLEAN  interceptMsg = TRUE;
BOOLEAN  hideFileBar = FALSE;
BYTE     NumItems[MAXMENUS];
BOOL     FileBarIsShell = FALSE;

////////////////////////////////////////////////////////////////////////////////
// main function - application entry point
////////////////////////////////////////////////////////////////////////////////
main( int argc, char* argv[] )
{
    PSZ buffer;
    struct tm *time_now;
    ULONG FrameFlags;
    time_t currentTime;
    hab = WinInitialize(0);                   // handle: anchor block
    hmq = WinCreateMsgQueue(hab, 0);          // handle: message queue
    CHAR ClassName[] = "FileBar";             // store a name for our class
    MENUITEM menuItem;                        // used to modify menu data

    //--------------------------------------------------------------------------
    // register the window class
    //--------------------------------------------------------------------------
    WinRegisterClass(hab,
                     ClassName,      // name of class being registered
                     ClientWndProc,  // window procedure for class
                     0,              // class style
                     0);             // extra memory to reserve

    //--------------------------------------------------------------------------
    // create a window with a menu bar added on.  Note that the menu bar could
    // be defined in the WinCreateStdWindow call (set the resource id equal= to
    // MENUBAR) but is not since I need a handle to the menu (so I can later
    // modify the menu).  Thus, WinLoadMenu is used following WinCreateStdWindow
    //--------------------------------------------------------------------------
    FrameFlags = FCF_AUTOICON|FCF_TASKLIST|FCF_BORDER|FCF_MENU;
    hwndFrame = WinCreateStdWindow(HWND_DESKTOP,       // parent
                                        WS_VISIBLE,    // style
                                        &FrameFlags,   // control data
                                        ClassName,     // client name
                                        ClassName,     // title bar text
                                        0,             // client style
                                        NULLHANDLE,    // resource handle
                                        MENUBAR,       // resource id
                                        &hwndClient);  // client pointer

    //--------------------------------------------------------------------------
    // move and size application to span entire top of desktop
    //--------------------------------------------------------------------------
    WinSetWindowPos( hwndFrame, (HWND)0, 0, (ScreenSizeY-MenuHeight),
                     ScreenSizeX, MenuHeight, SWP_MOVE|SWP_SIZE|SWP_MINIMIZE);
    WinEnableWindowUpdate( hwndFrame, FALSE);

    hwndMenu = WinWindowFromID( hwndFrame, FID_MENU );
    MakeHourglassPointer ();                  // switch to hourglass cursor
                                              // during initialization

    //--------------------------------------------------------------------------
    // perform basic initialization
    //--------------------------------------------------------------------------
    NumMenus = 0;
    MenuSelection = 100;

    for ( short k = 0; k < MAXMENUS; k++ ) {
        WinSendMsg( hwndMenu, MM_QUERYITEM, MPFROM2SHORT(100*(k+1),TRUE),
                    MPFROMP(&menuData[k]));
        menuItem = menuData[k];
        menuItem.afStyle = MIS_STATIC;
        menuItem.afAttribute = MIA_DISABLED;
        menuItem.hwndSubMenu = (HWND)0;
        WinSendMsg( hwndMenu, MM_SETITEM, MPFROM2SHORT(100*(k+1),TRUE),
                    MPFROMP(&menuItem));
        WinSetMenuItemText( hwndMenu, 100*(k+1), "");
        NumItems[ k ] = 0;
        }

    memset( &fileDlgInfo, 0, sizeof(FILEDLG));
    fileDlgInfo.cbSize = sizeof(fileDlgInfo);
    menuMessageHandler = WinSubclassWindow( hwndMenu, menuHandler );

    //--------------------------------------------------------------------------
    // decide if FileBar is replacement shell or not
    //--------------------------------------------------------------------------
    k=0;
    DosScanEnv( "RUNWORKPLACE", &buffer);
    while (buffer[k]!=0) {
        if ((buffer[k]=='F') || (buffer[k]=='f'))
            if (strnicmp(&buffer[k],"filebar",7)==0) {
                SWCNTRL swctl;
                HSWITCH sw = WinQuerySwitchHandle( hwndFrame, 0 );

                FileBarIsShell = TRUE;
                // make switch entry for FileBar "disappear"!
                WinQuerySwitchEntry( sw, &swctl );
                swctl.fbJump        = SWL_NOTJUMPABLE;
                swctl.uchVisibility = SWL_INVISIBLE;
                WinChangeSwitchEntry( sw, &swctl );
                }
        k++;
        }


    //--------------------------------------------------------------------------
    // change to directory that application executable is started from
    //--------------------------------------------------------------------------
    if (argc > 0) {
        strncpy( tmpBuffer, argv[0], sizeof(tmpBuffer) );
        if (tmpBuffer[1]==':')
            DosSetDefaultDisk( (ULONG)(toupper(tmpBuffer[0])-'A' + 1) );

        k = strlen(tmpBuffer);
        while ((tmpBuffer[k]!='\\') && (k>0))
           k--;

        if (k) {
            tmpBuffer[k]='\0';
            if (DosSetCurrentDir( tmpBuffer )!=0) {
                char mesg[]=MSG2;
                WinMessageBox( HWND_DESKTOP, hwndFrame, mesg, tmpBuffer, 0,
                               MB_MOVEABLE|MB_ERROR|MB_OK);
                }
            }
        strcpy( backgroundBitmap, tmpBuffer );
        strcat( backgroundBitmap, BITMAPNAME );
        strcpy( hourlyChimeWavFile, tmpBuffer );
        strcat( hourlyChimeWavFile, CHIMESOUNDFILE );
        }


    //--------------------------------------------------------------------------
    // if user has passed us a second argument, it is path to settings file
    //--------------------------------------------------------------------------
    //if (argc > 1) {
    //    settingsPath = new CHAR[MAXPATH];
    //    strncpy( settingsPath, argv[1], MAXPATH );
    //}


    //--------------------------------------------------------------------------
    // record time and date for scheduler program
    //--------------------------------------------------------------------------
    tzset();
    time(&currentTime);
    time_now = localtime( &currentTime );
    month = time_now->tm_mon;
    year = time_now->tm_year;


    //--------------------------------------------------------------------------
    // read in the user option file and set up the menu bar appropriately
    // check the user time/date option and put it on the menu bar
    // reset our timer in case they want the current time displayed
    //--------------------------------------------------------------------------
    readOptionFile();                         // read in option file
    sortTimeEntries( numAlarms );             // sort the alarm entries
    restartTimer();                           // resync our clock
    updateTimeDisplay( hwndMenu );            // display current date/time

    // make FileBar visible
    WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_RESTORE);

    if ((!FileBarIsShell) && (maximizeDesktop) && (BarPosition==AT_TOP)) {
        ULONG numItems;
        ULONG Buffer;
        PSWBLOCK SwitchBlockPtr;

        // get the # of items and the switch list from the system
        numItems = WinQuerySwitchList( hab, NULL, 0 );
        Buffer = (numItems * sizeof(SWENTRY)) + sizeof(HSWITCH);
        PVOID my = new BYTE[Buffer];
        WinQuerySwitchList( hab, (SWBLOCK*)my, Buffer );
        SwitchBlockPtr = (PSWBLOCK)(my);

        for (k = 0; k < numItems; k++ )
            if (strcmp(SwitchBlockPtr->aswentry[k].swctl.szSwtitle,
                                                         WPSDESKTOPNAME) == 0) {
                WinSetWindowPos( SwitchBlockPtr->aswentry[k].swctl.hwnd,
                                 (HWND)0, 0, 0, 0, 0, SWP_MAXIMIZE);
                WinSetWindowPos( SwitchBlockPtr->aswentry[k].swctl.hwnd,
                                 (HWND)0, 0, 0, ScreenSizeX,
                                 ScreenSizeY-MenuHeight+sysMenuHeight+1,
                                 SWP_MOVE|SWP_SIZE);
                }
        }


    displayBackground();                      // restore user background bitmap
    ExecuteStartUpList();                     // start execution list
    MakeArrowPointer ();                      // switch back to arrow pointer,

    WinSetParent( hwndFrame, HWND_DESKTOP, FALSE );
    WinSetFocus( HWND_DESKTOP, hwndFrame );

    //--------------------------------------------------------------------------
    // initialize our DLL so that we intercept window sizing messages and hide
    // the bar if we need to do so
    //--------------------------------------------------------------------------
    FileBarInit( hwndFrame );
    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight,
                      (interceptMsg==TRUE), allowPopUpMenu, popUpMessageID );
    WinEnableWindowUpdate( hwndFrame, TRUE);
    WinInvalidateRegion( hwndFrame, NULL, FALSE );

    if (hideFileBar)
        WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_HIDE);

    //--------------------------------------------------------------------------
    // create a message queue and then as long as there are messages to get,
    // get them and dispatch them to our message handlers
    //--------------------------------------------------------------------------
    {
        QMSG qmsg;                                     // create a message queue

        while( WinGetMsg( hab, &qmsg, (HWND)0, 0, 0 ) !=FALSE )
            WinDispatchMsg( hab, &qmsg );
    }


    //--------------------------------------------------------------------------
    // our application is done.  Destroy timer, window, the message queue and
    // release the DLL.  Call the system to destroy anchor block and do the
    // final clean up work
    //--------------------------------------------------------------------------
    if (timerNumber != 0)
        WinStopTimer( hab, hwndFrame, timerNumber );
    FileBarQuit();                                // release the DLL from memory
    WinDestroyWindow(hwndFrame);
    WinDestroyMsgQueue(hmq);
    WinTerminate(hab);
    return 0;
}


////////////////////////////////////////////////////////////////////////////////
// a new font has been selected for our menu, resize and redraw the menubar
////////////////////////////////////////////////////////////////////////////////
VOID resizeMenu()
{
    HPS hps;
    FONTMETRICS fm;

    hps = WinGetPS( hwndMenu );
    GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
    MenuHeight = fm.lLowerCaseDescent + fm.lMaxAscender + 4;
    if (MenuHeight < (fm.lLowerCaseDescent + fm.lLowerCaseAscent + 2))
        MenuHeight = fm.lLowerCaseDescent + fm.lLowerCaseAscent + 2;
    if (MenuHeight < (WinQuerySysValue(HWND_DESKTOP, SV_CYMENU) + 2))
        MenuHeight = WinQuerySysValue(HWND_DESKTOP, SV_CYMENU) + 2;
    WinReleasePS( hps );

    if (BarPosition==AT_BOTTOM)
        WinSetWindowPos( hwndFrame, (HWND)0, 0, -1,
                         ScreenSizeX, MenuHeight, SWP_MOVE|SWP_SIZE);
    else
        WinSetWindowPos( hwndFrame, (HWND)0, 0, (ScreenSizeY-MenuHeight)+1,
                         ScreenSizeX, MenuHeight, SWP_MOVE|SWP_SIZE);
    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight,
                      (interceptMsg==TRUE), allowPopUpMenu, popUpMessageID );
}


////////////////////////////////////////////////////////////////////////////////
// subclassed menu handler for main application window
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY menuHandler(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    switch (msg) {
        //----------------------------------------------------------------------
        // if a menu has been highlighted, save which one it is so that we know
        // which task to affect if something is chosen off cascading menu
        //----------------------------------------------------------------------
        case WM_MENUSELECT:
        {
            if ((SHORT1FROMMP(mp1)>TASKLIST_MENU) && (SHORT1FROMMP(mp1)<99))
                taskItemSelected = SHORT1FROMMP(mp1);
            return menuMessageHandler(hwnd, msg, mp1, mp2);
        }
        //----------------------------------------------------------------------
        // resize menubar if a font was just dropped on us
        //----------------------------------------------------------------------
        case WM_PRESPARAMCHANGED:
        {
            if ( (ULONG)mp1 == PP_FONTNAMESIZE)
                resizeMenu();
            return menuMessageHandler(hwnd, msg, mp1, mp2);
        }
        //----------------------------------------------------------------------
        // nothing of interest, pass it onto the system for default processing
        //----------------------------------------------------------------------
        default:
            break;
        }
    return menuMessageHandler(hwnd, msg, mp1, mp2);
}


//////////////////////////////////////////////////////////////////////////////
// ask user for a password and check it against goodPassword and see if they
// match.  Return boolean value that reflects this comparison
//////////////////////////////////////////////////////////////////////////////
BOOL checkAgainstPassWord( char* goodPassword )
{
    CHAR mesg[] = MSG3;

    sprintf( parameterTitle, MSG4 );
    ParameterTextPtr = mesg;
    oldProgType = PASSWORDLEN;
    (VOID*)WinDlgBox(HWND_DESKTOP, hwndFrame, (PFNWP)EnterParamProc, 0,
                     PASSWORDENTRY, (PVOID)NULL);
    if (strcmp( goodPassword, variableText ) == 0)
        return TRUE;
    WinMessageBox( HWND_DESKTOP, hwndFrame, MSG5,
                   MSG6, 0, MB_MOVEABLE|MB_ERROR|MB_OK);
    return FALSE;
}


//////////////////////////////////////////////////////////////////////////////
// This is the message processing facility for the main application thread
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY ClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    switch (msg) {
        //----------------------------------------------------------------------
        // if the application is terminating, write user settings to a file
        //----------------------------------------------------------------------
        case WM_CLOSE: {
            if ((globalProtection==YES) && ( !checkAgainstPassWord(password) ))
                return FALSE;                // they entered an invalid password
            writeOptionFile();
            return WinDefWindowProc(hwnd, msg, mp1, mp2);  // default processing
            }
        case WM_SAVEAPPLICATION:
        case WM_QUIT: {
            writeOptionFile();
            return WinDefWindowProc(hwnd, msg, mp1, mp2);  // default processing
            }
        //----------------------------------------------------------------------
        // the application has been designed such that a WM_TIMER is sent by the
        // system every minute (so that we can update our time on the menubar
        // if necessary)
        //----------------------------------------------------------------------
        case WM_TIMER: {
            if (!timeSync) {
                WinStopTimer( hab, hwndClient, timerNumber );
                timerNumber = WinStartTimer( hab, hwndClient, TIMERID, 60000);
                timeSync = TRUE;
                }
            displayTimeDate();
            return WinDefWindowProc(hwnd, msg, mp1, mp2);  // default processing
            }
        //----------------------------------------------------------------------
        // a WM_INITMENU message is sent just prior to any pulldown menu being
        // displayed.  This gives us a chance to change its contents before it
        // is displayed.  If necessary, we update menu contents for user menus
        //----------------------------------------------------------------------
        case WM_INITMENU: {
            SHORT menuId = SHORT1FROMMP(mp1);
            //------------------------------------------------------------------
            // if the FileBar menu is being readied for display, make sure the
            // move-bar top/bottom item and check items read appropriately!
            //------------------------------------------------------------------
            if (menuId == FILEBAR_MENU) {
                HWND window = HWNDFROMMP( mp2 );

                if (BarPosition == AT_TOP )
                    WinSetMenuItemText( window, FILEBAR_MOVEBAR, MSG7 );
                else
                    WinSetMenuItemText( window, FILEBAR_MOVEBAR, MSG8 );

                WinCheckMenuItem( window, FILEBAR_STARTUP, DoStartUpList);
                WinCheckMenuItem( window, FILEBAR_DISPLAYBACKGROUND, showBackground);
                WinCheckMenuItem( window, FILEBAR_FILEBARMENU, (TRUE - FileBarMenuOn));
                WinCheckMenuItem( window, FILEBAR_CONFIRMCLOSE, checkBeforeDelete);
                WinCheckMenuItem( window, FILEBAR_RESIZEWPS, maximizeDesktop);
                WinCheckMenuItem( window, FILEBAR_INTERCEPTMSG, interceptMsg );

                if (!FileBarIsShell)
                    WinEnableMenuItem( window, FILEBAR_RESIZEWPS, (BarPosition==AT_TOP));
                else {
                    WinSendMsg( window, MM_DELETEITEM, MPFROM2SHORT( FILEBAR_EXIT, TRUE ), 0 );
                    WinEnableMenuItem( window, FILEBAR_RESIZEWPS, FALSE);
                    }
                return WinDefWindowProc(hwnd, msg, mp1, mp2);  // default processing
                }
            //------------------------------------------------------------------
            // if the user is pulling down the task list, put a current copy of
            // the task list in the menu and store copies of all the tasks id
            // numbers and handles just in case they want to jump to one of them
            //------------------------------------------------------------------
            if (menuId == TASKLIST_MENU) {
                SHORT i,j;
                PCHAR text;
                MENUITEM menuItem;
                USHORT index;
                ULONG numItems;
                ULONG Buffer;
                SWCNTRL tmp;
                PVOID my;

                // clear out the menu, get it ready for new task entries
                for (i = menuId+1; i <= menuId+MAXITEMS; i++ )
                    WinSendMsg( HWNDFROMMP( mp2 ), MM_DELETEITEM,
                                MPFROM2SHORT( i, TRUE ), 0 );

                // get the # of items and the switch list from the system
                numItems = WinQuerySwitchList( hab, NULL, 0 );
                Buffer = (numItems * sizeof(SWENTRY)) + sizeof(HSWITCH);
                my = new BYTE[Buffer];
                WinQuerySwitchList( hab, (SWBLOCK*)my, Buffer );

                // insert each task as an entry under the task list menu
                menuItem.iPosition = 0;
                menuItem.afStyle = MIS_MULTMENU|MIS_SINGLE;
                menuItem.afAttribute = 0;
                menuItem.id = TASKLIST_MENU;

                for (j = 0; j < numItems; j++ ) {
                    tmp = ((PSWBLOCK)(my))->aswentry[j].swctl;
                    menuItem.id++;
                    if ((tmp.uchVisibility != SWL_GRAYED) &&
                        (tmp.uchVisibility != SWL_INVISIBLE) &&
                        (tmp.hwnd != hwndFrame)) {

                        // load in the cascading menu for this task entry
                        menuItem.hwndSubMenu = WinLoadMenu(hwndMenu, 0, TASKMENUCLOSE);

                        // remove ctrl characters from task list
                        index = 0;
                        text = tmp.szSwtitle;
                        while (text[++index])
                            if (text[index]<' ')
                                text[index]=' ';

                        // enter task into the menu structure
                        WinSendMsg( HWNDFROMMP(mp2), MM_INSERTITEM,
                                    (MENUITEM*)&menuItem,
                                    (tmp.szSwtitle) );
                                    //////////////////////////&(tmp.szSwtitle) );

                        TaskId[j] = tmp.idProcess;
                        TaskHandle[j] = tmp.hwnd;
                        WinSetWindowBits(menuItem.hwndSubMenu, QWL_STYLE, MS_CONDITIONALCASCADE, MS_CONDITIONALCASCADE);
                        WinSendMsg(menuItem.hwndSubMenu, MM_SETDEFAULTITEMID, MPFROMSHORT(TASK_SWITCHTO), NULL);
                        }
                    }
                delete( my );
                return WinDefWindowProc(hwnd, msg, mp1, mp2);  // default processing
                }
            //------------------------------------------------------------------
            // one of the user menus is being initialized; if it has been marked
            // as needing to be updated, fill the menu with the current items
            // the user has set up
            //------------------------------------------------------------------
            if (menuId >= 100) {
                int MenuToUpdate = menuId / 100 - 1;
                MENUITEM menuItem;
                SHORT i,j;

                for (i = menuId+1; i < menuId+MAXITEMS+1; i++ )
                    WinSendMsg( HWNDFROMMP( mp2 ), MM_DELETEITEM,
                                MPFROM2SHORT( i, TRUE ), 0 );
                menuItem.iPosition = MIT_END;
                menuItem.afStyle = MIS_TEXT;
                menuItem.afAttribute = 0;
                menuItem.hItem = 0;
                menuItem.hwndSubMenu = (HWND)0;
                menuItem.id = menuId;
                for (j = 0; j < NumItems[ MenuToUpdate ]; j++ ) {
                    menuItem.id++;
                    if (Menus[MenuToUpdate][j]->ItemName[0] != '\0')
                        WinSendMsg( HWNDFROMMP(mp2), MM_INSERTITEM,
                                    (MENUITEM*)&menuItem,
                                    Menus[MenuToUpdate][j]->ItemName );
                    else {
                        menuItem.afStyle = MIS_SEPARATOR;
                        WinSendMsg( HWNDFROMMP(mp2), MM_INSERTITEM,
                                    (MENUITEM*)&menuItem,
                                    0 );
                        menuItem.afStyle = MIS_TEXT;
                        }
                    }
                }
            }
        //----------------------------------------------------------------------
        // process all WM_COMMAND messages below:
        //----------------------------------------------------------------------
        case WM_COMMAND: {
            USHORT command = SHORT1FROMMP(mp1);
            //------------------------------------------------------------------
            // it was not a user item, process now as usual
            //------------------------------------------------------------------
            switch( command ) {
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case FILEBAR_PASSWORD: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return 0;
                    WinDlgBox(HWND_DESKTOP,
                          hwnd,
                          (PFNWP)globalPasswordProc,
                          0,
                          PASSWORDOPTIONS,
                          (PVOID)NULL);
                    return 0;
                    }
                //--------------------------------------------------------------
                // user has invoked popup menu
                //--------------------------------------------------------------
                case POPUPMENU: {
                    POINTL pointData;
                    SHORT i;

                    if (popUpMenu)
                        WinDestroyWindow( popUpMenu );

                    popUpMenu = WinLoadMenu( HWND_DESKTOP, NULLHANDLE, MENUBAR );

                    for (i=0; i<MAXMENUS; i++)
                        if (i<NumMenus)
                            WinSetMenuItemText( popUpMenu, 100*i+100, MenuName[i] );
                        else
                            WinSendMsg( popUpMenu, MM_REMOVEITEM, MPFROM2SHORT(i*100+100,TRUE), 0 );
                    updateTimeDisplay( popUpMenu );

                    WinQueryPointerPos( HWND_DESKTOP, &pointData );
                    WinPopupMenu( HWND_DESKTOP, hwndMenu, popUpMenu, pointData.x, pointData.y, 0,
                                  PU_HCONSTRAIN|PU_VCONSTRAIN|PU_MOUSEBUTTON1|PU_MOUSEBUTTON2|PU_MOUSEBUTTON3|PU_KEYBOARD );
                    return 0;
                    }
                //--------------------------------------------------------------
                // user wants to shutdown system
                //--------------------------------------------------------------
                case TASKLIST_SHUTDOWN: {
                    char text[] = MSG9;

                    // Shutdown no longer requires a password to function
                    //if (( globalProtection==YES ) &&
                    //    ( !checkAgainstPassWord( password ) ))
                    //    return FALSE;
                    if (WinMessageBox( HWND_DESKTOP, hwndFrame, text, MSG10, 0,
                                       MB_DEFBUTTON2|MB_MOVEABLE|MB_ICONEXCLAMATION|MB_OKCANCEL) == MBID_CANCEL)
                        return 0;

                    writeOptionFile();
                    WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_HIDE);
                    WinPostMsg( hwndClient, WM_QUIT, 0, 0 );
                    WinShutdownSystem( WinQueryAnchorBlock( HWND_DESKTOP ), hmq );
                    }
                //--------------------------------------------------------------
                // expand or shrink FileBar system menus
                //--------------------------------------------------------------
                case FILEBAR_FILEBARMENU: {
                    CHAR menuOn[] = FILEBARMENUON;
                    CHAR menuOff[] = FILEBARMENUOFF;
                    CHAR taskOn[] = TASKMENUON;
                    CHAR taskOff[] = TASKMENUOFF;

                    FileBarMenuOn = TRUE - FileBarMenuOn;
                    if (FileBarMenuOn) {
                        WinSetMenuItemText( hwndMenu, FILEBAR_MENU, menuOn);
                        WinSetMenuItemText( hwndMenu, TASKLIST_MENU, taskOn);
                        }
                    else {
                        WinSetMenuItemText( hwndMenu, FILEBAR_MENU, menuOff);
                        WinSetMenuItemText( hwndMenu, TASKLIST_MENU, taskOff);
                        }
                    return 0;
                    }
                //--------------------------------------------------------------
                // the user has selected something from the tasklist menu, switch
                // control to that task, if possible
                //--------------------------------------------------------------
                case TASK_SWITCHTO: {
                    CHAR title[] = MSG11;
                    CHAR text[] = MSG12;
                    HSWITCH switchHandle;
                    switchHandle = WinQuerySwitchHandle( TaskHandle[taskItemSelected - TASKLIST_MENU-1],
                                                         TaskId[taskItemSelected - TASKLIST_MENU-1]);

                    if (!switchHandle)
                        WinMessageBox( HWND_DESKTOP, hwnd, text, title, 0,
                                       MB_MOVEABLE|MB_ERROR|MB_OK);
                    else if (WinSwitchToProgram( switchHandle ) != 0)
                        WinMessageBox( HWND_DESKTOP, hwnd, text, title, 0,
                                       MB_MOVEABLE|MB_ERROR|MB_OK);
                    else
                        WinShowWindow( TaskHandle[taskItemSelected - TASKLIST_MENU - 1], TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // close the chosen task
                //--------------------------------------------------------------
                case TASK_CLOSE: {
                    ULONG numItems;
                    ULONG Buffer;
                    PSWBLOCK SwitchBlockPtr;
                    PID killedTaskId;
                    HWND killedTaskHandle;

                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;

                    if (checkBeforeDelete) {
                        if (WinMessageBox( HWND_DESKTOP, hwnd,
                                           MSG13, MSG14, 0,
                                           MB_MOVEABLE|MB_ICONQUESTION|MB_YESNO) == MBID_NO)
                            return 0;
                        }

                    killedTaskId = TaskId[taskItemSelected - TASKLIST_MENU - 1];
                    killedTaskHandle = TaskHandle[taskItemSelected - TASKLIST_MENU - 1];
                    WinSendMsg( killedTaskHandle, WM_CLOSE, 0, 0 );

                    // get the # of items and the switch list from the system
                    numItems = WinQuerySwitchList( hab, NULL, 0 );
                    Buffer = (numItems * sizeof(SWENTRY)) + sizeof(HSWITCH);
                    PVOID my = new BYTE[Buffer];
                    WinQuerySwitchList( hab, (SWBLOCK*)my, Buffer );
                    SwitchBlockPtr = (PSWBLOCK)(my);

                    // if task did not close willingly, kill its process!
                    for (short j = 0; j < numItems; j++ )
                        if (SwitchBlockPtr->aswentry[j].swctl.hwnd == killedTaskHandle)
                            DosKillProcess( DKP_PROCESS, killedTaskId );
                    delete( my );

                    return 0;
                    }
                //-------------------------------------------------------------
                // maximize the chosen task
                //-------------------------------------------------------------
                case TASK_MAX: {
                    HSWITCH switchHandle = WinQuerySwitchHandle( TaskHandle[taskItemSelected - TASKLIST_MENU- 1],
                                                                 TaskId[taskItemSelected - TASKLIST_MENU- 1]);

                    WinShowWindow( TaskHandle[taskItemSelected - TASKLIST_MENU- 1], TRUE );
                    WinSetWindowPos( TaskHandle[taskItemSelected - TASKLIST_MENU- 1],
                                     (HWND)0, 0, 0, 0, 0, SWP_MAXIMIZE);
                    WinSwitchToProgram( switchHandle );
                    return 0;
                    }
                //--------------------------------------------------------------
                // minimize the chosen task
                //--------------------------------------------------------------
                case TASK_MIN: {
                    WinShowWindow( TaskHandle[taskItemSelected - TASKLIST_MENU- 1], TRUE );
                    WinSetWindowPos( TaskHandle[taskItemSelected - TASKLIST_MENU- 1],
                                     (HWND)0, 0, 0, 0, 0, SWP_MINIMIZE);
                    return 0;
                    }
                //--------------------------------------------------------------
                // show the chosen task
                //--------------------------------------------------------------
                case TASK_SHOW: {
                    WinSetWindowPos( TaskHandle[taskItemSelected - TASKLIST_MENU- 1],
                                     (HWND)0, 0, 0, 0, 0, SWP_SHOW);
                    return 0;
                    }
                //--------------------------------------------------------------
                // hide the chosen task
                //--------------------------------------------------------------
                case TASK_HIDE: {
                    WinSetWindowPos( TaskHandle[taskItemSelected - TASKLIST_MENU- 1],
                                     (HWND)0, 0, 0, 0, 0, SWP_HIDE);
                    return 0;
                    }
                //--------------------------------------------------------------
                // show the display background dialog box
                //--------------------------------------------------------------
                case FILEBAR_DISPLAYBACKGROUND: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    WinDlgBox(HWND_DESKTOP,
                          hwnd,
                          (PFNWP)backgroundProc,
                          0,
                          BACKGROUNDWIN,
                          (PVOID)NULL);
                    displayBackground();
                    return 0;
                    }
                //--------------------------------------------------------------
                // user has altered "confirm on task close" check state
                //--------------------------------------------------------------
                case FILEBAR_CONFIRMCLOSE: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    checkBeforeDelete = TRUE - checkBeforeDelete;
                    return 0;
                    }
                //--------------------------------------------------------------
                // user has altered check state of "always on top" item
                //--------------------------------------------------------------
                case FILEBAR_INTERCEPTMSG: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    interceptMsg = TRUE - interceptMsg;
                    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                                      allowPopUpMenu, popUpMessageID );
                    return 0;
                    }
                //--------------------------------------------------------------
                // show the display background dialog box
                //--------------------------------------------------------------
                case FILEBAR_STARTUP: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    WinDlgBox(HWND_DESKTOP,
                              hwnd,
                              (PFNWP)startupProc,
                              0,
                              STARTUP_DIALOG,
                             (PVOID)NULL);
                    return 0;
                    }
                //--------------------------------------------------------------
                // user has invoked the scheduler
                //--------------------------------------------------------------
                case TIMEDATE: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    WinDlgBox(HWND_DESKTOP,
                              hwnd,
                              (PFNWP)schedulerProc,
                              0,
                              SCHEDULER,
                              (PVOID)NULL);
                    return 0;
                }
                //--------------------------------------------------------------
                // uer has altered check state of "resize desktop on boot" item
                //--------------------------------------------------------------
                case FILEBAR_RESIZEWPS: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    maximizeDesktop = TRUE - maximizeDesktop;
                    return 0;
                    }
                //--------------------------------------------------------------
                // user wants to change settings of popup menu
                //--------------------------------------------------------------
                case FILEBAR_POPMENU: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    WinDlgBox(HWND_DESKTOP,
                              hwnd,
                              (PFNWP)popUpOptionsProc,
                              0,
                              POPUPOPTIONS,
                              (PVOID)NULL);
                    return 0;
                    }
                //--------------------------------------------------------------
                // the user wants to save current options
                //--------------------------------------------------------------
                case FILEBAR_SAVEOPTIONS: {
                    char title[] = MSG15;
                    char message[] = MSG16;

                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    writeOptionFile();
                    WinMessageBox( HWND_DESKTOP, hwnd, message, title, 0,
                                   MB_MOVEABLE|MB_INFORMATION|MB_OK);
                    return 0;
                }
                //--------------------------------------------------------------
                // the user wants to edit the menu structure
                //--------------------------------------------------------------
                case FILEBAR_EDITMENU: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    return (VOID*)WinDlgBox(HWND_DESKTOP,
                                            hwnd,
                                            (PFNWP)EditMenuProc,
                                            0,
                                            EDITMENU,
                                            (PVOID)NULL);
                    }
                //--------------------------------------------------------------
                // the user wants to select their time/date display options
                //--------------------------------------------------------------
                case FILEBAR_TIMEOPTION: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    return (VOID*)WinDlgBox(HWND_DESKTOP,
                                            hwnd,
                                            (PFNWP)TimeDateProc,
                                            0,
                                            TIMEOPTIONS,
                                            (PVOID)NULL);
                    }
                //--------------------------------------------------------------
                // the user wants to get general help on filebar
                //--------------------------------------------------------------
                case FILEBAR_GENHELP: {
                    return (VOID*)WinDlgBox(HWND_DESKTOP,
                                            hwnd,
                                            (PFNWP)GenericProc,
                                            0,
                                            GENERAL_HELP,
                                            (PVOID)NULL);
                    }
                //--------------------------------------------------------------
                // the user wants to see product information for filebar
                //--------------------------------------------------------------
                case FILEBAR_PRODINFO: {
                    return (VOID*)WinDlgBox(HWND_DESKTOP,
                                            hwnd,
                                            (PFNWP)GenericProc,
                                            0,
                                            PRODUCT_INFO,
                                            (PVOID)NULL);
                    }
                //--------------------------------------------------------------
                // the user wishes to move the filebar from its current position
                // to either to the top or bottom of the desktop
                //--------------------------------------------------------------
                case FILEBAR_MOVEBAR: {
                    if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                        return FALSE;
                    if (BarPosition==AT_TOP) {
                        BarPosition = AT_BOTTOM;
                        WinSetWindowPos( hwndFrame, (HWND)0, 0, -1,
                                         ScreenSizeX, MenuHeight, SWP_MOVE);
                        }
                    else {
                        BarPosition = AT_TOP;
                        WinSetWindowPos( hwndFrame, (HWND)0, 0, (ScreenSizeY-MenuHeight)+1,
                                         ScreenSizeX, MenuHeight, SWP_MOVE);
                        }
                    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                                      allowPopUpMenu, popUpMessageID );
                    return 0;
                    }
                //--------------------------------------------------------------
                // the user wishes to exit the filebar application
                //--------------------------------------------------------------
                case FILEBAR_EXIT: {
                    return (VOID*)WinPostMsg( hwnd, WM_CLOSE, 0, 0);
                    }
                //--------------------------------------------------------------
                // something besides our menus sent a message, pass the message
                // to the system for default processing
                //--------------------------------------------------------------
                default:
                    break;
                }

            //------------------------------------------------------------------
            // the user has selected an item off the user menus.  Activate the
            // item they have selected
            //------------------------------------------------------------------
            if (( command > 99 ) && (command % 100)) {
                INT MenuToUpdate = command / 100 - 1;
                INT ItemToUpdate = command % 100 - 1;

                if ((ItemToUpdate>=MAXITEMS) || (MenuToUpdate>=MAXMENUS))
                    return 0;
                if (MenuToUpdate >= 0)
                    if ( Menus[MenuToUpdate][ItemToUpdate]->PasswordEnabled == YES )
                        if ( !checkAgainstPassWord( Menus[MenuToUpdate][ItemToUpdate]->Password ) )
                            return FALSE;
                    startApplication( MenuToUpdate, ItemToUpdate );
                return 0;
                }

            }
        //----------------------------------------------------------------------
        // we were sent a message that we don't care about, pass it onto system
        // for default processing
        //----------------------------------------------------------------------
        default:
            break;
        };

    return WinDefWindowProc(hwnd, msg, mp1, mp2);  // default processing
}


////////////////////////////////////////////////////////////////////////////////
// readOptionFile - will read the option file (generated by the app) from disk,
// if it exists and will restore the application to the state in which it was
// last left
////////////////////////////////////////////////////////////////////////////////
void readOptionFile( void )
{
    int currentMenu = 100;
    FILE *optionFile;

    //--------------------------------------------------------------------------
    // if the option file exists on disk, read it in and restore old menu,
    // otherwise we will return and rely on default values
    //--------------------------------------------------------------------------
    //if (settingsPath)
    //    optionFile = fopen(settingsPath, "rt");
    //else
    optionFile = fopen(OPTIONFILE, "rt");

    if (optionFile != NULL) {
        ALARMS* alarm;
        USERMENUITEM* menuItem;
        RGB2 rgb = {0,0,0,0};
        ULONG color;
        INT a,b,c,d,e,f;

        MenuHeight  = WinQuerySysValue(HWND_DESKTOP, SV_CYMENU) + 2;

        fscanf(optionFile, "%d %d", &timeOption, &BarPosition);
        // restore user's desired bar position
        if (BarPosition==AT_BOTTOM) {
            WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0 , SWP_MOVE|SWP_RESTORE);
            WinSetWindowPos( hwndFrame, (HWND)0, 0, -1,
                             ScreenSizeX, MenuHeight, SWP_MOVE|SWP_SIZE);
            WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0 , SWP_MOVE|SWP_MINIMIZE);
            }
        else {
            WinSetWindowPos( hwndFrame, (HWND)0, 0, (ScreenSizeY-MenuHeight)+1,
                             ScreenSizeX, MenuHeight, SWP_MOVE|SWP_SIZE);
            }
        setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                          allowPopUpMenu, popUpMessageID );

        // restore user's menus and menu choices
        fscanf(optionFile, "%d", &NumMenus);
        for (short i = 0; i < NumMenus; i++ ) {
            readString( optionFile, (CHAR*)&MenuName[i] );

            WinSendMsg( hwndMenu, MM_SETITEM, MPFROM2SHORT(100*i+100,TRUE),MPFROMP(&menuData[i]));
            /////////////////////WinSetMenuItemText( hwndMenu, 100*i+100, &MenuName[i]);
            WinSetMenuItemText( hwndMenu, 100*i+100, MenuName[i]);

            fscanf(optionFile, "%d", &a);
            NumItems[i] = (BYTE)(a % 256);
            for (short j = 0; j < NumItems[i]; j++) {
                Menus[i][j] = new USERMENUITEM;
                menuItem = Menus[i][j];
                readString( optionFile, (CHAR*)&menuItem->ItemName );
                readString( optionFile, (CHAR*)&menuItem->ActionToDo );
                readString( optionFile, (CHAR*)&menuItem->CmdLnArgs );
                readString( optionFile, (CHAR*)&menuItem->Directory );
                fscanf( optionFile, "%d", &a );
                menuItem->ProgType = a % 1024;
                menuItem->PasswordEnabled = NO;
                menuItem->Password[0] = 0;
                }
            currentMenu = currentMenu + 100;
            }

        readString( optionFile, (CHAR*)&tmpBuffer );
        if (tmpBuffer[0]!='\0') {
            WinSetPresParam( hwndMenu, PP_FONTNAMESIZE, sizeof(tmpBuffer), tmpBuffer );
            WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_RESTORE);
            resizeMenu();
            WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_MINIMIZE);
            }

        fscanf( optionFile, "%d", &checkBeforeDelete );
        if (fscanf( optionFile, "%d", &FileBarMenuOn )!=EOF) {
            CHAR menuOn[] = FILEBARMENUON;
            CHAR menuOff[] = FILEBARMENUOFF;
            CHAR taskOn[] = TASKMENUON;
            CHAR taskOff[] = TASKMENUOFF;

            if (FileBarMenuOn) {
                WinSetMenuItemText( hwndMenu, FILEBAR_MENU, menuOn);
                WinSetMenuItemText( hwndMenu, TASKLIST_MENU, taskOn);
                }
            else {
                WinSetMenuItemText( hwndMenu, FILEBAR_MENU, menuOff);
                WinSetMenuItemText( hwndMenu, TASKLIST_MENU, taskOff);
                }
            }

        if (fscanf( optionFile, "%d %d", &showBackground, &backgroundAttr )!=EOF)
            readString( optionFile, (CHAR*)&backgroundBitmap );

        for (i=PP_FOREGROUNDCOLOR; i<=PP_BORDERCOLOR; i=i+2)
            if (fscanf(optionFile, "%ld", &color )!=EOF)
                if ( color != NOCOLOR) {
                    rgb.bRed = (BYTE)(color/65536);
                    color = color%65536;
                    rgb.bGreen = (BYTE)(color/256);
                    color = color%256;
                    rgb.bBlue = (BYTE)(color);
                    WinSetPresParam( hwndMenu, i, sizeof(rgb), &rgb);
                    }

        for (i=PP_ACTIVECOLOR; i<=PP_INACTIVETEXTBGNDCOLOR; i=i+2)
            if (fscanf(optionFile, "%ld", &color )!=EOF)
                if ( color != NOCOLOR) {
                    rgb.bRed = (BYTE)(color/65536);
                    color = color%65536;
                    rgb.bGreen = (BYTE)(color/256);
                    color = color%256;
                    rgb.bBlue = (BYTE)(color);
                    WinSetPresParam( hwndMenu, i, sizeof(rgb), &rgb);
                    }

        if (fscanf(optionFile, "%ld", &color )!=EOF)
            if ( color != NOCOLOR) {
                rgb.bRed = (BYTE)(color/65536);
                color = color%65536;
                rgb.bGreen = (BYTE)(color/256);
                color = color%256;
                rgb.bBlue = (BYTE)(color);
                WinSetPresParam( hwndMenu, PP_SHADOW, sizeof(rgb), &rgb);
                }

        for (i=PP_MENUFOREGROUNDCOLOR; i<=PP_MENUDISABLEDBGNDCOLOR; i=i+2)
            if (fscanf(optionFile, "%ld", &color )!=EOF)
                if ( color != NOCOLOR) {
                    rgb.bRed = (BYTE)(color/65536);
                    color = color%65536;
                    rgb.bGreen = (BYTE)(color/256);
                    color = color%256;
                    rgb.bBlue = (BYTE)(color);
                    WinSetPresParam( hwndMenu, i, sizeof(rgb), &rgb);
                    }

        if (fscanf(optionFile, "%d %d", &DoStartUpList, &numStartItems ) != EOF)
            for (i=0; i<numStartItems; i++)
                fscanf(optionFile, "%d %d", &StartUpMenu[i], &StartUpItem[i] );

        if (fscanf(optionFile, "%d", &HourlyChime ) != EOF)
            readString( optionFile, (CHAR*)&hourlyChimeWavFile );

        // read in current task scheduler tasks
        if (fscanf(optionFile, "%d %d %d %d", &maximizeDesktop, &repeatTime, &interceptMsg, &numAlarms ) != EOF) {
            setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                              allowPopUpMenu, popUpMessageID );

            for (i=0; i<numAlarms; i++) {
                fscanf(optionFile, "%d %d %d %d %d %d", &a,&b,&c,&d,&e,&f);
                alarmPtr[i] = new ALARMS;
                alarm = alarmPtr[i];
                alarm->AlarmHour   = a % 256;
                alarm->AlarmMinute = b % 256;
                alarm->AlarmMonth  = c % 256;
                alarm->AlarmDay    = d % 256;
                alarm->AlarmYear   = e % 256;
                alarm->options     = f % 256;
                readString( optionFile, (CHAR*)&alarm->ActionToDo );
                readString( optionFile, (CHAR*)&alarm->ReminderWAV );
                }
        }

        fscanf(optionFile, "%d %d", &hideFileBar, &allowPopUpMenu );
        fscanf(optionFile, "%ld", &popUpMessageID );

        setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                           allowPopUpMenu, popUpMessageID );

        // read password for FileBar system administrator and tasks
        readString( optionFile, (CHAR*)&password );
        if (!password[0])
            strcpy( password, DEFAULTPASSWORD );

        for (i = 0; i < NumMenus; i++ )
            for (short j = 0; j < NumItems[i]; j++) {
                readString( optionFile, (CHAR*)&Menus[i][j]->Password );
                if (!Menus[i][j]->Password[0])
                    strcpy( Menus[i][j]->Password, DEFAULTPASSWORD );
                }

        fscanf( optionFile, "%d", &a );
        globalProtection = a % 256;

        readString( optionFile, (CHAR*)&tmpBuffer );
        for (i = 0; i < NumMenus; i++ )
            for (short j = 0; j < NumItems[i]; j++)
                fscanf( optionFile, "%c", &(Menus[i][j]->PasswordEnabled) );
        readString( optionFile, (CHAR*)&tmpBuffer );

        fclose( optionFile );
        }
}


////////////////////////////////////////////////////////////////////////////////
// writeOptionFile - will write the application state to the option file
////////////////////////////////////////////////////////////////////////////////
void writeOptionFile( void )
{
    SHORT currentMenu = 100;
    FILE *optionFile;

    //--------------------------------------------------------------------------
    // if the option file exists on disk, read it in and restore old menu,
    // otherwise we will return and rely on default values
    //--------------------------------------------------------------------------
    //if (settingsPath)
    //    optionFile = fopen(settingsPath, "wt");
    //else
    optionFile = fopen(OPTIONFILE, "wt");

    if (optionFile == NULL)
        // if not able to save, alert the user
        WinMessageBox( HWND_DESKTOP, hwndClient, MSG17,
                       0, 0, MB_MOVEABLE|MB_ERROR|MB_OK);
    else {
        ULONG length;
        RGB2 rgb;
        ALARMS* alarm;
        USERMENUITEM* menuItem;

        // save user's desired bar position
        //fprintf(optionFile, "%d %d\n", timeOption, BarPosition);
        // save user's menus and menu choices
        //fprintf(optionFile, "%d\n", NumMenus);
        fprintf(optionFile, "%d %d %d\n", timeOption, BarPosition, NumMenus);
        for (short i = 0; i < NumMenus; i++ ) {
            writeString( optionFile, (CHAR*)MenuName[i] );
            fprintf(optionFile, "%d\n", NumItems[i]);
            for (short j = 0; j < NumItems[i]; j++) {
                menuItem = Menus[i][j];
                writeString( optionFile, (CHAR*)menuItem->ItemName );
                writeString( optionFile, (CHAR*)menuItem->ActionToDo );
                writeString( optionFile, (CHAR*)menuItem->CmdLnArgs );
                writeString( optionFile, (CHAR*)menuItem->Directory );
                fprintf( optionFile, "%d\n", menuItem->ProgType );
                }
            currentMenu = currentMenu + 100;
            }

        if (WinQueryPresParam( hwndMenu, PP_FONTNAMESIZE, 0, &length, sizeof(tmpBuffer), tmpBuffer, 0)!=FALSE)
            writeString( optionFile, (CHAR*)tmpBuffer );
        else
            writeString( optionFile, "" );
            //fprintf( optionFile, "\"\"\n" );
        fprintf( optionFile, "%d %d %d %d\n", checkBeforeDelete, FileBarMenuOn, showBackground, backgroundAttr );
        writeString( optionFile, (CHAR*)backgroundBitmap );

        // save menu scheme of colors
        for (i=PP_FOREGROUNDCOLOR; i<=PP_BORDERCOLOR; i=i+2)
            if (WinQueryPresParam( hwndMenu, i, 0, 0, sizeof(rgb), &rgb, 0))
                fprintf(optionFile, "%ld\n", (ULONG)(rgb.bRed*65536+rgb.bGreen*256+rgb.bBlue) );
            else fprintf(optionFile, "%ld\n", NOCOLOR );

        for (i=PP_ACTIVECOLOR; i<=PP_INACTIVETEXTBGNDCOLOR; i=i+2)
            if (WinQueryPresParam( hwndMenu, i, 0, 0, sizeof(rgb), &rgb, 0))
                fprintf(optionFile, "%ld\n", (ULONG)(rgb.bRed*65536+rgb.bGreen*256+rgb.bBlue) );
            else fprintf(optionFile, "%ld\n", NOCOLOR );

        if (WinQueryPresParam( hwndMenu, PP_SHADOW, 0, 0, sizeof(rgb), &rgb, 0))
            fprintf(optionFile, "%ld\n", (ULONG)(rgb.bRed*65536+rgb.bGreen*256+rgb.bBlue) );
        else fprintf(optionFile, "%ld\n", NOCOLOR );

        for (i=PP_MENUFOREGROUNDCOLOR; i<=PP_MENUDISABLEDBGNDCOLOR; i=i+2)
            if (WinQueryPresParam( hwndMenu, i, 0, 0, sizeof(rgb), &rgb, 0))
                fprintf(optionFile, "%ld\n", (ULONG)(rgb.bRed*65536+rgb.bGreen*256+rgb.bBlue) );
            else fprintf(optionFile, "%ld\n", NOCOLOR );

        fprintf(optionFile, "%d\n%d\n", DoStartUpList, numStartItems );
        for (i=0; i<numStartItems; i++)
            fprintf(optionFile, "%d\n%d\n", StartUpMenu[i], StartUpItem[i] );

        fprintf(optionFile, "%d\n", HourlyChime );
        writeString( optionFile, (CHAR*)hourlyChimeWavFile );

        // save current task scheduler items
        fprintf(optionFile, "%d %d %d %d\n", maximizeDesktop, repeatTime, interceptMsg, numAlarms );
        for (i=0; i<numAlarms; i++) {
            alarm = alarmPtr[i];
            fprintf(optionFile, "%d %d %d %d %d %d\n", alarm->AlarmHour,
                                                       alarm->AlarmMinute,
                                                       alarm->AlarmMonth,
                                                       alarm->AlarmDay,
                                                       alarm->AlarmYear,
                                                       alarm->options );
            writeString( optionFile, (CHAR*)alarm->ActionToDo );
            writeString( optionFile, (CHAR*)alarm->ReminderWAV );
            }
        fprintf( optionFile, "%d %d\n", hideFileBar, allowPopUpMenu );
        fprintf( optionFile, "%ld\n", popUpMessageID );

        writeString( optionFile, (CHAR*)password );
        for (i = 0; i < NumMenus; i++ )
            for (short j = 0; j < NumItems[i]; j++)
                writeString( optionFile, (CHAR*)Menus[i][j]->Password );
        fprintf( optionFile, "%d\n", globalProtection );

        writeString( optionFile, "" );
        for (i = 0; i < NumMenus; i++ )
            for (short j = 0; j < NumItems[i]; j++)
                fprintf( optionFile, "%c", Menus[i][j]->PasswordEnabled );
        writeString( optionFile, "" );

        fclose( optionFile );
        }
}


////////////////////////////////////////////////////////////////////////////////
// readString will read a sequence of characters that is bounded on both sides
// by quote (") characters (We can't use fscanf because it won't read spaces)
////////////////////////////////////////////////////////////////////////////////
VOID readString( FILE* stream, CHAR* buffer )
{
    if (stringTerminator)
        do                                       // search for first " character
          if (fscanf( stream, "%c", buffer)==EOF) break;
          while ( (*buffer) != stringTerminator);
    else {
        do                                       // search for first " character
          if (fscanf( stream, "%c", buffer)==EOF) break;
          while ( ((*buffer) !='\"') && ((*buffer) != TERMCHAR) );
        stringTerminator= (*buffer);
        }
    buffer--;
    do {                               // keep putting characters into the buffer
        buffer++;                      // " character
        if (fscanf( stream, "%c", buffer)==EOF) break;
    } while ( (*buffer) != stringTerminator);
    *buffer = '\0';                    // store a NULL to terminate the string
}


////////////////////////////////////////////////////////////////////////////////
// Message handler for a generic information-only dialog box (help & prod info)
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY GenericProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            WinDismissDlg( hWnd, TRUE );
            return 0;
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            break;
    }
    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
}


////////////////////////////////////////////////////////////////////////////////
// starts or restarts a timer to signal our program when the next minute occurs
////////////////////////////////////////////////////////////////////////////////
VOID restartTimer( VOID )
{
    struct tm *time_now;
    time_t currentTime;

    tzset();
    time(&currentTime);
    time_now = localtime( &currentTime );
    timeSync = FALSE;

    timerNumber = WinStartTimer( hab, hwndClient, TIMERID, (60-(time_now->tm_sec))*1000);
}


////////////////////////////////////////////////////////////////////////////////
// ringChime - play a .WAV file sent to us as the parameter.
////////////////////////////////////////////////////////////////////////////////
VOID ringChime( CHAR* soundFile )
{
    APIRET rc;
    char mesg[MAXPATH+384];
    RXSTRING  INSTORE[2];
    RXSTRING  retstr;
    SHORT ReturnCode;
    LONG offset = 0;

    if (soundFile == 0)
        return;
    if (soundFile[0] == 0) {
        WinAlarm( HWND_DESKTOP, WA_NOTE );
        return;
        }

    MakeHourglassPointer ();                       // switch to hourglass cursor
    offset = offset + sprintf(mesg+offset, "/* */\r\n");
    offset = offset + sprintf(mesg+offset, "rc = call RxFuncAdd('mciRxInit','MCIAPI',,\r\n'mciRxInit')\r\n");
    offset = offset + sprintf(mesg+offset, "rc = call mciRxInit()\r\n");
    offset = offset + sprintf(mesg+offset, "rc = mciRxSendString('open waveaudio',\r\n'alias wave shareable wait',,\r\n'RetStr','0','0')\r\n");
    offset = offset + sprintf(mesg+offset, "rc = mciRxSendString('load wave %s wait',,\r\n'RetStr','0','0')\r\n", soundFile );
    offset = offset + sprintf(mesg+offset, "rc = mciRxSendString('play wave wait',,\r\n'RetStr','0','0')\r\n" );
    offset = offset + sprintf(mesg+offset, "rc = mciRxSendString('close wave wait',,\r\n'RetStr','0','0')\r\n" );
    offset = offset + sprintf(mesg+offset, "call mciRxExit\r\n" );
    sprintf(mesg+offset, "exit\r\n\x1A\0" );

    INSTORE[0].strptr=mesg;
    INSTORE[0].strlength=strlen(mesg);
    INSTORE[1].strptr=NULL;
    INSTORE[1].strlength=0;

    rc = rexxStart((LONG)0,
              (PRXSTRING)0,
              (PSZ)LAUNCHFILE,
              (PRXSTRING)INSTORE,
              (PSZ)"CMD",
              (LONG)RXCOMMAND,
              (PRXSYSEXIT)0,
              (SHORT*)&ReturnCode,
              (PRXSTRING)&retstr);

    // if there was an error (ie: no MMPM), make a system beep
    if (rc)
        WinAlarm( HWND_DESKTOP, WA_NOTE );

    MakeArrowPointer ();                      // switch back to arrow pointer,
}


////////////////////////////////////////////////////////////////////////////////
// update the time displayed on the FileBar menubar
////////////////////////////////////////////////////////////////////////////////
VOID updateTimeDisplay( HWND window ) {
    char tmp1[24];
    char tmp2[24];
    CHAR buffer[64] = { '\0' };
    struct tm *time_now;
    time_t currentTime;

    tzset();
    time(&currentTime);
    time_now = localtime( &currentTime );

    if ((timeOption == TIMEONLY) || (timeOption == TIMEANDDATE)) {
        strftime( tmp1, sizeof(tmp1), "%I", time_now);
        strftime( tmp2, sizeof(tmp2), ":%M %p  ", time_now);
        if (tmp1[0] == '0')
            tmp1[0]=' ';
        strcat( buffer, tmp1 );
        strcat( buffer, tmp2 );
        }
    if (timeOption == TIMEANDDATE)
        strcat( buffer, " " );
    if ((timeOption == DATEONLY) || (timeOption == TIMEANDDATE)) {
        strftime( tmp1, sizeof(tmp1), "%B", time_now);
        strftime( tmp2, sizeof(tmp2), "%d, %Y  ", time_now);

        if (tmp2[0] == '0') {
            tmp2[0] = ' ';
            strcat( buffer, tmp1 );
            strcat( buffer, tmp2 );
            }
        else {
            strcat( buffer, tmp1 );
            strcat( buffer, " \0" );
            strcat( buffer, tmp2 );
            }
        }
    else if (timeOption == OTHERTIMEONLY)
        strftime( buffer, sizeof(buffer), "%H:%M  ", time_now);
    else if (timeOption == OTHERDATEONLY)
        strftime( buffer, sizeof(buffer), "%d %B %Y  ", time_now);
    else if (timeOption == OTHERTIMEANDDATE) {
        strftime( tmp1, sizeof(tmp1), "%H:%M ", time_now );
        strftime( tmp2, sizeof(tmp2), "%d %B %Y  ", time_now );
        if (tmp1[0] == '0')
            tmp1[0] = ' ';
        if (tmp2[0] == '0')
            tmp2[0] = ' ';
        else
            strcat( tmp1, " " );
        strcat( buffer, tmp1 );
        strcat( buffer, tmp2 );
        }
    if (buffer[0]=='0')
        buffer[0]=' ';

    WinSetMenuItemText( window, TIMEDATE, &buffer );
}


////////////////////////////////////////////////////////////////////////////////
// displayTimeDate is used to check to see if time/date on the FileBar menu
// needs updateing and also to check to see if any alarms need to be serviced
////////////////////////////////////////////////////////////////////////////////
VOID displayTimeDate( VOID )
{
    struct tm *time_now;
    time_t currentTime;

    tzset();
    time(&currentTime);
    time_now = localtime( &currentTime );


    if (timeOption != NONE)
        if (((timeOption != DATEONLY) && (timeOption != OTHERDATEONLY)) ||
             (time_now->tm_min == 0) )
            updateTimeDisplay( hwndMenu );

    if (time_now->tm_min == 30)
        alreadyChimed = FALSE;

    if ((!alreadyChimed) && (time_now->tm_min == 0) && (HourlyChime)) {
        alreadyChimed = TRUE;
        ringChime( hourlyChimeWavFile );
        }

    checkAlarms( time_now->tm_hour, time_now->tm_min, time_now->tm_mon,
                 time_now->tm_mday, time_now->tm_year );
}


////////////////////////////////////////////////////////////////////////////////
// resets the file dialog control structure so its OK to use next time
////////////////////////////////////////////////////////////////////////////////
VOID resetFileDialog( VOID )
{
    SHORT s;

    s=strlen(fileDlgInfo.szFullFile);
    while((fileDlgInfo.szFullFile[s]!='\\') && (s>=0))
        s--;

    if (fileDlgInfo.szFullFile[s]=='\\')
        fileDlgInfo.szFullFile[s+1]='\0';
    else
        fileDlgInfo.szFullFile[0]='\0';
}

////////////////////////////////////////////////////////////////////////////////
// Message handler for time and date option setting dialog
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY TimeDateProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop and check
        // the appropriate radio button for whatever setting they currently have
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;

            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            WinSendDlgItemMsg( hWnd, timeOption, BM_SETCHECK,
                               MPFROM2SHORT( 1, 0 ), 0);
            WinCheckButton( hWnd, PLAYCHIME, HourlyChime );

            WinSendDlgItemMsg( hWnd, CHIMEWAVFILE, EM_SETTEXTLIMIT,
                               MPFROM2SHORT( MAXACTIONSTRINGLENGTH-1, 0 ), 0 );
            WinSetDlgItemText( hWnd, CHIMEWAVFILE, hourlyChimeWavFile);

            break;
            }
        //----------------------------------------------------------------------
        // we received a change in control, update menubar time
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            timeOption = NONE;
            if (WinQueryButtonCheckstate( hWnd, TIMEONLY ))
                timeOption = TIMEONLY;
            else if (WinQueryButtonCheckstate( hWnd, DATEONLY ))
                timeOption = DATEONLY;
            else if (WinQueryButtonCheckstate( hWnd, TIMEANDDATE ))
                timeOption = TIMEANDDATE;
            else if (WinQueryButtonCheckstate( hWnd, OTHERTIMEONLY ))
                timeOption = OTHERTIMEONLY;
            else if (WinQueryButtonCheckstate( hWnd, OTHERDATEONLY ))
                timeOption = OTHERDATEONLY;
            else if (WinQueryButtonCheckstate( hWnd, OTHERTIMEANDDATE ))
                timeOption = OTHERTIMEANDDATE;

            WinStopTimer( hab, hwndClient, timerNumber );
            restartTimer();
            updateTimeDisplay( hwndMenu );
            break;
        }

        //----------------------------------------------------------------------
        // if we receive any system message, dismiss dialog and store new option
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command ) {
            case TESTWAVEFILE: {
                WinQueryDlgItemText( hWnd, CHIMEWAVFILE, sizeof(hourlyChimeWavFile), hourlyChimeWavFile);
                ringChime( hourlyChimeWavFile );
                return 0;
                }
            case FINDWAVFILE: {
                CHAR title[] = MSG18;
                HWND hwndDialog;

                fileDlgInfo.fl = FDS_OPEN_DIALOG|FDS_CENTER;
                fileDlgInfo.pszTitle = title;

                strcpy(oldDirectory, fileDlgInfo.szFullFile);
                strcat(fileDlgInfo.szFullFile, "*.WAV\0");

                hwndDialog = WinFileDlg( HWND_DESKTOP, hWnd, &fileDlgInfo );
                if (hwndDialog && (fileDlgInfo.lReturn == DID_OK)) {
                    strcpy( hourlyChimeWavFile, fileDlgInfo.szFullFile );
                    resetFileDialog();
                    WinSetDlgItemText( hWnd, CHIMEWAVFILE, hourlyChimeWavFile );
                    }
                else
                    strcpy(fileDlgInfo.szFullFile, oldDirectory);
                return 0;
                }
            }

            timeOption = NONE;
            if (WinQueryButtonCheckstate( hWnd, TIMEONLY ))
                timeOption = TIMEONLY;
            else if (WinQueryButtonCheckstate( hWnd, DATEONLY ))
                timeOption = DATEONLY;
            else if (WinQueryButtonCheckstate( hWnd, TIMEANDDATE ))
                timeOption = TIMEANDDATE;
            else if (WinQueryButtonCheckstate( hWnd, OTHERTIMEONLY ))
                timeOption = OTHERTIMEONLY;
            else if (WinQueryButtonCheckstate( hWnd, OTHERDATEONLY ))
                timeOption = OTHERDATEONLY;
            else if (WinQueryButtonCheckstate( hWnd, OTHERTIMEANDDATE ))
                timeOption = OTHERTIMEANDDATE;

            HourlyChime = WinQueryButtonCheckstate( hWnd, PLAYCHIME );

            // stop current timer (if one exists) and start a new one
            // display new time and date according to new option setting
            WinStopTimer( hab, hwndClient, timerNumber );
            restartTimer();
            WinQueryDlgItemText( hWnd, CHIMEWAVFILE, sizeof(hourlyChimeWavFile), hourlyChimeWavFile);
            WinDismissDlg( hWnd, TRUE );
            return 0;
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            break;
    }
    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
}


////////////////////////////////////////////////////////////////////////////////
// EditMenuProc - the message handler for editing a menu dialog box
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY EditMenuProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    switch( msg )
    {
        //----------------------------------------------------------------------
        // if double-clicked an entry, allow them to edit it
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if ((SHORT1FROMMP(mp1)==CURMENULIST) && (SHORT2FROMMP(mp1)==LN_ENTER))
                return WinSendMsg( hWnd, WM_COMMAND, MPFROM2SHORT( EDITMENUBUTTON, 0 ), mp2 );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop and put
        // the current data into appropriate list boxes
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;

            for (short i=0; i<NumMenus; i++)
                WinSendDlgItemMsg( hWnd, CURMENULIST, LM_INSERTITEM,
                                   MPFROM2SHORT( LIT_END, 0 ),
                                   MenuName[i] );
            if (NumMenus > 0) {
                WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                   MPFROM2SHORT( 0, 0 ),
                                   MPFROM2SHORT( TRUE, 0 ) );
                }
            else {
                WinEnableControl( hWnd, EDITMENUBUTTON, FALSE );
                WinEnableControl( hWnd, REMOVEMENU, FALSE );
                WinEnableControl( hWnd, MOVEMENULEFT, FALSE );
                WinEnableControl( hWnd, MOVEMENURIGHT, FALSE );
                }
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // process a command message received from the system
        //----------------------------------------------------------------------
        case WM_COMMAND: {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                // if they pressed OK button, dismiss dialog and return
                //--------------------------------------------------------------
                case DID_OK: {
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // they want to edit a menu
                //--------------------------------------------------------------
                case EDITMENUBUTTON: {
                    if (NumMenus == 0) {
                        WinAlarm(HWND_DESKTOP, WA_ERROR);
                        return 0;
                        }
                    // find out what menu they've selected in list box
                    MenuSelection = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, CURMENULIST,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    // display edit menu dialog box
                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)EditItemProc,
                              0,
                              EDITITEM,
                              (PVOID)NULL);
                    // change the item in the list box and select it
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_DELETEALL, 0, 0 );
                    for (short i=0; i<NumMenus; i++)
                        WinSendDlgItemMsg( hWnd, CURMENULIST, LM_INSERTITEM,
                                           MPFROM2SHORT( LIT_END, 0 ),
                                           MenuName[i] );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                       MPFROM2SHORT( MenuSelection, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    return 0;
                    }
                //--------------------------------------------------------------
                // the user wants to add another menu to the menubar
                //--------------------------------------------------------------
                case ADDMENU: {
                    MenuSelection = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, CURMENULIST,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    // error if no room for another menu
                    if (NumMenus >= MAXMENUS) {
                        WinMessageBox( HWND_DESKTOP, hWnd,
                                       MSG19, MSG20, 0,
                                       MB_MOVEABLE|MB_ERROR|MB_OK);
                        return 0;
                        }
                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)AddAMenuProc,
                              0,
                              ADDAMENU,
                              (PVOID)NULL);
                    // if first menu to be added, enable buttons
                    if (NumMenus > 0) {
                        WinEnableControl( hWnd, EDITMENUBUTTON, TRUE );
                        WinEnableControl( hWnd, REMOVEMENU, TRUE );
                        WinEnableControl( hWnd, MOVEMENULEFT, TRUE );
                        WinEnableControl( hWnd, MOVEMENURIGHT, TRUE );
                        }

                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_DELETEALL, 0, 0 );
                    for (short i=0; i<NumMenus; i++)
                        WinSendDlgItemMsg( hWnd, CURMENULIST, LM_INSERTITEM,
                                           MPFROM2SHORT( LIT_END, 0 ),
                                           MenuName[i] );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                       MPFROM2SHORT( MenuSelection, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    return 0;
                    }
                //--------------------------------------------------------------
                // the user wants to remove a menu from the menu list box
                //--------------------------------------------------------------
                case REMOVEMENU: {
                    if (NumMenus == 0) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }

                    if (NumMenus > 0)
                        if (WinMessageBox( HWND_DESKTOP, hWnd,
                                           MSG21,
                                           MSG22, 0,
                                           MB_MOVEABLE|MB_WARNING|MB_YESNO|MB_DEFBUTTON2) == MBID_YES ) {
                            short index = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, CURMENULIST,
                                                                           LM_QUERYSELECTION,
                                                                           MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                           0 ) );
                            MENUITEM menuItem;

                            // delete it from the list box
                            WinSendDlgItemMsg( hWnd, CURMENULIST, LM_DELETEITEM,
                                               MPFROM2SHORT( index, 0 ), 0 );

                            // delete it from menu structure
                            MakeHourglassPointer ();
                            WinSetMenuItemText( hwndMenu, 100*index+100, "" );
                            for (short i=index+1; i<MAXMENUS; i++)
                                SwapTwoMenus( i-1, i );

                            ////////////////////////////////////////////////////
                            for (i=0; i<NumItems[MAXMENUS-1]; i++)
                                delete Menus[MAXMENUS-1][i];
                            ////////////////////////////////////////////////////
                            NumItems[MAXMENUS-1] = 0;
                            MenuName[MAXMENUS-1][0] = '\0';
                            if (NumMenus > 0) {
                                int newIndex = index-1;
                                if (0 > newIndex)
                                    newIndex = 0;

                                if (index == NumMenus-1)
                                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                                       MPFROM2SHORT( newIndex, 0 ),
                                                       MPFROM2SHORT( TRUE, 0 ) );
                                else
                                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                                       MPFROM2SHORT( index, 0 ),
                                                       MPFROM2SHORT( TRUE, 0 ) );
                                }
                            WinSendMsg( hwndMenu, MM_QUERYITEM, MPFROM2SHORT(NumMenus*100,TRUE),MPFROMP(&menuData[index]));
                            menuItem = menuData[index];
                            menuItem.afStyle = MIS_STATIC;
                            menuItem.afAttribute = MIA_DISABLED;
                            WinSendMsg( hwndMenu, MM_SETITEM, MPFROM2SHORT(NumMenus*100,TRUE),MPFROMP(&menuItem));
                            WinSetMenuItemText( hwndMenu, 100*MAXMENUS, "" );
                            NumItems[ NumMenus ] = 0;
                            NumMenus--;

                            // if we deleted only menu, disable menu buttons
                            if (NumMenus == 0) {
                                WinEnableControl( hWnd, EDITMENUBUTTON, FALSE );
                                WinEnableControl( hWnd, REMOVEMENU, FALSE );
                                WinEnableControl( hWnd, MOVEMENULEFT, FALSE );
                                WinEnableControl( hWnd, MOVEMENURIGHT, FALSE );
                                }
                            MakeArrowPointer ();
                            }
                    return 0;
                    }
                //--------------------------------------------------------------
                // move menu left in menu structure
                //--------------------------------------------------------------
                case MOVEMENULEFT: {
                    short index = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, CURMENULIST,
                                                             LM_QUERYSELECTION,
                                                             MPFROM2SHORT( LIT_FIRST, 0 ),
                                                             0 ) );
                    if ((NumMenus == 0) || (index == 0)) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }
                    MakeHourglassPointer ();
                    SwapTwoMenus( index-1, index );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_DELETEITEM,
                                       MPFROM2SHORT( index, 0 ), 0 );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_INSERTITEM,
                                       MPFROM2SHORT( index-1, 0 ), MenuName[index-1] );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                       MPFROM2SHORT( index-1, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    MakeArrowPointer ();
                    return 0;
                    }
                //--------------------------------------------------------------
                // move menu right in menu structure
                //--------------------------------------------------------------
                case MOVEMENURIGHT: {
                    short index = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, CURMENULIST,
                                                             LM_QUERYSELECTION,
                                                             MPFROM2SHORT( LIT_FIRST, 0 ),
                                                             0 ) );
                    if ((NumMenus == 0) || (index == (NumMenus)-1)) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }
                    SwapTwoMenus( index, index+1 );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_DELETEITEM,
                                       MPFROM2SHORT( index, 0 ), 0 );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_INSERTITEM,
                                       MPFROM2SHORT( index+1, 0 ), MenuName[index+1] );
                    WinSendDlgItemMsg( hWnd, CURMENULIST, LM_SELECTITEM,
                                       MPFROM2SHORT( index+1, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    return 0;
                    }
                //--------------------------------------------------------------
                // nothing we care about, pass it onto the system default proc
                //--------------------------------------------------------------
                default:
                    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
                }
            }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
// SwapTwoMenus will swap the FileBar stored information entries for two menus
// indicated by menu1 and menu2.  The text on the displayed menubar will also
// be changed to indicate the swap.
////////////////////////////////////////////////////////////////////////////////
void SwapTwoMenus( short menu1, short menu2 )
{
    USERMENUITEM* tmpPtr;
    BYTE t2;

    for (short i=0; i<MAXITEMS; i++) {
        tmpPtr = Menus[menu1][i];
        Menus[menu1][i] = Menus[menu2][i];
        Menus[menu2][i] = tmpPtr;
        }

    t2 = NumItems[menu2];
    NumItems[menu2] = NumItems[menu1];
    NumItems[menu1] = t2;

    strcpy( tmpBuffer, MenuName[menu1] );
    strcpy( MenuName[menu1], MenuName[menu2] );
    strcpy( MenuName[menu2], tmpBuffer );

    WinSetMenuItemText( hwndMenu, 100+menu1*100, MenuName[menu1] );
    WinSetMenuItemText( hwndMenu, 100+menu2*100, MenuName[menu2] );
}


////////////////////////////////////////////////////////////////////////////////
// AddAMenuProc - message handler for the dialog box that allows the user to
// add a menu to the menubar
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY AddAMenuProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop and put
        // the current data into controls
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinSendDlgItemMsg( hWnd, MENUNAME, EM_SETTEXTLIMIT,
                               MPFROM2SHORT( MAXMENUNAMELENGTH-1, 0 ), 0 );
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            break;
//            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // process a command message received from the system
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                // user press OK button.  Add the menu name they entered into
                // the menu structure and return
                //--------------------------------------------------------------
                case DID_OK: {
                    WinQueryDlgItemText( hWnd, MENUNAME, MAXMENUNAMELENGTH, MenuName[NumMenus]);
                    NumItems[NumMenus] = 0;
                    menuData[NumMenus].afStyle = 0;
                    menuData[NumMenus].afAttribute = 0;
                    WinSendMsg( hwndMenu, MM_SETITEM, MPFROM2SHORT(100*NumMenus+100,TRUE),MPFROMP(&menuData[NumMenus]));
                    WinSetMenuItemText( hwndMenu, 100*NumMenus+100, &MenuName[NumMenus]);
                    MenuSelection = NumMenus;
                    NumMenus++;
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // they decided not to add a menu, dismiss dialog and return
                //--------------------------------------------------------------
                case DID_CANCEL: {
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // nothing we care about, pass on for default processing
                //--------------------------------------------------------------
                default:
                    break;
                }
        }
        // ---------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        // ---------------------------------------------------------------------
        default:
            break;
    }
    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
}


////////////////////////////////////////////////////////////////////////////////
// Swap menu items item1 and item2 on menu Menu in the menu information arrays
////////////////////////////////////////////////////////////////////////////////
VOID SwapTwoItems(SHORT Menu, SHORT item1, SHORT item2)
{
    USERMENUITEM* tmpPtr;

    tmpPtr = Menus[Menu][item1];
    Menus[Menu][item1] = Menus[Menu][item2];
    Menus[Menu][item2] = tmpPtr;
}


////////////////////////////////////////////////////////////////////////////////
// updateItemList - refreshes the contents of the item list list-box in a dialog
////////////////////////////////////////////////////////////////////////////////
VOID updateItemList( HWND hWnd )
{
    CHAR Separator[] = SEPARATOR;
    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_DELETEALL, 0, 0 );
    for (short i=0; i<NumItems[MenuSelection]; i++)
        if (Menus[MenuSelection][i]->ItemName[0] != '\0')
            WinSendDlgItemMsg( hWnd, ITEMMENU, LM_INSERTITEM,
                               MPFROM2SHORT( LIT_END, 0 ),
                               Menus[MenuSelection][i]->ItemName );
        else
            WinSendDlgItemMsg( hWnd, ITEMMENU, LM_INSERTITEM,
                               MPFROM2SHORT( LIT_END, 0 ),
                               Separator );
    if (NumItems[MenuSelection] > 0)
        WinSendDlgItemMsg( hWnd, ITEMMENU, LM_SELECTITEM,
                           MPFROM2SHORT( ItemSelection, 0 ),
                           MPFROM2SHORT( TRUE, 0 ) );
}


////////////////////////////////////////////////////////////////////////////////
// EditItemProc - the message handler for the edit menu item dialog box
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY EditItemProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop and put
        // the current data into control fields
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinSendDlgItemMsg( hWnd, MENUNAME, EM_SETTEXTLIMIT,
                               MPFROM2SHORT( MAXMENUNAMELENGTH-1, 0 ), 0 );
            WinSetDlgItemText( hWnd, MENUNAME, MenuName[MenuSelection]);
            ItemSelection = 0;
            updateItemList( hWnd );
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            break;
//            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // if there is a control message, update enabled status of buttons
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if ((SHORT1FROMMP(mp1)==ITEMMENU) && (SHORT2FROMMP(mp1)==LN_ENTER))
                return WinSendMsg( hWnd, WM_COMMAND, MPFROM2SHORT( CHANGEITEM, 0 ), mp2 );
            break;
//            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // process a command message received from the system
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                // insert a separator into item list, if there is room
                //--------------------------------------------------------------
                case INSERTSEPARATOR: {
                    ItemSelection = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, ITEMMENU,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    if (NumItems[MenuSelection] >= MAXITEMS-1) {
                        // error and return if no room
                        WinMessageBox( HWND_DESKTOP, hWnd,
                                       MSG23, MSG24, 0,
                                       MB_MOVEABLE|MB_ERROR|MB_OK);
                        return 0;
                        }

                    // since this is a separator, blank out launch information
                    ItemSelection = 0;
                    if (NumItems[MenuSelection] > 0)
                        for (short i=NumItems[MenuSelection]-1; i>=0; i--)
                            SwapTwoItems( MenuSelection, i, i+1 );

                    Menus[MenuSelection][ItemSelection] = new USERMENUITEM;
                    Menus[MenuSelection][ItemSelection]->ItemName[0]='\0';
                    NumItems[MenuSelection]++;
//                    UpdateMenu[MenuSelection] = TRUE;
                    updateItemList( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // user wants to add an item to the current menu
                //--------------------------------------------------------------
                case ADDITEM: {
                    ItemSelection = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, ITEMMENU,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    // error and return if no room for another item
                    if (NumItems[MenuSelection] >= MAXITEMS) {
                        WinMessageBox( HWND_DESKTOP, hWnd,
                                       MSG25,
                                       MSG26, 0,
                                       MB_MOVEABLE|MB_ERROR|MB_OK);
                        return 0;
                        }
                    // get new item via add item dialog box
                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)AddAnItemProc,
                              0,
                              ADDANITEM,
                              (PVOID)NULL);
                    // update item list with possible new item
                    updateItemList( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // user wants to change a menu item
                //--------------------------------------------------------------
                case CHANGEITEM: {
                    ItemSelection = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, ITEMMENU,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    if ((NumItems[MenuSelection] == 0) || (Menus[MenuSelection][ItemSelection]->ItemName[0] == '\0')) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }
                    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, FALSE,
                                      allowPopUpMenu, popUpMessageID );
                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)EditItemDataProc,
                              0,
                              EDITITEMDATA,
                              (PVOID)NULL);
                    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                                      allowPopUpMenu, popUpMessageID );
                    updateItemList( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // move item down in menu order
                //--------------------------------------------------------------
                case MOVEITEMDOWN: {
                    CHAR Separator[] = SEPARATOR;
                    short i = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, ITEMMENU,
                                                               LM_QUERYSELECTION,
                                                               MPFROM2SHORT( LIT_FIRST, 0 ),
                                                               0 ) );
                    if ((i == NumItems[MenuSelection]-1) || (NumItems[MenuSelection] == 0)) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }
                    SwapTwoItems( MenuSelection, i, i+1 );
                    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_DELETEITEM,
                                       MPFROM2SHORT( i, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    if (Menus[MenuSelection][i+1]->ItemName[0] == '\0')
                        WinSendDlgItemMsg( hWnd, ITEMMENU, LM_INSERTITEM,
                                           MPFROM2SHORT( i+1, 0 ),
                                           Separator );
                    else WinSendDlgItemMsg( hWnd, ITEMMENU, LM_INSERTITEM,
                                            MPFROM2SHORT( i+1, 0 ),
                                            &Menus[MenuSelection][i+1]->ItemName );
                    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_SELECTITEM,
                                       MPFROM2SHORT( i+1, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    return 0;
                    }
                //--------------------------------------------------------------
                // move item up in menu order
                //--------------------------------------------------------------
                case MOVEITEMUP: {
                    CHAR Separator[] = SEPARATOR;
                    short i = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, ITEMMENU,
                                                               LM_QUERYSELECTION,
                                                               MPFROM2SHORT( LIT_FIRST, 0 ),
                                                               0 ) );
                    if ((i == 0) || (NumItems[MenuSelection] == 0)) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }
                    SwapTwoItems( MenuSelection, i-1, i );
                    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_DELETEITEM,
                                       MPFROM2SHORT( i, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    if (Menus[MenuSelection][i-1]->ItemName[0] == '\0')
                        WinSendDlgItemMsg( hWnd, ITEMMENU, LM_INSERTITEM,
                                           MPFROM2SHORT( i-1, 0 ),
                                           Separator );
                    else WinSendDlgItemMsg( hWnd, ITEMMENU, LM_INSERTITEM,
                                            MPFROM2SHORT( i-1, 0 ),
                                            &Menus[MenuSelection][i-1]->ItemName );
                    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_SELECTITEM,
                                       MPFROM2SHORT( i-1, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                    return 0;
                    }
                //--------------------------------------------------------------
                // remove a menu item
                //--------------------------------------------------------------
                case REMOVEITEM: {
                    if (NumItems[MenuSelection] == 0) {
                        WinAlarm(HWND_DESKTOP, WA_WARNING);
                        return 0;
                        }

                    if (NumItems[MenuSelection] > 0)
                        if (WinMessageBox( HWND_DESKTOP, hWnd,
                                           MSG27,
                                           MSG28, 0,
                                           MB_MOVEABLE|MB_WARNING|MB_YESNO|MB_DEFBUTTON2) == MBID_YES ) {
                            short index = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, ITEMMENU,
                                                                           LM_QUERYSELECTION,
                                                                           MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                           0 ) );
                            WinSendDlgItemMsg( hWnd, ITEMMENU, LM_DELETEITEM,
                                               MPFROM2SHORT( index, 0 ), 0 );

                            delete Menus[MenuSelection][index];
                            for (short i=index; i<MAXITEMS-1; i++)
                                Menus[MenuSelection][i] = Menus[MenuSelection][i+1];

                            if (NumItems[MenuSelection] > 0) {
                                int newIndex = index-1;
                                if (0 > newIndex)
                                    newIndex = 0;

                                if (index == NumItems[MenuSelection]-1)
                                    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_SELECTITEM,
                                                       MPFROM2SHORT( newIndex, 0 ),
                                                       MPFROM2SHORT( TRUE, 0 ) );
                                else
                                    WinSendDlgItemMsg( hWnd, ITEMMENU, LM_SELECTITEM,
                                                       MPFROM2SHORT( index, 0 ),
                                                       MPFROM2SHORT( TRUE, 0 ) );
                                }
                            NumItems[MenuSelection]--;
                            }
                    return 0;
                    }
                //--------------------------------------------------------------
                // user is done editing a menu, save menu name and return
                //--------------------------------------------------------------
                case DID_OK: {
                    WinQueryDlgItemText( hWnd, MENUNAME, MAXMENUNAMELENGTH, MenuName[MenuSelection]);
                    WinSetMenuItemText( hwndMenu, 100*MenuSelection+100, &MenuName[MenuSelection]);
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // not a message we care about, pass it onto the system
                //--------------------------------------------------------------
                default:
                    break;
//                    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
                }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
           break;
//           return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
}


////////////////////////////////////////////////////////////////////////////////
// update the enable/disabled state of the program type buttons
////////////////////////////////////////////////////////////////////////////////
void updateEditItemWindow( HWND hWnd )
{
    SHORT value = TRUE;

    if (WinQueryButtonCheckstate( hWnd, STARTWPS ))
        value = FALSE;

    WinEnableControl( hWnd, MAXIMIZED, value );
    WinEnableControl( hWnd, MINIMIZED, value );
    WinEnableControl( hWnd, FOLDER, value );
    WinEnableControl( hWnd, DOSWIN, value );
    WinEnableControl( hWnd, DOSFS, value );
    WinEnableControl( hWnd, OS2WIN, value );
    WinEnableControl( hWnd, OS2FS, value );
    WinEnableControl( hWnd, WINOS2WIN, value );
    WinEnableControl( hWnd, WINOS2FS, value );
    WinEnableControl( hWnd, PMAPP, value );
    WinEnableControl( hWnd, SETTINGSBUTTON, TRUE-value );

    if (WinQueryButtonCheckstate( hWnd, FOLDER )) {
        WinEnableControl( hWnd, MAXIMIZED, FALSE );
        WinEnableControl( hWnd, MINIMIZED, FALSE );
        }

    if ((WinQueryButtonCheckstate( hWnd, FOLDER )) || (WinQueryButtonCheckstate( hWnd, PMAPP )))
        WinEnableControl( hWnd, STARTWPS, FALSE );
    else
        WinEnableControl( hWnd, STARTWPS, TRUE );

    if (Menus[MenuSelection][ItemSelection]->ActionToDo[0]=='\0')
        WinEnableControl( hWnd, SETTINGSBUTTON, FALSE );
}


////////////////////////////////////////////////////////////////////////////////
// updateEditItemData - update the check states of all the buttons for the
// program item we are currently editing
////////////////////////////////////////////////////////////////////////////////
void updateEditItemData( HWND hWnd )
{
    // put item name and length of longest possible name in entry field
    USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];

    if ( Menus[MenuSelection][ItemSelection]->PasswordEnabled == YES )
        WinCheckButton( hWnd, PASSWORDPROTECT, TRUE );
    else WinCheckButton( hWnd, PASSWORDPROTECT, FALSE );

    WinSendDlgItemMsg( hWnd, ITEMNAME, EM_SETTEXTLIMIT,
                       MPFROM2SHORT( MAXITEMNAMELENGTH-1, 0 ), 0 );
    WinSetDlgItemText( hWnd, ITEMNAME, menuItem->ItemName);
    // put path name and length of longest possible name in entry field
    WinSendDlgItemMsg( hWnd, PATHNAME, EM_SETTEXTLIMIT,
                       MPFROM2SHORT( MAXACTIONSTRINGLENGTH-1, 0 ), 0 );
    WinSetDlgItemText( hWnd, PATHNAME, menuItem->ActionToDo);
    // put argument and length of longest possible in entry field
    WinSendDlgItemMsg( hWnd, ARGUMENTS, EM_SETTEXTLIMIT,
                       MPFROM2SHORT( MAXARGSTRINGLENGTH-1, 0 ), 0 );
    WinSetDlgItemText( hWnd, ARGUMENTS, menuItem->CmdLnArgs);
    // put directory and length of longest possible directory in entry field
    WinSendDlgItemMsg( hWnd, DIRECTORY, EM_SETTEXTLIMIT,
                       MPFROM2SHORT( MAXDIRSTRINGLENGTH-1, 0 ), 0 );
    WinSetDlgItemText( hWnd, DIRECTORY, menuItem->Directory);
    // set appropriate radio button for program startup option
    WinCheckButton( hWnd, MAXIMIZED, FALSE );
    WinCheckButton( hWnd, MINIMIZED, FALSE );
    SHORT ProgType = menuItem->ProgType;
    if (ProgType & STARTMAX)
        WinCheckButton( hWnd, MAXIMIZED, TRUE );
    else if (ProgType & STARTMIN)
        WinCheckButton( hWnd, MINIMIZED, TRUE );
    // set appropriate radio button for program startup option
    if (ProgType & PM)
        WinCheckButton( hWnd, PMAPP, TRUE );
    else if (ProgType & WPSFOLDER)
        WinCheckButton( hWnd, FOLDER, TRUE );
    else if ( (ProgType & DOS) && (ProgType & WINDOWED))
        WinCheckButton( hWnd, DOSWIN, TRUE );
    else if ( (ProgType & DOS) && (ProgType & FULLSCREEN))
        WinCheckButton( hWnd, DOSFS, TRUE );
    else if ( (ProgType & OS2) && (ProgType & WINDOWED))
        WinCheckButton( hWnd, OS2WIN, TRUE );
    else if ( (ProgType & OS2) && (ProgType & FULLSCREEN))
        WinCheckButton( hWnd, OS2FS, TRUE );
    else if ( (ProgType & WINOS2) && (ProgType & WINDOWED))
        WinCheckButton( hWnd, WINOS2WIN, TRUE );
    else if ( (ProgType & WINOS2) && (ProgType & FULLSCREEN))
        WinCheckButton( hWnd, WINOS2FS, TRUE );
    if (ProgType & STARTASWPS)
        WinCheckButton( hWnd, STARTWPS, TRUE );
    else
        WinCheckButton( hWnd, STARTWPS, FALSE );
    updateEditItemWindow( hWnd );
}


////////////////////////////////////////////////////////////////////////////////
// message handler for the dialog "edit an item's values"
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY EditItemDataProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    switch( msg )
    {
        //----------------------------------------------------------------------
        // if the object being drug over us is a single object, allow drag
        //----------------------------------------------------------------------
        case DM_DRAGOVER: {
            ULONG cbBuffer;
            DRAGITEM dragItem;
            PDRAGINFO dragInfoPtr;
            INT numObjects;

            dragInfoPtr = (PDRAGINFO)mp1;
            DrgAccessDraginfo(dragInfoPtr);
            numObjects = dragInfoPtr->cditem;
            cbBuffer = sizeof(DRAGITEM);
            DrgQueryDragitem( dragInfoPtr, cbBuffer, &dragItem, 0 );
            DrgFreeDraginfo(dragInfoPtr);

            // allow anything, if sent by itself, to be dropped on us
            if (numObjects == 1)
                return MPFROM2SHORT( DOR_DROP, DO_UNKNOWN );
            return MPFROM2SHORT( DOR_NEVERDROP, DO_UNKNOWN );
            }
        //----------------------------------------------------------------------
        // allow the dropping of a WPS object to our window.  Once dropped, get
        // necessary info and fill in dialog with the info we retrieve
        //----------------------------------------------------------------------
        case DM_DROP: {
            PDRAGINFO dragInfoPtr;
            ULONG cbBuffer;
            DRAGITEM dragItem;

            dragInfoPtr = (PDRAGINFO)mp1;
            DrgAccessDraginfo(dragInfoPtr);

            cbBuffer = sizeof(DRAGITEM);
            DrgQueryDragitem( dragInfoPtr, cbBuffer, &dragItem, 0 );

            USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];
            // get menu item name
            DrgQueryStrName( dragItem.hstrTargetName, MAXITEMNAMELENGTH, menuItem->ItemName);
            // get default directory
            DrgQueryStrName( dragItem.hstrContainerName, MAXDIRSTRINGLENGTH, menuItem->Directory);
            // get path name
            DrgQueryStrName( dragItem.hstrSourceName, MAXACTIONSTRINGLENGTH, menuItem->ActionToDo);

            menuItem->ProgType = WPSFOLDER;
            WinCheckButton( hWnd, FOLDER, TRUE );

            DrgFreeDraginfo(dragInfoPtr);
            updateEditItemData( hWnd );
            WinSetFocus( HWND_DESKTOP, hWnd );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop and put
        // the current data into control fields
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;

            // center dialog on screen
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            // save data in case of cancel or restore
            USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];
            oldProgType = menuItem->ProgType;
            strcpy( oldPassword, menuItem->Password );
            oldPasswordEnabled = menuItem->PasswordEnabled;
            strcpy( oldItemName, menuItem->ItemName );
            strcpy( oldDirectory, menuItem->Directory );
            strcpy( oldAction, menuItem->ActionToDo );
            strcpy( oldCmdLn, menuItem->CmdLnArgs );
            updateEditItemData( hWnd );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // we received a control message, update enabling of buttons
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            // make sure either maximize -or- minimize is checked, never both
            if ((SHORT1FROMMP(mp1)==MAXIMIZED) && (SHORT2FROMMP(mp1)==BN_CLICKED))
                WinCheckButton( hWnd, MINIMIZED, FALSE );
            if ((SHORT1FROMMP(mp1)==MINIMIZED) && (SHORT2FROMMP(mp1)==BN_CLICKED))
                WinCheckButton( hWnd, MAXIMIZED, FALSE );
            updateEditItemWindow( hWnd );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // process a command message received from the system
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case PASSWORDENTRY: {
                    changePassword( Menus[MenuSelection][ItemSelection]->Password );
                    return 0;
                    }
                //--------------------------------------------------------------
                // open the settings notebook and allow user modifications
                //--------------------------------------------------------------
                case SETTINGSBUTTON: {
                    HOBJECT object;

                    // open settings for current program in dialog controls
                    USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];
                    WinQueryDlgItemText( hWnd, ITEMNAME, MAXITEMNAMELENGTH,
                                         menuItem->ItemName);
                    WinQueryDlgItemText( hWnd, PATHNAME, MAXACTIONSTRINGLENGTH,
                                         menuItem->ActionToDo);
                    WinQueryDlgItemText( hWnd, ARGUMENTS, MAXARGSTRINGLENGTH,
                                         menuItem->CmdLnArgs);
                    WinQueryDlgItemText( hWnd, DIRECTORY, MAXDIRSTRINGLENGTH,
                                         menuItem->Directory);

                    if (menuItem->ProgType & WPSFOLDER)
                        sprintf(tmpBuffer, "%s%s\0", menuItem->Directory,
                                menuItem->ActionToDo);
                    else
                        sprintf(tmpBuffer, "%s\0", menuItem->ActionToDo);

                    object = WinQueryObject( tmpBuffer );
                    if (object==NULLHANDLE) {
                        if (FileBarIsShell)
                            WinMessageBox( HWND_DESKTOP, hwndFrame, MSG29, MSG30, 0,
                                           MB_MOVEABLE|MB_OK|MB_ERROR);
                        else WinMessageBox( HWND_DESKTOP, hwndFrame, MSG31, MSG30, 0,
                                            MB_MOVEABLE|MB_OK|MB_ERROR);
                        return 0;
                        }

                    WinSetObjectData( object, "OPEN=SETTINGS" );
                    return 0;
                    }
                //--------------------------------------------------------------
                // the user wants to find a file to call as a menu item.  Hook
                // into OS/2's file dialog procedure to ease the finding process
                // for us to program!  Then once a file is selected, fill in
                // the program path, directory and query the application for its
                // application type and mark the appropriate radio button
                //--------------------------------------------------------------
                case FINDFILE: {
                    CHAR title[] = MSG32;
                    ULONG s, t;
                    HWND hwndDialog;

                    fileDlgInfo.fl = FDS_OPEN_DIALOG|FDS_CENTER;
                    fileDlgInfo.pszTitle = title;
                    strcat(fileDlgInfo.szFullFile, "*.*\0");

                    USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];
                    hwndDialog = WinFileDlg( HWND_DESKTOP, hWnd, &fileDlgInfo );
                    if (hwndDialog && (fileDlgInfo.lReturn == DID_OK)) {

                        strcpy( menuItem->ActionToDo, fileDlgInfo.szFullFile );

                        s=strlen(fileDlgInfo.szFullFile);
                        while((fileDlgInfo.szFullFile[s]!='\\') && (s>=0))
                            s--;

                        t = 0;
                        while (t<s)
                            menuItem->Directory[t] = fileDlgInfo.szFullFile[t++];
                        menuItem->Directory[t] = '\0';

                        DosQueryAppType( menuItem->ActionToDo, &t);
                        menuItem->ProgType = OS2 + WINDOWED;
                        if (t == FAPPTYP_WINDOWAPI)
                            menuItem->ProgType = PM;
                        if (t == FAPPTYP_WINDOWCOMPAT)
                            menuItem->ProgType = OS2 + WINDOWED;
                        if (t == FAPPTYP_NOTWINDOWCOMPAT)
                            menuItem->ProgType = OS2 + FULLSCREEN;
                        if (t == FAPPTYP_DOS)
                            menuItem->ProgType = DOS + WINDOWED;
                        if ((t == FAPPTYP_WINDOWSREAL) || (t == FAPPTYP_WINDOWSPROT))
                            menuItem->ProgType = WINOS2 + FULLSCREEN;

                        updateEditItemData( hWnd );
                        updateEditItemWindow( hWnd );

                        if (fileDlgInfo.szFullFile[s]=='\\')
                            fileDlgInfo.szFullFile[s+1]='\0';
                        else
                            fileDlgInfo.szFullFile[0]='\0';
                        }
                    else
                        fileDlgInfo.szFullFile[0]='\0';
                    return 0;
                    }
                //--------------------------------------------------------------
                // user pressed Reset, restore old settings and continue
                //--------------------------------------------------------------
                case RESETBUTTON: {
                    USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];
                    menuItem->PasswordEnabled = oldPasswordEnabled;
                    menuItem->ProgType = oldProgType;
                    strcpy( menuItem->Password, oldPassword );
                    strcpy( menuItem->ItemName, oldItemName );
                    strcpy( menuItem->Directory, oldDirectory );
                    strcpy( menuItem->ActionToDo, oldAction );
                    strcpy( menuItem->CmdLnArgs, oldCmdLn );
                    updateEditItemData( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // user pressed CANCEL, restore old item data
                //--------------------------------------------------------------
                case DID_CANCEL: {
                    USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];
                    menuItem->PasswordEnabled = oldPasswordEnabled;
                    menuItem->ProgType = oldProgType;
                    strcpy( menuItem->Password, oldPassword );
                    strcpy( menuItem->ItemName, oldItemName );
                    strcpy( menuItem->Directory, oldDirectory );
                    strcpy( menuItem->ActionToDo, oldAction );
                    strcpy( menuItem->CmdLnArgs, oldCmdLn );
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // user pressed OK, save current information for this item
                //--------------------------------------------------------------
                case DID_OK: {
                    // save program type and max/min startup status
                    USERMENUITEM* menuItem = Menus[MenuSelection][ItemSelection];

                    if (WinQueryButtonCheckstate( hWnd, PASSWORDPROTECT ))
                        menuItem->PasswordEnabled = YES;
                    else menuItem->PasswordEnabled = NO;

                    menuItem->ProgType = 0;
                    if (WinQueryButtonCheckstate( hWnd, FOLDER ))
                        menuItem->ProgType = WPSFOLDER;
                    if (WinQueryButtonCheckstate( hWnd, OS2WIN ))
                        menuItem->ProgType = OS2 + WINDOWED;
                    if (WinQueryButtonCheckstate( hWnd, OS2FS ))
                        menuItem->ProgType = OS2 + FULLSCREEN;
                    if (WinQueryButtonCheckstate( hWnd, DOSWIN ))
                        menuItem->ProgType = DOS + WINDOWED;
                    if (WinQueryButtonCheckstate( hWnd, DOSFS ))
                        menuItem->ProgType = DOS + FULLSCREEN;
                    if (WinQueryButtonCheckstate( hWnd, WINOS2WIN ))
                        menuItem->ProgType = WINOS2 + WINDOWED;
                    if (WinQueryButtonCheckstate( hWnd, WINOS2FS ))
                        menuItem->ProgType = WINOS2 + FULLSCREEN;
                    if (WinQueryButtonCheckstate( hWnd, PMAPP ))
                        menuItem->ProgType = PM;
                    if (WinQueryButtonCheckstate( hWnd, MAXIMIZED ))
                        menuItem->ProgType = menuItem->ProgType | STARTMAX;
                    if (WinQueryButtonCheckstate( hWnd, MINIMIZED ))
                        menuItem->ProgType = menuItem->ProgType | STARTMIN;
                    if (WinQueryButtonCheckstate( hWnd, STARTWPS ))
                        menuItem->ProgType = menuItem->ProgType | STARTASWPS;

                    // save name, path, directory, command line args
                    WinQueryDlgItemText( hWnd, ITEMNAME, MAXITEMNAMELENGTH,
                                         menuItem->ItemName);
                    WinQueryDlgItemText( hWnd, PATHNAME, MAXACTIONSTRINGLENGTH,
                                         menuItem->ActionToDo);
                    WinQueryDlgItemText( hWnd, ARGUMENTS, MAXARGSTRINGLENGTH,
                                         menuItem->CmdLnArgs);
                    WinQueryDlgItemText( hWnd, DIRECTORY, MAXDIRSTRINGLENGTH,
                                         menuItem->Directory);
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
            default:
                return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
// AddAnItemProc - the message handler for the "add an item to a menu" dialog
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY AddAnItemProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop and put
        // the current data into control fields
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinSendDlgItemMsg( hWnd, ITEMNAME, EM_SETTEXTLIMIT,
                               MPFROM2SHORT( MAXITEMNAMELENGTH-1, 0 ), 0 );
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // process a command message received from the system
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                // if they pressed OK, then save the data in the dialog as an
                // item that we can now launch from the fileBar.
                //--------------------------------------------------------------
                case DID_OK: {
                    Menus[MenuSelection][ (NumItems[MenuSelection]) ] = new USERMENUITEM;
                    USERMENUITEM* menuItem = Menus[MenuSelection][ (NumItems[MenuSelection]) ];
                    WinQueryDlgItemText( hWnd, ITEMNAME, MAXMENUNAMELENGTH, menuItem->ItemName );
                    menuItem->ActionToDo[0] = '\0';
                    menuItem->CmdLnArgs[0] = '\0';
                    menuItem->Directory[0] = '\0';
                    menuItem->ProgType = PM;
                    WinDismissDlg( hWnd, TRUE );
                    ItemSelection = NumItems[MenuSelection];
                    NumItems[MenuSelection]++;
                    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, FALSE,
                                      allowPopUpMenu, popUpMessageID );
                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)EditItemDataProc,
                              0,
                              EDITITEMDATA,
                              (PVOID)NULL);
                    setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                                      allowPopUpMenu, popUpMessageID );
                    return 0;
                    }
                //--------------------------------------------------------------
                // if they pressed cancel, save no data and return
                //--------------------------------------------------------------
                case DID_CANCEL: {
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                // nothing further we care about, pass on for default processing
                //--------------------------------------------------------------
                default:
                    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
                }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
// Message handler for entering a runtime parameter
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY EnterParamProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;

            WinSetWindowText( hWnd, parameterTitle );
            WinSetDlgItemText( hWnd, PARAMETER_TEXT, ParameterTextPtr );
            WinSendDlgItemMsg( hWnd, PARAMETER_EDIT, EM_SETTEXTLIMIT, MPFROMSHORT( oldProgType ), 0 );
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            memset(variableText, 0, sizeof(variableText) );
            WinQueryDlgItemText( hWnd, PARAMETER_EDIT, oldProgType, (PSZ)variableText );
            WinDismissDlg( hWnd, TRUE );
            return 0;
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
// gives a newly start application the input focus
////////////////////////////////////////////////////////////////////////////////
void giveApplicationFocus( BOOLEAN maximize, BOOLEAN minimize )
{
    SHORT i,h;
    PSWBLOCK SwitchBlockPtr;
    ULONG numItems = WinQuerySwitchList( hab, NULL, 0 );
    ULONG Buffer;
    SHORT count = 0;

    while ((numItems == oldNumItems) && (++count < MAXCOUNT)) {
        DosSleep(20);
        numItems = WinQuerySwitchList( hab, NULL, 0 );
        }

    Buffer = (numItems * sizeof(SWENTRY)) + sizeof(HSWITCH);
    PVOID my = new BYTE[Buffer];
    WinQuerySwitchList( hab, (SWBLOCK*)my, Buffer );
    SwitchBlockPtr = (PSWBLOCK)(my);

    for (i=0; i<numItems; i++)
        for (h=0; h<oldNumItems; h++)
           if ( SwitchBlockPtr->aswentry[i].swctl.hwnd == oldTaskHandles[h])
                SwitchBlockPtr->aswentry[i].swctl.hwnd = NULLHANDLE;

    i = 0;
    while (SwitchBlockPtr->aswentry[i].swctl.hwnd == NULLHANDLE)
        i++;
    WinFocusChange( HWND_DESKTOP, hwndFrame, 0 );
    WinSwitchToProgram( SwitchBlockPtr->aswentry[i].hswitch );

    if (maximize)
        WinSetWindowPos( SwitchBlockPtr->aswentry[i].swctl.hwnd, (HWND)0, 0, 0,
                         0, 0, SWP_MAXIMIZE);
    else if (minimize)
        WinSetWindowPos( SwitchBlockPtr->aswentry[i].swctl.hwnd, (HWND)0, 0, 0,
                         0, 0, SWP_MINIMIZE);
}


////////////////////////////////////////////////////////////////////////////////
// startApplication uses DosStartSession to start a batch file to start an
// application pointed to in one of the user menus by menu and item variables.
////////////////////////////////////////////////////////////////////////////////
SHORT startApplication( SHORT menu, SHORT item )
{
    CHAR* settingsFile;
    APIRET rc;
    STARTDATA startData;
    ULONG sessionId;
    PID ppId;
    UCHAR ObjBuf[2];
    SHORT i;
    SHORT h;
    PSWBLOCK SwitchBlockPtr;
    ULONG oldBuffer;
    CHAR parameters[MAXARGSTRINGLENGTH*3];
    CHAR SettingsBuffer[WPSBUFFER];
    CHAR itemName[MAXITEMNAMELENGTH];
    USERMENUITEM* menuItem = Menus[menu][item];

/////////////////////////////////////////////////////////////////////////////////
    oldNumItems = WinQuerySwitchList( hab, NULL, 0 );
    oldBuffer = (oldNumItems * sizeof(SWENTRY)) + sizeof(HSWITCH);
    PVOID myBuffer = new BYTE[oldBuffer];
    WinQuerySwitchList( hab, (SWBLOCK*)myBuffer, oldBuffer );
    SwitchBlockPtr = (PSWBLOCK)(myBuffer);
    for (i=0; i < oldNumItems; i++)
        oldTaskHandles[i] = SwitchBlockPtr->aswentry[i].swctl.hwnd;
    delete(myBuffer);
/////////////////////////////////////////////////////////////////////////////////

    i = 0;
    h = 0;
    // remove tilde from title window

    while (menuItem->ItemName[i]!='\0') {
        if (menuItem->ItemName[i]!='~')
            itemName[h++] = menuItem->ItemName[i];
        i++;
        }
    itemName[h] = 0;

    // get command line arguments via user input if necessary
    i = 0;
    h = 0;
    while ( menuItem->CmdLnArgs[i] != 0 ) {
        if (menuItem->CmdLnArgs[i] == STARTINPUT) {
            short j = 0;
            CHAR tmp[MAXARGSTRINGLENGTH];

            i++;
            while ( (menuItem->CmdLnArgs[i] != 0) &&
                    (menuItem->CmdLnArgs[i] != ENDINPUT ))
                tmp[j++] = menuItem->CmdLnArgs[i++];
            tmp[j] = 0;

            if (menuItem->CmdLnArgs[i] != 0)
                i++;

            {
                CHAR mesg[18+MAXARGSTRINGLENGTH];
                SHORT k = 0;

                sprintf( parameterTitle, "%s %s", menuItem->ItemName, MSG33 );
                sprintf( mesg, "%s '%s'", MSG34, tmp);
                ParameterTextPtr = mesg;
                oldProgType = sizeof(variableText);
                (VOID*)WinDlgBox(HWND_DESKTOP,
                                 hwndFrame,
                                 (PFNWP)EnterParamProc,
                                 0,
                                 ENTERPARAMETER,
                                 (PVOID)NULL);

                while ( variableText[k] != '\0')
                    parameters[h++] = variableText[k++];
            }

            }
        else
            parameters[h++] = menuItem->CmdLnArgs[i++];
        }
    parameters[h] = '\0';

    //--------------------------------------------------------------------------
    // open a WPS folder/object
    //--------------------------------------------------------------------------
    if ((menuItem->ProgType & WPSFOLDER) || (menuItem->ProgType & STARTASWPS)) {
        CHAR string[MAXACTIONSTRINGLENGTH+MAXDIRSTRINGLENGTH+2];
        HOBJECT object;

        if (menuItem->ProgType & WPSFOLDER)
            sprintf(string, "%s%s\0", menuItem->Directory,menuItem->ActionToDo);
        else
            sprintf(string, "%s\0", menuItem->ActionToDo);

        object = WinQueryObject( string );
        if (object==NULLHANDLE) {
            CHAR errorText[] = MSG30;

            if (FileBarIsShell)
                WinMessageBox( HWND_DESKTOP, hwndFrame, MSG35, errorText, 0,
                               MB_MOVEABLE|MB_OK|MB_ERROR);
            else WinMessageBox( HWND_DESKTOP, hwndFrame, MSG36, errorText, 0,
                                MB_MOVEABLE|MB_OK|MB_ERROR);
            return 0;
            }

        if (menuItem->ProgType & STARTMIN)
            WinSetObjectData(object, "MINIMIZED=YES");
        else if (menuItem->ProgType & STARTMAX)
            WinSetObjectData(object, "MAXIMIZED=YES");

        WinSetObjectData(object, "OPEN=DEFAULT");

        giveApplicationFocus(FALSE,FALSE);
        return 0;
        }


    //--------------------------------------------------------------------------
    // try and locate a settings file
    //--------------------------------------------------------------------------
    {
    SHORT offset;
    FILE *FileHandle;

    settingsFile = SettingsBuffer;
    memset( &SettingsBuffer[0], 0, sizeof(SettingsBuffer) );
    if ((FileHandle = fopen("SETTINGS.INI","rt")) != NULL) {
        CHAR ch;

        while (fscanf(FileHandle, "%c", &ch) != EOF) {
            if ( ch == '\n' )
                SettingsBuffer[ offset++ ] = '\0';
            else
                if ( ch != '\r' )
                    SettingsBuffer[ offset++ ] = ch;
            }
        SettingsBuffer[ offset++ ] = '\0';
        SettingsBuffer[ offset++ ] = '\0';
        fclose(FileHandle);
        }

    else
        settingsFile = 0;
    }


    //--------------------------------------------------------------------------
    // this launches a command shell (DOS or OS2 (Windowed or FS session))
    //--------------------------------------------------------------------------
    if ((menuItem->ActionToDo[0] == '\0') && !(menuItem->ProgType & WINOS2)) {
        ULONG currentDrive;
        ULONG driveMap;
        CHAR InputDir[MAXPATH + 9];

        DosQueryCurrentDisk( &currentDrive, &driveMap );
        DosSetDefaultDisk( (ULONG)(toupper(menuItem->Directory[0])-'A' + 1) );

        memset( &startData, 0, sizeof(STARTDATA) );
        startData.Related = SSF_RELATED_INDEPENDENT;
        startData.FgBg = SSF_FGBG_FORE;
        startData.TraceOpt = SSF_TRACEOPT_NONE;
        startData.InheritOpt = SSF_INHERTOPT_PARENT;
        startData.ObjectBuffer = ObjBuf;
        startData.ObjectBuffLen = sizeof(ObjBuf);
        startData.Length = sizeof(startData);
        startData.PgmTitle = itemName;
        strcpy( InputDir, "/K cd  \0");
        strcpy( InputDir+6, menuItem->Directory );
        startData.PgmInputs = InputDir;

        ////////////////////////////////////////
        //startData.Environment = SettingsFile;
        ////////////////////////////////////////

        startData.PgmControl = SSF_CONTROL_VISIBLE;
        if (menuItem->ProgType & MAXIMIZED)
            startData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE;
        else if (menuItem->ProgType & MINIMIZED)
            startData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MINIMIZE;

        if (menuItem->ProgType & DOS) {
            if (menuItem->ProgType & WINDOWED)
                startData.SessionType = SSF_TYPE_WINDOWEDVDM;
            else
                startData.SessionType = SSF_TYPE_VDM;
            rc = DosStartSession( (STARTDATA*) &startData, (ULONG*)&sessionId,
                                  (PID*) &ppId );

            DosSetDefaultDisk( currentDrive );
            giveApplicationFocus( (menuItem->ProgType & MAXIMIZED),
                                  (menuItem->ProgType & MINIMIZED) );
            return 0;
            }
        else if (menuItem->ProgType & OS2) {
            if (menuItem->ProgType & WINDOWED)
                startData.SessionType = SSF_TYPE_WINDOWABLEVIO;
            else
                startData.SessionType = SSF_TYPE_FULLSCREEN;
            rc = DosStartSession( (STARTDATA*) &startData, (ULONG*)&sessionId,
                                  (PID*) &ppId );

            DosSetDefaultDisk( currentDrive );
            giveApplicationFocus( (menuItem->ProgType & MAXIMIZED),
                                  (menuItem->ProgType & MINIMIZED) );
            return 0;
            }
        WinMessageBox( HWND_DESKTOP, hwndFrame, MSG37, NULL, 0,
                       MB_MOVEABLE|MB_ERROR|MB_OK);

        return 0;
        }

    //--------------------------------------------------------------------------
    // this section of code launches a program (non-command shell application)
    //--------------------------------------------------------------------------
    {
    ULONG currentDrive;
    ULONG driveMap;
    UCHAR defaultDirectory[MAXPATH];
    CHAR inputs[1024];

    memset( &startData, 0, sizeof(STARTDATA) );
    startData.Length = sizeof(STARTDATA);
    startData.Related = SSF_RELATED_INDEPENDENT;
    startData.FgBg = SSF_FGBG_FORE;
    startData.TraceOpt = SSF_TRACEOPT_NONE;
    startData.PgmTitle = itemName;
    startData.InheritOpt = SSF_INHERTOPT_PARENT;
    startData.SessionType = SSF_TYPE_WINDOWABLEVIO;
    startData.PgmControl = SSF_CONTROL_VISIBLE;
    startData.SessionType = SSF_TYPE_PM;
    startData.PgmName = menuItem->ActionToDo;
    startData.PgmInputs = parameters;
    startData.Environment = settingsFile;

    if (menuItem->ProgType & DOS) {
        if (menuItem->ProgType & FULLSCREEN)
            startData.SessionType = SSF_TYPE_VDM;
        else if (menuItem->ProgType & WINDOWED)
            startData.SessionType = SSF_TYPE_WINDOWEDVDM;
        }
    else if (menuItem->ProgType & OS2) {
        if (menuItem->ProgType & FULLSCREEN)
            startData.SessionType = SSF_TYPE_FULLSCREEN;
        else if (menuItem->ProgType & WINDOWED)
            startData.SessionType = SSF_TYPE_WINDOWABLEVIO;
        }

    else if (menuItem->ProgType & WINOS2) {
        if (menuItem->ProgType & FULLSCREEN)
            startData.SessionType = SSF_TYPE_FULLSCREEN;
        else if (menuItem->ProgType & WINDOWED)
           startData.SessionType = 18;               //PROG_31_ENHSEAMLESSCOMMON
        if (menuItem->ActionToDo[0])
            sprintf( inputs, "/c winos2 %s %s", menuItem->ActionToDo, parameters );
        else
            sprintf( inputs, "/c winos2 %s", parameters );
        startData.PgmInputs = inputs;
        startData.PgmName = 0;
        }

    if (menuItem->ProgType & STARTMAX)
        startData.PgmControl |= SSF_CONTROL_MAXIMIZE;
    else if (menuItem->ProgType & STARTMIN)
        startData.PgmControl |= SSF_CONTROL_MINIMIZE;

    if (!(menuItem->ProgType & WINOS2) && (startData.PgmName != NULL) && (startData.SessionType != SSF_TYPE_PM)) {
        CHAR temp[MAXPATH+MAXARGSTRINGLENGTH+6];
        sprintf(temp, "/c %s %s\0", menuItem->ActionToDo, parameters);
        startData.PgmName = 0;
        strcpy(inputs, temp);
        startData.PgmInputs = inputs;
        }

    // save current drive and directory
    DosQueryCurrentDisk( &currentDrive, &driveMap );
    {
        CHAR temp[MAXPATH+5];
        ULONG tempSize = MAXPATH;
        defaultDirectory[0]= (currentDrive+'A'-1);
        defaultDirectory[1]= ':';
        defaultDirectory[2]= '\\';
        defaultDirectory[3]= '\0';
        DosQueryCurrentDir( currentDrive, (CHAR*)&temp, &tempSize );
        strcat( defaultDirectory, temp );
    }

    // point to working directory of program to execute
    if (((toupper(menuItem->Directory[0]))>='A') && ((toupper(menuItem->Directory[0]))<='Z'))
        DosSetDefaultDisk( (ULONG)(toupper(menuItem->Directory[0])-'A' + 1) );
    DosSetCurrentDir( menuItem->Directory );

    // launch application
    rc = DosStartSession( (STARTDATA*) &startData, (ULONG*)&sessionId,
                          (PID*) &ppId );

    // restore current drive and directory
    DosSetDefaultDisk( currentDrive );
    DosSetCurrentDir( defaultDirectory );

    if ((rc != 0) && (rc != ERROR_SMG_START_IN_BACKGROUND) && (!startUp)) {
        char text[] = MSG38;
        char title[28];

        sprintf(title, "%s #%d", MSG39, rc );
        WinMessageBox( HWND_DESKTOP, hwndFrame, text, title, 0,
                       MB_MOVEABLE|MB_ERROR|MB_OK);
        return 0;
        }

    giveApplicationFocus( (menuItem->ProgType & MAXIMIZED),
                          (menuItem->ProgType & MINIMIZED) );
    return 0;
    }
}


////////////////////////////////////////////////////////////////////////////////
// display a background bitmap
////////////////////////////////////////////////////////////////////////////////
VOID displayBackground( VOID )
{
    DESKTOP desktop;

//    if ((!FileBarIsShell) && (showBackground))
//        WinMessageBox( HWND_DESKTOP, hwndFrame, "The background bitmap could not be displayed since FileBar is not currently acting as the shell.", "FileBar - Display Background", 0,
//                       MB_MOVEABLE|MB_ERROR|MB_OK);
//    else
    if ((showBackground) || (isBackgroundDisplayed)) {
        desktop.cbSize = sizeof( DESKTOP );
        desktop.hbm = 0;
        desktop.x = 0;
        desktop.y = 0;
        desktop.fl = SDT_DESTROY;
        if (isBackgroundDisplayed)
            WinSetDesktopBkgnd( HWND_DESKTOP, &desktop );

        desktop.fl = SDT_LOADFILE|SDT_CENTER;
        if (backgroundAttr & SCALED)
            desktop.fl = SDT_SCALE|SDT_LOADFILE;
        if (backgroundAttr & TILED) {
            desktop.fl = SDT_TILE|SDT_LOADFILE;
            desktop.lTileCount = backgroundAttr - TILED;
            }
        strcpy( desktop.szFile, backgroundBitmap );
        if (showBackground) {
            WinSetDesktopBkgnd( HWND_DESKTOP, &desktop );
            isBackgroundDisplayed = TRUE;
            }
        }
}


////////////////////////////////////////////////////////////////////////////////
// Message handler for a generic information-only dialog box (help & prod info)
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY backgroundProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            char temp[12];

            WinCheckButton( hWnd, BKGND_NORMAL, TRUE );
            if (backgroundAttr & SCALED)
                WinCheckButton( hWnd, BKGND_SCALED, TRUE );
            else if (backgroundAttr & TILED) {
                WinCheckButton( hWnd, BKGND_TILED, TRUE );
                WinEnableControl( hWnd, BKGND_TILENUMBER, TRUE );
                WinEnableControl( hWnd, BKGND_TILENUMBERTEXT, TRUE );
                WinEnableControl( hWnd, BKGND_LESS, TRUE );
                WinEnableControl( hWnd, BKGND_MORE, TRUE );
                }

            if (backgroundAttr & SCALED)
                backgroundAttr = backgroundAttr - SCALED;
            if (backgroundAttr & TILED)
                backgroundAttr = backgroundAttr - TILED;

            sprintf(temp,"%d x %d", backgroundAttr, backgroundAttr);
            WinSetDlgItemText( hWnd, BKGND_TILENUMBER, temp );

            WinSendDlgItemMsg( hWnd, BKGND_BITMAPNAME, EM_SETTEXTLIMIT, MPFROMSHORT( sizeof(backgroundBitmap) ), 0 );
            WinSetDlgItemText( hWnd, BKGND_BITMAPNAME, backgroundBitmap );

            WinCheckButton( hWnd, BKGND_SHOW, showBackground );
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if (SHORT2FROMMP(mp1)==BN_CLICKED) {
                BOOLEAN option = FALSE;
                if (WinQueryButtonCheckstate( hWnd, BKGND_TILED))
                    option = TRUE;
                WinEnableControl( hWnd, BKGND_TILENUMBER, option );
                WinEnableControl( hWnd, BKGND_TILENUMBERTEXT, option );
                WinEnableControl( hWnd, BKGND_LESS, option );
                WinEnableControl( hWnd, BKGND_MORE, option );
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                // if they pressed OK, then save the data in the dialog as an
                // item that we can now launch from the fileBar.
                //--------------------------------------------------------------
                case DID_OK: {
                    WinQueryDlgItemText( hWnd, BKGND_BITMAPNAME, sizeof(backgroundBitmap), (PSZ)backgroundBitmap );
                    showBackground = WinQueryButtonCheckstate( hWnd, BKGND_SHOW );
                    if (WinQueryButtonCheckstate( hWnd, BKGND_SCALED))
                        backgroundAttr = backgroundAttr + SCALED;
                    if (WinQueryButtonCheckstate( hWnd, BKGND_TILED))
                        backgroundAttr = backgroundAttr + TILED;
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case BKGND_LESS: {
                    char temp[12];

                    if (backgroundAttr > 1)
                        backgroundAttr--;
                    sprintf(temp,"%d x %d", backgroundAttr, backgroundAttr);
                    WinSetDlgItemText( hWnd, BKGND_TILENUMBER, temp );
                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case BKGND_MORE: {
                    char temp[12];

                    if (backgroundAttr < 32)
                        backgroundAttr++;
                    sprintf(temp,"%d x %d", backgroundAttr, backgroundAttr);
                    WinSetDlgItemText( hWnd, BKGND_TILENUMBER, temp );
                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case BKGND_FINDFILE: {
                    CHAR title[] = MSG40;
                    HWND hwndDialog;
                    CHAR oldDir[MAXPATH];

                    fileDlgInfo.fl = FDS_OPEN_DIALOG|FDS_CENTER;
                    fileDlgInfo.pszTitle = title;
                    strcpy( oldDir, fileDlgInfo.szFullFile );
                    strcat(fileDlgInfo.szFullFile, "*.BMP\0");

                    hwndDialog = WinFileDlg( HWND_DESKTOP, hWnd, &fileDlgInfo );
                    if (hwndDialog && (fileDlgInfo.lReturn == DID_OK)) {
                        strcpy( backgroundBitmap, fileDlgInfo.szFullFile );
                        resetFileDialog();
                        WinSetDlgItemText( hWnd, BKGND_BITMAPNAME, backgroundBitmap );
                        }
                    else
                        strcpy( fileDlgInfo.szFullFile, oldDir );
                    return 0;
                    }
            }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
// Message handler for a generic information-only dialog box (help & prod info)
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY startupProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            short i,j;
            char temp[MAXITEMNAMELENGTH+8];

            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            WinSendDlgItemMsg( hWnd, STARTUP_ITEMLIST, LM_DELETEALL, 0, 0);
            temp[0] = ' ';
            temp[1] = ' ';
            temp[2] = '-';
            temp[3] = ' ';
            for (i=0; i<NumMenus; i++) {
                WinSendDlgItemMsg( hWnd, STARTUP_ITEMLIST, LM_INSERTITEM, MPFROMSHORT( LIT_END ), MenuName[i] );
                for (j=0; j<NumItems[i]; j++)
                    if (Menus[i][j]->ItemName[0] != '\0') {
                        temp[4] = '\0';
                        strcat(temp, Menus[i][j]->ItemName);
                        WinSendDlgItemMsg( hWnd, STARTUP_ITEMLIST, LM_INSERTITEM, MPFROMSHORT( LIT_END ), temp );
                        }
                }

            WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_DELETEALL, 0, 0);
            for( i = 0; i< numStartItems; i++)
                WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), Menus[(StartUpMenu[i])][(StartUpItem[i])]->ItemName );

            WinCheckButton( hWnd, STARTUP_LAUNCH, DoStartUpList );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if (SHORT2FROMMP(mp1)==BN_CLICKED) {
                BOOLEAN option = FALSE;
                if (WinQueryButtonCheckstate( hWnd, BKGND_TILED))
                    option = TRUE;
                WinEnableControl( hWnd, BKGND_TILENUMBER, option );
                WinEnableControl( hWnd, BKGND_TILENUMBERTEXT, option );
                WinEnableControl( hWnd, BKGND_LESS, option );
                WinEnableControl( hWnd, BKGND_MORE, option );
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);
            switch( command )
                {
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case STARTUP_ADD: {

                    if (numStartItems == MAXSTARTITEMS)
                        WinMessageBox( HWND_DESKTOP, hwndFrame, MSG41, MSG42, 0,
                                       MB_MOVEABLE|MB_ERROR|MB_OK);
                    else {
                        char buffer[MAXITEMNAMELENGTH + 8];
                        SHORT i,j;
                        BOOL found = FALSE;
                        SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, STARTUP_ITEMLIST,
                                                                              LM_QUERYSELECTION,
                                                                              MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                              0 ) );
                        if (itemSelected == LIT_NONE) {
                            WinMessageBox( HWND_DESKTOP, hwndFrame, MSG43, MSG44, 0,
                                           MB_MOVEABLE|MB_ERROR|MB_OK);
                            return 0;
                            }

                        for( i=0; i<NumMenus; i++)
                            for( j=0; j<NumItems[i]; j++) {
                                SHORT1FROMMP( WinSendDlgItemMsg( hWnd, STARTUP_ITEMLIST,
                                                         LM_QUERYITEMTEXT,
                                                         MPFROM2SHORT( itemSelected, sizeof(buffer) ),
                                                         &buffer ) );
                                if (strcmp(&(buffer[4]),Menus[i][j]->ItemName)==0) {
                                    StartUpMenu[ numStartItems ] = i;
                                    StartUpItem[ numStartItems ] = j;
                                    numStartItems++;
                                    WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), Menus[i][j]->ItemName );
                                    found = TRUE;
                                    }
                                }

                            if (!found)
                                WinMessageBox( HWND_DESKTOP, hwndFrame, MSG45, MSG46, 0,
                                               MB_MOVEABLE|MB_ERROR|MB_OK);
                        }
                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case STARTUP_REMOVE: {
                    SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    SHORT i;

                    if (itemSelected != LIT_NONE) {
                        for (i=itemSelected+1; i<numStartItems; i++) {
                            StartUpMenu[i-1] = StartUpMenu[i];
                            StartUpItem[i-1] = StartUpItem[i];
                            }
                        numStartItems--;
                        WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_DELETEALL, 0, 0);
                        for( i = 0; i< numStartItems; i++)
                            WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), Menus[(StartUpMenu[i])][(StartUpItem[i])]->ItemName );

                        if (itemSelected == numStartItems)
                            WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_SELECTITEM,
                                               MPFROM2SHORT( numStartItems-1, 0 ),
                                               MPFROM2SHORT( TRUE, 0 ) );
                        else
                            WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_SELECTITEM,
                                               MPFROM2SHORT( itemSelected, 0 ),
                                               MPFROM2SHORT( TRUE, 0 ) );
                        }

                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case STARTUP_CLEARALL: {
                    WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_DELETEALL, 0, 0);
                    numStartItems = 0;
                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case STARTUP_MOVEDOWN: {
                    SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    if ((itemSelected < (numStartItems-1)) && (itemSelected != LIT_NONE)) {
                        SHORT z;
                        SHORT i;

                        z = StartUpMenu[itemSelected+1];
                        StartUpMenu[itemSelected+1] = StartUpMenu[itemSelected];
                        StartUpMenu[itemSelected] = z;

                        z = StartUpItem[itemSelected+1];
                        StartUpItem[itemSelected+1] = StartUpItem[itemSelected];
                        StartUpItem[itemSelected] = z;

                        WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_DELETEALL, 0, 0);
                        for( i = 0; i< numStartItems; i++)
                            WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), Menus[(StartUpMenu[i])][(StartUpItem[i])]->ItemName );

                        WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_SELECTITEM,
                                           MPFROM2SHORT( itemSelected+1, 0 ),
                                           MPFROM2SHORT( TRUE, 0 ) );
                        }
                    return 0;
                    }
                //--------------------------------------------------------------
                //--------------------------------------------------------------
                case STARTUP_MOVEUP: {
                    SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS,
                                                                     LM_QUERYSELECTION,
                                                                     MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                     0 ) );
                    if ((itemSelected > 0) && (itemSelected != LIT_NONE)) {
                        SHORT z;
                        SHORT i;

                        z = StartUpMenu[itemSelected-1];
                        StartUpMenu[itemSelected-1] = StartUpMenu[itemSelected];
                        StartUpMenu[itemSelected] = z;

                        z = StartUpItem[itemSelected-1];
                        StartUpItem[itemSelected-1] = StartUpItem[itemSelected];
                        StartUpItem[itemSelected] = z;

                        WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_DELETEALL, 0, 0);
                        for( i = 0; i< numStartItems; i++)
                            WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), Menus[(StartUpMenu[i])][(StartUpItem[i])]->ItemName );

                        WinSendDlgItemMsg( hWnd, STARTUP_CURRITEMS, LM_SELECTITEM,
                                           MPFROM2SHORT( itemSelected-1, 0 ),
                                           MPFROM2SHORT( TRUE, 0 ) );
                        }
                    return 0;
                    }
                //--------------------------------------------------------------
                // if they pressed OK, then save the data in the dialog as an
                // item that we can now launch from the fileBar.
                //--------------------------------------------------------------
                case DID_OK: {
                    DoStartUpList = WinQueryButtonCheckstate( hWnd, STARTUP_LAUNCH);
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                    }
            }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
// execute start up list of applications
////////////////////////////////////////////////////////////////////////////////
VOID ExecuteStartUpList( VOID )
{
     SHORT i;

     if (DoStartUpList)
         for (i=0; i<numStartItems; i++)
             startApplication( StartUpMenu[i], StartUpItem[i] );
     startUp = FALSE;
}


////////////////////////////////////////////////////////////////////////////////
// update the buttons of the calendar to reflect current month structure
////////////////////////////////////////////////////////////////////////////////
VOID updateCalendar( HWND hWnd )
{
    LONG backgroundColor = CLR_YELLOW;
    LONG foregroundColor = CLR_BLACK;
    CHAR temp[50];
    int origDay;
    int origMonth;
    struct tm *time_now;
    time_t currentTime;
    short i;
    short numDaysInMonth;

    time(&currentTime);
    time_now = localtime( &currentTime );
    numDaysInMonth = numberOfDaysInMonth(month, year);

    origDay = time_now->tm_mday;
    origMonth = time_now->tm_mon;
    time_now->tm_mon = month;
    time_now->tm_year= year;

    strftime( temp, sizeof(temp), " %B - %Y ", time_now);
    WinSetDlgItemText( hWnd, 550, temp );

    for( i=500; i<543; i++) {
        WinRemovePresParam( WinWindowFromID(hWnd, i), PP_BACKGROUNDCOLORINDEX );
        WinRemovePresParam( WinWindowFromID(hWnd, i), PP_FOREGROUNDCOLORINDEX );
        }

    for( i=0; i<startDay; i++) {
        WinSetDlgItemText( hWnd, i+500, "" );
        WinEnableControl( hWnd, i+500, FALSE );
        }

    if (month==origMonth) {
        WinSetPresParam( WinWindowFromID(hWnd, origDay+startDay+499), PP_BACKGROUNDCOLORINDEX, sizeof(LONG), (PVOID)&backgroundColor );
        WinSetPresParam( WinWindowFromID(hWnd, origDay+startDay+499), PP_FOREGROUNDCOLORINDEX, sizeof(LONG), (PVOID)&foregroundColor );
        }

    for( i=1; i<=numDaysInMonth; i++) {
        sprintf(temp, "%d", i);
        WinEnableControl( hWnd, i+startDay+500-1, TRUE );
        WinSetDlgItemText( hWnd, i+startDay+500-1, temp );
        }

    for( i=numDaysInMonth+startDay+500; i<543; i++) {
        WinSetDlgItemText( hWnd, i, "" );
        WinEnableControl( hWnd, i, FALSE );
        }
}


////////////////////////////////////////////////////////////////////////////////
// return # of days in # (even checking for leap year)
////////////////////////////////////////////////////////////////////////////////
BYTE numberOfDaysInMonth(int month, int year)
{
    if (((1900+year) % 4) || (month != 1))
        return daysInMonth[month];
    else
        return daysInMonth[month]+1;    //handle leap year
}


////////////////////////////////////////////////////////////////////////////////
// display scheduling calendar and let user schedule and revise tasks
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY schedulerProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            struct tm *time_now;
            CHAR mesg[24];
            time_t currentTime;
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            time(&currentTime);
            time_now = localtime( &currentTime );
            month = time_now->tm_mon;
            year = time_now->tm_year;

            startDay = (time_now->tm_wday - (time_now->tm_mday % 7 - 1));
            if (startDay > 6)
                startDay = startDay - 7;
            else if (startDay < 0)
                startDay = startDay + 7;
            updateCalendar( hWnd );

            sprintf( mesg, "%s %d %s", MSG47, repeatTime, MSG48 );
            WinSetDlgItemText( hWnd, REMINDERTIME, mesg );

            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // process a command message from the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);

            //------------------------------------------------------------------
            // if the user pressed a day button, show daily schedule window
            //------------------------------------------------------------------
            if ((command>=500) && (command<=542)) {
                day = command - 500 - startDay;
                WinDlgBox(HWND_DESKTOP,
                          hWnd,
                          (PFNWP)scheduleProc,
                          0,
                          SCHEDULEITEM,
                          (PVOID)NULL);
                return 0;
                }
            //------------------------------------------------------------------
            // handle user commands
            //------------------------------------------------------------------
            switch( command ) {
                //------------------------------------------------------------------
                // show all currently scheduled tasks
                //------------------------------------------------------------------
                case SHOWALL: {
                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)showAllItemsProc,
                              0,
                              SHOWALLITEMS,
                              (PVOID)NULL);
                    return 0;
                    }
                //--------------------------------------------------------------
                // reduce amount of time between reminder sounds
                //--------------------------------------------------------------
                case LESSTIME: {
                    char mesg[24];
                    if (repeatTime>0)
                        repeatTime--;
                    sprintf( mesg, "%s %d %s", MSG47, repeatTime, MSG48 );
                    WinSetDlgItemText( hWnd, REMINDERTIME, mesg );
                    return 0;
                    }
                //--------------------------------------------------------------
                // increase amount of time between reminder sounds
                //--------------------------------------------------------------
                case MORETIME: {
                    char mesg[24];
                    if (repeatTime<32767)
                        repeatTime++;
                    sprintf( mesg, "%s %d %s", MSG47, repeatTime, MSG48 );
                    WinSetDlgItemText( hWnd, REMINDERTIME, mesg );
                    return 0;
                    }
                //--------------------------------------------------------------
                // go back 1 month
                //--------------------------------------------------------------
                case 551: {
                    month--;
                    if (month < 0) {
                        month = 11;
                        year--;
                        }

                    startDay = startDay - numberOfDaysInMonth(month, year) % 7;

                    if (startDay > 6)
                        startDay = startDay - 7;
                    if (startDay < 0)
                        startDay = startDay + 7;

                    updateCalendar( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // advance 1 month
                //--------------------------------------------------------------
                case 553: {
                    SHORT oldMonth = month;
                    SHORT oldYear = year;

                    month++;
                    if (month > 11) {
                        month = 0;
                        year++;
                        }

                    startDay = (startDay + numberOfDaysInMonth(oldMonth, oldYear)) % 7;
                    if (startDay > 6)
                        startDay = startDay - 7;
                    if (startDay < 0)
                        startDay = startDay + 7;

                    updateCalendar( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // go back to current month
                //--------------------------------------------------------------
                case 552: {
                    time_t currentTime;
                    struct tm *time_now;

                    time(&currentTime);
                    time_now = localtime( &currentTime );
                    month = time_now->tm_mon;
                    year = time_now->tm_year;

                    startDay = time_now->tm_wday - (time_now->tm_mday % 7 - 1);
                    if (startDay > 6)
                        startDay = startDay - 7;
                    if (startDay < 0)
                        startDay = startDay + 7;

                    updateCalendar( hWnd );
                    return 0;
                    }
                //--------------------------------------------------------------
                // user pressed OK, cancel dialog
                //--------------------------------------------------------------
                case DID_OK: {
                    WinDismissDlg( hWnd, TRUE );
                    return 0;
                }
            }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY showAllItemsProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            USERMENUITEM* userItem;
            ALARMS* alarm;
            CHAR temp[64+MAXACTIONSTRINGLENGTH];
            CHAR s[MAXACTIONSTRINGLENGTH+11];
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            sprintf(temp, "%d %s %d %s)", numAlarms, MSG49, MAXALARMS, MSG50 );
            WinSetWindowText( hWnd, temp );

            WinSendDlgItemMsg( hWnd, SHOWITEMS, LM_DELETEALL, MPFROMSHORT( LIT_END ), temp );
            for( short i = 0; i< numAlarms; i++) {
                alarm = alarmPtr[i];
                CHAR c = 'a';
                //BYTE hour = alarm[i].AlarmHour;
                BYTE hour = alarm->AlarmHour;

                //if (alarm[i].options & SCHEDULE_LAUNCHAPP) {
                if (alarm->options & SCHEDULE_LAUNCHAPP) {
                    short j = 10;
                    short k = 0;
                    strcpy(s, MSG51);
//                    while ((ItemName[((int)alarm[i].ActionToDo[0])][((int)alarm[i].ActionToDo[1])][k])!='\0')
//                        if ((ItemName[((int)alarm[i].ActionToDo[0])][((int)alarm[i].ActionToDo[1])][k])=='~')
                    userItem = Menus[((int)alarm->ActionToDo[0])][((int)alarm->ActionToDo[1])];
                    while (userItem->ItemName[k] != '\0')
                        if (userItem->ItemName[k] == '~')
                            k++;
                        else
//                            s[j++] = ItemName[((int)alarm[i].ActionToDo[0])][((int)alarm[i].ActionToDo[1])][k++];
                            s[j++] = userItem->ItemName[k++];
                        s[j] = '\0';
                    }
                else
                    //strcpy(s, alarm[i].ActionToDo);
                    strcpy(s, alarm->ActionToDo);

                //if (alarm[i].AlarmHour>11)
                if (alarm->AlarmHour>11)
                    c='p';
                if (!(hour = hour % 12))
                    hour = 12;

                sprintf( temp, "%2d:%2d%cm (%2d:%2d) -- %d/%d/%d (%d/%d/%d) -- %s", hour,
                                                                    alarm->AlarmMinute,
                                                                    c,
                                                                    alarm->AlarmHour,
                                                                    alarm->AlarmMinute,
                                                                    alarm->AlarmMonth+1,
                                                                    alarm->AlarmDay+1,
                                                                    alarm->AlarmYear,
                                                                    alarm->AlarmDay+1,
                                                                    alarm->AlarmMonth+1,
                                                                    alarm->AlarmYear,
                                                                    s );
/*
                sprintf( temp, "%2d:%2d%cm (%2d:%2d) -- %d/%d/%d (%d/%d/%d) -- %s", hour,
                                                                    alarm[i].AlarmMinute,
                                                                    c,
                                                                    alarm[i].AlarmHour,
                                                                    alarm[i].AlarmMinute,
                                                                    alarm[i].AlarmMonth+1,
                                                                    alarm[i].AlarmDay+1,
                                                                    alarm[i].AlarmYear,
                                                                    alarm[i].AlarmDay+1,
                                                                    alarm[i].AlarmMonth+1,
                                                                    alarm[i].AlarmYear,
                                                                    s );
*/
                if (temp[3]==' ') {
                    temp[3] = '0';
                    temp[12]= '0';
                    }

                WinSendDlgItemMsg( hWnd, SHOWITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), temp );
                }

            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if (SHORT2FROMMP(mp1)==LN_ENTER) {
                SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, SHOWITEMS,
                                                                      LM_QUERYSELECTION,
                                                                      MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                      0 ) );

                oldProgType = numAlarms;
                numAlarms = 0;

                reviseScheduledItem( itemSelected );
                sortTimeEntries( oldProgType );
                numAlarms = oldProgType;
                WinSendMsg( hWnd, WM_INITDLG, 0, 0 );
                WinSendDlgItemMsg( hWnd, SHOWITEMS, LM_SELECTITEM,
                                   MPFROM2SHORT( itemSelected, 0 ),
                                   MPFROM2SHORT( TRUE, 0 ) );
                return WinDefDlgProc( hWnd, msg, mp1, mp2 );
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            if (SHORT1FROMMP(mp1)==DID_OK)
                WinDismissDlg( hWnd, TRUE );
            return 0;
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY scheduleProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            CHAR temp[MAXACTIONSTRINGLENGTH+32];
            SWP swp;
            SHORT i;
            ALARMS* alarm;
            USERMENUITEM* menuItem;

            // disable alarms while editing calendar
            oldProgType = numAlarms;
            numAlarms = 0;

            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            sprintf( temp, "%s %d/%d/%4d...", MSG52, month+1, day+1, 1900+year);
            WinSetWindowText( hWnd, temp );

            WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS, LM_DELETEALL, MPFROMSHORT( LIT_END ), temp );

            for( i = 0; i< oldProgType; i++) {
                alarm = alarmPtr[i];
                if (alarm->AlarmDay == day)
                  if (alarm->AlarmMonth == month)
                    if (alarm->AlarmYear == year) {
                        CHAR c = 'a';
                        CHAR s[11+MAXACTIONSTRINGLENGTH];
                        BYTE hour = alarm->AlarmHour;

                        if (alarm->options & SCHEDULE_LAUNCHAPP) {
                            short j = 10;
                            short k = 0;
                            strcpy(s, MSG51);
                            menuItem = Menus[((int)alarmPtr[i]->ActionToDo[0])][((int)alarmPtr[i]->ActionToDo[1])];
                            while (menuItem->ItemName[k] !='\0')
                                if (menuItem->ItemName[k] =='~')
                                    k++;
                                else
                                    s[j++] = menuItem->ItemName[k++];
                            s[j] = '\0';
                            }
                        else
                            strcpy(s, alarm->ActionToDo);

                        if (alarm->AlarmHour>11)
                            c='p';
                        if (!(hour = hour % 12))
                            hour = 12;

                        sprintf( temp, "%2d:%2d%cm (%2d:%2d) -- %s", hour,
                                                                    alarm->AlarmMinute,
                                                                    c,
                                                                    alarm->AlarmHour,
                                                                    alarm->AlarmMinute,
                                                                    s );
                        if (temp[3]==' ') {
                            temp[3] = '0';
                            temp[12]= '0';
                            }


                        WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS, LM_INSERTITEM, MPFROMSHORT( LIT_END ), temp );
                        }
                }

            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if ((SHORT1FROMMP(mp1)==SCHEDULEDITEMS) && (SHORT2FROMMP(mp1)==LN_ENTER))
                return WinSendMsg( hWnd, WM_COMMAND, MPFROM2SHORT( REVISEITEM, 0 ), mp2 );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);

            //------------------------------------------------------------------
            //------------------------------------------------------------------
            if ( command==DELETEITEM ) {
                BOOL continueOn = TRUE;
                SHORT index = 0;
                SHORT item = 0;
                SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS,
                                                                      LM_QUERYSELECTION,
                                                                      MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                      0 ) );
                if (itemSelected==LIT_NONE) {
                    WinMessageBox( HWND_DESKTOP, hwndFrame,
                                   MSG53,
                                   MSG54, 0,
                                   MB_MOVEABLE|MB_ERROR|MB_OK);
                    return 0;
                    }

                if (WinMessageBox( HWND_DESKTOP, hwndFrame,
                                   MSG55,
                                   MSG54, 0,
                                   MB_MOVEABLE|MB_ICONQUESTION|MB_YESNO) == MBID_NO)
                    return 0;

                itemSelected++;
                while (continueOn) {
                    if ((alarmPtr[index]->AlarmYear  == (BYTE)(year%100)) &&
                        (alarmPtr[index]->AlarmMonth == (BYTE)(month%14)) &&
                        (alarmPtr[index]->AlarmDay   == (BYTE)(day%40))) {
                            item++;
                            if (item == itemSelected)
                                continueOn = FALSE;
                            }
                    index++;
                    }

                delete alarmPtr[index-1];
                {
                    struct ALARMS* tmp;
                    //struct ALARMS tmp;
                    for ( item=index-1; item<MAXALARMS-1; item++) {
                        tmp = alarmPtr[item];
                        alarmPtr[item]   = alarmPtr[item+1];
                        alarmPtr[item+1] = tmp;
                        }
                }
                numAlarms = oldProgType-1;
                sortTimeEntries( numAlarms );
                WinSendMsg( hWnd, WM_INITDLG, 0, 0 );
                if (index-1 >= oldProgType)
                    WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS, LM_SELECTITEM,
                                       MPFROM2SHORT( oldProgType-1, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                else
                    WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS, LM_SELECTITEM,
                                       MPFROM2SHORT( index-1, 0 ),
                                       MPFROM2SHORT( TRUE, 0 ) );
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            if ( command==ADDITEM ) {
                ALARMS* alarm;
                SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS,
                                                                      LM_QUERYSELECTION,
                                                                      MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                      0 ) );
                if (oldProgType == MAXALARMS) {
                    WinMessageBox( HWND_DESKTOP, hwndFrame,
                                   MSG56,
                                   MSG57, 0,
                                   MB_MOVEABLE|MB_ERROR|MB_OK);
                    return 0;
                    }

                alarmPtr[oldProgType] = new ALARMS;
                alarm = alarmPtr[oldProgType];
                alarm->AlarmYear = (BYTE)(year%100);
                alarm->AlarmMonth = (BYTE)(month%14);
                alarm->AlarmDay = (BYTE)(day%40);
                alarm->AlarmHour = 0;
                alarm->AlarmMinute = 0;
                alarm->options = SCHEDULE_USEWAVFILE | SCHEDULE_USEWAVFILE;
                alarm->ActionToDo[0] = 0;
                alarm->ReminderWAV[0] = 0;
                oldProgType++;
                reviseScheduledItem( oldProgType-1 );
                sortTimeEntries( oldProgType );
                numAlarms = oldProgType;
                WinSendMsg( hWnd, WM_INITDLG, 0, 0 );
                WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS, LM_SELECTITEM,
                                   MPFROM2SHORT( itemSelected, 0 ),
                                   MPFROM2SHORT( TRUE, 0 ) );
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            if (( command==REVISEITEM ) || (command==LN_ENTER)) {
                BOOL continueOn = TRUE;
                SHORT index = 0;
                SHORT item = 0;
                SHORT itemSelected = 1 + SHORT1FROMMP( WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS,
                                                                          LM_QUERYSELECTION,
                                                                          MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                          0 ) );

                if ( (itemSelected-1) == LIT_NONE ) {
                    WinMessageBox( HWND_DESKTOP, hwndFrame,
                                   MSG58,
                                   MSG59, 0,
                                   MB_MOVEABLE|MB_ERROR|MB_OK);
                    return 0;
                    }

                while (continueOn) {
                    if ((alarmPtr[index]->AlarmYear  == (BYTE)(year%100)) &&
                        (alarmPtr[index]->AlarmMonth == (BYTE)(month%14)) &&
                        (alarmPtr[index]->AlarmDay   == (BYTE)(day%40))) {
                            item++;
                            if (item == itemSelected)
                                continueOn = FALSE;
                            }
                    index++;
                    }
                reviseScheduledItem( index-1 );
                sortTimeEntries( oldProgType );
                numAlarms = oldProgType;
                WinSendMsg( hWnd, WM_INITDLG, 0, 0 );
                WinSendDlgItemMsg( hWnd, SCHEDULEDITEMS, LM_SELECTITEM,
                                   MPFROM2SHORT( itemSelected-1, 0 ),
                                   MPFROM2SHORT( TRUE, 0 ) );
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            if ( command==DID_OK ) {
                WinDismissDlg( hWnd, TRUE );
                numAlarms = oldProgType;
                return 0;
                }
            }
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
VOID checkAlarms( SHORT hour, SHORT minute, SHORT month, SHORT day, SHORT year ) {
    ALARMS* alarm = alarmPtr[0];
    struct tm *time_now;
    time_t currentTime;

    day--;
    if ((numAlarms == 0) || (alarm->AlarmYear > year ))
        return;
    if ((alarm->AlarmYear == year) && (alarm->AlarmMonth > month))
        return;
    if ((alarm->AlarmMonth == month) && (alarm->AlarmDay > day))
        return;
    if ((alarm->AlarmDay == day) && (alarm->AlarmHour > hour))
        return;
    if ((alarm->AlarmHour == hour) && (alarm->AlarmMinute > minute))
        return;

    if ((alarm->options & SCHEDULE_LAUNCHAPP) && (!(alarm->options & SCHEDULE_SOUNDONLY)))
        startApplication( (SHORT)alarm->ActionToDo[0], (SHORT)alarm->ActionToDo[1] );
    else {
        currentReminderWavFile = 0;
        if (alarm->options & SCHEDULE_USEWAVFILE)
            currentReminderWavFile = alarm->ReminderWAV;
        if (alarm->options & SCHEDULE_SOUNDONLY)
            ringChime( currentReminderWavFile );
        else {
            oldItemName[0] = TRUE;
            WinDlgBox(HWND_DESKTOP,
            hwndFrame,
            (PFNWP)reminderNoteProc,
            0,
            REMINDER_DIALOG,
            (PVOID)alarm->ActionToDo);
            if (oldItemName[0]) {
                checkAlarms( hour, minute, month, day, year );
                return;
                }
            }
        }

        // make it so that we reschedule from the current time
        // and not the time the task was supposed to go off
        tzset();
        time(&currentTime);
        time_now = localtime( &currentTime );

        // reschedule or delete note
        if (alarm->options & SCHEDULE_EVERYHOUR) {
            alarm->AlarmHour = time_now->tm_hour;
            alarm->AlarmDay = time_now->tm_mday-1;
            alarm->AlarmMonth = time_now->tm_mon;
            alarm->AlarmYear = time_now->tm_year;

            alarm->AlarmHour++;
            validateTimeEntry();
            sortTimeEntries( numAlarms );
            }
        else if (alarm->options & SCHEDULE_EVERYDAY) {
            alarm->AlarmDay = time_now->tm_mday-1;
            alarm->AlarmMonth = time_now->tm_mon;
            alarm->AlarmYear = time_now->tm_year;
            alarm->AlarmDay++;
            validateTimeEntry();
            sortTimeEntries( numAlarms );
            }
        else if (alarmPtr[0]->options & SCHEDULE_EVERYWEEK) {
            alarm->AlarmDay = time_now->tm_mday-1;
            alarm->AlarmMonth = time_now->tm_mon;
            alarm->AlarmYear = time_now->tm_year;
            alarm->AlarmDay = alarm->AlarmDay + 7;
            validateTimeEntry();
            sortTimeEntries( numAlarms );
            }
        else if (alarm->options & SCHEDULE_EVERYMONTH) {
            alarm->AlarmMonth = time_now->tm_mon;
            alarm->AlarmYear = time_now->tm_year;
            alarm->AlarmMonth++;
            validateTimeEntry();
            sortTimeEntries( numAlarms );
            }
        else if (alarm->options & SCHEDULE_EVERYYEAR) {
            alarm->AlarmYear = time_now->tm_year;
            alarm->AlarmYear++;
            validateTimeEntry();
            sortTimeEntries( numAlarms );
            }
        else {
        ////// delete the reminder we just performed ///////
            delete alarm;
            for (short i=0; i<numAlarms-1; i++)
                alarmPtr[i] = alarmPtr[i+1];
            numAlarms--;
            }
        // check to see if another alarm needs to be serviced
        checkAlarms( hour, minute, month, day, year );
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
VOID validateTimeEntry( VOID )
{
    ALARMS* alarm = alarmPtr[0];

    if (alarm->AlarmMinute > 59) {
        alarm->AlarmMinute = alarm->AlarmMinute - 60;
        alarm->AlarmHour++;
        }
    if (alarm->AlarmHour > 23) {
        alarm->AlarmMinute = alarm->AlarmMinute - 24;
        alarm->AlarmDay++;
        }
    if (alarm->AlarmDay > daysInMonth[alarm->AlarmMonth] ) {
        alarm->AlarmDay = alarm->AlarmDay - daysInMonth[alarm->AlarmMonth];
        alarm->AlarmMonth++;
        }
    if (alarm->AlarmMonth > 11) {
        alarm->AlarmMonth = alarm->AlarmMonth - 12;
        alarm->AlarmYear++;
        }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
VOID swapTwoTimeEntries( INT entry1, INT entry2 )
{
    ALARMS* tmp;

    tmp = alarmPtr[entry1];
    alarmPtr[entry1] = alarmPtr[entry2];
    alarmPtr[entry2] = tmp;
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
VOID sortTimeEntries( INT entries )
{
    short i,j;

    // bubble sort all scheduled events so that closest event tops the list
    for (i=0; i<entries; i++)
        for (j=0; j<entries-1; j++)
            if ( alarmPtr[j]->AlarmMinute > alarmPtr[j+1]->AlarmMinute )
                swapTwoTimeEntries(j, j+1);
    for (i=0; i<entries; i++)
        for (j=0; j<entries-1; j++)
            if ( alarmPtr[j]->AlarmHour > alarmPtr[j+1]->AlarmHour )
                swapTwoTimeEntries(j, j+1);
    for (i=0; i<entries; i++)
        for (j=0; j<entries-1; j++)
            if ( alarmPtr[j]->AlarmDay > alarmPtr[j+1]->AlarmDay )
                swapTwoTimeEntries(j, j+1);
    for (i=0; i<entries; i++)
        for (j=0; j<entries-1; j++)
            if ( alarmPtr[j]->AlarmMonth > alarmPtr[j+1]->AlarmMonth )
                swapTwoTimeEntries(j, j+1);
    for (i=0; i<entries; i++)
        for (j=0; j<entries-1; j++)
            if ( alarmPtr[j]->AlarmYear > alarmPtr[j+1]->AlarmYear )
                swapTwoTimeEntries(j, j+1);
}


////////////////////////////////////////////////////////////////////////////////
// reviseScheduledItem - call dialog box to revise a currently scheduled event
////////////////////////////////////////////////////////////////////////////////
VOID reviseScheduledItem( INT itemToEdit )
{
    EditItem = itemToEdit;
    WinDlgBox(HWND_DESKTOP,
              hwndFrame,
              (PFNWP)itemProc,
              0,
              SCHEDULEITEMDIALOG,
              (PVOID)0);
    return;
}


////////////////////////////////////////////////////////////////////////////////
// displayReminderTime - update display of time in revision dialog box
////////////////////////////////////////////////////////////////////////////////
VOID displayReminderTime( HWND hWnd, INT offset )
{
    SHORT hour;
    CHAR c;
    CHAR time[16];
    ALARMS* alarm = alarmPtr[offset];

    c='a';
    if (alarm->AlarmHour>11)
        c='p';
    if (!(hour = alarm->AlarmHour % 12))
        hour = 12;

    sprintf( time, "%2d:%2d%cm (%2d:%2d)", hour,
                                           alarm->AlarmMinute,
                                           c,
                                           alarm->AlarmHour,
                                           alarm->AlarmMinute);
    if (time[3]==' ') {
        time[3] = '0';
        time[12]= '0';
        }
    WinSetDlgItemText( hWnd, TIME_TEXT, (CHAR*)time );
}


////////////////////////////////////////////////////////////////////////////////
// displayReminderDate - update display of date in revision dialog box
////////////////////////////////////////////////////////////////////////////////
VOID displayReminderDate( HWND hWnd, INT offset )
{
    ALARMS* alarm = alarmPtr[offset];
    CHAR date[24];

    sprintf( date, " %d/%d/%d (%d/%d/%d) ",  alarm->AlarmMonth+1,
                                             alarm->AlarmDay+1,
                                             alarm->AlarmYear,
                                             alarm->AlarmDay+1,
                                             alarm->AlarmMonth+1,
                                             alarm->AlarmYear);
    WinSetDlgItemText( hWnd, DATETEXT, (CHAR*)date );
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY itemProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   ALARMS* alarm = alarmPtr[EditItem];

   switch( msg )
    {
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            CHAR s[MAXPATH+11];
            SWP swp;
            //ALARMS* alarm = alarmPtr[EditItem];

            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            WinSendDlgItemMsg( hWnd, SOUNDFILE, EM_SETTEXTLIMIT, MPFROMSHORT( MAXACTIONSTRINGLENGTH ), 0 );
            WinSendDlgItemMsg( hWnd, REMINDER, EM_SETTEXTLIMIT, MPFROMSHORT( MAXACTIONSTRINGLENGTH ), 0 );

            WinCheckButton( hWnd, DELETEITEM, TRUE );
            if (alarm->options & SCHEDULE_EVERYHOUR)
                WinCheckButton( hWnd, EVERYHOUR, TRUE );
            else if (alarm->options & SCHEDULE_EVERYDAY)
                WinCheckButton( hWnd, EVERYDAY, TRUE );
            else if (alarm->options & SCHEDULE_EVERYWEEK)
                WinCheckButton( hWnd, EVERYWEEK, TRUE );
            else if (alarm->options & SCHEDULE_EVERYMONTH)
                WinCheckButton( hWnd, EVERYMONTH, TRUE );
            else if (alarm->options & SCHEDULE_EVERYYEAR)
                WinCheckButton( hWnd, EVERYYEAR, TRUE );

            if ( alarm->options & SCHEDULE_USEWAVFILE )
                WinCheckButton( hWnd, PLAYSOUND, TRUE );
            if ( alarm->options & SCHEDULE_SOUNDONLY )
                WinCheckButton( hWnd, SOUNDONLY, TRUE );

            WinSetDlgItemText( hWnd, SOUNDFILE, (CHAR*)alarm->ReminderWAV );
            displayReminderTime( hWnd, EditItem );
            displayReminderDate( hWnd, EditItem );

            if (alarm->options & SCHEDULE_LAUNCHAPP) {
                short j = 10;
                short k = 0;
                USERMENUITEM* menuItem = Menus[((int)alarmPtr[EditItem]->ActionToDo[0])][((int)alarmPtr[EditItem]->ActionToDo[1])];

                strcpy(s, MSG51 );
                while (menuItem->ItemName[k] !='\0')
                    if (menuItem->ItemName[k] =='~')
                        k++;
                    else
                        s[j++] = menuItem->ItemName[k++];
                s[j] = '\0';

                WinSetDlgItemText( hWnd, REMINDER, (CHAR*)s );
                WinEnableControl( hWnd, REMINDER, FALSE );
                }
            else {
                WinEnableControl( hWnd, REMINDER, TRUE );
                WinSetDlgItemText( hWnd, REMINDER, (CHAR*)alarm->ActionToDo );
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);


            switch(command) {
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case LAUNCHITEM: {
                    short tmp = 0;

                    if (WinQueryButtonCheckstate( hWnd, EVERYHOUR ))
                        tmp += SCHEDULE_EVERYHOUR;
                    else if (WinQueryButtonCheckstate( hWnd, EVERYDAY ))
                        tmp += SCHEDULE_EVERYDAY;
                    else if (WinQueryButtonCheckstate( hWnd, EVERYWEEK ))
                        tmp += SCHEDULE_EVERYWEEK;
                    else if (WinQueryButtonCheckstate( hWnd, EVERYMONTH ))
                        tmp += SCHEDULE_EVERYMONTH;
                    else if (WinQueryButtonCheckstate( hWnd, EVERYYEAR ))
                        tmp += SCHEDULE_EVERYYEAR;
                    if (WinQueryButtonCheckstate( hWnd, PLAYSOUND ))
                        tmp += SCHEDULE_USEWAVFILE;
                    if (WinQueryButtonCheckstate( hWnd, SOUNDONLY ))
                        tmp += SCHEDULE_SOUNDONLY;

                    WinDlgBox(HWND_DESKTOP,
                              hWnd,
                              (PFNWP)LaunchItemProc,
                              0,
                              LAUNCHITEMDIALOG,
                              (PVOID)0);

                    if (alarm->options & SCHEDULE_LAUNCHAPP)
                        tmp = tmp + SCHEDULE_LAUNCHAPP;

                    alarm->options = tmp;
                    WinSendMsg( hWnd, WM_INITDLG, 0, 0 );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case SELECTSOUNDFILE: {
                    CHAR title[] = MSG60;
                    HWND hwndDialog;
                    CHAR oldDir[MAXPATH];

                    fileDlgInfo.fl = FDS_OPEN_DIALOG|FDS_CENTER;
                    fileDlgInfo.pszTitle = title;
                    strcpy( oldDir, fileDlgInfo.szFullFile );
                    strcat(fileDlgInfo.szFullFile, "*.WAV\0");

                    hwndDialog = WinFileDlg( HWND_DESKTOP, hWnd, &fileDlgInfo );
                    if (hwndDialog && (fileDlgInfo.lReturn == DID_OK)) {
                        strcpy( alarm->ReminderWAV, fileDlgInfo.szFullFile );
                        strcat( alarm->ReminderWAV, "\0" );
                        resetFileDialog();

                        /*
                        s=0;
                        while(fileDlgInfo.szFullFile[s]!='\0')
                            s++;
                        while((fileDlgInfo.szFullFile[s]!='\\') && (s>=0))
                            s--;

                        if (fileDlgInfo.szFullFile[s]=='\\')
                            fileDlgInfo.szFullFile[s+1]='\0';
                        else
                            fileDlgInfo.szFullFile[0]='\0';
                        */

                        WinSetDlgItemText( hWnd, SOUNDFILE, alarm->ReminderWAV );
                        }
                    else
                        strcpy( fileDlgInfo.szFullFile, oldDir );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case DAY_MORE: {
                    alarm->AlarmDay = (alarm->AlarmDay + 1) % daysInMonth[alarm->AlarmMonth];
                    displayReminderDate( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case DAY_LESS: {
                    if (alarm->AlarmDay==0)
                        alarm->AlarmDay = daysInMonth[alarm->AlarmMonth] - 1;
                    else
                        alarm->AlarmDay = (alarm->AlarmDay - 1) % daysInMonth[alarm->AlarmMonth];
                    displayReminderDate( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case MONTH_MORE: {
                    alarm->AlarmMonth = (alarm->AlarmMonth + 1) % 12;
                    displayReminderDate( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case MONTH_LESS: {
                    if (alarm->AlarmMonth == 0)
                        alarm->AlarmMonth = 11;
                    else
                        alarm->AlarmMonth--;
                    displayReminderDate( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case YEAR_MORE: {
                    alarm->AlarmYear++;
                    displayReminderDate( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case YEAR_LESS: {
                    alarm->AlarmYear--;
                    displayReminderDate( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case MINUTE_MORE: {
                    alarm->AlarmMinute = (alarm->AlarmMinute+1) % 60;
                    displayReminderTime( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case MINUTE_LESS: {
                    if (alarm->AlarmMinute == 0)
                        alarm->AlarmMinute = 59;
                    else
                        alarm->AlarmMinute = (alarm->AlarmMinute-1) % 60;
                    displayReminderTime( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case HOUR_MORE: {
                    alarm->AlarmHour = (alarm->AlarmHour+1) % 24;
                    displayReminderTime( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case HOUR_LESS: {
                    if (alarm->AlarmHour == 0)
                        alarm->AlarmHour = 23;
                    else
                        alarm->AlarmHour = (alarm->AlarmHour-1) % 24;
                    displayReminderTime( hWnd, EditItem );
                    return 0;
                    }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
                case DID_OK:  {
                    if (alarm->options & SCHEDULE_LAUNCHAPP)
                        alarm->options = SCHEDULE_LAUNCHAPP;
                    else {
                        alarm->options = 0;
                        WinQueryDlgItemText( hWnd, REMINDER,
                                             MAXACTIONSTRINGLENGTH,
                                             (PSZ)alarm->ActionToDo );
                        }

                if (WinQueryButtonCheckstate( hWnd, EVERYHOUR ))
                    alarm->options += SCHEDULE_EVERYHOUR;
                else if (WinQueryButtonCheckstate( hWnd, EVERYDAY ))
                    alarm->options += SCHEDULE_EVERYDAY;
                else if (WinQueryButtonCheckstate( hWnd, EVERYWEEK ))
                    alarm->options += SCHEDULE_EVERYWEEK;
                else if (WinQueryButtonCheckstate( hWnd, EVERYMONTH ))
                    alarm->options += SCHEDULE_EVERYMONTH;
                else if (WinQueryButtonCheckstate( hWnd, EVERYYEAR ))
                    alarm->options += SCHEDULE_EVERYYEAR;

                if (WinQueryButtonCheckstate( hWnd, PLAYSOUND ))
                    alarm->options += SCHEDULE_USEWAVFILE;
                if (WinQueryButtonCheckstate( hWnd, SOUNDONLY ))
                    alarm->options += SCHEDULE_SOUNDONLY;

                WinQueryDlgItemText( hWnd, SOUNDFILE,
                                     MAXACTIONSTRINGLENGTH,
                                     (PSZ)alarm->ReminderWAV );

                WinDismissDlg( hWnd, TRUE );
                return 0;
                }
                default:
                    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );

    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY reminderNoteProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_TIMER: {
            ringChime( currentReminderWavFile );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            noteTimerNumber = WinStartTimer( hab, hWnd, TIMERID+1, (LONG)repeatTime*1000 );
            numberOfAlarms = numAlarms;
            numAlarms = 0;
            if (mp2 != 0)
                WinSetDlgItemText( hWnd, REMINDER, (CHAR*)LONGFROMMP( mp2 ) );
            WinPostMsg( hWnd, WM_TIMER, mp1, mp2 );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            USHORT command = SHORT1FROMMP(mp1);

            switch(command) {
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            case DID_OK: {
                WinStopTimer( hab, TIMERID+1, noteTimerNumber );
                WinDismissDlg( hWnd, TRUE );
                numAlarms = numberOfAlarms;
                oldItemName[0] = FALSE;
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            case SNOOZE: {
                ALARMS* alarm = alarmPtr[0];
                struct tm *time_now;
                time_t currentTime;

                WinStopTimer( hab, TIMERID+1, noteTimerNumber );

                tzset();
                time(&currentTime);
                time_now = localtime( &currentTime );
                alarm->AlarmDay = time_now->tm_mday-1;
                alarm->AlarmMonth = time_now->tm_mon;
                alarm->AlarmYear = time_now->tm_year;
                alarm->AlarmHour = time_now->tm_hour;
                alarm->AlarmMinute = time_now->tm_min + 9;

                validateTimeEntry();
                sortTimeEntries( numberOfAlarms );
                WinDismissDlg( hWnd, TRUE );
                numAlarms = numberOfAlarms;
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            case REVISE: {
                WinStopTimer( hab, TIMERID+1, noteTimerNumber );
                reviseScheduledItem( 0 );
                validateTimeEntry();
                sortTimeEntries( numberOfAlarms );
                WinDismissDlg( hWnd, TRUE );
                numAlarms = numberOfAlarms;
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            case ERASE: {
                WinStopTimer( hab, TIMERID+1, noteTimerNumber );
                if (WinMessageBox( HWND_DESKTOP, hwndFrame,
                                   MSG61,
                                   MSG62, 0,
                                   MB_MOVEABLE|MB_ICONQUESTION|MB_YESNO)==MBID_YES) {
                    delete alarmPtr[ 0 ];
                    for (short i=1; i<MAXALARMS; i++)
                        alarmPtr[ i-1 ] = alarmPtr[ i ];
                    WinDismissDlg( hWnd, TRUE );
                    numAlarms = numberOfAlarms-1;
                    }
                noteTimerNumber = WinStartTimer( hab, hWnd, TIMERID+1, (LONG)repeatTime*1000 );
                return 0;
                }
            //------------------------------------------------------------------
            //------------------------------------------------------------------
            default:
                return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY LaunchItemProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   ALARMS* alarm = alarmPtr[EditItem];

   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SHORT i,j;
            CHAR temp[MAXACTIONSTRINGLENGTH+5];
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            oldAction[LAUNCHED] = alarm->options & SCHEDULE_LAUNCHAPP;
            WinSendDlgItemMsg( hWnd, CURITEMLIST, LM_DELETEALL, 0, 0);
            temp[0] = ' ';
            temp[1] = ' ';
            temp[2] = '-';
            temp[3] = ' ';
            for (i=0; i<NumMenus; i++) {
                WinSendDlgItemMsg( hWnd, CURITEMLIST, LM_INSERTITEM, MPFROMSHORT( LIT_END ), MenuName[i] );
                for (j=0; j<NumItems[i]; j++)
                   if (Menus[i][j]->ItemName[0] != '\0') {
                        temp[4] = '\0';
                        strcat(temp, Menus[i][j]->ItemName);
                        WinSendDlgItemMsg( hWnd, CURITEMLIST, LM_INSERTITEM, MPFROMSHORT( LIT_END ), temp );
                        }
                }

            // if they had requested to launch an application previously
            // restore their choice in the dialog box
            WinCheckButton( hWnd, LAUNCHITEM, FALSE );
            if (oldAction[LAUNCHED]) {
                SHORT item, index;
                WinCheckButton( hWnd, LAUNCHITEM, TRUE );

                item = 0;
                index = alarm->ActionToDo[0];
                if (index > 0) {
                    for (i=0; i<index; i++) {
                        item++;
                        for (j=0; j<NumItems[i]; j++)
                            if (Menus[i][j]->ItemName[0] != '\0')
                                item++;
                        }
                    }

                item += alarm->ActionToDo[1]+1;

                for (j=0; j<alarm->ActionToDo[1]; j++)
                    if (Menus[index][j]->ItemName[0] == '\0')
                        item--;

                WinSendDlgItemMsg( hWnd, CURITEMLIST, LM_SELECTITEM,
                                   MPFROM2SHORT( item, 0 ),
                                   MPFROM2SHORT( TRUE, 0 ) );
                }

            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if (SHORT1FROMMP(mp1)==CURITEMLIST) {
                if (SHORT2FROMMP(mp1)==LN_ENTER) {
                    WinCheckButton( hWnd, LAUNCHITEM, TRUE );
                    WinSendMsg( hWnd, WM_COMMAND, MPFROMSHORT(DID_OK), 0 );
                    }
                if (SHORT2FROMMP(mp1)==LN_SELECT)
                    WinCheckButton( hWnd, LAUNCHITEM, TRUE );
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            if (SHORT1FROMMP(mp1)==DID_OK) {
                SHORT itemSelected = SHORT1FROMMP( WinSendDlgItemMsg( hWnd, CURITEMLIST,
                                                                      LM_QUERYSELECTION,
                                                                      MPFROM2SHORT( LIT_FIRST, 0 ),
                                                                      0 ) );
                if (WinQueryButtonCheckstate( hWnd, LAUNCHITEM )) {
                        short i,j;
                        char temp[MAXPATH];

                        WinSendDlgItemMsg( hWnd, CURITEMLIST,
                                               LM_QUERYITEMTEXT,
                                               MPFROM2SHORT( itemSelected, sizeof(temp) ),
                                               (PSZ)temp );

                        if (strncmp(temp, "  - ", 4) != 0) {
                            WinMessageBox( HWND_DESKTOP, hwndFrame,
                                           MSG63,
                                           MSG64, 0,
                                           MB_MOVEABLE|MB_ERROR|MB_OK);
                            return 0;
                            }

                        if ( !oldAction[LAUNCHED] )
                            alarm->options += SCHEDULE_LAUNCHAPP;

                        for (i=0; i<NumMenus; i++)
                            for (j=0; j<NumItems[i]; j++)
                                if (strcmp( temp+4, Menus[i][j]->ItemName ) == 0) {
                                    alarm->ActionToDo[0] = i;
                                    alarm->ActionToDo[1] = j;
                                    }
                    }
                else {
                    if ( oldAction[LAUNCHED] ) {
                        alarm->options -= SCHEDULE_LAUNCHAPP;
                        alarm->ActionToDo[0] = 0;
                        }
                    }
                WinDismissDlg( hWnd, TRUE );
                return 0;
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY popUpOptionsProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);
            WinCheckButton( hWnd, MOUSE_CHORD, (popUpMessageID==WM_CHORD) );
            WinCheckButton( hWnd, MOUSE_BUT3, (popUpMessageID==WM_BUTTON3CLICK) );
            WinCheckButton( hWnd, HIDE_FILEBAR, (hideFileBar==TRUE) );
            WinCheckButton( hWnd, ENABLE_POPUP, (allowPopUpMenu==TRUE) );
            WinEnableControl( hWnd, REMINDER, FALSE );

            if (WinQueryButtonCheckstate( hWnd, HIDE_FILEBAR ))
                WinEnableControl( hWnd, ENABLE_POPUP, FALSE );
            else
                WinEnableControl( hWnd, ENABLE_POPUP, TRUE );

            if (WinQueryButtonCheckstate( hWnd, ENABLE_POPUP ))
                WinEnableControl( hWnd, HIDE_FILEBAR, TRUE );
            else
                WinEnableControl( hWnd, HIDE_FILEBAR, FALSE );

            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }
        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_CONTROL:
        {
            if (WinQueryButtonCheckstate( hWnd, HIDE_FILEBAR ))
                WinEnableControl( hWnd, ENABLE_POPUP, FALSE );
            else
                WinEnableControl( hWnd, ENABLE_POPUP, TRUE );

            if (WinQueryButtonCheckstate( hWnd, ENABLE_POPUP ))
                WinEnableControl( hWnd, HIDE_FILEBAR, TRUE );
            else
                WinEnableControl( hWnd, HIDE_FILEBAR, FALSE );
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }

        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            if (WinQueryButtonCheckstate( hWnd, MOUSE_CHORD ))
                popUpMessageID = WM_CHORD;
            else      //if (WinQueryButtonCheckstate( hWnd, MOUSE_BUT3 ))
                popUpMessageID = WM_BUTTON3CLICK;
            hideFileBar = WinQueryButtonCheckstate( hWnd, HIDE_FILEBAR );
            allowPopUpMenu = WinQueryButtonCheckstate( hWnd, ENABLE_POPUP );
            setFileBarScreen( (BOOL)(BarPosition==AT_TOP), MenuHeight, (interceptMsg==TRUE),
                              allowPopUpMenu, popUpMessageID );
            if (hideFileBar)
                WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_HIDE);
            else
                WinSetWindowPos( hwndFrame, (HWND)0, 0, 0, 0, 0, SWP_SHOW);
            WinDismissDlg( hWnd, TRUE );
            return 0;
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            break;
    }
    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
VOID changePassword( CHAR* password )
{
    char mesg[64];
    char newpwd[PASSWORDLEN+1];

    sprintf( parameterTitle, MSG65 );
    sprintf( mesg, MSG66 );
    ParameterTextPtr = mesg;
    oldProgType = PASSWORDLEN;
    (VOID*)WinDlgBox(HWND_DESKTOP,
                     hwndFrame,
                     (PFNWP)EnterParamProc,
                     0,
                     PASSWORDENTRY,
                     (PVOID)NULL);
    strcpy( newpwd, variableText );

    sprintf( mesg, MSG67 );
    ParameterTextPtr = mesg;
    (VOID*)WinDlgBox(HWND_DESKTOP,
                     hwndFrame,
                     (PFNWP)EnterParamProc,
                     0,
                     PASSWORDENTRY,
                     (PVOID)NULL);

    if (strcmp( newpwd, variableText ) == 0) {
        strcpy( password, newpwd );
        WinMessageBox( HWND_DESKTOP, hwndFrame,
                       MSG68,
                       MSG69, 0,
                       MB_MOVEABLE|MB_ICONEXCLAMATION|MB_OK);
        }
    else
        WinMessageBox( HWND_DESKTOP, hwndFrame,
                       MSG70,
                       MSG69, 0,
                       MB_MOVEABLE|MB_ERROR|MB_OK);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
MRESULT EXPENTRY globalPasswordProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   switch( msg )
    {
        //----------------------------------------------------------------------
        // when the dialog is being initialized, center it on desktop
        //----------------------------------------------------------------------
        case WM_INITDLG: {
            SWP swp;
            WinQueryWindowPos( hWnd, (PSWP)&swp);
            WinSetWindowPos( hWnd, (HWND)0,
                             ((SHORT)((ScreenSizeX-swp.cx)/2)),
                             ((SHORT)((ScreenSizeY-swp.cy)/2)),
                             0, 0, SWP_MOVE);

            WinCheckButton( hWnd, USEPASSWORD, (globalProtection==YES) );
            tmpBuffer[0] = globalProtection;

            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
            }

        //----------------------------------------------------------------------
        // if we receive any system message, dismiss the dialog box
        //----------------------------------------------------------------------
        case WM_COMMAND:
        {
            if (SHORT1FROMMP(mp1)==DID_OK) {
                if (WinQueryButtonCheckstate( hWnd, USEPASSWORD ))
                    globalProtection=YES;
                else
                    globalProtection=NO;
                WinDismissDlg( hWnd, TRUE );
                }
            else if (SHORT1FROMMP(mp1)==CHANGEPASSWORD) {
                if ((globalProtection==YES) && ( !checkAgainstPassWord( password ) ))
                    return 0;
                changePassword( password );
                return 0;
                }
            return WinDefDlgProc( hWnd, msg, mp1, mp2 );
        }
        //----------------------------------------------------------------------
        // if nothing further we want to intercept, pass message onto system
        //----------------------------------------------------------------------
        default:
            break;
    }
    return WinDefDlgProc( hWnd, msg, mp1, mp2 );
}




