home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / sysutils / nead / nead.c < prev    next >
Text File  |  1990-07-05  |  32KB  |  823 lines

  1. /*************************************************************
  2.  
  3.  This program implements an extended attributes editor.
  4.  Included in this file are all of the PM interface procedures.
  5.  All of these procs represent procedures for dialog boxes.
  6.  
  7.  This program was written by Jeff Johnson, 7/89, with pieces
  8.  of code pooled from already existing applications.
  9.  
  10.  This code is not fully implemented as it was written to show
  11.  how to use EAs.  Specifically, the Copy, Copy all, and Paste
  12.  buttons are not implemented, Icons and bitmaps are not
  13.  supported, and Multi-value, single-type EAs are also not
  14.  implemented.
  15.  
  16.  The EA code revolves around the HoldFEA structure.  This
  17.  structure is a linked list which contains one EA per
  18.  structure.  Each HoldFEA structure is dynamically allocated
  19.  as are the two string pointer members of the structure,
  20.  szName and aValue.  This is done to make handling the EAs
  21.  easier and more flexable.
  22.  
  23.  Procedures in this file:
  24.    main()          Sets up the PM environment and heap and
  25.                    calls the main dialog procedure MainDlgProc
  26.    MainDlgProc()   Handles the main window messages
  27.    AddEAProc()     Handles new EA name entry and type selection
  28.    AsciiEditProc() Handles editing of EA name/value
  29.    IconDlgProc()   Unimplemented icon procedure handler
  30.    MultiTypeProc() Handles the Multi-type dialog box
  31.    ShowEAType()    Shows Selected EA Type for MainDlgProc
  32.    EditEA()        Handles selection of an EA in the listbox
  33.    GetCurFEA()     Gets a ptr to the hi-lited EA in the listbox
  34.  
  35. **************************************************************/
  36.  
  37. #include "nead.h"
  38.  
  39. /********************* GLOBALS *******************************/
  40.  
  41. CHAR szFileName[CCHMAXPATH];    /* Holds current EA file */
  42. CHAR szEAName[MAXEANAME+1];     /* Used to return the EA name +1 for NULL */
  43. USHORT usRetEAType;             /* Used to return selected EA Type */
  44. BOOL FILE_ISOPEN = FALSE;       /* File Open flag */
  45. BOOL FILE_CHANGED = FALSE;      /* File Changed flag */
  46. BOOL COMMAND_LINE_FILE = FALSE; /* Flag to determine if a file was on the CL */
  47. HHEAP hhp;                      /* Pointer to the heap */
  48. CHAR *szAscii,*szScratch;       /* 2 Pointer used to return misc. strings */
  49. HOLDFEA *pHoldFEA;              /* Global EA linked-list pointer          */
  50. DELETELIST *pDelList;           /* Global ptr to l-l of deleted EAs       */
  51. EADATA ConvTable[EATABLESIZE] = {    /* Setup the table */
  52.    { EA_LPBINARY  ,"Length preceeded hex binary\0        ",IDD_LPDATA},
  53.    { EA_LPASCII   ,"Length preceeded ascii\0             ",IDD_LPDATA},
  54.    { EA_ASCIIZ    ,"Asciiz\0                             ",IDD_ASCIIZ},
  55.    { EA_LPBITMAP  ,"Length preceeded bitmap\0            ",IDD_LPDATA},
  56.    { EA_LPMETAFILE,"Metafile\0                           ",IDD_LPDATA},
  57.    { EA_LPICON    ,"Length preceeded icon\0              ",IDD_LPDATA},
  58.    { EA_ASCIIZFN  ,"Asciiz file name of associated data\0",IDD_ASCIIZ},
  59.    { EA_ASCIIZEA  ,"Asciiz EA of associated data\0       ",IDD_ASCIIZ},
  60.    { EA_MVMT      ,"Multi value multi type field\0       ",IDD_MULTILIST},
  61.    { EA_MVST      ,"Multi value single type field\0      ",IDD_MULTILIST},
  62.    { EA_ASN1      ,"ASN.1 field\0                        ",IDD_ASCIIZ},
  63.    { 0            ,"Non conventional format\0            ",IDD_ASCIIZ}
  64.    };
  65.  
  66. /*************************************************************/
  67.  
  68. /*
  69.  * Function name: main()
  70.  *
  71.  * Parameters:  argc, argv.  If the user places a file name on the command
  72.  *              line, its EAs will be retrieved by default, otherwise
  73.  *              the user will be prompted to select a file.
  74.  *
  75.  * Returns: Always returns 0
  76.  *
  77.  * Purpose: Parses the command line, sets up the PM environment, creates
  78.  *          a global memory heap, calls the main dialog proc, then
  79.  *          cleans up and exits.
  80.  *
  81.  * Usage/Warnings:
  82.  *
  83.  * Calls: ParseFileName, MainDlgProc (thru PM)
  84.  */
  85.  
  86. int main(int argc, char *argv[])
  87. {
  88.    HAB          hab;
  89.    HMQ          hmq;
  90.  
  91.    if(argc > 1)  /* If a command line file, get EAs from it */
  92.       if(ParseFileName(szFileName,argv[1]) != FILE_VALID) /* Bad file name */
  93.          *szFileName=0;
  94.       else
  95.          COMMAND_LINE_FILE = TRUE;
  96.  
  97.    /* Note:  The following 3 setup calls aren't currently checked for errors */
  98.    hab = WinInitialize(0);
  99.    hmq = WinCreateMsgQueue(hab, 0);
  100.    hhp = WinCreateHeap(0, 0, GROWSIZE, 0, 0,
  101.                           HM_MOVEABLE | HM_VALIDSIZE | HM_VALIDFLAGS);
  102.  
  103.    WinDlgBox(HWND_DESKTOP, HWND_DESKTOP,
  104.                          MainDlgProc,(HMODULE) NULL,IDD_MAIN,NULL);
  105.  
  106.    WinDestroyMsgQueue(hmq);
  107.    WinTerminate(hab);
  108.    return 0;
  109. }
  110.  
  111.  
  112. /*
  113.  * Function name: MainDlgProc()
  114.  *
  115.  * Parameters:  hwnd, msg, mp1, mp2.  Standard PM Dialog Proc params.
  116.  *              No user data is expected in the WM_INITDLG.
  117.  *
  118.  * Returns: Always returns 0, Exits with WinDismissDlg set to TRUE
  119.  *
  120.  * Purpose: Handles all the messages associated with the main window
  121.  *          and calls the appropriate handling procedures.  The initialize
  122.  *          routine sets up the program icon and posts a load file message
  123.  *          to itself.
  124.  *
  125.  * Usage/Warnings: Called only by main()
  126.  *
  127.  * Calls:  OpenFile(), AddEA(), DeleteCurEA, WriteEAs, ShowEAType, EditEA
  128.  */
  129.  
  130. MRESULT EXPENTRY MainDlgProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  131. {
  132.    HPOINTER hpointer;
  133.    USHORT   usRet;
  134.  
  135.    switch(msg)
  136.    {
  137.       case WM_INITDLG:
  138.          hpointer = WinLoadPointer(HWND_DESKTOP,            /* Set Nead Icon */
  139.                                    (HMODULE) NULL,IDR_EAD);
  140.          WinPostMsg(hwnd,WM_SETICON,hpointer,0L);
  141.  
  142.          /* Get EAs from file on Command line, or prompt for file name */
  143.          WinPostMsg(hwnd,WM_USER,NULL,NULL);
  144.          return 0L;
  145.  
  146.       case WM_USER:  /* Posted by WM_INITDLG allows main window to open 1st */
  147.          OpenFile(hwnd, COMMAND_LINE_FILE ? ARGFILE : 0);
  148.          return 0L;
  149.  
  150.       case WM_COMMAND:
  151.          switch(COMMANDMSG(&msg)->cmd)
  152.          {
  153.             case IDD_NEWFILE:     /* Select another file to view/edit EAs */
  154.                OpenFile(hwnd,0);
  155.                return 0L;
  156.  
  157.             case IDD_ADD:         /* Add an EA to current list in memory  */
  158.                AddEA(hwnd);
  159.                return 0L;
  160.  
  161.             case IDD_DELETE:      /* Delete an EA from memory             */
  162.                DeleteCurEA(hwnd);
  163.                return 0L;
  164.  
  165.             case IDD_WRITE:       /* Write EA's out to disk               */
  166.                WriteEAs(hwnd);
  167.                return 0L;
  168.  
  169.             case IDD_EDIT:        /* Edit the hilited EA                  */
  170.                EditEA(hwnd);
  171.                return 0L;
  172.  
  173.             case IDD_COPY:        /* Copy and Paste aren't                */
  174.             case IDD_PASTE:       /* currently implemented                */
  175.                return 0L;
  176.  
  177.             case IDD_QUIT:
  178.                if(FILE_CHANGED)   /* Give user a chance to save changes   */
  179.                {
  180.                   usRet=WinMessageBox(HWND_DESKTOP,hwnd,
  181.                   "The current file has been changed.  Do you \
  182. wish to save the changes before proceeding?",
  183.                   "Warning",0,MB_YESNOCANCEL | MB_ICONQUESTION);
  184.                   switch(usRet)
  185.                   {
  186.                      case MBID_YES:    /* They want to save the EAs       */
  187.                         WriteEAs(hwnd);
  188.                         break;
  189.                      case MBID_CANCEL: /* They don't really want to quit  */
  190.                         return 0L;
  191.                   }
  192.                }
  193.                WinDismissDlg(hwnd,TRUE);
  194.                return 0L;
  195.          }
  196.  
  197.       case WM_CONTROL:
  198.          switch(SHORT1FROMMP(mp1))
  199.          {
  200.             case IDD_LBOX:
  201.                switch(SHORT2FROMMP(mp1))
  202.                {
  203.                   case LN_SELECT:       /* A new item has been hi-lited */
  204.                      ShowEAType(hwnd);  /* Display appropriate EA Type  */
  205.                      return 0L;
  206.  
  207.                   case LN_ENTER:        /* Edit the selected EA         */
  208.                      EditEA(hwnd);
  209.                      return 0L;
  210.                }
  211.          }
  212.    }
  213.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  214. }
  215.  
  216.  
  217. /*
  218.  * Function name: AddEAProc()
  219.  *
  220.  * Parameters:  hwnd, msg, mp1, mp2.  Standard PM Dialog Proc params.
  221.  *              If user data is passed in, it indicates it is a m-m
  222.  *              add and the EA Name is in ->Point and the user should
  223.  *              not be allowed to edit it.
  224.  *
  225.  * Returns: Exits with WinDismissDlg set to TRUE if the user selects OK,
  226.  *          FALSE if the user selects CANCEL.
  227.  *
  228.  * Purpose: Handles the screen that allows the user to enter a new EA Name
  229.  *          and select the EA type.  It checks to make sure the name is
  230.  *          unique and is not NULL before returning.  The user pointer is
  231.  *          used to determine whether the name is allowed to change or not.
  232.  *          If it points to a PassData structure, the Point member gives the
  233.  *          static EA Name.
  234.  *
  235.  * Usage/Warnings: Called by both the add EA routine and the m-m EA add
  236.  *                 routine.  This routine places the user typed name in
  237.  *                 global szEAName, and the EA type in global usRetEAType.
  238.  *
  239.  * Calls:  EAExists()
  240.  */
  241.  
  242. MRESULT EXPENTRY AddEAProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  243. {
  244.    static CHAR bPDat = 0; /* flag indicating if the pPDat struct is valid */
  245.    PASSDATA FAR *pPDat;   /* struct used to pass in default EA name       */
  246.  
  247.    switch(msg)
  248.    {
  249.       case WM_INITDLG:
  250.          bPDat = 0;
  251.          WinSendDlgItemMsg(hwnd, IDD_EANAME,EM_SETTEXTLIMIT,
  252.                                  MPFROM2SHORT(MAXEANAME,0),NULL);
  253.          WinSendDlgItemMsg(hwnd, EA_LPASCII,BM_CLICK,0L,0L);
  254.  
  255.          pPDat=PVOIDFROMMP(mp2);
  256.          if(pPDat)
  257.          {
  258.             bPDat = 1;
  259.             WinSetDlgItemText(hwnd, IDD_EANAME,pPDat->Point);
  260.             WinSetDlgItemText(hwnd, IDD_TITLE,
  261.                               "Add a Multi-type field to the EA");
  262.             WinEnableWindow(WinWindowFromID(hwnd,IDD_EANAME),
  263.                             FALSE);                /* Disable EA Name field */
  264.             WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,DID_OK));
  265.  
  266.             return (MRESULT) TRUE;       /* We don't want default focus setting */
  267.          }
  268.          return 0L;
  269.  
  270.       case WM_COMMAND:
  271.          switch(COMMANDMSG(&msg)->cmd)
  272.          {
  273.             case DID_OK:
  274.                if(bPDat == 0)          /* It is a new EA (not multi-type)   */
  275.                {
  276.                   WinQueryDlgItemText(hwnd, IDD_EANAME, MAXEANAME+1, szEAName);
  277.  
  278.                   if(!strlen(szEAName))    /* Don't allow a Null EA Name    */
  279.                   {
  280.                      WinAlarm(HWND_DESKTOP,WA_ERROR);
  281.                      WinMessageBox(HWND_DESKTOP, hwnd,
  282.                                    "Cannot create a NULL EA name.",
  283.                                    NULL, 0, MB_OK);
  284.                      return 0L;
  285.                   }
  286.  
  287.                   if(EAExists(szEAName))   /* Don't allow duplicate EA Name */
  288.                   {
  289.                      WinAlarm(HWND_DESKTOP,WA_ERROR);
  290.                      WinMessageBox(HWND_DESKTOP, hwnd,
  291.                           "EA name already exists.  Can't create that name.",
  292.                           NULL, 0, MB_OK);
  293.                      return 0L;
  294.                   }
  295.                }
  296.                usRetEAType = SHORT1FROMMR( WinSendDlgItemMsg(hwnd, EA_ASCIIZ,
  297.                                                    BM_QUERYCHECKINDEX, 0L, 0L));
  298.                WinDismissDlg(hwnd, TRUE);
  299.                return 0L;
  300.  
  301.             case DID_CANCEL:
  302.                WinDismissDlg(hwnd, FALSE);
  303.                return 0L;
  304.          }
  305.          break;
  306.    }
  307.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  308. }
  309.  
  310.  
  311. /*
  312.  * Function name: AddEAProc()
  313.  *
  314.  * Parameters:  hwnd, msg, mp1, mp2.  Standard PM Dialog Proc params.
  315.  *              The user pointer passes in a PassData struct.  The Point
  316.  *              member points to the default EA Name and the usIndex
  317.  *              member determines whether or not the user can modify the
  318.  *              EA Name.  The fFlag member determines the status of the
  319.  *              Need/nice bit.  TRUE indicates the Need bit is set.  The
  320.  *              default Value is passed in global szAscii.
  321.  *
  322.  * Returns: Exits with WinDismissDlg set to TRUE if the user selects OK,
  323.  *          FALSE if the user selects CANCEL.  Global szEAName contains the
  324.  *          modified EA Value.  the fFlag member of the passed in data will
  325.  *          be updated to reflect the current state of the Need bit.
  326.  *
  327.  * Purpose: This proc handles the editing of EA Names and their associated
  328.  *          ASCII strings.
  329.  *
  330.  * Usage/Warnings: A PassData struct must be passed in when called.
  331.  *                 Note that the Value buffer is dynamically allocated and
  332.  *                 it is the responsibility of the calling procedure to
  333.  *                 deallocate the buffer (szScratch) when finished with it.
  334.  *                 Note also that memory allocations are NOT fully error
  335.  *                 trapped.
  336.  *
  337.  * Calls:  EAExists()
  338.  */
  339.  
  340.  
  341. MRESULT EXPENTRY AsciiEditProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  342. {
  343.    static PASSDATA FAR *pPDat;
  344.  
  345.    switch(msg)
  346.    {
  347.       case WM_INITDLG:
  348.          WinSendDlgItemMsg(hwnd, IDD_EANAME,EM_SETTEXTLIMIT,
  349.                                  MPFROM2SHORT(MAXEANAME,0),NULL);
  350.          WinSendDlgItemMsg(hwnd, IDD_EAVALUE,EM_SETTEXTLIMIT,
  351.                                  MPFROM2SHORT(MAXEAVALUE,0),NULL);
  352.          pPDat=PVOIDFROMMP(mp2);
  353.  
  354.          WinSetDlgItemText(hwnd, IDD_EANAME,pPDat->Point);
  355.          WinSetDlgItemText(hwnd, IDD_EATYPE,ConvTable[usRetEAType].szFormat);
  356.          WinSendDlgItemMsg(hwnd, IDD_NEEDBIT, BM_SETCHECK,
  357.                            MPFROM2SHORT(pPDat->fFlag,0),NULL);
  358.  
  359.          if(szAscii)   /* Set default EA Value if global var is != NULL */
  360.             WinSetDlgItemText(hwnd, IDD_EAVALUE,szAscii);
  361.  
  362.          if(pPDat->usIndex) /* Disable EANAME if passed in a non-zero value */
  363.          {
  364.             WinEnableWindow(WinWindowFromID(hwnd,IDD_EANAME),FALSE);
  365.             WinEnableWindow(WinWindowFromID(hwnd,IDD_NEEDBIT),FALSE);
  366.             WinSetFocus(HWND_DESKTOP,WinWindowFromID(hwnd,IDD_EAVALUE));
  367.             return (MRESULT) TRUE;       /* We don't want default focus setting */
  368.          }
  369.          return 0L;
  370.  
  371.       case WM_COMMAND:
  372.          switch(COMMANDMSG(&msg)->cmd)
  373.          {
  374.             case DID_OK:
  375.                pPDat->fFlag = (BYTE) SHORT1FROMMR( WinSendDlgItemMsg(hwnd, IDD_NEEDBIT,
  376.                                                        BM_QUERYCHECK,
  377.                                                        0L, 0L) );
  378.                WinQueryDlgItemText(hwnd, IDD_EANAME, MAXEANAME+1, szEAName);
  379.  
  380.                if(!strlen(szEAName))    /* They nulled out the name */
  381.                {
  382.                   WinAlarm(HWND_DESKTOP,WA_ERROR);
  383.                   WinMessageBox(HWND_DESKTOP, hwnd,
  384.                                 "Cannot create a NULL EA name.",
  385.                                 NULL, 0, MB_OK);
  386.                   return 0L;
  387.                }
  388.  
  389.                GetMem(szScratch,MAXEAVALUE+1);  /* Allocate buffer for value */
  390.                WinQueryDlgItemText(hwnd, IDD_EAVALUE, MAXEAVALUE+1, szScratch);
  391.  
  392.                if(!strlen(szScratch))    /* They nulled out the value */
  393.                {
  394.                   FreeMem(szScratch,MAXEAVALUE+1); /* Free the value buffer */
  395.                   WinAlarm(HWND_DESKTOP,WA_ERROR);
  396.                   WinMessageBox(HWND_DESKTOP, hwnd,
  397.                                 "An EA can't have a NULL value.",
  398.                                 NULL, 0, MB_OK);
  399.                   return 0L;
  400.                }
  401.  
  402.                if(stricmp(szEAName,pPDat->Point)) /* changed the EA name */
  403.                {
  404.                   if(EAExists(szEAName))  /* Can't have duplicate EA names */
  405.                   {
  406.                      WinAlarm(HWND_DESKTOP,WA_ERROR);
  407.                      WinMessageBox(HWND_DESKTOP, hwnd,
  408.                             "EA name already exists.  Can't create that name.",
  409.                             NULL, 0, MB_OK);
  410.  
  411.                      FreeMem(szScratch,MAXEAVALUE+1);  /* Free value buffer */
  412.                      return 0L;
  413.                   }
  414.                }
  415.  
  416.                ResizeMem(szScratch,MAXEAVALUE+1,/* Resize buf to actual size */
  417.                          strlen(szScratch)+1);
  418.  
  419.                WinDismissDlg(hwnd, TRUE);
  420.                return 0L;
  421.  
  422.             case DID_CANCEL:
  423.                WinDismissDlg(hwnd, FALSE);
  424.                return 0L;
  425.          }
  426.          break;
  427.    }
  428.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  429. }
  430.  
  431.  
  432. /*
  433.  * Function name: IconDlgProc()
  434.  *
  435.  * Parameters:  hwnd, msg, mp1, mp2.  Standard PM Dialog Proc params.
  436.  *              No user data is expected.
  437.  *
  438.  * Returns: Currently just calls WinDefDlgProc.
  439.  *
  440.  * Purpose: This proc is unimplemented, but is intedned to handle displaying
  441.  *          and editing icons/bitmaps.
  442.  *
  443.  * Usage/Warnings:
  444.  *
  445.  * Calls:
  446.  */
  447.  
  448. MRESULT EXPENTRY IconDlgProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  449. {
  450.    switch(msg)
  451.    {
  452.       case WM_INITDLG:
  453.          return 0L;
  454.  
  455.       case WM_COMMAND:
  456.          switch(COMMANDMSG(&msg)->cmd)
  457.          {
  458.             case DID_OK:
  459.                WinDismissDlg(hwnd, TRUE);
  460.                return 0L;
  461.          }
  462.    }
  463.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  464. }
  465.  
  466.  
  467. /*
  468.  * Function name: MultiTypeProc()
  469.  *
  470.  * Parameters:  hwnd, msg, mp1, mp2.  Standard PM Dialog Proc params.
  471.  *              Expects a user pointer to a PassData structure with Point
  472.  *              member pointing to the current pFEA structure.  The Multi
  473.  *              member fields of the PassData struct should also be
  474.  *              filled in to indicate the location and size of the current
  475.  *              m-m field.
  476.  *
  477.  * Returns: Always returns TRUE thru WinDismissDlg when DONE is clicked.
  478.  *
  479.  * Purpose: This proc handles the multi-type EA stuff.  Allows the fields
  480.  *          in a given m-m to be edited.
  481.  *
  482.  * Usage/Warnings:  NOTE that this procedure is fully reentrant/recursive
  483.  *                  in that it calls EditEAValue() which can call
  484.  *                  MultiTypeProc.  Since PassData information is placed
  485.  *                  in static variables, the ReEnter structure is used to
  486.  *                  hold a dynamic linked list of values passed into the
  487.  *                  proc and thus keeps the static data set to the proper
  488.  *                  values.
  489.  *
  490.  * Calls: MultiTypeIndex(), EAValueString(), EditEAValue(), MultiAdd()
  491.  */
  492.  
  493. MRESULT EXPENTRY MultiTypeProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  494. {
  495.    static HOLDFEA *pFEA;        /* Points to the current EA         */
  496.    static PASSDATA FAR *pPDat;  /* Points to the passed Data struct */
  497.    static REENTER *CurEntry;    /* Points to most recent data frame */
  498.    REENTER *ReEntHold;          /* Temp used to setup the frame     */
  499.    PASSDATA PDat;               /* Used for call to EditEAValue     */
  500.    USHORT *pusPtr,cnt;          /* Utility vars                     */
  501.    SHORT  sOffset;
  502.    CHAR   *pInsert,*pValue,*pDelete;
  503.    CHAR   szCodePage[LENUSHORTBUF];
  504.    BYTE   fNeed;                /* Holds state of need checkbox     */
  505.  
  506.    switch(msg)
  507.    {
  508.       case WM_INITDLG:
  509.          pPDat = PVOIDFROMMP(mp2);             /* Set up static vars        */
  510.          pFEA  = (HOLDFEA *) pPDat->Point;
  511.  
  512.          GetMem(ReEntHold,sizeof(REENTER));    /* Allows for recusive calls */
  513.          ReEntHold->pPDat = pPDat;
  514.          ReEntHold->pFEA  = pFEA;
  515.          ReEntHold->next  = CurEntry;
  516.          CurEntry = ReEntHold;
  517.  
  518.          WinSendDlgItemMsg(hwnd, IDD_NEEDBIT, BM_SETCHECK, /* Need bit setup */
  519.                            MPFROM2SHORT((pFEA->fEA&0x80)? TRUE : FALSE,0),
  520.                            NULL);
  521.  
  522.          WinSetDlgItemText(hwnd,IDD_EATYPE,"");  /* Setup the codepage */
  523.          WinSetDlgItemText(hwnd,IDD_EANAME,pFEA->szName);
  524.          WinSendDlgItemMsg(hwnd, IDD_CODEPAGE,EM_SETTEXTLIMIT,
  525.                                  MPFROM2SHORT(LENUSHORTBUF-1,0),NULL);
  526.  
  527.          pusPtr= (USHORT *) ((CHAR *) pFEA->aValue+pPDat->usMultiOffset);
  528.          pusPtr++;       /* Skip the EA_Type field and point to codepage */
  529.          sprintf(szCodePage,"%u",*pusPtr);
  530.          WinSetDlgItemText(hwnd, IDD_CODEPAGE,szCodePage);
  531.  
  532.          pusPtr++;      /* Skip codepage and point to the field count */
  533.  
  534.          for(cnt=0;cnt< *pusPtr;cnt++) /* Add each field to the L-Box */
  535.          {
  536.             pInsert = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,cnt);
  537.             pValue = EAValueString(hwnd,pInsert); /* Ptr to asciiz string */
  538.  
  539.             WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
  540.                               MPFROM2SHORT(LIT_END,0),
  541.                               MPFROMP(pValue));
  542.             FreeMem(pValue,strlen(pValue)+1);  /* Free asciiz string */
  543.          }
  544.          return 0L;
  545.  
  546.       case WM_CONTROL:
  547.          switch(SHORT1FROMMP(mp1))
  548.          {
  549.             case IDD_LBOX:
  550.                switch(SHORT2FROMMP(mp1))
  551.                {
  552.                   case LN_SELECT:   /* Display proper EA type for selection */
  553.                      sOffset = SHORT1FROMMR( WinSendDlgItemMsg(hwnd, IDD_LBOX,
  554.                                                        LM_QUERYSELECTION,0,0));
  555.                      if(sOffset<0)
  556.                         break;
  557.  
  558.                      pValue = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  559.                                              sOffset);
  560.                      pusPtr = (USHORT *) pValue;
  561.  
  562.                      WinSetDlgItemText(hwnd,IDD_EATYPE,
  563.                                 ConvTable[LookupEAType(*pusPtr)].szFormat);
  564.                      break;
  565.  
  566.                   case LN_ENTER:  /* Setup and edit a m-m field */
  567.                      sOffset = SHORT1FROMMR( WinSendDlgItemMsg(hwnd, IDD_LBOX,
  568.                                                        LM_QUERYSELECTION,0,0));
  569.                      if(sOffset<0)
  570.                         return 0L;
  571.  
  572.                      PDat.Point         = (CHAR *) pFEA; /* Pass curr data */
  573.                      PDat.cbMulti       = pPDat->cbMulti;
  574.                      PDat.usMultiOffset = pPDat->usMultiOffset;
  575.                      PDat.usIndex       = (USHORT) sOffset;
  576.  
  577.                      if(EditEAValue(hwnd,&PDat)) /* They didn't cancel */
  578.                      {
  579.                         pInsert=MultiTypeIndex(pFEA->aValue
  580.                                                 + pPDat->usMultiOffset,
  581.                                                sOffset);
  582.                         pValue =EAValueString(hwnd,pInsert);
  583.  
  584.                         WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_SETITEMTEXT,
  585.                                           MPFROMSHORT(sOffset),
  586.                                           MPFROMP(pValue));
  587.                         FreeMem(pValue,strlen(pValue)+1); /* Free asciiz str */
  588.                      }
  589.                      return 0L;
  590.                }
  591.          }
  592.  
  593.       case WM_COMMAND:
  594.          switch(COMMANDMSG(&msg)->cmd)
  595.          {
  596.             case IDD_ADD:                  /* Add an item for a m-m */
  597.                MultiAdd(hwnd, pFEA,pPDat);
  598.                return 0L;
  599.  
  600.             case IDD_EDIT:  /* Setup and edit a m-m field */
  601.                sOffset = SHORT1FROMMR( WinSendDlgItemMsg(hwnd, IDD_LBOX,
  602.                                                    LM_QUERYSELECTION,0,0));
  603.                if(sOffset<0)
  604.                   return 0L;
  605.  
  606.                PDat.Point         = (CHAR *) pFEA; /* Pass curr data */
  607.                PDat.cbMulti       = pPDat->cbMulti;
  608.                PDat.usMultiOffset = pPDat->usMultiOffset;
  609.                PDat.usIndex       = (USHORT) sOffset;
  610.  
  611.                if(EditEAValue(hwnd,&PDat)) /* They didn't cancel */
  612.                {
  613.                   pInsert=MultiTypeIndex(pFEA->aValue + pPDat->usMultiOffset,
  614.                                          sOffset);
  615.                   pValue =EAValueString(hwnd,pInsert);
  616.  
  617.                   WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_SETITEMTEXT,
  618.                                     MPFROMSHORT(sOffset),
  619.                                     MPFROMP(pValue));
  620.                   FreeMem(pValue,strlen(pValue)+1); /* Free asciiz str */
  621.                }
  622.                return 0L;
  623.  
  624.             case IDD_DELETE:               /* Delete hi-lited item  */
  625.                sOffset = SHORT1FROMMR( WinSendDlgItemMsg(hwnd, IDD_LBOX,
  626.                                                     LM_QUERYSELECTION,0,0));
  627.                if(sOffset<0)   /* No item is currently selected */
  628.                   return 0L;
  629.  
  630.                WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_DELETEITEM,
  631.                                  MPFROMSHORT(sOffset),0L);
  632.  
  633.                /* Get pointers to start of selected field and the following
  634.                   field, then move the rest of the EA back, resize the
  635.                   buffer, and change the EA Value counter                  */
  636.  
  637.                pDelete = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  638.                                         sOffset);
  639.                pValue  = MultiTypeIndex(pFEA->aValue+pPDat->usMultiOffset,
  640.                                         sOffset+1);
  641.                memmove(pDelete,pValue,pFEA->cbValue-(pValue-pFEA->aValue));
  642.                ResizeMem(pFEA->aValue,pFEA->cbValue,
  643.                          pFEA->cbValue-(pValue-pDelete));
  644.                pFEA->cbValue -= pValue-pDelete;
  645.  
  646.                /* Decrement the field count in the m-m */
  647.                pusPtr  = (USHORT *) ((CHAR *) pFEA->aValue +
  648.                                               pPDat->usMultiOffset);
  649.                pusPtr+=2;         /* Point to the field count */
  650.                *pusPtr -= 1;      /* Decrement the field cnt  */
  651.  
  652.                FILE_CHANGED = TRUE;
  653.                return 0L;
  654.  
  655.             case DID_DONE:
  656.                /* Handle the possible change of the need checkbox */
  657.                fNeed = (BYTE) SHORT1FROMMR(WinSendDlgItemMsg(hwnd, IDD_NEEDBIT,
  658.                                                 BM_QUERYCHECK,
  659.                                                 0L, 0L));
  660.                if(fNeed)
  661.                   fNeed = 0x80;
  662.                if(fNeed != (pFEA->fEA & (BYTE) 0x80)) /* Need changed */
  663.                {
  664.                   pFEA->fEA = (pFEA->fEA & (BYTE) 0x7F) | fNeed;
  665.                   FILE_CHANGED = TRUE;
  666.                }
  667.  
  668.                /* Handle the possible change of the codepage */
  669.                WinQueryDlgItemText(hwnd, IDD_CODEPAGE,
  670.                                    LENUSHORTBUF, szCodePage);
  671.                sscanf(szCodePage,"%u",&cnt);
  672.                pusPtr= (USHORT *) ((CHAR *) pFEA->aValue+pPDat->usMultiOffset);
  673.                pusPtr++;    /* Skip the EA_Type field and point to codepage */
  674.                if(*pusPtr != cnt) /* They changed the codepage value */
  675.                {
  676.                   *pusPtr = cnt;
  677.                   FILE_CHANGED = TRUE;
  678.                }
  679.  
  680.                ReEntHold = CurEntry->next;       /* Finish recursion safety */
  681.                FreeMem(CurEntry,sizeof(REENTER));
  682.                CurEntry = ReEntHold;
  683.                if(CurEntry)
  684.                {
  685.                   pPDat = CurEntry->pPDat;
  686.                   pFEA  = CurEntry->pFEA;
  687.                }
  688.                WinDismissDlg(hwnd, TRUE);
  689.                return 0L;
  690.          }
  691.    }
  692.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  693. }
  694.  
  695.  
  696. /*
  697.  * Function name: ShowEAType()
  698.  *
  699.  * Parameters:  hwnd which is the current window handle.
  700.  *
  701.  * Returns: VOID
  702.  *
  703.  * Purpose: This routine handles the display of the current EA type by
  704.  *          setting the text in the appropriate dialog field.
  705.  *
  706.  * Usage/Warnings:  Routine should be bullet proof as it does its own
  707.  *                  error checking.  It assumes that hwnd points to the
  708.  *                  correct window with the name listbox in it.
  709.  *
  710.  * Calls: GetCurFEA(), LookupEAType()
  711.  */
  712.  
  713. VOID ShowEAType(HWND hwnd)
  714. {
  715.    USHORT usEAType;         /* Holds the offset of EAType into ConvTable */
  716.    HOLDFEA *pFEA;
  717.  
  718.    pFEA = GetCurFEA(hwnd,pHoldFEA); /* Points to the selected EA */
  719.    if(!pFEA)                        /* Kill line if nothing is selected */
  720.    {
  721.       WinSetDlgItemText(hwnd,IDD_EATYPE,"");
  722.       return;
  723.    }
  724.    usEAType = LookupEAType((USHORT) *pFEA->aValue);
  725.  
  726.    WinSetDlgItemText(hwnd,IDD_EATYPE,ConvTable[usEAType].szFormat);
  727. }
  728.  
  729.  
  730.  
  731. /*
  732.  * Function name: EditEA()
  733.  *
  734.  * Parameters:  hwnd which is the current window handle.
  735.  *
  736.  * Returns: TRUE iff the edit was successful.
  737.  *
  738.  * Purpose: This routine handles the editing of an EA when it is selected
  739.  *          from the listbox.  It get the item selected, sets up the PassData
  740.  *          structure then calls EditEAValue to do the actual edit.
  741.  *
  742.  * Usage/Warnings:  Routine should be bullet proof as it does its own
  743.  *                  error checking.  It assumes that hwnd points to the
  744.  *                  correct window with the name listbox in it.
  745.  *
  746.  * Calls: EditEAValue()
  747.  */
  748.  
  749. BOOL EditEA(HWND hwnd)
  750. {
  751.    HOLDFEA *pFEA=pHoldFEA;  /* Pointer for selected EA */
  752.    LONG offset,lCnt;        /* Both used to reference offset of selected EA */
  753.    PASSDATA PData;
  754.  
  755.    if(!FILE_ISOPEN)
  756.       return(FALSE);
  757.  
  758.    offset = lCnt = (LONG) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  759.                                             LM_QUERYSELECTION,0,0);
  760.  
  761.    if(offset<0)        /* Nothing was selected */
  762.       return(FALSE);
  763.  
  764.    while(lCnt--)         /* Get to the right EA */
  765.       pFEA = pFEA->next;
  766.  
  767.    PData.Point         = (CHAR *) pFEA;        /* Set the pass data struct */
  768.    PData.usMultiOffset = 0;
  769.    PData.cbMulti       = 0;
  770.  
  771.    if(EditEAValue(hwnd,&PData))  /* It worked */
  772.    {
  773.       WinSendDlgItemMsg(hwnd, IDD_LBOX,LM_SETITEMTEXT,
  774.                         MPFROMSHORT((SHORT) offset),MPFROMP(pFEA->szName));
  775.       return(TRUE);
  776.    }
  777.    return(FALSE);
  778. }
  779.  
  780.  
  781. /* This routine returns a pointer to the EA currently highlighted in the
  782.    list box. */
  783.  
  784. /*
  785.  * Function name: GetCurFEA()
  786.  *
  787.  * Parameters:  hwnd which is the current window handle.
  788.  *              pFEA which points to the base FEA in the linked list.
  789.  *
  790.  * Returns: The current EA as determined by querying the l-box selector,
  791.  *          returns NULL if there is an error or nothing is selected.
  792.  *
  793.  * Purpose: This routine returns a pointer to the EA currently highlighted
  794.  *          in the list box.
  795.  *
  796.  * Usage/Warnings:  Routine should be bullet proof as it does its own
  797.  *                  error checking.  It assumes that hwnd points to the
  798.  *                  correct window with the name listbox in it.
  799.  *
  800.  * Calls: EditEAValue()
  801.  */
  802.  
  803. HOLDFEA *GetCurFEA(HWND hwnd, HOLDFEA *pFEA)
  804. {
  805.    LONG lOffset;
  806.  
  807.    lOffset = (LONG) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  808.                                       LM_QUERYSELECTION,0,0);
  809.  
  810.    if(lOffset<0)      /* Nothing is highlighted */
  811.       return(NULL);
  812.  
  813.    while(lOffset--)
  814.    {
  815.       pFEA = pFEA->next;
  816.    }
  817.  
  818.    return(pFEA);
  819. }
  820.  
  821.  
  822. 
  823.