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