home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / dlgedit / status.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  58KB  |  1,870 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /****************************** Module Header *******************************
  13. * Module Name: status.c
  14. *
  15. * Support for the Status window.
  16. *
  17. * Functions:
  18. *
  19. *    StatusDlgProc()
  20. *    StatusApplyChanges()
  21. *    StatusFillSymbolList()
  22. *    StatusSetCoords()
  23. *    StatusUpdate()
  24. *    StatusSetEnable()
  25. *    StatusInit()
  26. *    StatusProcessCommand()
  27. *    ValidateNewName()
  28. *    ValidateNewID()
  29. *    ApplyNewName()
  30. *    ApplyNewID()
  31. *    ApplyNewText()
  32. *    StatusSetText()
  33. *    StatusSetTextLabels()
  34. *    StatusSetID()
  35. *    StatusSetName()
  36. *    StatusSetNameID()
  37. *    StatusClearID()
  38. *    StatusClearName()
  39. *    StatusClear()
  40. *    StatusShowFields()
  41. *
  42. * Comments:
  43. *
  44. ****************************************************************************/
  45.  
  46. #include "dlgedit.h"
  47. #include "dlgfuncs.h"
  48. #include "dlgextrn.h"
  49. #include "dialogs.h"
  50.  
  51. STATICFN BOOL StatusInit(HWND hwnd);
  52. STATICFN VOID StatusProcessCommand(HWND hwnd, INT idCtrl,
  53.     INT NotifyCode);
  54. STATICFN BOOL ValidateNewName(NPCTYPE npc, LPTSTR pszName,
  55.     LPTSTR pszID, LPTSTR pszSym, PINT pidNew, BOOL *pfAddLabel);
  56. STATICFN BOOL ValidateNewID(NPCTYPE npc, LPTSTR pszSym, LPTSTR pszID,
  57.     PINT pidNew, BOOL *pfAddLabel);
  58. STATICFN BOOL ApplyNewName(NPCTYPE npc, LPTSTR pszName,
  59.     BOOL fAddLabel, LPTSTR pszSym, INT idNew);
  60. STATICFN BOOL ApplyNewID(NPCTYPE npc, INT idNew, BOOL fAddLabel,
  61.     LPTSTR pszSym);
  62. STATICFN BOOL ApplyNewText(NPCTYPE npc, LPTSTR pszNewText);
  63. STATICFN VOID StatusSetText(LPTSTR pszText, INT Type);
  64. STATICFN VOID StatusSetTextLabels(INT Type, BOOL fIsOrd);
  65. STATICFN VOID StatusSetID(INT id, BOOL fSymAlso);
  66. STATICFN VOID StatusSetName(LPTSTR pszName, INT Type);
  67. STATICFN VOID StatusSetNameID(INT id, INT Type);
  68. STATICFN VOID StatusClearID(VOID);
  69. STATICFN VOID StatusClearName(VOID);
  70. STATICFN VOID StatusClear(VOID);
  71. STATICFN VOID StatusShowFields(INT Type);
  72.  
  73. /*
  74.  * TRUE if the user has changed the entry fields in the status window.
  75.  * This will be reset to FALSE whenever new information is placed
  76.  * into the fields.
  77.  */
  78. static BOOL gfStatusChanged = FALSE;
  79.  
  80. /*
  81.  * These globals save the window positions of the upper and lower
  82.  * combo boxes and edit controls.  This is used to position them
  83.  * depending on what type of control is selected.
  84.  */
  85. static RECT grcTopCombo;
  86. static RECT grcBottomCombo;
  87. static RECT grcTopEdit;
  88. static RECT grcBottomEdit;
  89.  
  90.  
  91.  
  92. /************************************************************************
  93. * StatusDlgProc
  94. *
  95. * This is the dialog procedure for the Status ribbon window.
  96. *
  97. ************************************************************************/
  98.  
  99. DIALOGPROC StatusDlgProc(
  100.     HWND hwnd,
  101.     UINT msg,
  102.     WPARAM wParam,
  103.     LPARAM lParam)
  104. {
  105.     switch (msg) {
  106.         case WM_INITDIALOG:
  107.             return StatusInit(hwnd);
  108.  
  109.         case WM_PAINT:
  110.             {
  111.                 HDC hdc;
  112.                 RECT rc;
  113.                 PAINTSTRUCT ps;
  114.                 HPEN hpenWindowFrame;
  115.  
  116.                 /*
  117.                  * Draw our border lines.
  118.                  */
  119.                 GetClientRect(hwnd, &rc);
  120.                 hdc = BeginPaint(hwnd, &ps);
  121.  
  122.                 SelectObject(hdc, GetStockObject(WHITE_PEN));
  123.                 MoveToEx(hdc, rc.left, rc.top, NULL);
  124.                 LineTo(hdc, rc.right, rc.top);
  125.  
  126.                 SelectObject(hdc, hpenDarkGray);
  127.                 MoveToEx(hdc, rc.left, (rc.top + gcyStatus) - gcyBorder - 1, NULL);
  128.                 LineTo(hdc, rc.right, (rc.top + gcyStatus) - gcyBorder - 1);
  129.  
  130.                 hpenWindowFrame = CreatePen(PS_SOLID, gcyBorder,
  131.                         GetSysColor(COLOR_WINDOWFRAME));
  132.                 SelectObject(hdc, hpenWindowFrame);
  133.                 MoveToEx(hdc, rc.left, (rc.top + gcyStatus) - gcyBorder, NULL);
  134.                 LineTo(hdc, rc.right, (rc.top + gcyStatus) - gcyBorder);
  135.  
  136.                 EndPaint(hwnd, &ps);
  137.                 DeleteObject(hpenWindowFrame);
  138.             }
  139.  
  140.             break;
  141.  
  142.         case WM_CTLCOLORDLG:
  143.         case WM_CTLCOLORLISTBOX:
  144.         case WM_CTLCOLORSTATIC:
  145.             switch ((WORD)(msg - WM_CTLCOLORMSGBOX)) {
  146.                 case CTLCOLOR_DLG:
  147.                 case CTLCOLOR_LISTBOX:
  148.                     return (BOOL)GetStockObject(LTGRAY_BRUSH);
  149.  
  150.                 case CTLCOLOR_STATIC:
  151.                     SetBkColor((HDC)(wParam),
  152.                             LIGHTGRAY);
  153.                     return (BOOL)GetStockObject(LTGRAY_BRUSH);
  154.             }
  155.  
  156.             return (BOOL)NULL;
  157.  
  158.         case WM_COMMAND:
  159.             StatusProcessCommand(hwnd,
  160.                     LOWORD(wParam),
  161.                     HIWORD(wParam));
  162.             break;
  163.  
  164.         default:
  165.             return FALSE;
  166.     }
  167.  
  168.     return FALSE;
  169. }
  170.  
  171.  
  172.  
  173. /************************************************************************
  174. * StatusInit
  175. *
  176. * Initializes the Status ribbon window.
  177. *
  178. * Arguments:
  179. *     HWND hwnd = The window handle.
  180. *
  181. * Returns:
  182. *     
  183. * TRUE 
  184. *
  185. ************************************************************************/
  186.  
  187. STATICFN BOOL StatusInit(
  188.     HWND hwnd)
  189. {
  190.     /*
  191.      * Set this global right away.  Other routines that will be called
  192.      * before CreateDialog returns depend on this global.
  193.      */
  194.     hwndStatus = hwnd;
  195.  
  196.     GetChildRect(GetDlgItem(hwnd, DID_STATUSSYM), &grcTopCombo);
  197.     GetChildRect(GetDlgItem(hwnd, DID_STATUSSYMID), &grcTopEdit);
  198.     GetChildRect(GetDlgItem(hwnd, DID_STATUSNAME), &grcBottomCombo);
  199.     GetChildRect(GetDlgItem(hwnd, DID_STATUSNAMEID), &grcBottomEdit);
  200.  
  201.     SendDlgItemMessage(hwnd, DID_STATUSSYM, EM_LIMITTEXT, CCHTEXTMAX, 0L);
  202.     SendDlgItemMessage(hwnd, DID_STATUSNAME, EM_LIMITTEXT, CCHTEXTMAX, 0L);
  203.     SendDlgItemMessage(hwnd, DID_STATUSSYMID, EM_LIMITTEXT, CCHIDMAX, 0L);
  204.     SendDlgItemMessage(hwnd, DID_STATUSNAMEID, EM_LIMITTEXT, CCHIDMAX, 0L);
  205.     SendDlgItemMessage(hwnd, DID_STATUSTEXT, EM_LIMITTEXT, CCHTEXTMAX, 0L);
  206.  
  207.     StatusFillSymbolList(plInclude);
  208.     StatusUpdate();
  209.     StatusSetEnable();
  210.  
  211.     /*
  212.      * Return TRUE so that the dialog manager does NOT set the focus
  213.      * for me.  This prevents the status window from initially having
  214.      * the focus when the editor is started.
  215.      */
  216.     return TRUE;
  217. }
  218.  
  219.  
  220.  
  221. /************************************************************************
  222. * StatusProcessCommand
  223. *
  224. * Function that processes commands sent to the status window.
  225. *
  226. * Arguments:
  227. *   HWND hwnd        - The window handle.
  228. *   INT idCtrl       - The id of the control the WM_COMMAND is for.
  229. *   INT NotifyCode   - The control's notification code.
  230. *
  231. *
  232. ************************************************************************/
  233.  
  234. STATICFN VOID StatusProcessCommand(
  235.     HWND hwnd,
  236.     INT idCtrl,
  237.     INT NotifyCode)
  238. {
  239.     TCHAR szSym[CCHTEXTMAX];
  240.     TCHAR szID[CCHIDMAX + 1];
  241.     NPLABEL npLabel;
  242.     INT id;
  243.     INT nIndex;
  244.     LPTSTR pszOldName;
  245.  
  246.     switch (idCtrl) {
  247.         case DID_STATUSSYM:
  248.             /*
  249.              * Did the symbol edit field change and is
  250.              * something selected?
  251.              */
  252.             if (gnpcSel && (NotifyCode == CBN_EDITCHANGE ||
  253.                     NotifyCode == CBN_SELCHANGE)) {
  254.                 /*
  255.                  * Get the symbol and begin looking for it.
  256.                  */
  257.                 if (NotifyCode == CBN_EDITCHANGE) {
  258.                     /*
  259.                      * The edit field was typed into.  Get the
  260.                      * new text from there.
  261.                      */
  262.                     GetDlgItemText(hwnd, DID_STATUSSYM, szSym, CCHTEXTMAX);
  263.                 }
  264.                 else {
  265.                     /*
  266.                      * A new string was selected from the list
  267.                      * box.  Get it from the list box, because
  268.                      * at this point the new text is not yet set
  269.                      * into the edit control!
  270.                      */
  271.                     nIndex = (INT)SendDlgItemMessage(hwnd,
  272.                             DID_STATUSSYM, CB_GETCURSEL, 0, 0L);
  273.  
  274.                     if (nIndex != CB_ERR)
  275.                         SendDlgItemMessage(hwnd, DID_STATUSSYM, CB_GETLBTEXT,
  276.                                 nIndex, (DWORD)szSym);
  277.                     else
  278.                         *szSym = CHAR_NULL;
  279.                 }
  280.  
  281.                 /*
  282.                  * Convert the symbol field to the associated id value,
  283.                  * taking into account the special IDOK values, etc.
  284.                  */
  285.                 if (!LabelToID(szSym, &id)) {
  286.                     /*
  287.                      * The symbol was not found.
  288.                      * If the symbol is not blank, and the
  289.                      * id of the control is already taken
  290.                      * by another label, fill the id field
  291.                      * with the next available id.  Otherwise,
  292.                      * fill the id field with the controls
  293.                      * id value.  It is assumed here that the
  294.                      * dialog cannot be selected if the symbol
  295.                      * field was able to be changed.
  296.                      */
  297.                     if (*szSym && FindID(gnpcSel->id, plInclude))
  298.                         id = NextID(NEXTID_CONTROL, plInclude, 0);
  299.                     else
  300.                         id = gnpcSel->id;
  301.                 }
  302.  
  303.                 StatusSetID(id, FALSE);
  304.  
  305.                 gfStatusChanged = TRUE;
  306.             }
  307.  
  308.             break;
  309.  
  310.         case DID_STATUSNAME:
  311.             /*
  312.              * Did the name edit field change and is
  313.              * something selected?
  314.              */
  315.             if (gnpcSel && (NotifyCode == CBN_EDITCHANGE ||
  316.                     NotifyCode == CBN_SELCHANGE)) {
  317.                 /*
  318.                  * Get the symbol and begin looking for it.
  319.                  */
  320.                 if (NotifyCode == CBN_EDITCHANGE) {
  321.                     /*
  322.                      * The edit field was typed into.  Get the
  323.                      * new text from there.
  324.                      */
  325.                     GetDlgItemText(hwnd, DID_STATUSNAME, szSym, CCHTEXTMAX);
  326.                 }
  327.                 else {
  328.                     /*
  329.                      * A new string was selected from the list
  330.                      * box.  Get it from the list box, because
  331.                      * at this point the new text is not yet set
  332.                      * into the edit control!
  333.                      */
  334.                     nIndex = (INT)SendDlgItemMessage(hwnd,
  335.                             DID_STATUSNAME, CB_GETCURSEL, 0, 0L);
  336.  
  337.                     if (nIndex != CB_ERR)
  338.                         SendDlgItemMessage(hwnd, DID_STATUSNAME, CB_GETLBTEXT,
  339.                                 nIndex, (DWORD)szSym);
  340.                     else
  341.                         *szSym = CHAR_NULL;
  342.                 }
  343.  
  344.                 /*
  345.                  * Try and convert the name to an ordinal.
  346.                  */
  347.                 StrToNameOrd(szSym, (gnpcSel->pwcd->iType == W_DIALOG) ?
  348.                         TRUE : FALSE);
  349.  
  350.                 /*
  351.                  * Was the name converted to an ordinal?
  352.                  */
  353.                 if (IsOrd(szSym)) {
  354.                     id = OrdID(szSym);
  355.                 }
  356.                 /*
  357.                  * Is it an existing label?
  358.                  */
  359.                 else if (npLabel = FindLabel(szSym, plInclude)) {
  360.                     id = npLabel->id;
  361.                 }
  362.                 else {
  363.                     /*
  364.                      * Get a pointer to the original name.
  365.                      */
  366.                     pszOldName = (gnpcSel->pwcd->iType == W_DIALOG) ?
  367.                             gcd.pszDlgName : gnpcSel->text;
  368.  
  369.                     /*
  370.                      * If the old name was originally an ordinal, and
  371.                      * there was no corresponding label for it,
  372.                      * assume that the user is trying to enter a
  373.                      * define for it and leave it alone.  Otherwise,
  374.                      * pick the next available id.  But if the user
  375.                      * completely blanks out the field, leave it
  376.                      * alone also (this is a benign case).
  377.                      */
  378.                     if (IsOrd(pszOldName) &&
  379.                             (!*szSym || !FindID(OrdID(pszOldName), plInclude)))
  380.                         id = OrdID(pszOldName);
  381.                     else
  382.                         id = NextID((gnpcSel->pwcd->iType == W_DIALOG) ?
  383.                                 NEXTID_DIALOG : NEXTID_CONTROL, plInclude, 0);
  384.                 }
  385.  
  386.                 StatusSetNameID(id, gnpcSel->pwcd->iType);
  387.  
  388.                 /*
  389.                  * Change the labels to reflect that the entered name
  390.                  * is an ID instead of a name.
  391.                  */
  392.                 StatusSetTextLabels(gnpcSel->pwcd->iType, TRUE);
  393.  
  394.                 gfStatusChanged = TRUE;
  395.             }
  396.  
  397.             break;
  398.  
  399.         case DID_STATUSSYMID:
  400.         case DID_STATUSNAMEID:
  401.         case DID_STATUSTEXT:
  402.             if (!gnpcSel)
  403.                 break;
  404.  
  405.             if (NotifyCode == EN_CHANGE)
  406.                 gfStatusChanged = TRUE;
  407.  
  408.             if (idCtrl == DID_STATUSNAMEID) {
  409.                 GetDlgItemText(hwnd, DID_STATUSNAME, szSym, CCHTEXTMAX);
  410.                 GetDlgItemText(hwnd, DID_STATUSNAMEID, szID, CCHIDMAX + 1);
  411.                 StrToNameOrd(szSym, (gnpcSel->pwcd->iType == W_DIALOG) ?
  412.                         TRUE : FALSE);
  413.  
  414.                 /*
  415.                  * Change the labels to reflect whether the entered name
  416.                  * is an ID or a name.  It is considered an id if the
  417.                  * edit field has something in it, or if the name field
  418.                  * is a valid label, or if the name field represents an
  419.                  * ordinal (it is numeric).
  420.                  */
  421.                 StatusSetTextLabels(gnpcSel->pwcd->iType,
  422.                         (IsOrd(szSym) || *szID ||
  423.                         FindLabel(szSym, plInclude)) ? TRUE : FALSE);
  424.             }
  425.  
  426.             break;
  427.  
  428.         case IDOK:
  429.             if (StatusApplyChanges())
  430.                 SetFocus(ghwndMain);
  431.  
  432.             break;
  433.  
  434.         case IDCANCEL:
  435.             StatusUpdate();
  436.             SetFocus(ghwndMain);
  437.             break;
  438.     }
  439. }
  440.  
  441.  
  442.  
  443. /************************************************************************
  444. * StatusApplyChanges
  445. *
  446. * Processes the Enter command from the "Status" bar window to apply
  447. * the current value of the fields to the current control.
  448. *
  449. * Returns:
  450. *
  451. * TRUE is successful; otherwise, FALSE is returned.
  452. *
  453. ************************************************************************/
  454.  
  455. BOOL StatusApplyChanges(VOID)
  456. {
  457.     TCHAR szText[CCHTEXTMAX];
  458.     TCHAR szSym[CCHTEXTMAX];
  459.     TCHAR szName[CCHTEXTMAX];
  460.     TCHAR szSymID[CCHIDMAX + 1];
  461.     TCHAR szNameID[CCHIDMAX + 1];
  462.     TCHAR szNameSym[CCHTEXTMAX];
  463.     INT idSymNew;
  464.     INT idNameNew;
  465.     BOOL fAddSymLabel;
  466.     BOOL fAddNameLabel;
  467.     BOOL fSuccess = FALSE;
  468.  
  469.     /*
  470.      * Quit if nothing is selected, or if nothing was changed.
  471.      */
  472.     if (!gnpcSel || !gfStatusChanged)
  473.         return TRUE;
  474.  
  475.     idSymNew = gnpcSel->id;
  476.  
  477.     switch (gnpcSel->pwcd->iType) {
  478.         case W_DIALOG:
  479.             GetDlgItemText(hwndStatus, DID_STATUSNAME, szName, CCHTEXTMAX);
  480.             GetDlgItemText(hwndStatus, DID_STATUSNAMEID, szNameID, CCHIDMAX + 1);
  481.             GetDlgItemText(hwndStatus, DID_STATUSTEXT, szText, CCHTEXTMAX);
  482.             if (!ValidateNewName(gnpcSel, szName, szNameID, szNameSym,
  483.                     &idNameNew, &fAddNameLabel))
  484.                 return FALSE;
  485.  
  486.             if (ApplyNewName(gnpcSel, szName, fAddNameLabel,
  487.                     szNameSym, idNameNew) &&
  488.                     ApplyNewText(gnpcSel, szText))
  489.                 fSuccess = TRUE;
  490.  
  491.             break;
  492.  
  493.         case W_ICON:
  494.             GetDlgItemText(hwndStatus, DID_STATUSNAME, szName, CCHTEXTMAX);
  495.             GetDlgItemText(hwndStatus, DID_STATUSNAMEID, szNameID, CCHIDMAX + 1);
  496.             GetDlgItemText(hwndStatus, DID_STATUSSYM, szSym, CCHTEXTMAX);
  497.             GetDlgItemText(hwndStatus, DID_STATUSSYMID, szSymID, CCHIDMAX + 1);
  498.             if (!ValidateNewName(gnpcSel, szName, szNameID, szNameSym,
  499.                     &idNameNew, &fAddNameLabel) ||
  500.                     !ValidateNewID(gnpcSel, szSym, szSymID,
  501.                     &idSymNew, &fAddSymLabel))
  502.                 return FALSE;
  503.  
  504.             if (ApplyNewID(gnpcSel, idSymNew, fAddSymLabel, szSym) &&
  505.                     ApplyNewName(gnpcSel, szName, fAddNameLabel,
  506.                     szNameSym, idNameNew))
  507.                 fSuccess = TRUE;
  508.  
  509.             break;
  510.  
  511.         default:
  512.             GetDlgItemText(hwndStatus, DID_STATUSSYM, szSym, CCHTEXTMAX);
  513.             GetDlgItemText(hwndStatus, DID_STATUSSYMID, szSymID, CCHIDMAX + 1);
  514.             GetDlgItemText(hwndStatus, DID_STATUSTEXT, szText, CCHTEXTMAX);
  515. #ifdef JAPAN
  516.             {
  517.                 TCHAR   szTmp[CCHTEXTMAX];
  518.  
  519.                 KKExpandCopy(szTmp, szText, CCHTEXTMAX);
  520.                 lstrcpy(szText, szTmp);
  521.             }
  522. #endif
  523.             if (!ValidateNewID(gnpcSel, szSym, szSymID, &idSymNew, &fAddSymLabel))
  524.                 return FALSE;
  525.  
  526.             if (ApplyNewID(gnpcSel, idSymNew, fAddSymLabel, szSym) &&
  527.                     ApplyNewText(gnpcSel, szText))
  528.                 fSuccess = TRUE;
  529.  
  530.             break;
  531.     }
  532.  
  533.     if (fSuccess) {
  534.         ShowFileStatus(FALSE);
  535.         StatusUpdate();
  536.     }
  537.  
  538.     return fSuccess;
  539. }
  540.  
  541.  
  542.  
  543. /************************************************************************
  544. * ValidateNewName
  545. *
  546. * Validates the new name from the processing of the OK command
  547. * from the Status ribbon window.
  548. *
  549. * The name is considered valid if it does not have any blanks in it,
  550. * it is not already used by another dialog in the resource file, and
  551. * it is not an empty string.
  552. *
  553. * Arguments:
  554. *   NPCTYPE npc      - Pointer to the control.
  555. *   LPTSTR pszName   - The new name.
  556. *   LPTSTR pszID     - The ID.
  557. *   LPTSTR pszSym    - The symbol.
  558. *   PINT pidNew      - Where to return the new ID if successful.
  559. *   BOOL *pfAddLabel - Set to TRUE if this symbol/id should be added
  560. *                      to the include list.  Not touched otherwise.
  561. *
  562. * Returns:
  563. *   TRUE if the new name is valid, FALSE otherwise.
  564. *
  565. ************************************************************************/
  566.  
  567. STATICFN BOOL ValidateNewName(
  568.     NPCTYPE npc,
  569.     LPTSTR pszName,
  570.     LPTSTR pszID,
  571.     LPTSTR pszSym,
  572.     PINT pidNew,
  573.     BOOL *pfAddLabel)
  574. {
  575.     NPLABEL npLabel;
  576.     BOOL fIDEmpty = FALSE;
  577.     BOOL fNameEmpty = FALSE;
  578.     BOOL fAddLabel = FALSE;
  579.     INT idNew;
  580.     TCHAR szIDTemp[CCHIDMAX + 1];
  581.  
  582.     /*
  583.      * Start by assuming that the label will NOT be added.
  584.      */
  585.     *pfAddLabel = FALSE;
  586.  
  587.     /*
  588.      * Is the ID field non-blank?
  589.      */
  590.     if (*pszID) {
  591.         /*
  592.          * Is the id valid?
  593.          */
  594.         if (!IsValue(pszID)) {
  595.             Message(MSG_BADSYMBOLID);
  596.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSNAMEID));
  597.             return FALSE;
  598.         }
  599.  
  600.         idNew = valtoi(pszID);
  601.     }
  602.     else {
  603.         /*
  604.          * The id field is blank.
  605.          */
  606.         fIDEmpty = TRUE;
  607.     }
  608.  
  609.     /*
  610.      * Is the name field blank?
  611.      */
  612.     if (!(*pszName))
  613.         fNameEmpty = TRUE;
  614.  
  615.     if (fNameEmpty) {
  616.         if (fIDEmpty) {
  617.             Message((npc->pwcd->iType == W_DIALOG) ?
  618.                     MSG_NODLGNAME : MSG_NOICONNAME);
  619.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSNAME));
  620.             return FALSE;
  621.         }
  622.         else {
  623.             WriteOrd((PORDINAL)pszName, idNew);
  624.         }
  625.     }
  626.     else {
  627.         /*
  628.          * Error if there are imbedded blanks.
  629.          */
  630.         if (HasBlanks(pszName)) {
  631.             Message((npc->pwcd->iType == W_DIALOG) ?
  632.                     MSG_DLGNAMEHASBLANKS : MSG_ICONNAMEHASBLANKS);
  633.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSNAME));
  634.             return FALSE;
  635.         }
  636.  
  637.         /*
  638.          * Convert the name to an ordinal, if appropriate.
  639.          */
  640.         StrToNameOrd(pszName, (npc->pwcd->iType == W_DIALOG) ? TRUE : FALSE);
  641.  
  642.         /*
  643.          * If the name was translated to an ordinal, we are done.
  644.          * Otherwise, keep trying to figure out whether it is a
  645.          * name or a define.
  646.          */
  647.         if (!IsOrd(pszName)) {
  648.             /*
  649.              * Is the name a symbol in the current include list?
  650.              */
  651.             if (npLabel = FindLabel(pszName, plInclude)) {
  652.                 /*
  653.                  * Yes.  If the id field was blank, just assume they
  654.                  * wanted the corresponding id.
  655.                  */
  656.                 if (fIDEmpty)
  657.                     idNew = npLabel->id;
  658.  
  659.                 /*
  660.                  * If they somehow entered a valid define but tried to
  661.                  * give it a different id value, show an error.
  662.                  */
  663.                 if (npLabel->id != idNew) {
  664.                     Myitoa(npLabel->id, szIDTemp);
  665.                     Message(MSG_IDSYMMISMATCH, szIDTemp);
  666.                     SetFocus(GetDlgItem(hwndStatus, DID_STATUSNAMEID));
  667.                     return FALSE;
  668.                 }
  669.  
  670.                 /*
  671.                  * Make the name field into an ordinal.
  672.                  */
  673.                 WriteOrd((PORDINAL)pszName, idNew);
  674.             }
  675.             else {
  676.                 /*
  677.                  * The name was not found as a label.  Is the id field
  678.                  * empty?
  679.                  */
  680.                 if (fIDEmpty) {
  681.                     /*
  682.                      * Since the id field is empty, we can assume that
  683.                      * what they entered is a name (not a define)
  684.                      * and we are done.
  685.                      */
  686.                 }
  687.                 else {
  688.                     /*
  689.                      * At this point we know the name field is not empty,
  690.                      * and there is an id entered along with it.  We also
  691.                      * know that the name (which we can now assume is
  692.                      * a symbol) is not already found in the include file.
  693.                      * We will check it for validity, copy it to the
  694.                      * pszSym buffer, translate the name to an ordinal
  695.                      * and set a flag saying that the sym/id pair should
  696.                      * be added to the include list.
  697.                      */
  698.                     if (!IsSymbol(pszName)) {
  699.                         Message(MSG_BADSYMBOLID);
  700.                         SetFocus(GetDlgItem(hwndStatus, DID_STATUSNAME));
  701.                         return FALSE;
  702.                     }
  703.  
  704.                     /*
  705.                      * Pass back the values.
  706.                      */
  707.                     lstrcpy(pszSym, pszName);
  708.                     WriteOrd((PORDINAL)pszName, idNew);
  709.                     *pidNew = idNew;
  710.  
  711.                     fAddLabel = TRUE;
  712.                 }
  713.             }
  714.         }
  715.     }
  716.  
  717.     /*
  718.      * Inform caller whether they should add this id/symbol
  719.      * as a label to the include list.
  720.      */
  721.     *pfAddLabel = fAddLabel;
  722.  
  723.     /*
  724.      * Return success.
  725.      */
  726.     return TRUE;
  727. }
  728.  
  729.  
  730.  
  731. /************************************************************************
  732. * ValidateNewID
  733. *
  734. * Validates the new ID from the processing of the OK command from
  735. * the Status ribbon window.  It will return the new id in *pidNew.
  736. * Note that the control is not actually updated by this routine.  This
  737. * is so that if other validations fail nothing will have been done to the
  738. * control.  It is assumed that ApplyNewID will be called later to do
  739. * the actual update of the control.
  740. *
  741. * Arguments:
  742. *   NPCTYPE npc      = Pointer to the control.
  743. *   LPTSTR pszSym    = The symbol.
  744. *   LPTSTR pszID     = The ID.
  745. *   PINT pidNew      = Where to return the new ID if successful.
  746. *   BOOL *pfAddLabel = Set to TRUE if this symbol/id should be added
  747. *                      to the include list.  Not touched otherwise.
  748. *
  749. * Returns:
  750. *   TRUE if successful, FALSE otherwise.  If TRUE is returned and they
  751. *   changed the id, the new id will have been placed in *pidNew.
  752. *
  753. ************************************************************************/
  754.  
  755. STATICFN BOOL ValidateNewID(
  756.     NPCTYPE npc,
  757.     LPTSTR pszSym,
  758.     LPTSTR pszID,
  759.     PINT pidNew,
  760.     BOOL *pfAddLabel)
  761. {
  762.     NPLABEL npLabel;
  763.     BOOL fIDEmpty = FALSE;
  764.     BOOL fIDChanged = FALSE;
  765.     BOOL fSymEmpty = FALSE;
  766.     BOOL fSymChanged = FALSE;
  767.     BOOL fAddLabel = FALSE;
  768.     INT idNew;
  769.     TCHAR szIDTemp[CCHIDMAX + 1];
  770.  
  771.     /*
  772.      * Start by assuming that the label will NOT be added.
  773.      */
  774.     *pfAddLabel = FALSE;
  775.  
  776.     /*
  777.      * If in translate mode, they cannot change the symbol or id,
  778.      * and so it should not be validated.  Even if there was a
  779.      * problem, they could not fix it.
  780.      */
  781.     if (gfTranslateMode)
  782.         return TRUE;
  783.  
  784.     /*
  785.      * Special case if they selected the "unused" label.
  786.      * Blank out the symbol so it doesn't cause trouble
  787.      * later, force the id to be zero, and then check if
  788.      * the id was changed.
  789.      */
  790.     if (lstrcmp(pszSym, ids(IDS_UNUSED)) == 0) {
  791.         pszSym = szEmpty;
  792.         idNew = IDUNUSED;
  793.         if (idNew != npc->id)
  794.             fIDChanged = TRUE;
  795.     }
  796.     else if (lstrcmp(pszSym, ids(IDS_IDOK)) == 0 &&
  797.             !FindLabel(ids(IDS_IDOK), plInclude)) {
  798.         pszSym = szEmpty;
  799.         idNew = IDOK;
  800.         if (idNew != npc->id)
  801.             fIDChanged = TRUE;
  802.     }
  803.     else if (lstrcmp(pszSym, ids(IDS_IDCANCEL)) == 0 &&
  804.             !FindLabel(ids(IDS_IDCANCEL), plInclude)) {
  805.         pszSym = szEmpty;
  806.         idNew = IDCANCEL;
  807.         if (idNew != npc->id)
  808.             fIDChanged = TRUE;
  809.     }
  810.     /*
  811.      * Is the ID field non-blank?
  812.      */
  813.     else if (*pszID) {
  814.         /*
  815.          * Is the id valid?
  816.          */
  817.         if (!IsValue(pszID)) {
  818.             Message(MSG_BADSYMBOLID);
  819.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSSYMID));
  820.             return FALSE;
  821.         }
  822.  
  823.         /*
  824.          * Did they change the id value?
  825.          */
  826.         idNew = valtoi(pszID);
  827.         if (idNew != npc->id)
  828.             fIDChanged = TRUE;
  829.     }
  830.     else {
  831.         /*
  832.          * The id field is blank.  This implies they changed it.
  833.          */
  834.         fIDEmpty = TRUE;
  835.         fIDChanged = TRUE;
  836.     }
  837.  
  838.     /*
  839.      * Is the symbol field blank?
  840.      */
  841.     if (!(*pszSym))
  842.         fSymEmpty = TRUE;
  843.  
  844.     /*
  845.      * Determine if they have changed the symbol.
  846.      * Did the original id have a symbol associated with it?
  847.      */
  848.     if (npLabel = FindID(npc->id, plInclude)) {
  849.         if (lstrcmp(npLabel->pszLabel, pszSym) != 0)
  850.             fSymChanged = TRUE;
  851.     }
  852.     else {
  853.         /*
  854.          * Since the original id did not have a symbol, if they
  855.          * have entered a symbol it is changed.
  856.          */
  857.         if (!fSymEmpty)
  858.             fSymChanged = TRUE;
  859.     }
  860.  
  861.     /*
  862.      * Quit if nothing changed.
  863.      */
  864.     if (!fSymChanged && !fIDChanged)
  865.         return TRUE;
  866.  
  867.     /*
  868.      * Is the symbol field empty?
  869.      */
  870.     if (fSymEmpty) {
  871.         /*
  872.          * If the id field is empty also, return an error.
  873.          */
  874.         if (fIDEmpty) {
  875.             Message(MSG_BADSYMBOLID);
  876.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSSYMID));
  877.             return FALSE;
  878.         }
  879.         else {
  880.             /*
  881.              * Otherwise, go on to the final test.  It doesn't matter
  882.              * if this new id has a symbol or not.
  883.              */
  884.             goto CheckForDups;
  885.         }
  886.     }
  887.  
  888.     /*
  889.      * At this point we know the symbol field is not empty.
  890.      * Is it a valid symbol?
  891.      */
  892.     if (!IsSymbol(pszSym)) {
  893.         Message(MSG_BADSYMBOLID);
  894.         SetFocus(GetDlgItem(hwndStatus, DID_STATUSSYM));
  895.         return FALSE;
  896.     }
  897.  
  898.     /*
  899.      * Does this symbol already exist?
  900.      */
  901.     if (npLabel = FindLabel(pszSym, plInclude)) {
  902.         /*
  903.          * Since the symbol exists, if they blanked the id field
  904.          * be friendly and assume they want the matching id value.
  905.          */
  906.         if (fIDEmpty)
  907.             idNew = npLabel->id;
  908.  
  909.         /*
  910.          * Does the id that is in the id field match the id of the
  911.          * symbol they entered?
  912.          */
  913.         if (npLabel->id == idNew) {
  914.             /*
  915.              * Yes, go on to the final test.
  916.              */
  917.             goto CheckForDups;
  918.         }
  919.         else {
  920.             /*
  921.              * No, give them an error message saying that it has to.
  922.              */
  923.             Myitoa(npLabel->id, szIDTemp);
  924.             Message(MSG_IDSYMMISMATCH, szIDTemp);
  925.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSSYMID));
  926.             return FALSE;
  927.         }
  928.     }
  929.     else {
  930.         /*
  931.          * Since the symbol doesn't exist, if they left the id field
  932.          * blank, assume they want the next available id.
  933.          */
  934.         if (fIDEmpty)
  935.             idNew = NextID(NEXTID_CONTROL, plInclude, 0);
  936.  
  937.         /*
  938.          * They should add this id/symbol as a label to the
  939.          * include list.
  940.          */
  941.         fAddLabel = TRUE;
  942.         goto CheckForDups;
  943.     }
  944.  
  945. CheckForDups:
  946.     /*
  947.      * If the id changed, it is not the special "unused" id,
  948.      * and it is a duplicate of another id, don't allow it.
  949.      */
  950.     if (idNew != npc->id && !IsUniqueID(idNew)) {
  951.         Message(MSG_CTRLDUPID);
  952.         SetFocus(GetDlgItem(hwndStatus, DID_STATUSSYM));
  953.         return FALSE;
  954.     }
  955.     else {
  956.         /*
  957.          * Pass back the new id value.
  958.          */
  959.         *pidNew = idNew;
  960.  
  961.         /*
  962.          * Inform caller whether they should add this id/symbol
  963.          * as a label to the include list.
  964.          */
  965.         *pfAddLabel = fAddLabel;
  966.  
  967.         /*
  968.          * Return success.
  969.          */
  970.         return TRUE;
  971.     }
  972. }
  973.  
  974.  
  975.  
  976. /************************************************************************
  977. * ApplyNewName
  978. *
  979. * Updates an icon control's or dialog's name with a new name.
  980. *
  981. * If fAddLabel is TRUE, pszSym is assumed to be a string that is
  982. * the symbol to be added and idNew contains the value associated with
  983. * it.  This will cause a new define to be added to the current include
  984. * file.  In either event, pszName will contain either a new name or
  985. * an ordinal that is to be the name.  For dialogs, the dialog name will
  986. * be updated.  For icon controls, the icon's text is updated with the
  987. * name/ordinal.
  988. *
  989. * Arguments:
  990. *   NPCTYPE npc     = Pointer to the control.
  991. *   LPTSTR pszName  = New name.  A string or ordinal.
  992. *   BOOL fAddLabel  = TRUE if a new label for this id/name should be added.
  993. *   LPTSTR pszSym   = The new symbol to add (only valid if fAddLabel is TRUE).
  994. *   INT idNew       = The new ID (only valid if fAddLabel is TRUE).
  995. *
  996. * Returns:
  997. *
  998. * TRUE if successful; otherwise, FALSE is returned.
  999. *
  1000. ************************************************************************/
  1001.  
  1002. STATICFN BOOL ApplyNewName(
  1003.     NPCTYPE npc,
  1004.     LPTSTR pszName,
  1005.     BOOL fAddLabel,
  1006.     LPTSTR pszSym,
  1007.     INT idNew)
  1008. {
  1009.     LPTSTR psz;
  1010.  
  1011.     if (fAddLabel) {
  1012.         /*
  1013.          * Go ahead and quietly add the label for them.
  1014.          */
  1015.         if (AddLabel(pszSym, idNew, FPOS_MAX, 0, &plInclude,
  1016.                 &plDelInclude, NULL, NULL)) {
  1017.             /*
  1018.              * Return the controls new id, update the status
  1019.              * windows symbol combo box, mark the fact that
  1020.              * we have changed the include file, and return
  1021.              * success.
  1022.              */
  1023.             gfIncChged = TRUE;
  1024.             StatusFillSymbolList(plInclude);
  1025.         }
  1026.         else {
  1027.             /*
  1028.              * An error occurred on the AddLabel.  The most likely
  1029.              * cause of this is if they are trying to add a symbol
  1030.              * with a duplicate id.
  1031.              */
  1032.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSNAMEID));
  1033.             return FALSE;
  1034.         }
  1035.     }
  1036.  
  1037.     switch (npc->pwcd->iType) {
  1038.         case W_ICON:
  1039.             /*
  1040.              * The resource name for an icon is stored in it's text.
  1041.              */
  1042.             ApplyNewText(npc, pszName);
  1043.             break;
  1044.  
  1045.         case W_DIALOG:
  1046.             /*
  1047.              * We are done if the name was not changed.
  1048.              */
  1049.             if (NameOrdCmp(gcd.pszDlgName, pszName) == 0)
  1050.                 break;
  1051.  
  1052.             /*
  1053.              * Allocate room for the new name (it can be an ordinal!).
  1054.              */
  1055.             if (!(psz = MyAlloc(NameOrdLen(pszName))))
  1056.                 return FALSE;
  1057.  
  1058.             NameOrdCpy(psz, pszName);
  1059.  
  1060.             if (gcd.pszDlgName)
  1061.                 MyFree(gcd.pszDlgName);
  1062.  
  1063.             gcd.pszDlgName = psz;
  1064.  
  1065.             /*
  1066.              * If the new name is an ordinal, update the base id of
  1067.              * the dialog with it.
  1068.              */
  1069.             if (IsOrd(gcd.pszDlgName))
  1070.                 gcd.npc->id = OrdID(gcd.pszDlgName);
  1071.  
  1072.             /*
  1073.              * Finally, set the "changed" flag.
  1074.              */
  1075.             gfResChged = gfDlgChanged = TRUE;
  1076.  
  1077.             break;
  1078.     }
  1079.  
  1080.     return TRUE;
  1081. }
  1082.  
  1083.  
  1084.  
  1085. /************************************************************************
  1086. * ApplyNewID
  1087. *
  1088. * Updates the control with the new id.
  1089. *
  1090. * Arguments:
  1091. *   NPCTYPE npc    = Pointer to the control.
  1092. *   INT idNew      = The ID.
  1093. *   BOOL fAddLabel = TRUE if a new label for this id/symbol should be added.
  1094. *   LPTSTR pszSym  = Symbol to add if fAddLabel is TRUE.
  1095. *
  1096. * Returns:
  1097. *
  1098. * TRUE if successful; otherwise, FALSE is returned.
  1099. *
  1100. ************************************************************************/
  1101.  
  1102. STATICFN BOOL ApplyNewID(
  1103.     NPCTYPE npc,
  1104.     INT idNew,
  1105.     BOOL fAddLabel,
  1106.     LPTSTR pszSym)
  1107. {
  1108.     if (fAddLabel) {
  1109.         /*
  1110.          * Go ahead and quietly add the label for them.
  1111.          */
  1112.         if (AddLabel(pszSym, idNew, FPOS_MAX, 0, &plInclude,
  1113.                 &plDelInclude, NULL, NULL)) {
  1114.             /*
  1115.              * Return the controls new id, update the status
  1116.              * windows symbol combo box, mark the fact that
  1117.              * we have changed the include file, and return
  1118.              * success.
  1119.              */
  1120.             gfIncChged = TRUE;
  1121.             StatusFillSymbolList(plInclude);
  1122.         }
  1123.         else {
  1124.             /*
  1125.              * An error occurred on the AddLabel.  The most likely
  1126.              * cause of this is if they are trying to add a symbol
  1127.              * with a duplicate id.
  1128.              */
  1129.             SetFocus(GetDlgItem(hwndStatus, DID_STATUSSYMID));
  1130.             return FALSE;
  1131.         }
  1132.     }
  1133.  
  1134.     /*
  1135.      * Return if the id wasn't changed.
  1136.      */
  1137.     if (npc->id == idNew)
  1138.         return TRUE;
  1139.  
  1140.     /*
  1141.      * Update the controls id and set the resource changed flag.
  1142.      */
  1143.     npc->id = idNew;
  1144.     gfResChged = gfDlgChanged = TRUE;
  1145.     return TRUE;
  1146. }
  1147.  
  1148.  
  1149.  
  1150. /************************************************************************
  1151. * ApplyNewText
  1152. *
  1153. * Sets the new text from the processing of the OK command from
  1154. * the Status ribbon window.  If the text was changed, the selected
  1155. * control will have its text updated.
  1156. *
  1157. * Arguments:
  1158. *   NPCTYPE npc       = Pointer to the control.
  1159. *   LPTSTR pszNewText = The new text.
  1160. *
  1161. * Returns:
  1162. *
  1163. * TRUE if successful, FALSE otherwise.
  1164. *
  1165. ************************************************************************/
  1166.  
  1167. STATICFN BOOL ApplyNewText(
  1168.     NPCTYPE npc,
  1169.     LPTSTR pszNewText)
  1170. {
  1171.     INT cb;
  1172.     LPTSTR psz;
  1173.  
  1174.     /*
  1175.      * Did the text change?
  1176.      */
  1177.     if ((npc->text == NULL && *pszNewText) ||
  1178.             (npc->text != NULL && NameOrdCmp(npc->text, pszNewText) != 0)) {
  1179.         if (*pszNewText) {
  1180.             cb = NameOrdLen(pszNewText);
  1181.  
  1182.             if (npc->text == NULL)
  1183.                 psz = MyAlloc(cb);
  1184.             else
  1185.                 psz = MyRealloc(npc->text, cb);
  1186.  
  1187.             if (psz == NULL) {
  1188.                 return FALSE;
  1189.             }
  1190.             else {
  1191.                 NameOrdCpy(psz, pszNewText);
  1192.                 npc->text = psz;
  1193.             }
  1194.         }
  1195.         else {
  1196.             if (npc->text) {
  1197.                 MyFree(npc->text);
  1198.                 npc->text = NULL;
  1199.             }
  1200.         }
  1201.  
  1202.         /*
  1203.          * Change the text of the control, except for W_ICON controls
  1204.          * because they have resource names.  In that case, we don't
  1205.          * want to change the text of the actual control because
  1206.          * the resource would probably not be found.
  1207.          */
  1208.         if (npc->pwcd->iType != W_ICON) {
  1209.             SetWindowText(npc->hwnd, pszNewText);
  1210.  
  1211.             /*
  1212.              * Redraw the control after the text changed.  This is
  1213.              * necessary because changing the text probably caused
  1214.              * the drag handles to get overwritten.
  1215.              */
  1216.             if (npc->pwcd->iType == W_DIALOG)
  1217.                 /*
  1218.                  * Redraw the frame, which just overwrote the drag
  1219.                  * handles when the text was changed.
  1220.                  */
  1221.                 SetWindowPos(npc->hwnd, NULL, 0, 0, 0, 0,
  1222.                         SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOMOVE |
  1223.                         SWP_NOSIZE | SWP_NOZORDER);
  1224.             else
  1225.                 /*
  1226.                  * Redraw the control(s).
  1227.                  */
  1228.                 RedrawSelection();
  1229.         }
  1230.  
  1231.         gfResChged = gfDlgChanged = TRUE;
  1232.     }
  1233.  
  1234.     return TRUE;
  1235. }
  1236.  
  1237.  
  1238.  
  1239. /************************************************************************
  1240. * StatusFillSymbolList
  1241. *
  1242. * This function fills the Symbol and Name combo boxes with
  1243. * the given list of labels.
  1244. *
  1245. * Arguments:
  1246. *   NPLABEL plHead - pointer to the list of labels.
  1247. *
  1248. ************************************************************************/
  1249.  
  1250. VOID StatusFillSymbolList(
  1251.     NPLABEL plHead)
  1252. {
  1253.     NPLABEL npLabel;
  1254.     HWND hwndSymCB;
  1255.     HWND hwndNameCB;
  1256.     HCURSOR hcurSave;
  1257.  
  1258.     hcurSave = SetCursor(hcurWait);
  1259.  
  1260.     /*
  1261.      * Get the handles to the combo boxes and clear out all items.
  1262.      */
  1263.     hwndSymCB = GetDlgItem(hwndStatus, DID_STATUSSYM);
  1264.     hwndNameCB = GetDlgItem(hwndStatus, DID_STATUSNAME);
  1265.     SendMessage(hwndSymCB, CB_RESETCONTENT, 0, 0L);
  1266.     SendMessage(hwndNameCB, CB_RESETCONTENT, 0, 0L);
  1267.  
  1268.     /*
  1269.      * Fill the combo boxes with the items.
  1270.      */
  1271.     for (npLabel = plHead; npLabel; npLabel = npLabel->npNext) {
  1272.         SendMessage(hwndSymCB, CB_ADDSTRING, 0, (DWORD)npLabel->pszLabel);
  1273.         SendMessage(hwndNameCB, CB_ADDSTRING, 0, (DWORD)npLabel->pszLabel);
  1274.     }
  1275.  
  1276.     /*
  1277.      * Put some special entries into the symbol combo.  Note that we allow
  1278.      * the user to have defined IDOK and IDCANCEL to be something else,
  1279.      * in which case we will NOT add these special entries after all.
  1280.      */
  1281.     SendMessage(hwndSymCB, CB_ADDSTRING, 0, (DWORD)ids(IDS_UNUSED));
  1282.  
  1283.     if (!FindLabel(ids(IDS_IDOK), plInclude))
  1284.         SendMessage(hwndSymCB, CB_ADDSTRING, 0, (DWORD)ids(IDS_IDOK));
  1285.  
  1286.     if (!FindLabel(ids(IDS_IDCANCEL), plInclude))
  1287.         SendMessage(hwndSymCB, CB_ADDSTRING, 0, (DWORD)ids(IDS_IDCANCEL));
  1288.  
  1289.     SetCursor(hcurSave);
  1290. }
  1291.  
  1292.  
  1293.  
  1294. /************************************************************************
  1295. * StatusSetCoords
  1296. *
  1297. * This function sets the coordinates in the status display
  1298. * to the given rectangle.
  1299. *
  1300. * Arguments:
  1301. *    PRECT prc - coordinates.
  1302. *
  1303. ************************************************************************/
  1304.  
  1305. VOID StatusSetCoords(
  1306.     PRECT prc)
  1307. {
  1308.     static INT xSave = 0x7FFF;
  1309.     static INT ySave = 0x7FFF;
  1310.     static INT cxSave = 0x7FFF;
  1311.     static INT cySave = 0x7FFF;
  1312.     static INT x2Save = 0x7FFF;
  1313.     static INT y2Save = 0x7FFF;
  1314.     TCHAR szBuf[CCHTEXTMAX];
  1315.  
  1316.     if (prc) {
  1317.         if (prc->bottom - prc->top != cySave) {
  1318.             /*
  1319.              *  Save it for the next time.
  1320.              */
  1321.             cySave = prc->bottom - prc->top;
  1322.  
  1323.             wsprintf(szBuf, ids(IDS_CYFMTSTR), cySave);
  1324.             SetDlgItemText(hwndStatus, DID_STATUSCY, szBuf);
  1325.         }
  1326.  
  1327.         if (prc->right != x2Save || prc->bottom != y2Save) {
  1328.             /*
  1329.              *  Save them for the next time.
  1330.              */
  1331.             x2Save = prc->right;
  1332.             y2Save = prc->bottom;
  1333.  
  1334.             wsprintf(szBuf, L"(%d, %d)", x2Save, y2Save);
  1335.             SetDlgItemText(hwndStatus, DID_STATUSX2Y2, szBuf);
  1336.         }
  1337.  
  1338.         if (prc->left != xSave || prc->top != ySave) {
  1339.             /*
  1340.              *  Save them for the next time.
  1341.              */
  1342.             xSave = prc->left;
  1343.             ySave = prc->top;
  1344.  
  1345.             wsprintf(szBuf, L"(%d, %d)", xSave, ySave);
  1346.             SetDlgItemText(hwndStatus, DID_STATUSXY, szBuf);
  1347.         }
  1348.  
  1349.         if (prc->right - prc->left != cxSave) {
  1350.             /*
  1351.              *  Save it for the next time.
  1352.              */
  1353.             cxSave = prc->right - prc->left;
  1354.  
  1355.             wsprintf(szBuf, ids(IDS_CXFMTSTR), cxSave);
  1356.             SetDlgItemText(hwndStatus, DID_STATUSCX, szBuf);
  1357.         }
  1358.     }
  1359.     else {
  1360.         /*
  1361.          * Clear the fields.
  1362.          */
  1363.         SetDlgItemText(hwndStatus, DID_STATUSXY, szEmpty);
  1364.         SetDlgItemText(hwndStatus, DID_STATUSX2Y2, szEmpty);
  1365.         SetDlgItemText(hwndStatus, DID_STATUSCX, szEmpty);
  1366.         SetDlgItemText(hwndStatus, DID_STATUSCY, szEmpty);
  1367.  
  1368.         /*
  1369.          * Reset the cache variables so that the next "set" of
  1370.          * the coords is sure to update the display fields.
  1371.          */
  1372.         xSave =
  1373.         ySave =
  1374.         cxSave =
  1375.         cySave =
  1376.         x2Save =
  1377.         y2Save = 0x7FFF;
  1378.     }
  1379. }
  1380.  
  1381.  
  1382.  
  1383. /************************************************************************
  1384. * StatusSetText
  1385. *
  1386. * This function sets the "Text" field in the status display
  1387. * to the given text.
  1388. *
  1389. * Arguments:
  1390. *   LPTSTR pszText - The text to display.  This can be NULL.
  1391. *   INT Type       - Type of control.  One of the W_* constants.
  1392. *
  1393. ************************************************************************/
  1394.  
  1395. STATICFN VOID StatusSetText(
  1396.     LPTSTR pszText,
  1397.     INT Type)
  1398. {
  1399.     /*
  1400.      * Protect against getting a null value.
  1401.      */
  1402.     if (!pszText)
  1403.         pszText = szEmpty;
  1404.  
  1405.     /*
  1406.      * If this is an icon control, set the name instead (the text
  1407.      * of an icon is really a resource name).
  1408.      */
  1409.     if (Type == W_ICON)
  1410.         StatusSetName(pszText, Type);
  1411.     else
  1412. #ifdef JAPAN
  1413.     {
  1414.         TCHAR   szTmp[CCHTEXTMAX];
  1415.  
  1416.         KDExpandCopy(szTmp, pszText, CCHTEXTMAX);
  1417.         SetDlgItemText(hwndStatus, DID_STATUSTEXT, szTmp);
  1418.     }
  1419. #else
  1420.         SetDlgItemText(hwndStatus, DID_STATUSTEXT, pszText);
  1421. #endif
  1422. }
  1423.  
  1424.  
  1425.  
  1426. /************************************************************************
  1427. * StatusSetTextLabels
  1428. *
  1429. * This function sets the labels of the descriptive text fields in
  1430. * Status window based on the type of control that is selected.
  1431. *
  1432. * Arguments:
  1433. *   INT Type    - Type of control.  One of the W_* constants.
  1434. *   BOOL fIsOrd - TRUE if the name is an ordinal.  This is ignored
  1435. *                 unless Type is W_DIALOG or W_ICON.
  1436. *
  1437. ************************************************************************/
  1438.  
  1439. STATICFN VOID StatusSetTextLabels(
  1440.     INT Type,
  1441.     BOOL fIsOrd)
  1442. {
  1443.     WORD ids1;
  1444.     WORD ids2;
  1445.  
  1446.     switch (Type) {
  1447.         case W_DIALOG:
  1448.             ids1 = (WORD)(fIsOrd ? IDS_DLGIDLABEL : IDS_DLGNAMELABEL);
  1449.             ids2 = IDS_CAPTIONLABEL;
  1450.             break;
  1451.  
  1452.         case W_ICON:
  1453.             ids1 = IDS_SYMBOLLABEL;
  1454.             ids2 = (WORD)(fIsOrd ? IDS_ICONIDLABEL : IDS_ICONNAMELABEL);
  1455.             break;
  1456.  
  1457.         default:
  1458.             ids1 = IDS_SYMBOLLABEL;
  1459.             ids2 = IDS_TEXTLABEL;
  1460.             break;
  1461.     }
  1462.  
  1463.     SetDlgItemText(hwndStatus, DID_STATUSLABEL1, ids(ids1));
  1464.     SetDlgItemText(hwndStatus, DID_STATUSLABEL2, ids(ids2));
  1465. }
  1466.  
  1467.  
  1468.  
  1469. /************************************************************************
  1470. * StatusSetID
  1471. *
  1472. * Updates the id field of the given label.
  1473. *
  1474. * Arguments:
  1475. *     INT id        = The id.
  1476. *     BOOL fSymAlso = Find the corresponding label and update the
  1477. *                     symbol field also.
  1478. *
  1479. ************************************************************************/
  1480.  
  1481. STATICFN VOID StatusSetID(
  1482.     INT id,
  1483.     BOOL fSymAlso)
  1484. {
  1485.     TCHAR szValue[CCHIDMAX + 1];
  1486.     NPLABEL npLabel;
  1487.     LPTSTR pszLabel;
  1488.  
  1489.     Myitoa(id, szValue);
  1490.     SetDlgItemText(hwndStatus, DID_STATUSSYMID, szValue);
  1491.  
  1492.     if (fSymAlso) {
  1493.         /*
  1494.          * If a matching label is found, the text is used.
  1495.          * Otherwise, if the id is zero, we use the "unused"
  1496.          * label.  Otherwise, we just use an empty string.
  1497.          */
  1498.         if (npLabel = FindID(id, plInclude))
  1499.             pszLabel = npLabel->pszLabel;
  1500.         else if (id == IDUNUSED)
  1501.             pszLabel = ids(IDS_UNUSED);
  1502.         else if (id == IDOK && !FindLabel(ids(IDS_IDOK), plInclude))
  1503.             pszLabel = ids(IDS_IDOK);
  1504.         else if (id == IDCANCEL && !FindLabel(ids(IDS_IDCANCEL), plInclude))
  1505.             pszLabel = ids(IDS_IDCANCEL);
  1506.         else
  1507.             pszLabel = szEmpty;
  1508.  
  1509.         SetDlgItemText(hwndStatus, DID_STATUSSYM, pszLabel);
  1510.     }
  1511. }
  1512.  
  1513.  
  1514.  
  1515. /************************************************************************
  1516. * StatusSetName
  1517. *
  1518. * This function sets the "Res. Name" field in the status display
  1519. * to the given text.
  1520. *
  1521. * Arguments:
  1522. *
  1523. *   LPTSTR pszName - The name to display.  NULL values and ordinals
  1524. *                    are handled properly.
  1525. *   INT Type       - Type of control.  One of the W_* constants.
  1526. *
  1527. ************************************************************************/
  1528.  
  1529. STATICFN VOID StatusSetName(
  1530.     LPTSTR pszName,
  1531.     INT Type)
  1532. {
  1533.     NPLABEL npLabel;
  1534.  
  1535.     /*
  1536.      * Protect against getting a null value.
  1537.      */
  1538.     if (!pszName)
  1539.         pszName = szEmpty;
  1540.  
  1541.     /*
  1542.      * Does the name represent an ordinal?  If so, set the nameid
  1543.      * field to the value and fill in the name field with the
  1544.      * associated symbol, if there is one.
  1545.      *
  1546.      * Note that this does NOT produce a hex value in Hex Mode for
  1547.      * dialog names, because rc.exe does not parse hex ordinals
  1548.      * for dialog names.
  1549.      */
  1550.     if (IsOrd(pszName)) {
  1551.         StatusSetNameID(OrdID(pszName), Type);
  1552.  
  1553.         if (npLabel = FindID(OrdID(pszName), plInclude))
  1554.             pszName = npLabel->pszLabel;
  1555.         else
  1556.             pszName = szEmpty;
  1557.     }
  1558.     else {
  1559.         SetDlgItemText(hwndStatus, DID_STATUSNAMEID, szEmpty);
  1560.     }
  1561.  
  1562.     SetDlgItemText(hwndStatus, DID_STATUSNAME, pszName);
  1563. }
  1564.  
  1565.  
  1566.  
  1567. /************************************************************************
  1568. * StatusSetNameID
  1569. *
  1570. * This function sets the id edit field associated with the
  1571. * "Res. Name" field in the status display
  1572. *
  1573. * Arguments:
  1574. *
  1575. *   INT id   - The id to set into the field.
  1576. *   INT Type - Type of control.  One of the W_* constants.
  1577. *
  1578. ************************************************************************/
  1579.  
  1580. STATICFN VOID StatusSetNameID(
  1581.     INT id,
  1582.     INT Type)
  1583. {
  1584.     TCHAR szValue[CCHIDMAX + 1];
  1585.  
  1586.     /*
  1587.      * If the current control is a dialog, do NOT produce a hex
  1588.      * value, even if the hex mode is on.  RC.Exe doesn't recognize
  1589.      * hex values for the dialog name as ordinals.
  1590.      */
  1591.     if (Type == W_DIALOG)
  1592.         itoaw(id, szValue, 10);
  1593.     else
  1594.         Myitoa(id, szValue);
  1595.  
  1596.     SetDlgItemText(hwndStatus, DID_STATUSNAMEID, szValue);
  1597. }
  1598.  
  1599.  
  1600.  
  1601. /************************************************************************
  1602. * StatusClearID
  1603. *
  1604. * Clears the id of the status window..
  1605. *
  1606. ************************************************************************/
  1607.  
  1608. STATICFN VOID StatusClearID(VOID)
  1609. {
  1610.     SetDlgItemText(hwndStatus, DID_STATUSSYM, szEmpty);
  1611.     SetDlgItemText(hwndStatus, DID_STATUSSYMID, szEmpty);
  1612. }
  1613.  
  1614.  
  1615.  
  1616. /************************************************************************
  1617. * StatusClearName
  1618. *
  1619. * Clears the name of the status window.
  1620. *
  1621. ************************************************************************/
  1622.  
  1623. STATICFN VOID StatusClearName(VOID)
  1624. {
  1625.     SetDlgItemText(hwndStatus, DID_STATUSNAME, szEmpty);
  1626.     SetDlgItemText(hwndStatus, DID_STATUSNAMEID, szEmpty);
  1627. }
  1628.  
  1629.  
  1630.  
  1631. /************************************************************************
  1632. * StatusClear
  1633. *
  1634. * Clears the status window.
  1635. *
  1636. ************************************************************************/
  1637.  
  1638. STATICFN VOID StatusClear(VOID)
  1639. {
  1640.     StatusSetCoords(NULL);
  1641.     StatusSetText(NULL, W_NOTHING);
  1642.     StatusShowFields(W_NOTHING);
  1643.     StatusClearID();
  1644.     StatusClearName();
  1645.     gfStatusChanged = FALSE;
  1646. }
  1647.  
  1648.  
  1649.  
  1650. /************************************************************************
  1651. * StatusUpdate
  1652. *
  1653. * Updates the status window to the current selection.
  1654. *
  1655. ************************************************************************/
  1656.  
  1657. VOID StatusUpdate(VOID)
  1658. {
  1659.     if (gnpcSel) {
  1660.         StatusSetCoords(&gnpcSel->rc);
  1661.         StatusSetText(gnpcSel->text, gnpcSel->pwcd->iType);
  1662.  
  1663.         if (gfDlgSelected)
  1664.             StatusSetName(gcd.pszDlgName, W_DIALOG);
  1665.         else
  1666.             StatusSetID(gnpcSel->id, TRUE);
  1667.  
  1668.         StatusShowFields(gnpcSel->pwcd->iType);
  1669.  
  1670.         gfStatusChanged = FALSE;
  1671.     }
  1672.     else {
  1673.         StatusClear();
  1674.     }
  1675. }
  1676.  
  1677.  
  1678.  
  1679. /************************************************************************
  1680. * StatusShowFields
  1681. *
  1682. * This function shows and hides fields in the Status ribbon based on
  1683. * whether the dialog is currently selected or not.  This is necessary
  1684. * because dialogs have a name, whereas controls do not, and controls
  1685. * have an id that dialogs do not have, etc.
  1686. *
  1687. * It will also call StatusSetTextLabels to set the text for the
  1688. * descriptive labels in front of the fields.
  1689. *
  1690. * This function should be called whenever it is possible that the current
  1691. * selection has been changed.
  1692. *
  1693. * Arguments:
  1694. *   INT Type - Type of control that is selected (W_* constant).
  1695. *
  1696. ************************************************************************/
  1697.  
  1698. STATICFN VOID StatusShowFields(
  1699.     INT Type)
  1700. {
  1701.     /*
  1702.      * This static caches the type of the selected control.
  1703.      */
  1704.     static INT TypeSave = W_NOTHING;
  1705.  
  1706.     /*
  1707.      * We only have special cases for the dialog and for icon controls.
  1708.      * All other types are treated the same (we use W_CHECKBOX arbitrarily).
  1709.      * This prevents some repainting when switching between controls that
  1710.      * have the same layout of fields in the status window.
  1711.      */
  1712.     if (Type != W_DIALOG && Type != W_ICON)
  1713.         Type = W_CHECKBOX;
  1714.  
  1715.     if (Type != TypeSave) {
  1716.         switch (Type) {
  1717.             case W_DIALOG:
  1718.                 MoveWindow(GetDlgItem(hwndStatus, DID_STATUSNAME),
  1719.                         grcTopCombo.left, grcTopCombo.top,
  1720.                         grcTopCombo.right - grcTopCombo.left,
  1721.                         grcTopCombo.bottom - grcTopCombo.top, TRUE);
  1722.                 MoveWindow(GetDlgItem(hwndStatus, DID_STATUSNAMEID),
  1723.                         grcTopEdit.left, grcTopEdit.top,
  1724.                         grcTopEdit.right - grcTopEdit.left,
  1725.                         grcTopEdit.bottom - grcTopEdit.top, TRUE);
  1726.  
  1727.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSNAME), SW_SHOW);
  1728.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSNAMEID), SW_SHOW);
  1729.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSTEXT), SW_SHOW);
  1730.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSSYM), SW_HIDE);
  1731.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSSYMID), SW_HIDE);
  1732.  
  1733.                 StatusSetTextLabels(Type, IsOrd(gcd.pszDlgName));
  1734.  
  1735.                 break;
  1736.  
  1737.             case W_ICON:
  1738.                 MoveWindow(GetDlgItem(hwndStatus, DID_STATUSNAME),
  1739.                         grcBottomCombo.left, grcBottomCombo.top,
  1740.                         grcBottomCombo.right - grcBottomCombo.left,
  1741.                         grcBottomCombo.bottom - grcBottomCombo.top, TRUE);
  1742.                 MoveWindow(GetDlgItem(hwndStatus, DID_STATUSNAMEID),
  1743.                         grcBottomEdit.left, grcBottomEdit.top,
  1744.                         grcBottomEdit.right - grcBottomEdit.left,
  1745.                         grcBottomEdit.bottom - grcBottomEdit.top, TRUE);
  1746.  
  1747.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSNAME), SW_SHOW);
  1748.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSNAMEID), SW_SHOW);
  1749.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSTEXT), SW_HIDE);
  1750.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSSYM), SW_SHOW);
  1751.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSSYMID), SW_SHOW);
  1752.  
  1753.                 StatusSetTextLabels(Type,
  1754.                         gnpcSel->text ? IsOrd(gnpcSel->text) : FALSE);
  1755.  
  1756.                 break;
  1757.  
  1758.             default:
  1759.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSTEXT), SW_SHOW);
  1760.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSSYM), SW_SHOW);
  1761.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSSYMID), SW_SHOW);
  1762.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSNAME), SW_HIDE);
  1763.                 ShowWindow(GetDlgItem(hwndStatus, DID_STATUSNAMEID), SW_HIDE);
  1764.  
  1765.                 StatusSetTextLabels(Type, FALSE);
  1766.  
  1767.                 break;
  1768.         }
  1769.  
  1770.         TypeSave = Type;
  1771.     }
  1772. }
  1773.  
  1774.  
  1775.  
  1776. /************************************************************************
  1777. * StatusSetEnable
  1778. *
  1779. * This routine sets the enable state of the editable controls in the
  1780. * status window based on various state globals.
  1781. *
  1782. * The controls will be disabled on the following conditions:
  1783. *
  1784. *   1. Nothing is selected.
  1785. *   2. We are in Test mode.
  1786. *   3. One of the editors own dialogs is up (gfDisabled == TRUE).
  1787. *
  1788. * In addition, some controls will always be disabled if in Translate
  1789. * mode, and the text field will be disabled if this control cannot
  1790. * have text.
  1791. *
  1792. ************************************************************************/
  1793.  
  1794. VOID StatusSetEnable(VOID)
  1795. {
  1796.     BOOL fEnableText = TRUE;
  1797.     BOOL fEnableSym = TRUE;
  1798.     BOOL fEnableName = TRUE;
  1799.  
  1800.     if (!gnpcSel || gfTestMode || gfDisabled)
  1801.         fEnableText = fEnableSym = fEnableName = FALSE;
  1802.  
  1803.     /*
  1804.      * Disable the text field if this control cannot have text.
  1805.      */
  1806.     if (gnpcSel && !gnpcSel->pwcd->fHasText)
  1807.         fEnableText = FALSE;
  1808.  
  1809.     /*
  1810.      * If the dialog is selected and the style does not include
  1811.      * a caption, disable the text field.
  1812.      */
  1813.     if (gfDlgSelected && (gnpcSel->flStyle & WS_CAPTION) != WS_CAPTION)
  1814.         fEnableText = FALSE;
  1815.  
  1816.     /*
  1817.      * Always disable the symbol and name fields if Translating.
  1818.      */
  1819.     if (gfTranslateMode)
  1820.         fEnableSym = fEnableName = FALSE;
  1821.  
  1822.     EnableWindow(GetDlgItem(hwndStatus, DID_STATUSTEXT), fEnableText);
  1823.  
  1824.     EnableWindow(GetDlgItem(hwndStatus, DID_STATUSSYM), fEnableSym);
  1825.     EnableWindow(GetDlgItem(hwndStatus, DID_STATUSSYMID), fEnableSym);
  1826.  
  1827.     EnableWindow(GetDlgItem(hwndStatus, DID_STATUSNAME), fEnableName);
  1828.     EnableWindow(GetDlgItem(hwndStatus, DID_STATUSNAMEID), fEnableName);
  1829. }
  1830. #ifdef JAPAN
  1831. /************************************************************************
  1832. * Copy strings to the buffer. text strings "\036" and "\037" are expanded to
  1833. * Codes \036 and \037 respectively.
  1834. ************************************************************************/
  1835.  
  1836. VOID KKExpandCopy(LPTSTR pszDest, LPTSTR pszSrc, WORD wLimit)
  1837. {
  1838.     int  i;
  1839.     LPTSTR p = pszSrc;
  1840. #if defined(DBCS) && !defined(UNICODE)
  1841. #define wcsncmp     strncmp
  1842. #endif
  1843.  
  1844.     wLimit--;
  1845.     for (i = 0; i < wLimit && p && *p; i++) {
  1846.         if (*p == TEXT('\\')) {
  1847.             if(!wcsncmp(p+1, TEXT("036"), 3)) {
  1848.                 pszDest[i] = 036;
  1849.                 p+=4;
  1850.                 continue;
  1851.             }
  1852.             else if(!wcsncmp(p+1, TEXT("037"), 3)) {
  1853.                 pszDest[i] = 037;
  1854.                 p+=4;
  1855.                 continue;
  1856.            }
  1857.         }
  1858.         pszDest[i] = *p;
  1859.         if (IsDBCSLeadByte((BYTE)*p)) {
  1860.             if (i == wLimit - 1) {
  1861.                 break;
  1862.             }
  1863.             pszDest[++i] = *(p+1);
  1864.         }
  1865.         p = CharNext(p);
  1866.     }
  1867.     pszDest[i] = '\0';
  1868. }
  1869. #endif
  1870.