home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / TOOLKIT / OS2 / EAEDIT / EAS.C next >
C/C++ Source or Header  |  1994-11-17  |  71KB  |  1,538 lines

  1. /*static char *SCCSID = "@(#)eas.c    6.14 92/03/18";*/
  2. /*==============================================================*\
  3.  *  EAS.C -New Extended Attribute Display sample PM application *
  4.  *                                                              *
  5.  *  (C) Copyright IBM Corporation 1992.                         *
  6.  *--------------------------------------------------------------*
  7.  *                                                              *
  8.  *  This program implements an extended attributes editor.      *
  9.  *  Included in this file are all of the PM interface procedures*
  10.  *  All of these procs represent procedures for dialog boxes.   *
  11.  *  This code is implemented as it was written to show how to   *
  12.  *  show how to use EA editor.                                  *
  13.  *                                                              *
  14.  *  The EA code revolves around the HoldFEA structure.  This    *
  15.  *  structure is a linked list which contains one EA per        *
  16.  *  structure.  Each HoldFEA structure is dynamically allocated *
  17.  *  as are the two string pointer members of the structure,     *
  18.  *  szName and aValue.  This is done to make handling the EAs   *
  19.  *  easier and more flexable.                                   *
  20.  *                                                              *
  21.  *  This application also serves as a template that can be      *
  22.  *  easily modified by an application developer.  The source    *
  23.  *  files are organized so that the overhead code that should   *
  24.  *  be in all applications is located in the same files so      *
  25.  *  that these files do not need to be modified.  The routines  *
  26.  *  that deal with application specific code are also located   *
  27.  *  in their own modules.  An application developer need only   *
  28.  *  change these files in order to modify this template for     *
  29.  *  his application.                                            *
  30.  *                                                              *
  31.  *--------------------------------------------------------------*
  32.  *  Procedures in this file:                                    *
  33.  *   main()         Sets up the PM environment and heap and     *
  34.  *                       calls the MainWndProc                  *
  35.  *   MainWndProc()  Handles the main window messages            *
  36.  *   MainPaint()    Handles the main paint window messages      *
  37.  *   MainCommand()  Handles the main command window messages    *
  38.  *   ProcExit()     Handles the WinClose window messages        *
  39.  *   UserCommand()  Handles the user command window messages    *
  40.  *   MainControl()  Handles the main control window messages    *
  41.  *   MessageBox     Handles all error messages                  *
  42.  *   AddEAProc()    Handles new EA name entry and type selection*
  43.  *   AsciiEditProc()Handles editing of EA name/value            *
  44.  *   IconDlgProc()  Unimplemented icon procedure handler        *
  45.  *   MultiTypeProc()Handles the Multi-type dialog box           *
  46.  *   ShowEAType()   Shows Selected EA Type for MainDlgProc      *
  47.  *   EditEA()       Handles selection of an EA in the listbox   *
  48.  *   GetCurFEA()    Gets a ptr to the hi-lited EA in the listbox*
  49.  *   GetMem()                                                   *
  50. \*==============================================================*/
  51. /*--------------------------------------------------------------*\
  52.  *  Include files, macros, defined constants, and externs       *
  53. \*--------------------------------------------------------------*/
  54. #include "eas.h"
  55.  
  56.        /* Setup the table, the order is related to DLGTEMPLATE of IDD_ADDEA */
  57. EADATA ConvTable[EATABLESIZE] = {
  58.    { EA_LPASCII   ,"Length preceeded ascii\0             ",IDD_LPDATA},
  59.    { EA_LPBINARY  ,"Length preceeded hex binary\0        ",IDD_LPDATA},
  60.    { EA_ASCIIZ    ,"Asciiz\0                             ",IDD_ASCIIZ},
  61.    { EA_LPMETAFILE,"Metafile\0                           ",IDD_LPDATA},
  62.    { EA_ASCIIZFN  ,"Asciiz file name of associated data\0",IDD_ASCIIZ},
  63.    { EA_ASCIIZEA  ,"Asciiz EA of associated data\0       ",IDD_ASCIIZ},
  64.    { EA_MVMT      ,"Multi value multi type field\0       ",IDD_MULTILIST},
  65.    { EA_ASN1      ,"ASN.1 field\0                        ",IDD_ASCIIZ},
  66.    { EA_LPBITMAP  ,"Length preceeded bitmap\0            ",IDD_LPDATA},
  67.    { EA_LPICON    ,"Length preceeded icon\0              ",IDD_LPDATA},
  68.    { EA_MVST      ,"Multi value single type field\0      ",IDD_MULTILIST},
  69.    { 0            ,"Non conventional format\0            ",IDD_ASCIIZ}
  70.    };
  71.  
  72. /****************************************************************\
  73.  *  Main routine                                                *
  74.  *--------------------------------------------------------------*
  75.  *                                                              *
  76.  *  Name:    main(int argc, char *argv[])                       *
  77.  *                                                              *
  78.  *  Purpose: Initializes the PM environment, calls the          *
  79.  *           initialization routine, creates the main window,   *
  80.  *           and polls the message queue.                       *
  81.  *                                                              *
  82.  *  Usage:                                                      *
  83.  *                                                              *
  84.  *  Method:  -obtains anchor block handle and creates message   *
  85.  *              queue                                           *
  86.  *           -calls the initialization routine                  *
  87.  *           -creates the main frame window which creates the   *
  88.  *              main client window                              *
  89.  *           -polls the message queue via Get/Dispatch Msg loop *
  90.  *           -upon exiting the loop, exits                      *
  91.  *                                                              *
  92.  *  Returns: 1 - if sucessful execution completed               *
  93.  *           0 - if error                                       *
  94.  *                                                              *
  95. \****************************************************************/
  96. INT main(int argc, char *argv[])
  97. {
  98.    QMSG qmsg;                                         /* message structure */
  99.    ULONG ctlData=FCF_SYSMENU | FCF_MENU | FCF_ICON | /* frame control data */
  100.                  FCF_TASKLIST | FCF_TITLEBAR |
  101.                  FCF_SIZEBORDER | FCF_ACCELTABLE |
  102.                  FCF_MINMAX | FCF_SHELLPOSITION;
  103.  
  104.    FILE_ISOPEN = FALSE;
  105.    FILE_CHANGED = FALSE;
  106.    COMMAND_LINE_FILE = FALSE;
  107.    if(argc > 1)                  /* If a command line file, get EAs from it */
  108.       if(ParseFileName(szFileName,argv[1]) != FILE_VALID)  /* Bad file name */
  109.          *szFileName=0;
  110.       else
  111.          COMMAND_LINE_FILE = TRUE;
  112.  
  113.    /* Note: The following 3 setup calls aren't currently checked for errors */
  114.    hab = WinInitialize(0);
  115.    if(!hab)  {
  116.        DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  117.        return(RETURN_ERROR);
  118.    }
  119.    hmq = WinCreateMsgQueue(hab, 0);
  120.    if(!hmq)  {
  121.        DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
  122.        WinTerminate(hab);
  123.        return(RETURN_ERROR);
  124.    }
  125.    if(!Init())
  126.    {
  127.        MessageBox(HWND_DESKTOP, IDMSG_INITFAILED, "Error !",
  128.                            MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
  129.        DosExit(EXIT_PROCESS, RETURN_ERROR);
  130.    }
  131.                                               /* create the main window */
  132.    hwndMainFrame = WinCreateStdWindow(HWND_DESKTOP,
  133.                                       WS_VISIBLE,
  134.                                       (PVOID)&ctlData,
  135.                                       (PSZ)szAppName,
  136.                                       (PSZ)NULL,
  137.                                       WS_VISIBLE,
  138.                                       (HMODULE)NULL,
  139.                                       ID_RESOURCE,
  140.                                       (PHWND)&hwndMain);
  141.    if(!hwndMainFrame)
  142.    {
  143.        MessageBox(HWND_DESKTOP, IDMSG_MAINWINCREATEFAILED, "Error !",
  144.                            MB_OK | MB_ERROR | MB_MOVEABLE, TRUE);
  145.        DosExit(EXIT_PROCESS, RETURN_ERROR);
  146.    }
  147.    InitHelp();
  148.  
  149.    while(WinGetMsg(hmq, (PQMSG)&qmsg, 0L, 0L, 0L))
  150.            WinDispatchMsg(hmq, (PQMSG)&qmsg);
  151.  
  152.                                            /* destroy the help instance */
  153.    DestroyHelpInstance();
  154.                                     /* will normally be put in ExitProc */
  155.    DosExit(EXIT_PROCESS, RETURN_SUCCESS);
  156.    return 0;
  157. }                                                              /* main() */
  158.  
  159. /****************************************************************\
  160.  *  Main client window procedure                                *
  161.  *--------------------------------------------------------------*
  162.  *                                                              *
  163.  *  Name:    MainWndProc(hwnd, msg, mp1, mp2)                   *
  164.  *                                                              *
  165.  *  Purpose: Processes the messages sent to the main client     *
  166.  *           window. This routine processes the basic messages  *
  167.  *           all client windows should process and passes all   *
  168.  *           others onto UserWndProc where the developer can    *
  169.  *           process any others.                                *
  170.  *                                                              *
  171.  *  Usage:   Called for each message placed in the main         *
  172.  *           window's message queue                             *
  173.  *                                                              *
  174.  *  Method:  a switch statement branches to the routines to be  *
  175.  *           performed for each message processed. Any messages *
  176.  *           not specifically process are passed to the user's  *
  177.  *           message processing procedure UserWndProc().        *
  178.  *                                                              *
  179.  *  Returns: Return values are determined by each message       *
  180.  *                                                              *
  181. \****************************************************************/
  182. MRESULT EXPENTRY MainWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  183. {
  184.    MRESULT sRC;
  185.  
  186.    switch(msg)
  187.    {
  188.       case WM_CREATE:
  189.           WinPostMsg(hwnd,WM_USER,(MPARAM)0,(MPARAM)0);
  190.           break;
  191.  
  192.       case WM_USER:  /* Posted by WM_INITDLG allows main window to open 1st */
  193.           if(COMMAND_LINE_FILE)
  194.           {
  195.              OpenFile(hwnd, ARGFILE);
  196.           }
  197.           break;
  198.       case WM_PAINT:
  199.           MainPaint(hwnd);
  200.           break;
  201.  
  202.       case WM_COMMAND:
  203.           MainCommand(hwnd, mp1, mp2);
  204.           break;
  205.  
  206.       case WM_CONTROL:
  207.           MainControl(hwnd, mp1, mp2);
  208.           break;
  209.  
  210.    /*--------------------------------------------------*\
  211.     *      Any messages not processed are passed on    *
  212.     *      to the user's window proc.  It is           *
  213.     *      responsible for passing any messages it     *
  214.     *      doesn't handle onto WinDefWindowProc()      *
  215.    \*--------------------------------------------------*/
  216.       case HM_QUERY_KEYS_HELP:
  217.           return ((MRESULT)PANEL_KEYSHELP);
  218.  
  219.       default:
  220.           sRC = WinDefWindowProc(hwnd, msg, mp1, mp2);
  221.           return sRC;
  222.    }
  223.    return (MRESULT)0L;
  224.                     /* all window procedures should return 0 as a default */
  225. }                                                        /* MainWndProc() */
  226.  
  227. /****************************************************************\
  228.  *  Main client painting routine                                *
  229.  *--------------------------------------------------------------*
  230.  *                                                              *
  231.  *  Name:    MainPaint(hwnd)                                    *
  232.  *                                                              *
  233.  *  Purpose: Paints the main client window.                     *
  234.  *                                                              *
  235.  *  Usage:   Routine is called whenver the client window        *
  236.  *           procedure receives a WM_PAINT message              *
  237.  *                                                              *
  238.  *  Method:  -begins painting by calling WinBeginPaint          *
  239.  *              and retriving the HPS for the window            *
  240.  *           -paint page info boxes                             *
  241.  *                                                              *
  242.  *           -ends painting by calling WinEndPaint              *
  243.  *                                                              *
  244.  *  Returns: VOID                                               *
  245.  *                                                              *
  246. \****************************************************************/
  247. VOID MainPaint(HWND hwnd)
  248. {
  249.    HPS    hps;                          /* Handle for painting           */
  250.    RECTL  rect;                         /* Rectangle struct for painting */
  251.    CHAR   szBuffer[BUFF_SIZE];
  252.    POINTL ptl;
  253.  
  254.    hps = WinBeginPaint(hwnd, 0L, (PRECTL)&rect);
  255.    WinFillRect(hps, (PRECTL)&rect, CLR_BACKGROUND);
  256.                               /* Fill update rectangle with window color */
  257.    WinQueryWindowRect(hwndMain, (PRECTL)&rect);
  258.  
  259.       ptl.x = HORZ_INDENT;
  260.       ptl.y = rect.yTop - VERT_TEXT_POS;
  261.       memset(szBuffer, 0, sizeof(szBuffer));
  262.       strcpy(szBuffer, "File Name:");
  263.       GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);
  264.  
  265.       ptl.x = HORZ_INDENT;
  266.       ptl.y = rect.yTop - VERT_TEXT_POS*3;
  267.       memset(szBuffer, 0, sizeof(szBuffer));
  268.       strcpy(szBuffer, "EA Type:");
  269.       GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);
  270.  
  271.       ptl.x = HORZ_INDENT;
  272.       ptl.y = rect.yTop - VERT_TEXT_POS*5;
  273.       memset(szBuffer, 0, sizeof(szBuffer));
  274.       strcpy(szBuffer, "EA Names:");
  275.       GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);
  276.  
  277.    if(FILE_ISOPEN)
  278.    {
  279.       ptl.x = HORZ_INDENT + 10;
  280.       ptl.y = rect.yTop - VERT_TEXT_POS*2;
  281.       GpiCharStringAt(hps, &ptl, strlen(szFileName), szFileName);
  282.  
  283.       ptl.x = HORZ_INDENT + 10;
  284.       ptl.y = rect.yTop - VERT_TEXT_POS*4;
  285.       GpiCharStringAt(hps, &ptl, strlen(szEAType), szEAType);
  286.    }
  287.    else
  288.    {
  289.       ptl.x = HORZ_INDENT + 10;
  290.       ptl.y = rect.yTop - VERT_TEXT_POS*2;
  291.       strcpy(szBuffer, "File name will appear here!");
  292.       GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);
  293.  
  294.       ptl.x = HORZ_INDENT + 10;
  295.       ptl.y = rect.yTop - VERT_TEXT_POS*4;
  296.       strcpy(szBuffer, "EA types will appear here!");
  297.       GpiCharStringAt(hps, &ptl, strlen(szBuffer), szBuffer);
  298.    }
  299.    WinEndPaint(hps);
  300.    return ;
  301. }                                                        /* MainPaint() */
  302.  
  303. /****************************************************************\
  304.  *  Main window WM_COMMAND processing procedure                 *
  305.  *--------------------------------------------------------------*
  306.  *                                                              *
  307.  *  Name:   MainCommand(hwnd, mp1, mp2)                         *
  308.  *                                                              *
  309.  *  Purpose:Calls the appropriate procedures that deal with     *
  310.  *           the selected menu item.                            *
  311.  *                                                              *
  312.  *  Usage:  Routine is called whenever a WM_COMMAND message     *
  313.  *          is posted to the main window.                       *
  314.  *                                                              *
  315.  *  Method: a switch statement branches on the id of the        *
  316.  *          menu item that posted the message and the           *
  317.  *          appropriate action for that item is taken.  Any     *
  318.  *          menu ids that are not part of the standard menu     *
  319.  *          set are passed onto the user defined WM_COMMAND     *
  320.  *          processing procedure.                               *
  321.  *                                                              *
  322.  *  Returns: VOID                                               *
  323.  *                                                              *
  324. \****************************************************************/
  325. VOID MainCommand(HWND hwnd, MPARAM mp1, MPARAM mp2)
  326. {
  327.     switch(SHORT1FROMMP(mp1))
  328.     {
  329.         case IDM_GENERALHELP:
  330.            HelpExtended(mp2);
  331.            break;
  332.  
  333.         case IDM_USINGHELP:
  334.            HelpHelpForHelp(mp2);
  335.            break;
  336.  
  337.         case IDM_TUTORIAL:
  338.            HelpKeys(mp2);
  339.            break;
  340.  
  341.         case IDM_HELPINDEX:
  342.            HelpIndex(mp2);
  343.            break;
  344.  
  345.         case IDM_HELPPRODUCTINFO:
  346.            HelpAbout(mp2);
  347.            break;
  348.  
  349.     /*--------------------------------------------------*\
  350.      *      User command processing routine is called   *
  351.      *      here so any ids not procecessed here can be *
  352.      *      processed                                   *
  353.     \*--------------------------------------------------*/
  354.         default:
  355.             UserCommand(hwnd, mp1, mp2);
  356.             break;
  357.     }
  358.     return;
  359. }                                                /* MainCommand() */
  360.  
  361. /****************************************************************\
  362.  *  Main window WM_CONTROL processing procedure                 *
  363.  *--------------------------------------------------------------*
  364.  *                                                              *
  365.  *  Name:   MainControl(hwnd, mp1, mp2)                         *
  366.  *                                                              *
  367.  *  Purpose:Calls the appropriate procedures that deal with     *
  368.  *           the selected menu item.                            *
  369.  *                                                              *
  370.  *  Usage:  Routine is called whenever a WM_CONTROL message     *
  371.  *          is posted to the main window.                       *
  372.  *                                                              *
  373.  *  Method: a switch statement branches on the id of the        *
  374.  *          menu item that posted the message and the           *
  375.  *          appropriate action for that item is taken.  Any     *
  376.  *          menu ids that are not part of the standard menu     *
  377.  *          set are passed onto the user defined WM_CONTROL     *
  378.  *          processing procedure.                               *
  379.  *                                                              *
  380.  *  Returns: VOID                                               *
  381.  *                                                              *
  382. \****************************************************************/
  383. VOID MainControl(HWND hwnd, MPARAM mp1, MPARAM mp2)
  384. {
  385.    switch(SHORT1FROMMP(mp1))
  386.    {
  387.       case IDD_WINLBOX:
  388.          switch(SHORT2FROMMP(mp1))
  389.          {
  390.             case LN_SELECT:           /* A new item has been hi-lited */
  391.                ShowEAType(hwnd);      /* Display appropriate EA Type  */
  392.                break;
  393.  
  394.             case LN_ENTER:            /* Edit the selected EA         */
  395.                EditEA(hwnd);
  396.                break;
  397.          }
  398.    }
  399.     /* This routine currently doesn't use the msg & mp2 parameter but *\
  400.      *  it is referenced here to prevent an 'Unreferenced Parameter'  *
  401.     \*  warning at compile time.                                      */
  402.    return;
  403. }
  404.  
  405. /****************************************************************\
  406.  *  Exit routine                                                *
  407.  *--------------------------------------------------------------*
  408.  *                                                              *
  409.  *  Name:    ProcExit(hwnd, mp2)                                *
  410.  *                                                              *
  411.  *  Purpose: Processes the menu's Exit item.                    *
  412.  *                                                              *
  413.  *  Usage:   called whenever Exit from the menu is selected     *
  414.  *                                                              *
  415.  *  Method:  Routine posts a WM_CLOSE message to the main       *
  416.  *           application window.                                *
  417.  *                                                              *
  418.  *  Returns: VOID                                               *
  419.  *                                                              *
  420. \****************************************************************/
  421. VOID ProcExit(HWND hwnd, MPARAM mp2)
  422. {
  423.    USHORT   usRet;
  424.  
  425.    if(FILE_CHANGED)     /* Give user a chance to save changes   */
  426.    {
  427.       usRet= MessageBox(hwnd, IDMSG_FILECHANGED, "Warning !",
  428.                         MB_YESNOCANCEL | MB_ICONEXCLAMATION, TRUE);
  429.       switch(usRet)
  430.       {
  431.          case MBID_YES:            /* They want to save the EAs */
  432.             WriteEAs();
  433.             break;
  434.          case MBID_CANCEL:    /* They don't really want to quit */
  435.             break;
  436.       }
  437.    }
  438.    WinPostMsg(hwndMain, WM_CLOSE, (MPARAM)NULL, (MPARAM)NULL);
  439.  
  440.     /* This routine currently doesn't use the mp2 parameter but       *\
  441.      *  it is referenced here to prevent an 'Unreferenced Parameter'  *
  442.     \*  warning at compile time.                                      */
  443.    return;
  444. }                                                        /* ProcExit() */
  445.  
  446. /****************************************************************\
  447.  *  Non-standard menu item command processing procedure         *
  448.  *--------------------------------------------------------------*
  449.  *                                                              *
  450.  *  Name:    UserCommand(hwnd, mp1, mp2)                        *
  451.  *                                                              *
  452.  *  Purpose: Process any WM_COMMAND messages send to hwndMain   *
  453.  *              that are not processed by MainCommand           *
  454.  *                                                              *
  455.  *  Usage:   Routine is called for each WM_COMMAND that is      *
  456.  *           not posted by a standard menu item                 *
  457.  *                                                              *
  458.  *  Method:  A switch statement branches control based upon     *
  459.  *           the id of the control which posted the message     *
  460.  *                                                              *
  461.  *  Returns: VOID                                               *
  462.  *                                                              *
  463. \****************************************************************/
  464. VOID UserCommand(HWND hwnd, MPARAM mp1, MPARAM mp2)
  465. {
  466.    RECTL  rect;                       /* Rectangle struct for painting */
  467.    LONG usRet;
  468.  
  469.    switch (SHORT1FROMMP(mp1))
  470.    {
  471.        case IDM_OPEN:          /* Select another file to view/edit EAs */
  472.           if(FILE_CHANGED)        /* Give them a chance to save modifications */
  473.           {
  474.              usRet = MessageBox(hwnd, IDMSG_FILECHANGED, "Warning !",
  475.                                   MB_YESNOCANCEL | MB_ICONEXCLAMATION, TRUE);
  476.              switch(usRet)
  477.              {
  478.                 case MBID_YES:
  479.                      WriteEAs();
  480.                      break;
  481.  
  482.                 case MBID_NO:
  483.                      break;
  484.  
  485.                 case MBID_CANCEL:
  486.                      return;
  487.              }
  488.           }
  489.           WinQueryWindowRect(hwnd, &rect);
  490.           if(hwndChild1)
  491.              WinDestroyWindow(hwndChild1);
  492.  
  493.           hwndChild1 = WinCreateWindow(hwnd,
  494.                           WC_LISTBOX,
  495.                           NULL,
  496.                           WS_VISIBLE,
  497.                           rect.xLeft,
  498.                           rect.yBottom,
  499.                           rect.xRight-rect.xLeft,
  500.                           rect.yTop -rect.yBottom -VERT_TEXT_POS*5,
  501.                           hwnd,
  502.                           HWND_TOP,
  503.                           IDD_WINLBOX,
  504.                           NULL,
  505.                           (PVOID)NULL);
  506.           if(OpenFile(hwnd,0))                         /* File open ok */
  507.                        break;
  508.           break;
  509.  
  510.        case IDM_SAVE:          /* Write EA's out to disk               */
  511.           WriteEAs();
  512.           break;
  513.  
  514.        case IDM_ADD:           /* Add an EA to current list in memory  */
  515.           AddEA(hwnd);
  516.           break;
  517.  
  518.        case IDM_DELETE:        /* Delete an EA from memory             */
  519.           DeleteCurEA(hwnd);
  520.           break;
  521.  
  522.        case IDM_EDIT:          /* Edit the hilited EA                  */
  523.           EditEA(hwnd);
  524.           break;
  525.  
  526.        default:
  527.          break;
  528.    }
  529.     /* This routine currently doesn't use the mp2 parameter but       *\
  530.      *  it is referenced here to prevent an 'Unreferenced Parameter'  *
  531.     \*  warning at compile time.                                      */
  532.    return;
  533. }
  534.  
  535. /****************************************************************\
  536.  *  Message Box procedure                                       *
  537.  *--------------------------------------------------------------*
  538.  *                                                              *
  539.  *  Name:    MessageBox(hwndOwner,IdMsg,pszMsg,fsStyle,bBeep)   *
  540.  *                                                              *
  541.  *  Purpose: Displays the warning message box with the message  *
  542.  *              given in nIdMsg retrived from the message table *
  543.  *                                                              *
  544.  *  Usage:   Called whever an error occurs and a message wishes *
  545.  *           to be displayed to the user                        *
  546.  *                                                              *
  547.  *  Method:  - Message string is loaded from the process'       *
  548.  *              message table                                   *
  549.  *           - Alarm beep is sounded if desired                 *
  550.  *           - Message box with the message is displayed        *
  551.  *                                                              *
  552.  *  Returns:                                                    *
  553.  *                                                              *
  554. \****************************************************************/
  555. LONG MessageBox(HWND hwndOwner, LONG IdMsg, PSZ pszMsg, LONG fsStyle,
  556.                      BOOL bBeep)
  557. {
  558.     CHAR szText[MESSAGELEN];
  559.     LONG usRet;
  560.  
  561.     if(!WinLoadMessage(hab, (HMODULE)NULL, IdMsg, MESSAGELEN, (PSZ)szText))
  562.     {
  563.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  564.         return RETURN_ERROR;
  565.     }
  566.     if(bBeep)
  567.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  568.  
  569.     usRet = WinMessageBox(HWND_DESKTOP,
  570.                          hwndOwner,
  571.                          szText,
  572.                          (PSZ)pszMsg,
  573.                          IDM_MSGBOX,
  574.                          fsStyle);
  575.     return usRet;
  576. }                                                   /* MessageBox() */
  577.  
  578. /****************************************************************\
  579.  *                                                              *
  580.  *  Name:    AddEAProc(hwnd, msg, mp1, mp2)                     *
  581.  *                                                              *
  582.  *  Purpose: Handles the screen that allows the user to enter a *
  583.  *           new EA Name and select the EA type.  It checks to  *
  584.  *           make sure the name is unique and is not NULL before*
  585.  *           returning. The user pointer is used to determine   *
  586.  *           whether the name is allowed to change or not.      *
  587.  *           If it points to a PassData structure, the Point    *
  588.  *           member gives the static EA Name.                   *
  589.  *                                                              *
  590.  *  Usage:   Called by MainDlgProc when user select the ADD.    *
  591.  *                                                              *
  592.  *  Method:  Called by both the add EA routine and the m-m EA   *
  593.  *           add routine.  This routine places the user typed   *
  594.  *           name in global szEAName, and the EA type in global *
  595.  *            usRetEAType.                                      *
  596.  *                                                              *
  597.  *  Returns: Exits with WinDismissDlg set to TRUE if the user   *
  598.  *           selects OK, FALSE if the user selects CANCEL.      *
  599.  *                                                              *
  600. \****************************************************************/
  601. MRESULT EXPENTRY AddEAProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  602. {
  603.    static CHAR bPDat = 0;   /* flag indicating if the pPDat struct is valid */
  604.    PASSDATA FAR *pPDat;     /* struct used to pass in default EA name       */
  605.    USHORT   i;
  606.    MRESULT  sRC;
  607.  
  608.    switch(msg)
  609.    {
  610.       case WM_INITDLG:
  611.          FixSysMenu(hwnd);
  612.          bPDat = 0;
  613.          WinSendDlgItemMsg(hwnd, IDD_EANAME,EM_SETTEXTLIMIT,
  614.                                  MPFROM2SHORT(MAXEANAME,0),NULL);
  615.          WinSendDlgItemMsg(hwnd, EA_LPASCII, BM_CLICK,(MPARAM)0L,(MPARAM)0L);
  616.  
  617.          pPDat=PVOIDFROMMP(mp2);
  618.          if(pPDat)
  619.          {
  620.             bPDat = 1;
  621.             WinSetDlgItemText(hwnd, IDD_EANAME, pPDat->Point);
  622.             WinEnableWindow(WinWindowFromID(hwnd,IDD_EANAME),
  623.                             FALSE);                /* Disable EA Name field */
  624.             WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,DID_OK));
  625.  
  626.             return (MRESULT)TRUE;    /* We don't want default focus setting */
  627.          }
  628.          return (MRESULT)0L;
  629.  
  630.       case WM_COMMAND:
  631.          switch(LOUSHORT(mp1))
  632.          {
  633.             case DID_OK:
  634.                if(bPDat == 0)          /* It is a new EA (not multi-type)   */
  635.                {
  636.                   WinQueryDlgItemText(hwnd, IDD_EANAME, MAXEANAME+1, szEAName);
  637.  
  638.                   if(!strlen(szEAName))    /* Don't allow a Null EA Name    */
  639.                   {
  640.                      MessageBox(hwnd, IDMSG_ERROREANAME, "Error !",
  641.                                          MB_OK | MB_ERROR, TRUE);
  642.                      return (MRESULT)0L;
  643.                   }
  644.  
  645.                   if(EAExists(szEAName))   /* Don't allow duplicate EA Name */
  646.                   {
  647.                      MessageBox(hwnd, IDMSG_DUPLICATENAME, "Error !",
  648.                                              MB_OK | MB_ERROR, TRUE);
  649.                      return (MRESULT)0L;
  650.                   }
  651.                   usRetEAType = (USHORT) WinSendDlgItemMsg(hwnd, EA_ASCIIZ,
  652.                             BM_QUERYCHECKINDEX,(MPARAM)0L,(MPARAM)0L);
  653.                                                          /* New MVST EAname */
  654.                   if (ConvTable[usRetEAType].usPrefix == EA_MVST)
  655.                   {
  656.                      for (i=0; i<MAXEANAME+1 && szEAName[i] != '\000'; i++)
  657.                      {                   /* Transfer lowercase to uppercase */
  658.                         if(szEAName[i]>='a' && szEAName[i]<='z')
  659.                            szEAName[i] = szEAName[i] - (CHAR)' ';
  660.                      }
  661.                                                   /* Store MVST name & type */
  662.                      for(i=0; i<MSNUM && MSdata[i].szName != NULL;)
  663.                               i++;
  664.                      GetMem((PPVOID)&MSdata[i].szName, sizeof(MVSTDATA));
  665.                      strcpy(MSdata[i].szName,szEAName);
  666.                      MSdata[i].usType  = usRetEAType;
  667.                   }
  668.                }
  669.                else                                    /* It is multi value */
  670.                {
  671.                   usRetEAType = (USHORT) WinSendDlgItemMsg(hwnd,
  672.                                               EA_ASCIIZ,
  673.                                               BM_QUERYCHECKINDEX,
  674.                                               (MPARAM)0L,(MPARAM)0L);
  675.  
  676.                            /* Check Type Name is in the list of MVST or not */
  677.                   for (i=0; i<MSNUM && MSdata[i].szName!=NULL &&
  678.                                   strcmp(szEAName,MSdata[i].szName)!=0;)
  679.                             i++;
  680.                                          /* 2'nd value of existed MVST type */
  681.                   if(i<MSNUM && MSdata[i].szName!=NULL)
  682.                   {
  683.                      if (ConvTable[usRetEAType].usPrefix == EA_MVST)
  684.                      {
  685.                         MessageBox(hwnd, IDMSG_ERRORMULTIVALUE, "Error !",
  686.                                              MB_OK | MB_ERROR, TRUE);
  687.                         return (MRESULT)0L;
  688.                      }
  689.                      if (ConvTable[usRetEAType].usPrefix == EA_MVMT)
  690.                      {
  691.                         MessageBox(hwnd, IDMSG_ERRORMULTITYPE, "Error !",
  692.                                              MB_OK | MB_ERROR, TRUE);
  693.                         return (MRESULT)0L;
  694.                      }
  695.                      MSdata[i].usType = usRetEAType;
  696.                   }
  697.                }
  698.                WinDismissDlg(hwnd, TRUE);
  699.                return (MRESULT)0L;
  700.  
  701.             case DID_CANCEL:
  702.                WinDismissDlg(hwnd, FALSE);
  703.                return (MRESULT)0L;
  704.          }
  705.          break;
  706.  
  707.       case WM_CLOSE:
  708.          WinDismissDlg(hwnd, FALSE);
  709.          return (MRESULT)0L;
  710.    }
  711.    sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
  712.    return sRC;
  713. }
  714.  
  715. /****************************************************************\
  716.  *                                                              *
  717.  *  Name:    AsciiEditProc(hwnd, msg, mp1, mp2)                 *
  718.  *                                                              *
  719.  *  Purpose: This proc handles the editing of EA Names and their*
  720.  *           associated ASCII strings.                          *
  721.  *                                                              *
  722.  *  Method:  A PassData struct must be passed in when called.   *
  723.  *           Note that the Value buffer is dynamically allocated*
  724.  *           and it is the responsibility of the calling        *
  725.  *           procedure to deallocate the buffer (szScratch) when*
  726.  *           finished with it. Note also that memory allocations*
  727.  *           are NOT fully error trapped.                       *
  728.  *                                                              *
  729.  *  Returns: Exits with WinDismissDlg set to TRUE if the user   *
  730.  *           selects OK, FALSE if the user selects CANCEL. Global
  731.  *           szEAName contains the modified EA Value.  the fFlag*
  732.  *           member of the passed in data will be updated to    *
  733.  *           reflect the currentstate of the Need bit.          *                   *
  734.  *                                                              *
  735. \****************************************************************/
  736. MRESULT EXPENTRY AsciiEditProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  737. {
  738.    static PASSDATA FAR *pPDat;
  739.    MRESULT sRC;
  740.  
  741.    switch(msg)
  742.    {
  743.       case WM_INITDLG:
  744.          FixSysMenu(hwnd);
  745.          WinSendDlgItemMsg(hwnd, IDD_EANAME,EM_SETTEXTLIMIT,
  746.                                  MPFROM2SHORT(MAXEANAME,0),NULL);
  747.          WinSendDlgItemMsg(hwnd, IDD_EAVALUE,EM_SETTEXTLIMIT,
  748.                                  MPFROM2SHORT(MAXEAVALUE,0),NULL);
  749.          pPDat=PVOIDFROMMP(mp2);
  750.  
  751.          WinSetDlgItemText(hwnd, IDD_EANAME,pPDat->Point);
  752.          WinSetDlgItemText(hwnd, IDD_EATYPE,ConvTable[usRetEAType].szFormat);
  753.          WinSendDlgItemMsg(hwnd, IDD_NEEDBIT, BM_SETCHECK,
  754.                            MPFROM2SHORT(pPDat->fFlag,0),NULL);
  755.  
  756.          if(szAscii)   /* Set default EA Value if global var is != NULL */
  757.             WinSetDlgItemText(hwnd, IDD_EAVALUE,szAscii);
  758.  
  759.          if(pPDat->usIndex) /* Disable EANAME if passed in a non-zero value */
  760.          {
  761.             WinEnableWindow(WinWindowFromID(hwnd,IDD_EANAME),FALSE);
  762.             WinEnableWindow(WinWindowFromID(hwnd,IDD_NEEDBIT),FALSE);
  763.             WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,IDD_EAVALUE));
  764.             return (MRESULT)TRUE;    /* We don't want default focus setting */
  765.          }
  766.          return (MRESULT)0L;
  767.  
  768.       case WM_COMMAND:
  769.          switch(LOUSHORT(mp1))
  770.          {
  771.             case DID_OK:
  772.                pPDat->fFlag = (BYTE) WinSendDlgItemMsg(hwnd, IDD_NEEDBIT,
  773.                                                        BM_QUERYCHECK, 0L, 0L);
  774.                WinQueryDlgItemText(hwnd, IDD_EANAME, MAXEANAME+1, szEAName);
  775.  
  776.                if(!strlen(szEAName))            /* They nulled out the name */
  777.                {
  778.                   MessageBox(hwnd, IDMSG_ERROREANAME, "Error !",
  779.                                      MB_OK | MB_ERROR, TRUE);
  780.                   return (MRESULT)0L;
  781.                }
  782.  
  783.                GetMem( &szScratch, (ULONG)MAXEAVALUE+1L); /* Allocate buffer for value */
  784.                WinQueryDlgItemText(hwnd, IDD_EAVALUE, MAXEAVALUE+1, szScratch);
  785.  
  786.                if(!strlen(szScratch))          /* They nulled out the value */
  787.                {
  788.                   FreeMem(szScratch);              /* Free the value buffer */
  789.                   MessageBox(hwnd, IDMSG_ERRORVALUE, "Error !",
  790.                                          MB_OK | MB_ERROR, TRUE);
  791.                   return (MRESULT)0L;
  792.                }
  793.                if(stricmp(szEAName,pPDat->Point))    /* changed the EA name */
  794.                {
  795.                   if(EAExists(szEAName))   /* Can't have duplicate EA names */
  796.                   {
  797.                      MessageBox(hwnd, IDMSG_DUPLICATENAME, "Error !",
  798.                                            MB_OK | MB_ERROR, TRUE);
  799.                      FreeMem(szScratch);               /* Free value buffer */
  800.                      return (MRESULT)0L;
  801.                   }
  802.                }
  803.  
  804.                DosSetMem(szScratch, strlen(szScratch)+1, fPERM|PAG_COMMIT);
  805.  
  806.                WinDismissDlg(hwnd, TRUE);
  807.                return (MRESULT)0L;
  808.  
  809.             case DID_CANCEL:
  810.                WinDismissDlg(hwnd, FALSE);
  811.                return (MRESULT)0L;
  812.          }
  813.          break;
  814.  
  815.       case WM_CLOSE:
  816.          WinDismissDlg(hwnd, FALSE);
  817.          return (MRESULT)0L;
  818.    }
  819.    sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
  820.    return sRC;
  821. }
  822.  
  823. /****************************************************************\
  824.  *  Name:    IconDlgProc(hwnd, msg, mp1, mp2)                   *
  825.  *                                                              *
  826.  *  Purpose: This proc is intedned to handle displaying and     *
  827.  *            editing icons/bitmaps.                            *
  828.  *                                                              *
  829.  *  Usage  :                                                    *
  830.  *                                                              *
  831.  *  Method :                                                    *
  832.  *                                                              *
  833.  *  Returns:                                                    *
  834.  *                                                              *
  835. \****************************************************************/
  836. MRESULT EXPENTRY IconDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  837. {
  838.    MRESULT sRC;
  839.  
  840.    switch(msg)
  841.    {
  842.       case WM_INITDLG:
  843.          FixSysMenu(hwnd);
  844.          return 0L;
  845.  
  846.       case WM_COMMAND:
  847.          WinDismissDlg(hwnd, TRUE);
  848.          return 0L;
  849.       case WM_PAINT:
  850.       {
  851.          SWP      swpTxt, swpDlg;
  852.          HPS      hps;
  853.          POINTL   ptl;
  854.          HBITMAP  hbm;
  855.  
  856.          WinDefDlgProc(hwnd, WM_PAINT, mp1, mp2);  /* normal dialog painting */
  857.  
  858.          hps = WinGetPS(hwnd);                         /* now, add our stuff */
  859.                                                     /* load and draw Example */
  860.          hbm = GpiLoadBitmap(hps, 0, ID_BMP, 0L, 0L);
  861.  
  862.          WinQueryWindowPos(WinWindowFromID(hwnd, ID_LOGOTEXT), &swpTxt);
  863.          WinQueryWindowPos(hwnd, &swpDlg);
  864.          ptl.x = (LONG)((swpDlg.cx - 95) / 2);
  865.          ptl.y = (LONG)((((swpDlg.cy - swpTxt.y) - 53) / 2) + swpTxt.y);
  866.          WinDrawBitmap(hps,
  867.                        hbm,
  868.                        NULL,
  869.                        &ptl,
  870.                        0L,
  871.                        0L,
  872.                        DBM_IMAGEATTRS);
  873.          WinReleasePS(hps);
  874.          return (MRESULT)0L;
  875.       }
  876.    }
  877.    sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
  878.    return sRC;
  879. }
  880. /****************************************************************\
  881.  *                                                              *
  882.  *  Name:    MultiValueProc(hwnd, msg, mp1, mp2)                *
  883.  *                                                              *
  884.  *  Purpose: This proc handles the multi-valuee EA stuff. Allows*
  885.  *           the fields in a given m-m to be edited.            *
  886.  *  Usage :                                                     *
  887.  *                                                              *
  888.  *  Method : NOTE that this procedure is fully reentrant/       *
  889.  *           recursive in that it calls EditEAValue() which can *
  890.  *           call MultiValueProc. Since PassData information is *
  891.  *           placed in static variables,the ReEnter structure is*
  892.  *           used to hold a dynamic linked  list of values      *
  893.  *           passed intothe proc and thus keeps the  static data*
  894.  *           set to the proper values.                          *
  895.  *                                                              *
  896.  *  Returns: Always returns TRUE thru WinDismissDlg when DONE is*
  897.  *           clicked.                                           *
  898.  *                                                              *
  899. \****************************************************************/
  900. MRESULT EXPENTRY MultiValueProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  901. {
  902.    static HOLDFEA *pFEA;                /* Points to the current EA         */
  903.    static PASSDATA FAR *pPDat;          /* Points to the passed Data struct */
  904.    static REENTER *CurEntry;            /* Points to most recent data frame */
  905.    REENTER *ReEntHold=NULL;             /* Temp used to setup the frame     */
  906.    PASSDATA PDat;                       /* Used for call to EditEAValue     */
  907.    USHORT *pusPtr,cnt;                  /* Utility vars                     */
  908.    SHORT  sOffset;
  909.    CHAR   *pInsert,*pValue,*pDelete;
  910.    CHAR   szCodePage[LENUSHORTBUF];
  911.    BYTE   fNeed;                        /* Holds state of need checkbox     */
  912.    MRESULT sRC;
  913.  
  914.    switch(msg)
  915.    {
  916.       case WM_INITDLG:
  917.          FixSysMenu(hwnd);
  918.          pPDat = PVOIDFROMMP(mp2);                    /* Set up static vars */
  919.          pFEA  = (HOLDFEA *) pPDat->Point;
  920.  
  921.          GetMem((PPVOID)&ReEntHold, (LONG)sizeof(REENTER));  /* Allows for recusive calls */
  922.          ReEntHold->pPDat = pPDat;
  923.          ReEntHold->pFEA  = pFEA;
  924.          ReEntHold->next  = CurEntry;
  925.          CurEntry = ReEntHold;
  926.  
  927.          WinSendDlgItemMsg(hwnd, IDD_NEEDBIT, BM_SETCHECK,/* Need bit setup */
  928.                            MPFROM2SHORT((pFEA->fEA&0x80)? TRUE : FALSE,0),
  929.                            NULL);
  930.  
  931.          WinSetDlgItemText(hwnd, IDD_EATYPE,"");      /* Setup the codepage */
  932.          WinSetDlgItemText(hwnd, IDD_EANAME,pFEA->szName);
  933.          WinSendDlgItemMsg(hwnd, IDD_CODEPAGE,EM_SETTEXTLIMIT,
  934.                                  MPFROM2SHORT(LENUSHORTBUF-1,0),NULL);
  935.  
  936.          pusPtr= (USHORT *) ((CHAR *) pFEA->aValue+pPDat->usMultiOffset);
  937.          pusPtr++;          /* Skip the EA_Type field and point to codepage */
  938.          sprintf(szCodePage,"%u",*pusPtr);
  939.          WinSetDlgItemText(hwnd, IDD_CODEPAGE,szCodePage);
  940.  
  941.          pusPtr++;            /* Skip codepage and point to the field count */
  942.  
  943.          for(cnt=0;cnt< *pusPtr;cnt++)       /* Add each field to the L-Box */
  944.          {
  945.             pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,cnt);
  946.             pValue = EAValueString(pInsert);        /* Ptr to asciiz string */
  947.  
  948.             WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
  949.                               MPFROM2SHORT(LIT_END,0),
  950.                               MPFROMP(pValue));
  951.             FreeMem(pValue);                          /* Free asciiz string */
  952.          }
  953.          return (MRESULT)0L;
  954.  
  955.       case WM_CONTROL:
  956.          switch(SHORT1FROMMP(mp1))
  957.          {
  958.             case IDD_LBOX:
  959.                switch(SHORT2FROMMP(mp1))
  960.                {
  961.                   case LN_SELECT:   /* Display proper EA type for selection */
  962.                      sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  963.                                                   LM_QUERYSELECTION,0,0);
  964.                      if(sOffset<0)
  965.                         break;
  966.  
  967.                      pValue = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  968.                                              sOffset);
  969.                      pusPtr = (USHORT *) pValue;
  970.  
  971.                      WinSetDlgItemText(hwnd,IDD_EATYPE,
  972.                                 ConvTable[LookupEAType(*pusPtr)].szFormat);
  973.                      break;
  974.  
  975.                   case LN_ENTER:  /* Setup and edit a m-m field */
  976.                      sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  977.                                                        LM_QUERYSELECTION,0,0);
  978.                      if(sOffset<0)
  979.                         return 0L;
  980.  
  981.                      PDat.Point         = (CHAR *) pFEA; /* Pass curr data */
  982.                      PDat.cbMulti       = pPDat->cbMulti;
  983.                      PDat.usMultiOffset = pPDat->usMultiOffset;
  984.                      PDat.usIndex       = sOffset;
  985.  
  986.                      if(EditEAValue(hwnd,&PDat))     /* They didn't cancel */
  987.                      {
  988.                         pInsert=MultiTypeIndex(pFEA->aValue
  989.                                                 + pPDat->usMultiOffset,
  990.                                                sOffset);
  991.                         pValue =EAValueString(pInsert);
  992.  
  993.                         WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_SETITEMTEXT,
  994.                                           MPFROMSHORT(sOffset),
  995.                                           MPFROMP(pValue));
  996.                         FreeMem(pValue);               /* Free asciiz str */
  997.                      }
  998.                      return (MRESULT)0L;
  999.                }
  1000.          }
  1001.          break;
  1002.  
  1003.       case WM_COMMAND:
  1004.          switch(LOUSHORT(mp1))
  1005.          {
  1006.             case IDD_ADD:                        /* Add an item for a m-m */
  1007.                if(!WinDlgBox(HWND_DESKTOP,       /* Do an ascii text edit */
  1008.                              hwnd,
  1009.                              AsciiEditProc,
  1010.                              '\0',
  1011.                              IDD_ASCIIEDIT,
  1012.                              &PDat))
  1013.                      return (MRESULT)0L;              /* They said cancel */
  1014.                break;
  1015.  
  1016.             case IDD_EDIT:                  /* Setup and edit a m-m field */
  1017.                sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  1018.                                                    LM_QUERYSELECTION,0,0);
  1019.                if(sOffset<0)
  1020.                {
  1021.                   MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1022.                                        MB_OK | MB_ERROR, TRUE);
  1023.                   return (MRESULT)0L;
  1024.                }
  1025.                PDat.Point         = (CHAR *) pFEA;       /* Pass curr data */
  1026.                PDat.cbMulti       = pPDat->cbMulti;
  1027.                PDat.usMultiOffset = pPDat->usMultiOffset;
  1028.                PDat.usIndex       = sOffset;
  1029.  
  1030.                if(EditEAValue(hwnd,&PDat))           /* They didn't cancel */
  1031.                {
  1032.                   pInsert=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
  1033.                                          sOffset);
  1034.                   pValue =EAValueString(pInsert);
  1035.  
  1036.                   WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_SETITEMTEXT,
  1037.                                     MPFROMSHORT(sOffset),
  1038.                                     MPFROMP(pValue));
  1039.                   FreeMem(pValue);                      /* Free asciiz str */
  1040.                }
  1041.                return (MRESULT)0L;
  1042.  
  1043.             case IDD_DELETE:                      /* Delete hi-lited item  */
  1044.                sOffset = (USHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  1045.                                                     LM_QUERYSELECTION,0,0);
  1046.                if(sOffset<0)              /* No item is currently selected */
  1047.                {
  1048.                   MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1049.                                        MB_OK | MB_ERROR, TRUE);
  1050.                   return (MRESULT)0L;
  1051.                }
  1052.                WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_DELETEITEM,
  1053.                                  MPFROMSHORT(sOffset),0L);
  1054.  
  1055.                /* Get pointers to start of selected field and the following
  1056.                   field, then move the rest of the EA back, resize the
  1057.                   buffer, and change the EA Value counter                  */
  1058.  
  1059.                pDelete = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  1060.                                         sOffset);
  1061.                pValue  = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  1062.                                         (sOffset+1) );
  1063.                memmove(pDelete,pValue,pFEA->cbValue-(pValue-pFEA->aValue));
  1064.                DosSetMem(pFEA->aValue, pFEA->cbValue-(pValue-pDelete), fPERM|PAG_COMMIT);
  1065.                pFEA->cbValue -= pValue-pDelete;
  1066.  
  1067.                                     /* Decrement the field count in the m-m */
  1068.                pusPtr  = (USHORT *) ((CHAR *) pFEA->aValue +
  1069.                                               pPDat->usMultiOffset);
  1070.                pusPtr+=2;                       /* Point to the field count */
  1071.                *pusPtr -= 1;                    /* Decrement the field cnt  */
  1072.  
  1073.                FILE_CHANGED = TRUE;
  1074.                return (MRESULT)0L;
  1075.  
  1076.             case DID_DONE:
  1077.                          /* Handle the possible change of the need checkbox */
  1078.                fNeed = (BYTE) WinSendDlgItemMsg(hwnd, IDD_NEEDBIT,
  1079.                                                 BM_QUERYCHECK,
  1080.                                                 0L, 0L);
  1081.                if(fNeed)
  1082.                   fNeed = 0x80;
  1083.                if(fNeed != (BYTE) (pFEA->fEA & 0x80))       /* Need changed */
  1084.                {
  1085.                   pFEA->fEA = (BYTE)((pFEA->fEA & 0x7F) | fNeed);
  1086.                   FILE_CHANGED = TRUE;
  1087.                }
  1088.  
  1089.                               /* Handle the possible change of the codepage */
  1090.                WinQueryDlgItemText(hwnd, IDD_CODEPAGE,
  1091.                                    LENUSHORTBUF, szCodePage);
  1092.                sscanf(szCodePage,"%u",&cnt);
  1093.                pusPtr= (USHORT *) ((CHAR *) pFEA->aValue+pPDat->usMultiOffset);
  1094.                pusPtr++;    /* Skip the EA_Type field and point to codepage */
  1095.                if(*pusPtr != cnt)        /* They changed the codepage value */
  1096.                {
  1097.                   *pusPtr = cnt;
  1098.                   FILE_CHANGED = TRUE;
  1099.                }
  1100.                ReEntHold = CurEntry->next;       /* Finish recursion safety */
  1101.                FreeMem(CurEntry);
  1102.                CurEntry = ReEntHold;
  1103.                if(CurEntry)
  1104.                {
  1105.                   pPDat = CurEntry->pPDat;
  1106.                   pFEA  = CurEntry->pFEA;
  1107.                }
  1108.                WinDismissDlg(hwnd, TRUE);
  1109.                return (MRESULT)0L;
  1110.          }
  1111.  
  1112.       case WM_CLOSE:
  1113.          WinDismissDlg(hwnd, FALSE);
  1114.          return (MRESULT)0L;
  1115.    }
  1116.    sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
  1117.    return sRC;
  1118. }
  1119.  
  1120. /****************************************************************\
  1121.  *                                                              *
  1122.  *  Name:    MultiTypeProc(hwnd, msg, mp1, mp2)                 *
  1123.  *                                                              *
  1124.  *  Purpose: This proc handles the multi-type EA stuff. Allows  *
  1125.  *           the fields in a given m-m to be edited.            *
  1126.  *  Usage :                                                     *
  1127.  *                                                              *
  1128.  *  Method : NOTE that this procedure is fully reentrant/       *
  1129.  *           recursive in that it calls EditEAValue() which can *
  1130.  *           call MultiTypeProc. Since PassData information is  *
  1131.  *           placed in static variables, the ReEnter structure  *
  1132.  *           is used to hold a dynamic linked list of values    *
  1133.  *           passed into the proc and thus keeps the static data*
  1134.  *           set to the proper values.                          *
  1135.  *                                                              *
  1136.  *  Returns: Always returns TRUE thru WinDismissDlg when DONE is*
  1137.  *           clicked.                                           *
  1138.  *                                                              *
  1139. \****************************************************************/
  1140. MRESULT EXPENTRY MultiTypeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  1141. {
  1142.    static HOLDFEA *pFEA;                /* Points to the current EA         */
  1143.    static PASSDATA FAR *pPDat;          /* Points to the passed Data struct */
  1144.    static REENTER *CurEntry;            /* Points to most recent data frame */
  1145.    REENTER *ReEntHold=NULL;             /* Temp used to setup the frame     */
  1146.    PASSDATA PDat;                       /* Used for call to EditEAValue     */
  1147.    USHORT *pusPtr,cnt;                  /* Utility vars                     */
  1148.    SHORT  sOffset;
  1149.    CHAR   *pInsert,*pValue,*pDelete;
  1150.    CHAR   szCodePage[LENUSHORTBUF];
  1151.    BYTE   fNeed;                        /* Holds state of need checkbox     */
  1152.    MRESULT sRC;
  1153.  
  1154.    switch(msg)
  1155.    {
  1156.       case WM_INITDLG:
  1157.          FixSysMenu(hwnd);
  1158.          pPDat = PVOIDFROMMP(mp2);                    /* Set up static vars */
  1159.          pFEA  = (HOLDFEA *) pPDat->Point;
  1160.  
  1161.          GetMem((PPVOID)&ReEntHold, (ULONG)sizeof(REENTER));  /* Allows for recusive calls */
  1162.          ReEntHold->pPDat = pPDat;
  1163.          ReEntHold->pFEA  = pFEA;
  1164.          ReEntHold->next  = CurEntry;
  1165.          CurEntry = ReEntHold;
  1166.  
  1167.          WinSendDlgItemMsg(hwnd, IDD_NEEDBIT, BM_SETCHECK,/* Need bit setup */
  1168.                            MPFROM2SHORT((pFEA->fEA&0x80)? TRUE : FALSE,0),
  1169.                            NULL);
  1170.  
  1171.          WinSetDlgItemText(hwnd, IDD_EATYPE,"");      /* Setup the codepage */
  1172.          WinSetDlgItemText(hwnd, IDD_EANAME,pFEA->szName);
  1173.          WinSendDlgItemMsg(hwnd, IDD_CODEPAGE,EM_SETTEXTLIMIT,
  1174.                                  MPFROM2SHORT(LENUSHORTBUF-1,0),NULL);
  1175.  
  1176.          pusPtr= (USHORT *) ((CHAR *) pFEA->aValue+pPDat->usMultiOffset);
  1177.          pusPtr++;          /* Skip the EA_Type field and point to codepage */
  1178.          sprintf(szCodePage,"%u",*pusPtr);
  1179.          WinSetDlgItemText(hwnd, IDD_CODEPAGE,szCodePage);
  1180.  
  1181.          pusPtr++;            /* Skip codepage and point to the field count */
  1182.  
  1183.          for(cnt=0;cnt< *pusPtr;cnt++)       /* Add each field to the L-Box */
  1184.          {
  1185.             pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,cnt);
  1186.             pValue = EAValueString(pInsert);        /* Ptr to asciiz string */
  1187.  
  1188.             WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
  1189.                               MPFROM2SHORT(LIT_END,0),
  1190.                               MPFROMP(pValue));
  1191.             FreeMem(pValue);                          /* Free asciiz string */
  1192.          }
  1193.          return (MRESULT)0L;
  1194.  
  1195.       case WM_CONTROL:
  1196.          switch(SHORT1FROMMP(mp1))
  1197.          {
  1198.             case IDD_LBOX:
  1199.                switch(SHORT2FROMMP(mp1))
  1200.                {
  1201.                   case LN_SELECT:   /* Display proper EA type for selection */
  1202.                      sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  1203.                                                        LM_QUERYSELECTION,0,0);
  1204.                      if(sOffset<0)
  1205.                         break;
  1206.  
  1207.                      pValue = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  1208.                                              sOffset);
  1209.                      pusPtr = (USHORT *) pValue;
  1210.  
  1211.                      WinSetDlgItemText(hwnd,IDD_EATYPE,
  1212.                                 ConvTable[LookupEAType(*pusPtr)].szFormat);
  1213.                      break;
  1214.  
  1215.                   case LN_ENTER:  /* Setup and edit a m-m field */
  1216.                      sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  1217.                                                        LM_QUERYSELECTION,0,0);
  1218.                      if(sOffset<0)
  1219.                         return (MRESULT)0L;
  1220.  
  1221.                      PDat.Point         = (CHAR *) pFEA; /* Pass curr data */
  1222.                      PDat.cbMulti       = pPDat->cbMulti;
  1223.                      PDat.usMultiOffset = pPDat->usMultiOffset;
  1224.                      PDat.usIndex       = sOffset;
  1225.  
  1226.                      if(EditEAValue(hwnd,&PDat))     /* They didn't cancel */
  1227.                      {
  1228.                         pInsert=MultiTypeIndex(pFEA->aValue
  1229.                                                 + pPDat->usMultiOffset,
  1230.                                                sOffset);
  1231.                         pValue =EAValueString(pInsert);
  1232.  
  1233.                         WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_SETITEMTEXT,
  1234.                                           MPFROMSHORT(sOffset),
  1235.                                           MPFROMP(pValue));
  1236.                         FreeMem(pValue);               /* Free asciiz str */
  1237.                      }
  1238.                      return (MRESULT)0L;
  1239.                }
  1240.          }
  1241.          break;
  1242.  
  1243.       case WM_COMMAND:
  1244.          switch(LOUSHORT(mp1))
  1245.          {
  1246.             case IDD_ADD:                        /* Add an item for a m-m */
  1247.                MultiAdd(hwnd, pFEA,pPDat);
  1248.                return (MRESULT)0L;
  1249.  
  1250.             case IDD_EDIT:                  /* Setup and edit a m-m field */
  1251.                if(ConvTable[usRetEAType].usPrefix != EA_MVST)
  1252.                {
  1253.                   sOffset = (SHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  1254.                                                    LM_QUERYSELECTION,0,0);
  1255.                   if(sOffset<0)
  1256.                   {
  1257.                      MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1258.                                        MB_OK | MB_ERROR, TRUE);
  1259.                      return (MRESULT)0L;
  1260.                   }
  1261.                } else       sOffset=0;
  1262.  
  1263.                PDat.Point         = (CHAR *) pFEA;       /* Pass curr data */
  1264.                PDat.cbMulti       = pPDat->cbMulti;
  1265.                PDat.usMultiOffset = pPDat->usMultiOffset;
  1266.                PDat.usIndex       = sOffset;
  1267.  
  1268.                if(EditEAValue(hwnd,&PDat))           /* They didn't cancel */
  1269.                {
  1270.                   pInsert=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
  1271.                                          sOffset);
  1272.                   pValue =EAValueString(pInsert);
  1273.  
  1274.                   WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_SETITEMTEXT,
  1275.                                     MPFROMSHORT(sOffset),
  1276.                                     MPFROMP(pValue));
  1277.                   FreeMem(pValue);                      /* Free asciiz str */
  1278.                }
  1279.                return (MRESULT)0L;
  1280.  
  1281.             case IDD_DELETE:                      /* Delete hi-lited item  */
  1282.                sOffset = (USHORT) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  1283.                                                     LM_QUERYSELECTION,0,0);
  1284.                if(sOffset<0)              /* No item is currently selected */
  1285.                {
  1286.                   MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1287.                                        MB_OK | MB_ERROR, TRUE);
  1288.                   return (MRESULT)0L;
  1289.                }
  1290.                WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_DELETEITEM,
  1291.                                  MPFROMSHORT(sOffset),0L);
  1292.  
  1293.                /* Get pointers to start of selected field and the following
  1294.                   field, then move the rest of the EA back, resize the
  1295.                   buffer, and change the EA Value counter                  */
  1296.  
  1297.                pDelete = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  1298.                                         sOffset);
  1299.                pValue  = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  1300.                                         (sOffset+1) );
  1301.                memmove(pDelete,pValue,pFEA->cbValue-(pValue-pFEA->aValue));
  1302.                DosSetMem(pFEA->aValue, pFEA->cbValue-(pValue-pDelete), fPERM|PAG_COMMIT);
  1303.                pFEA->cbValue -= pValue-pDelete;
  1304.  
  1305.                                     /* Decrement the field count in the m-m */
  1306.                pusPtr  = (USHORT *) ((CHAR *) pFEA->aValue +
  1307.                                               pPDat->usMultiOffset);
  1308.                pusPtr+=2;                       /* Point to the field count */
  1309.                *pusPtr -= 1;                    /* Decrement the field cnt  */
  1310.  
  1311.                FILE_CHANGED = TRUE;
  1312.                return (MRESULT)0L;
  1313.  
  1314.             case DID_DONE:
  1315.                          /* Handle the possible change of the need checkbox */
  1316.                fNeed = (BYTE) WinSendDlgItemMsg(hwnd, IDD_NEEDBIT,
  1317.                                                 BM_QUERYCHECK,
  1318.                                                 0L, 0L);
  1319.                if(fNeed)
  1320.                   fNeed = 0x80;
  1321.                if(fNeed != (BYTE) (pFEA->fEA & 0x80))       /* Need changed */
  1322.                {
  1323.                   pFEA->fEA = (BYTE)((pFEA->fEA & 0x7F) | fNeed);
  1324.                   FILE_CHANGED = TRUE;
  1325.                }
  1326.  
  1327.                               /* Handle the possible change of the codepage */
  1328.                WinQueryDlgItemText(hwnd, IDD_CODEPAGE,
  1329.                                    LENUSHORTBUF, szCodePage);
  1330.                sscanf(szCodePage,"%u",&cnt);
  1331.                pusPtr= (USHORT *) ((CHAR *) pFEA->aValue+pPDat->usMultiOffset);
  1332.                pusPtr++;    /* Skip the EA_Type field and point to codepage */
  1333.                if(*pusPtr != cnt)        /* They changed the codepage value */
  1334.                {
  1335.                   *pusPtr = cnt;
  1336.                   FILE_CHANGED = TRUE;
  1337.                }
  1338.                ReEntHold = CurEntry->next;       /* Finish recursion safety */
  1339.                FreeMem(CurEntry);
  1340.                CurEntry = ReEntHold;
  1341.                if(CurEntry)
  1342.                {
  1343.                   pPDat = CurEntry->pPDat;
  1344.                   pFEA  = CurEntry->pFEA;
  1345.                }
  1346.                WinDismissDlg(hwnd, TRUE);
  1347.                return (MRESULT)0L;
  1348.          }
  1349.  
  1350.       case WM_CLOSE:
  1351.          WinDismissDlg(hwnd, FALSE);
  1352.          return (MRESULT)0L;
  1353.    }
  1354.    sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
  1355.    return sRC;
  1356. }
  1357.  
  1358. /****************************************************************\
  1359.  *                                                              *
  1360.  *  Name:    ShowEAType(hwnd)                                   *
  1361.  *                                                              *
  1362.  *  Purpose: This routine handles the display of the current EA *
  1363.  *           type by setting the text in the appropriate dialog *
  1364.  *           field.                                             *
  1365.  *  Usage  :                                                    *
  1366.  *  Method : Routine should be bullet proof as it does its own  *
  1367.  *           error checking. It assumes that hwnd points to the *
  1368.  *           correct window with the name listbox in it.        *
  1369.  *                                                              *
  1370.  *  Returns: VOID                                               *
  1371.  *                                                              *
  1372. \****************************************************************/
  1373. VOID ShowEAType(HWND hwnd)
  1374. {
  1375.    HOLDFEA *pFEA;
  1376.  
  1377.    pFEA = GetCurFEA(hwnd, pHoldFEA);           /* Points to the selected EA */
  1378.    if(!pFEA)                            /* Kill line if nothing is selected */
  1379.    {
  1380.       memset(szEAType, 0, sizeof(szEAType) );
  1381.       WinInvalidateRect(hwndMain, NULL, FALSE);
  1382.       return;
  1383.    }
  1384.    strcpy(szEAType, ConvTable[usRetEAType].szFormat);
  1385.    WinInvalidateRect(hwndMain, NULL, FALSE);
  1386.    return;
  1387. }
  1388.  
  1389. /****************************************************************\
  1390.  *                                                              *
  1391.  *  Name:    EditEA(hwnd)                                       *
  1392.  *                                                              *
  1393.  *  Purpose: This routine handles the editing of an EA when it  *
  1394.  *           is selected from the listbox.  It get the item     *
  1395.  *           selected, sets up the PassData structure then calls*
  1396.  *           EditEAValue to do the actual edi                   *
  1397.  *  Usage  :                                                    *
  1398.  *  Method : Routine should be bullet proof as it does its own  *
  1399.  *           error checking. It assumes that hwnd points to the *
  1400.  *           correct window with the name listbox in it.        *                *
  1401.  *                                                              *
  1402.  *  Returns: TRUE if the edit was successful.                   *
  1403.  *                                                              *
  1404. \****************************************************************/
  1405. BOOL EditEA(HWND hwnd)
  1406. {
  1407.    HOLDFEA  *pFEA=pHoldFEA;                      /* Pointer for selected EA */
  1408.    SHORT    soffset,sCnt;    /* Both used to reference offset of selected EA */
  1409.    PASSDATA PData;
  1410.  
  1411.    if(!FILE_ISOPEN)
  1412.    {
  1413.       MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1414.                                MB_OK | MB_ERROR, TRUE);
  1415.       return(FALSE);
  1416.    }
  1417.    soffset = sCnt = (SHORT) WinSendDlgItemMsg(hwnd, IDD_WINLBOX,
  1418.                                             LM_QUERYSELECTION,0,0);
  1419.    if(soffset< 0)                              /* Nothing is selected */
  1420.    {
  1421.       MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1422.                                MB_OK | MB_ERROR, TRUE);
  1423.       return(FALSE);
  1424.    }
  1425.    while(sCnt--)                                     /* Get to the right EA */
  1426.       pFEA = pFEA->next;
  1427.  
  1428.    PData.Point         = (CHAR *)pFEA;          /* Set the pass data struct */
  1429.    PData.usMultiOffset = 0;
  1430.    PData.cbMulti       = 0;
  1431.  
  1432.    if(EditEAValue(hwnd,&PData))                                /* It worked */
  1433.    {
  1434.       WinSendDlgItemMsg(hwnd, IDD_WINLBOX, LM_SETITEMTEXT,
  1435.                         MPFROMSHORT(soffset),MPFROMP(pFEA->szName));
  1436.       return(TRUE);
  1437.    }
  1438.    return(FALSE);
  1439. }
  1440.  
  1441. /****************************************************************\
  1442.  *                                                              *
  1443.  * Name:    GetCurFEA(hwnd, pFEA)                               *
  1444.  *                                                              *
  1445.  * Purpose: This routine returns a pointer to the EA currently  *
  1446.  *          highlighted in the list box.                        *
  1447.  * Usage  :                                                     *
  1448.  * Method : Routine should be bullet proof as it does its own   *
  1449.  *          error checking. It assumes that hwnd points to the  *
  1450.  *          correct window with the name listbox in it.         *
  1451.  *                                                              *
  1452.  * Returns: The current EA as determined by querying the l-box  *
  1453.  *          selector, returns NULL if there is an error or      *
  1454.  *          nothing is selected.                                *
  1455.  *                                                              *
  1456. \****************************************************************/
  1457. HOLDFEA *GetCurFEA(HWND hwnd, HOLDFEA *pFEA)
  1458. {
  1459.    LONG  lOffset;
  1460.  
  1461.    lOffset = (LONG) WinSendDlgItemMsg(hwnd, IDD_WINLBOX,
  1462.                                       LM_QUERYSELECTION,0,0);
  1463.  
  1464.    if(lOffset == 0xffff)                          /* Nothing is highlighted */
  1465.    {
  1466.       MessageBox(hwnd, IDMSG_ERRORSELECT, "Error !",
  1467.                                MB_OK | MB_ERROR, TRUE);
  1468.       return(NULL);
  1469.    }
  1470.    while(lOffset--)
  1471.    {
  1472.       pFEA = pFEA->next;
  1473.    }
  1474.    return(pFEA);
  1475. }
  1476.  
  1477. /****************************************************************\
  1478.  *                                                              *
  1479.  *  Name:    GetMem (ppv, cb)                                   *
  1480.  *                                                              *
  1481.  *  Purpose: This routine returns a pointer to a available*     *
  1482.  *           memory space.                                      *
  1483.  *                                                              *
  1484.  *  Usage  :                                                    *
  1485.  *  Method : Routine should be bullet proof as it does its own  *
  1486.  *           error checking. It assumes that hwnd points to the *
  1487.  *           correct window with the name listbox in it.        *
  1488.  *                                                              *
  1489.  *  Returns: The current EA as determined by querying the l-box *
  1490.  *           selector.                                          *
  1491.  *                                                              *
  1492. \****************************************************************/
  1493. VOID GetMem (PVOID *ppv, ULONG cb)
  1494. {
  1495.     BOOL        f;
  1496.  
  1497.     f =(BOOL) DosAllocMem(ppv, cb, fPERM|PAG_COMMIT);
  1498.     if (f)
  1499.     {
  1500.         MessageBox(HWND_DESKTOP, IDMSG_MEMORYFULL, "Error !",
  1501.                                MB_OK | MB_ERROR, TRUE);
  1502.         *ppv = NULL;
  1503.         return;
  1504.     }
  1505.     return;
  1506. }
  1507.  
  1508. /****************************************************************\
  1509.  *                                                              *
  1510.  *  Name:    ResizeMem(ppv, cbOld, cbNew)                       *
  1511.  *                                                              *
  1512.  *  Purpose: This routine returns a pointer to a available      *
  1513.  *           memory space.                                      *
  1514.  *                                                              *
  1515.  *  Usage  :                                                    *
  1516.  *  Method :                                                    *
  1517.  *                                                              *
  1518.  *  Returns: VOID                                               *
  1519.  *                                                              *
  1520. \****************************************************************/
  1521. VOID ResizeMem (PVOID *ppv, ULONG cbOld, ULONG cbNew)
  1522. {
  1523.     BOOL        f;
  1524.     PVOID       pvNew=NULL;
  1525.  
  1526.     f = (BOOL) DosAllocMem(&pvNew, cbNew, fPERM|PAG_COMMIT);
  1527.     if (f) {
  1528.         MessageBox(HWND_DESKTOP, IDMSG_MEMORYFULL, "Error !",
  1529.                                  MB_OK | MB_ERROR, TRUE);
  1530.         *ppv = NULL;
  1531.         return;
  1532.     }
  1533.     memcpy(pvNew, *ppv, cbOld);
  1534.     f = (BOOL) DosFreeMem(*ppv);
  1535.     *ppv = pvNew;
  1536.     return ;
  1537. }
  1538.