/****************************************************************************
**
**  Name:  peridial.cpp
**
**  Description:
**     Source file for peripheral presenter dialogs.                
**
**  $Log:   S:/tbird/arcppc/peri/peridial.cpv  $
** 
**    Rev 1.2   28 Nov 1997 15:32:56   kevin
** added more masks for HandleFieldValueEdit()
** 
**    Rev 1.1   28 Aug 1997 10:14:38   cjchen
** 
**    Rev 1.0   17 Jan 1997 08:47:34   kevin
** Initial revision.
** 
**    Rev 1.0   03 Jun 1996 11:09:00   gene
** Initial revision.
** 
**    Rev 1.2   10 Apr 1996 16:42:04   kevin
** modified WRITE-ONLY notice
** 
**    Rev 1.1   03 Oct 1995 14:55:44   kevin
** updated field value while pressing write button
** 
**    Rev 1.0   07 Sep 1995 09:49:16   gene
** Initial revision.
** 
**    Rev 1.17   19 Apr 1994 16:32:48   nghia
** Fixed PPR 9252 - bad input in Goto Address will get GPF.
** Added check if MakeProcInstance is valid before open the dialog box.
** Revised to follow coding standard.  Cleanup address descriptor leakage.
** Major cleanup.
** 
**    Rev 1.16   22 Nov 1993 16:24:16   ron
** fixes for PPRs 9155,9173,9175
** 
**    Rev 1.15   22 Nov 1993 11:03:36   ron
** fixes for pprs 9105, 9119, 9120
** 
**    Rev 1.14   17 Nov 1993 15:27:24   ron
** fix for ppr9100
** 
**    Rev 1.13   17 Nov 1993 14:39:16   ron
** fix for ppr 9101: return in register value does something.
** 
**    Rev 1.12   16 Nov 1993 10:48:36   ron
** Fix for PPR 9090
** 
**    Rev 1.11   11 Nov 1993 10:36:22   ron
** bug fixes 90xx
** 
**    Rev 1.10   08 Nov 1993 15:59:40   ron
** bug fixes for pv2.1
** 
**    Rev 1.9   05 Nov 1993 11:00:54   ron
** fixed bug in edit field value stuff
** 
**    Rev 1.8   04 Nov 1993 10:35:38   ron
** misc bug fixes
** 
**    Rev 1.7   03 Nov 1993 13:55:24   ron
** first cut at 2.1
** 
**  $Header:   S:/tbird/arcppc/peri/peridial.cpv   1.2   28 Nov 1997 15:32:56   kevin  $
**
**  Copyright (C) 1993 Microtek International.  All rights reserved.
**
*****************************************************************************/


                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#define WIN31
#define STRICT

#ifndef _PERIPRES_
#include "peripres.h"
#endif

#ifndef _PERIDIAL_
#include "peridial.h"
#endif

#ifndef _VLIST_
#include "vlist.h"
#endif

//BorlandC includes
#ifndef __CTYPE_H
#include <ctype.h>
#endif
#ifndef __STDIO_H
#include <stdio.h>
#endif


                       /****************************
                        *                          *
                        *        DEFINITIONS       *
                        *                          *
                        ****************************/

#pragma warn -par  // suppress Parameters never used warning

                       /****************************
                        *                          *
                        *       EXTERNALS          *
                        *                          *
                        ****************************/

extern PTPeriServer PeriServer;   // Peripheral server object ptr
static U16 CurFieldIndex = 0;     // Used for expediency...
U32 savedValue = 0xF42458L;       // nonsense value to force refresh
U32 origValue;
U32 savedFieldValue = 0xF42458L;    // nonsense value to force refresh
static BOOLEAN ReadOnly = FALSE;
static BOOLEAN WriteOnly = FALSE;
extern HWND hwndPeriList;
extern U32 PeriLastLineSelected;


                       /****************************
                        *                          *
                        *        PROTOTYPES        *
                        *                          *
                        ****************************/
VOID UpdateDialog(HWND hDlg);
VOID UpdateFieldValue(HWND hDlg, PTField field);
U32 getCurrentFieldValue(HWND hDlg);
VOID HandleFieldValueEdit(HWND hDlg, U32 newFieldValue);
U32 getCurrentValue(HWND hDlg);
VOID SubstEditVal (HWND hDlg, HWND hwndList);

PRIVATE PTRegister RegPtr;
PRIVATE RETCODE RegErr;
PRIVATE int tabStops[2] = {24, 48};

/*****************************************************************************
**
**  DrawListBox
**
*****************************************************************************/
VOID DrawListBox(HWND hDlg, PTRegister reg) {
   CHAR tempStr[MAX_INFOSTR*5];
   PTField field = NULL;
   LPSTR fieldDesc = NULL;
   S16 which = 0;
   U16 i = 0;
   S16 nFields = reg->GetFieldCnt();
   S16 nLines = 0;
   HWND hwndList = GetDlgItem(hDlg, ER_LISTBOX_ID);

   nLines = SendMessage(hwndList, LB_GETCOUNT, 0, 0L);
   if (nLines == LB_ERR) {
      nLines = 0;
   }
   if (nLines != 0) {
      which = SendMessage(hwndList, LB_GETCURSEL, 0, 0L);
      if (which == LB_ERR) {
         which = 0;
      }
   }
   if (nLines > nFields) {
      SendMessage(hwndList, LB_RESETCONTENT, 0, 0L);
      nLines = 0;
   }
   SendMessage(hwndList, WM_SETREDRAW, 0, 0L);
   for (i=0; i < nFields; i++) {
      field = reg->GetFieldInfo(i);
      if (field == NULL) continue; // firewall
      field->GetName(tempStr);
      strcat(tempStr,"\t");
      fieldDesc = tempStr + lstrlen(tempStr);
      field->LookupFieldDesc(fieldDesc,NULL);
      if (i < nLines) {
         SendMessage(hwndList, LB_DELETESTRING, i, 0L);
         SendMessage(hwndList, LB_INSERTSTRING, i, (LONG) (LPSTR) tempStr);
      }
      else {
         SendMessage(hwndList, LB_INSERTSTRING, -1, (LONG) (LPSTR) tempStr);
      }
   }
   SendMessage(hwndList, WM_SETREDRAW, 1, 0L);
   InvalidateRect(hwndList, NULL, FALSE);
   SendMessage(hwndList, LB_SETCURSEL, which, 0L);
}

/*****************************************************************************
**
**  EditReg
**
*****************************************************************************/
RETCODE EditReg(HINSTANCE module, HWND parent,
                       PTRegister reg, U16 fieldNo) {
   U16 helpIndex;
   WORD helpEntry;
   HANDLE helpWnd;
   HWND tmp;
   U16 rval;
   PRIVATE DLGPROC lpfnMainDlgProc;
   CurFieldIndex = fieldNo;

   RegErr = GOOD; // PRIVATE global for convenience
   helpIndex = HI_PERIPHERAL;
   helpEntry = HE_EDITPERIPHREG;
   RegisterHelpEntry(helpIndex, (long) parent, helpEntry);

   if ((lpfnMainDlgProc = (DLGPROC)MakeProcInstance((FARPROC) RegMainDlgProc,
      module)) != NULL) {         
      RegPtr = reg;
      tmp = parent;
      DialogBox (module, DIA_EDITREG, tmp, lpfnMainDlgProc);
      FreeProcInstance((FARPROC)lpfnMainDlgProc);
   }
   return (RegErr);
}

/*****************************************************************************
**
**  UpdateDialog
**
*****************************************************************************/
VOID UpdateDialog(HWND hDlg) {
   S8 regAddr[32];
   S8 mnemonic[MAX_MNEMONIC];
   S8 desc[MAX_INFOSTR];
   S8 groupname[MAX_MNEMONIC];
   S8 caption[2 * MAX_INFOSTR];
   DESCRIPTOR tmpDesc = NULL;
   PTRegister reg = NULL;
   PTField field = NULL;
   HWND hwndWriteButton;
   HWND hwndWriteOnly;
   PTGroup grp = NULL;
   RETCODE err = GOOD;

   reg = RegPtr;
   mnemonic[0] = '\0';
   desc[0] = '\0';
   caption[0] = '\0';
   reg->GetName(mnemonic);
   reg->GetDesc(desc);
   WriteOnly = ReadOnly = FALSE;
   hwndWriteButton = GetDlgItem(hDlg, ER_WRITE_ID);
   EnableWindow(hwndWriteButton, TRUE);
   hwndWriteOnly = GetDlgItem(hDlg, ER_WRITE_ONLY_ID);
   SetWindowText(hwndWriteOnly, (LPSTR)" ");
   if (!reg->GetWritePermission()) {
      EnableWindow(hwndWriteButton, FALSE);
      ReadOnly = TRUE;
   }
   else if (!reg->GetReadPermission()) {
      SetWindowText(hwndWriteOnly,
         (LPSTR)"<== WRITE ONLY!! What you see\n    in the box isn't an actual value.");
      WriteOnly = TRUE;
   }
   grp = PeriServer->GetGroupInfo(reg->GetGroupId());
   grp->GetName(groupname);
   regAddr[0] = '\0';
   if ((err = PeriServer->GetRegisterAddress(reg,&tmpDesc)) != GOOD) {
      RegErr = err;
   }
   else if ((err = AdrConvAddressToTextWithParams(tmpDesc,FALSE,
      FALSE,regAddr)) != GOOD) {
      RegErr = err;
   }
   // 04/15/94 - Nghia
   // Destroy the tmpDesc before exit
   if (tmpDesc != NULL) AdrDestroyAddress(tmpDesc);
   if (RegErr != GOOD) {
      return;
   }
   sprintf(caption,"%s %s - %s", groupname, mnemonic, desc);
   SetWindowText(hDlg, caption);
   DrawListBox(hDlg, reg);
   field = reg->GetFieldInfo(CurFieldIndex);
   savedValue = reg->GetValue();
   origValue = savedValue; 
   SetDlgItemText(hDlg, ER_FVALUE_ID, (LPSTR) " ");
   UpdateFieldValue(hDlg, field);
}

/*****************************************************************************
**
**  UpdateFieldValue
**
*****************************************************************************/
VOID UpdateFieldValue(HWND hDlg, PTField field) {
   CHAR tempEditVal[MAX_EDIT_TEXT];

   if (field != NULL && *field != NOOBJECT) {
      savedFieldValue = field->GetValue() - 1; // force redraw
      SendDlgItemMessage(hDlg, ER_LISTBOX_ID, LB_SETCURSEL,
                         (WORD)CurFieldIndex, 0L);
   }
   else {
      sprintf(tempEditVal, "0x%lX", savedValue);
      SetDlgItemText(hDlg, ER_VALUE_ID, (LPSTR) tempEditVal);
   }
   HandleFieldValueEdit(hDlg, savedFieldValue + 1); // force redraw
}

/*****************************************************************************
**
**  RegMainDlgProc
**
*****************************************************************************/
BOOL EXPORT RegMainDlgProc (HWND hDlg, UINT message, UINT wParam,
                            LONG lParam){
   HWND hasFocus;
   HWND hwndList;
   HWND hwndEditField;
   U32 newFieldValue;
   S16 i;
   U8 bufChar[4];
   PTRegister reg = NULL;
   PTRegister otherReg = NULL;
   U8 *tempVal;
   S16 mVal;
   RETCODE err;
   U32 lTmp;
   U16 maxBufIndex;
   PTField field = NULL;
   S16 buttonValue;
   U32 which, other, numLines, fieldNo;
   BOOLEAN isPeriph;
   LPSTR statInfo;

   
   reg = RegPtr;
   hwndList = GetDlgItem(hDlg, ER_LISTBOX_ID);
   switch (message) {
      case WM_INITDIALOG:
         UpdateDialog(hDlg);
         if (RegErr != GOOD) {
            EndDialog (hDlg, 0);
            return (TRUE);
         }
         return (TRUE);

      case WM_VSCROLL:
         field = reg->GetFieldInfo(CurFieldIndex);
         if (field == NULL || *field == NOOBJECT) return (TRUE); // firewall
         if (wParam == SB_LINEUP) {
            newFieldValue = getCurrentFieldValue(hDlg);
            if (newFieldValue < field->GetMaxValue()) {
               newFieldValue++;
            }
            else {
               newFieldValue = field->GetMinValue();
            }
            HandleFieldValueEdit(hDlg, newFieldValue);
         }
         else if (wParam == SB_LINEDOWN) {
            newFieldValue = getCurrentFieldValue(hDlg);
            if (newFieldValue > field->GetMinValue()) {
               newFieldValue--;
            }
            else {
               newFieldValue = field->GetMaxValue();
            }
            HandleFieldValueEdit(hDlg, newFieldValue);
         }
         return (TRUE);

      case WM_DESTROY:         
         if (!ReadOnly && origValue != getCurrentValue(hDlg))
            reg->SetValue(origValue, NULL); 
         return (TRUE);
      
      case WM_COMMAND:
         switch (wParam) {
            case IDCANCEL:
               EndDialog (hDlg, 0);
               return (TRUE);
            case ER_LISTBOX_ID:
               if (HIWORD(lParam) == LBN_SELCHANGE) {
                  // old field
                  newFieldValue = getCurrentFieldValue(hDlg);
                  HandleFieldValueEdit(hDlg, newFieldValue);
                  CurFieldIndex = SendMessage(hwndList, LB_GETCURSEL, 0, 0L);
                  // new field
                  field = reg->GetFieldInfo(CurFieldIndex);
                  if (field != NULL && *field != NOOBJECT) {
                     savedFieldValue = field->GetValue() - 1; // force redraw
                     newFieldValue = savedFieldValue + 1;
                     HandleFieldValueEdit(hDlg, newFieldValue);
                  }
                  else {
                     SetDlgItemText(hDlg, ER_FVALUE_ID, (LPSTR) " ");
                     statInfo = reg->GetStatusInfo(NULL);
                     if (statInfo != NULL) {
                        SetDlgItemText(hDlg, ER_FLDINFO_ID, (LPSTR) statInfo);
                     }
                     else {
                        SetDlgItemText(hDlg, ER_FLDINFO_ID, (LPSTR) " ");
                     }
                  }
               }
               return (TRUE);
            case ER_FVALUE_ID:
               if (HIWORD(lParam) == EN_KILLFOCUS) {
                  newFieldValue = getCurrentFieldValue(hDlg);
                  field = reg->GetFieldInfo(CurFieldIndex);
                  if (field == NULL || *field == NOOBJECT)
                     return (TRUE); // firewall
                  if (newFieldValue >= field->GetMinValue() &&
                     newFieldValue <= field->GetMaxValue()) {
                     HandleFieldValueEdit(hDlg, newFieldValue);
                  }
               }
               return (TRUE);
            case ER_VALUE_ID:
               savedValue = getCurrentValue(hDlg);
               return (TRUE);
            case ER_SPIN_ID:
               return (TRUE);
            case IDOK:
            case ER_WRITE_ID:
               hasFocus = GetFocus();
               if (hasFocus == hwndList) {
                  if (CurFieldIndex < reg->GetFieldCnt() - 1) {
                     CurFieldIndex++;
                     SendMessage(hwndList, LB_SETCURSEL, CurFieldIndex, 0L);
                     field = reg->GetFieldInfo(CurFieldIndex);
                     if (field != NULL && *field != NOOBJECT) {
                        // force redraw
                        savedFieldValue = field->GetValue() - 1; 
                        SendMessage(hwndList, LB_SETCURSEL, CurFieldIndex, 0L);
                     }
                     // force redraw
                     HandleFieldValueEdit(hDlg, savedFieldValue + 1); 
                  }
                  return(TRUE);
               }
               else if (hasFocus == GetDlgItem(hDlg, ER_VALUE_ID)) {
                  savedValue = getCurrentValue(hDlg);
                  field = reg->GetFieldInfo(CurFieldIndex);
                  DrawListBox(hDlg, reg);
                  // doesn't write memory (yet)
                  reg->SetValue(savedValue, NULL); 
                  UpdateFieldValue(hDlg, field);
                  SetFocus(hwndList);
                  return (TRUE);
               }
               else if (hasFocus == GetDlgItem(hDlg, ER_FVALUE_ID)) {
                  newFieldValue = getCurrentFieldValue(hDlg);
                  field = reg->GetFieldInfo(CurFieldIndex);
                  if (field == NULL || *field == NOOBJECT)
                     return (TRUE); // firewall
                  if (newFieldValue >= field->GetMinValue() &&
                     newFieldValue <= field->GetMaxValue()) {
                     HandleFieldValueEdit(hDlg, newFieldValue);
                  }
                  savedValue = getCurrentValue(hDlg);
                  DrawListBox(hDlg, reg);
                  UpdateFieldValue(hDlg, field);
                  SendMessage(hwndList, LB_SETCURSEL, CurFieldIndex, 0L);
                  return (TRUE);
               }
               else if (hasFocus != GetDlgItem(hDlg, ER_WRITE_ID)) {
                  savedValue = getCurrentValue(hDlg);
                  DrawListBox(hDlg, reg);
                  // doesn't write memory (yet)
                  reg->SetValue(savedValue, NULL); 
                  field = reg->GetFieldInfo(CurFieldIndex);
                  UpdateFieldValue(hDlg, field);
                  return (TRUE);
               }
               reg->SetValue(savedValue, NULL); 
               field = reg->GetFieldInfo(CurFieldIndex);
               UpdateFieldValue(hDlg, field);
               origValue = savedValue = getCurrentValue(hDlg);
               PeriServer->SetRegValue(reg, savedValue);
               return (TRUE);
            case ER_NEXT_ID:
               if (!ReadOnly && origValue != getCurrentValue(hDlg)) {
                  SetFocus(hDlg);
                  ErrMessageBox((LPSTR) "Register Value Changed", 
                     (LPSTR) "Write changes before getting next?", 
                     MB_YESNOCANCEL | MB_ICONQUESTION,
                     HE_EDITPERIPHREG, (S16 FAR *) &buttonValue);
                  SetFocus(GetDlgItem(hDlg, ER_NEXT_ID));
                  if (buttonValue == IDYES) {
                     savedValue = getCurrentValue(hDlg);
                     PeriServer->SetRegValue(reg, savedValue);
                  }
                  else if (buttonValue == IDCANCEL) {
                     return (FALSE);
                  }
                  else {
                     reg->SetValue(origValue, NULL); 
                     savedValue = reg->GetValue();
                  }
               }
               else if (ReadOnly) {
                  reg->SetValue(origValue, NULL); 
                  savedValue = reg->GetValue();
               }
               which = PeriServer->RegToLine(reg);
               numLines = PeriServer->CountLines();
               for (other = which + 1; other < numLines; other++) {
                  otherReg = PeriServer->LineToReg(other, (U32 FAR *) &fieldNo,
                        (BOOLEAN FAR *) &isPeriph);
                  if (otherReg != reg && otherReg != NULL && 
                      !isPeriph && !otherReg->IsBuffer()) break;
               }
               if (other < numLines && otherReg != NULL && !isPeriph) {
                  reg = RegPtr = otherReg;
                  which = PeriServer->RegToLine(reg);
                  SendMessage(hwndPeriList, VLB_SETCURSEL,
                              (WORD) VLB_FINDITEM, (LONG) which);
                  PeriLastLineSelected = which;
                  UpdateDialog(hDlg);
               }
               return (TRUE);
            case ER_PREV_ID:
               if (!ReadOnly && origValue != getCurrentValue(hDlg)) {
                  SetFocus(hDlg);
                  ErrMessageBox((LPSTR) "Register Value Changed", 
                     (LPSTR) "Write changes before getting next?", 
                     MB_YESNOCANCEL | MB_ICONQUESTION,
                     HE_EDITPERIPHREG, (S16 FAR *) &buttonValue);
                  SetFocus(GetDlgItem(hDlg, ER_NEXT_ID));
                  if (buttonValue == IDYES) {
                     savedValue = getCurrentValue(hDlg);
                     PeriServer->SetRegValue(reg, savedValue);
                  }
                  else if (buttonValue == IDCANCEL) {
                     return (FALSE);
                  }
                  else {
                     reg->SetValue(origValue, NULL); 
                     savedValue = reg->GetValue();
                  }
               }
               else if (ReadOnly) {
                  reg->SetValue(origValue, NULL); 
                  savedValue = reg->GetValue();
               }
               which = PeriServer->RegToLine(reg);
               for (other = which - 1; other > 0; other--) {
                  otherReg = PeriServer->LineToReg(other, (U32 FAR *) &fieldNo,
                        (BOOLEAN FAR *) &isPeriph);
                  if (otherReg != reg && otherReg != NULL && 
                      !isPeriph && !otherReg->IsBuffer()) break;
               }
               if (other > 0 && otherReg != NULL && !isPeriph) {
                  reg = RegPtr = otherReg;
                  which = PeriServer->RegToLine(reg);
                  SendMessage(hwndPeriList, VLB_SETCURSEL,
                              (WORD) VLB_FINDITEM, (LONG) which);
                  PeriLastLineSelected = which;
                  UpdateDialog(hDlg);
               }
               return (TRUE);
            case ER_CLOSE_ID:
               if (!ReadOnly && origValue != getCurrentValue(hDlg)) {
                  SetFocus(hDlg);
                  ErrMessageBox((LPSTR) "Register Value Changed", 
                     (LPSTR) "Write changes before closing?", 
                     MB_YESNOCANCEL | MB_ICONQUESTION,
                     HE_EDITPERIPHREG, (S16 FAR *) &buttonValue);
                  SetFocus(GetDlgItem(hDlg, ER_CLOSE_ID));
                  if (buttonValue == IDYES) {
                     savedValue = getCurrentValue(hDlg);
                     PeriServer->SetRegValue(reg, savedValue);
                  }
                  else if (buttonValue == IDCANCEL) {
                     return (FALSE);
                  }
                  else {
                     reg->SetValue(origValue, NULL); 
                     savedValue = reg->GetValue();
                  }
               }
               else if (ReadOnly) {
                  reg->SetValue(origValue, NULL); 
                  savedValue = reg->GetValue();
               }
               EndDialog (hDlg, 0);
               return (TRUE);
            case IDHELP:
               WinHelp(hDlg, "PWRVIEWS.HLP",
                  HELP_CONTEXT, HE_EDITPERIPHREG);
               return TRUE;
      }
      break;
   }
   return (FALSE);
}
                  
/*****************************************************************************
**
**  GetCurrentFieldValue
**
*****************************************************************************/
U32 getCurrentFieldValue(HWND hDlg) {
   CHAR tempEditVal[MAX_EDIT_TEXT];
   U32 lTmp;
   S16 nChars;
   CHAR *endptr;
   nChars = GetDlgItemText(hDlg, ER_FVALUE_ID, (LPSTR) tempEditVal,
                           MAX_EDIT_TEXT);
   if (nChars <= 0) {
      return(savedFieldValue);
   }
   lTmp = strtoul(tempEditVal, &endptr, 0);
   if (!((endptr != NULL && *endptr != '\0' && !isspace(*endptr)))) {
     return (lTmp);
   }
   sprintf(tempEditVal, "0x%lX", savedFieldValue);
   SetDlgItemText(hDlg, ER_FVALUE_ID, (LPSTR) tempEditVal);
   MessageBeep(0);
   return (savedFieldValue);
}

/*****************************************************************************
**
**  HandleFieldValueEdit
**
*****************************************************************************/
VOID HandleFieldValueEdit(HWND hDlg, U32 newFieldValue) {
   U8 tempBuf[128];
   LPSTR fieldDesc = NULL;
   PRIVATE BOOLEAN inHereAlready = FALSE;
   PRIVATE U32 masks[33] = { 0x0, 0x1, 0x3, 0x7, 
                            0x0F, 0x1F, 0x3F, 0x7F, 
                            0xFF, 0x1FF, 0x3FF, 0x7FF,
                            0xFFF, 0x1FFF, 0x3FFF, 0x7FFF,
                            0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF,
                            0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
                            0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF,
                            0xFFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
                            0xFFFFFFFF };

   PTField field = NULL;
   PTValue ptv;
   S32 fieldIndex;
   U32 oldFieldValue;
   S8 fieldPos,shiftPos;
   PTRegister reg;
   U32 regVal;
   U32 regMask;
   U32 fieldMask;
   BOOLEAN okToChange;
   S16 buttonValue;
   U16 regSize,fieldSize;

   if (inHereAlready) return;
   inHereAlready = TRUE;
   oldFieldValue = savedFieldValue;

   if (oldFieldValue == newFieldValue) {
      inHereAlready = FALSE;
      return;
   }

   fieldIndex = CurFieldIndex;
   reg = RegPtr;
   if (reg == NULL) {
      inHereAlready = FALSE;
      return; // firewall
   }
   field = reg->GetFieldInfo(fieldIndex);
   if (field == NULL || *field == NOOBJECT) {
      if (reg->GetStatusInfo(tempBuf) != NULL) {
         SetDlgItemText(hDlg, ER_FLDINFO_ID, (LPSTR) tempBuf);
      }
      else {
         SetDlgItemText(hDlg, ER_FLDINFO_ID, (LPSTR) " ");
      }
      inHereAlready = FALSE;
      return; // firewall
   }
   if (field != NULL) {
      okToChange = FALSE;
      if (field->DontCareValue()) { // any value is ok
         if (newFieldValue >= field->GetMinValue() && 
                newFieldValue <= field->GetMaxValue()) {
            okToChange = TRUE;
         }
      }
      else {
         ptv = new TValue(newFieldValue);
         if (field->LookupFieldDesc(tempBuf,ptv) != NULL) {
            okToChange = TRUE;
         }
         delete ptv;
      }
      if (okToChange) {
          field->SetValue(newFieldValue);
          // convert high bit to low bit... e.g. pos = 3, size = 4, goes to
          // pos 0
          fieldPos = field->GetFieldLocation() - field->GetSize() + 1;
          shiftPos = (8*reg->GetSize()-1) - field->GetFieldLocation();
          regSize = reg->GetSize() * 8; // in bits
          if (fieldPos < 0 || regSize < (fieldPos + field->GetSize())) {
             sprintf(tempBuf, "size/pos inconsistency with reg: %s, field: %s", 
                reg->GetName(NULL),field->GetName(NULL));
            ErrMessageBox((LPSTR) "Config File Error", 
               (LPSTR) tempBuf,
               MB_OK | MB_ICONEXCLAMATION,
               HE_EDITPERIPHREG, (S16 FAR *) &buttonValue);
          }
          regVal = savedValue;
          savedValue = reg->GetValue();
          fieldSize = field->GetSize();
          fieldMask = (masks[fieldSize] << shiftPos);
          regVal = (regVal & ~fieldMask);
          regVal = (regVal | (newFieldValue << shiftPos));
          savedValue = regVal;
          regMask = reg->GetUnusedBitMask();
          regVal = (regVal & regMask);
          reg->SetValue(regVal, NULL); // doesn't write memory (yet)
          if (origValue == savedValue)
             origValue = savedValue = regVal;
          if (regSize > 16)
             sprintf(tempBuf, "0x%08lX", regVal);
          else if (regSize > 8)
             sprintf(tempBuf, "0x%04lX", regVal);
          else
             sprintf(tempBuf, "0x%02lX", regVal);
          SetDlgItemText(hDlg, ER_VALUE_ID, (LPSTR) tempBuf);
          savedFieldValue = newFieldValue;
          sprintf(tempBuf, "0x%lX", newFieldValue);
          SetDlgItemText(hDlg, ER_FVALUE_ID, (LPSTR) tempBuf);
          if (fieldSize > 1)
             sprintf(tempBuf,"%u-%u: ", field->GetFieldLocation(),
                field->GetFieldLocation()+1-fieldSize);
          else   
             sprintf(tempBuf,"%u: ", field->GetFieldLocation());
          strcat(tempBuf,field->GetLongName(NULL));
          strcat(tempBuf,"  ");
          strcat(tempBuf,"\r\n");
          fieldDesc = tempBuf + lstrlen(tempBuf);
          field->LookupFieldDesc(fieldDesc,NULL);
          SetDlgItemText(hDlg, ER_FLDINFO_ID, (LPSTR) tempBuf);
          DrawListBox(hDlg, reg);
          inHereAlready = FALSE;
          return;
      }
   }
   sprintf(tempBuf, "0x%lX", savedFieldValue);
   SetDlgItemText(hDlg, ER_FVALUE_ID, (LPSTR) tempBuf);
   DrawListBox(hDlg, reg);
   MessageBeep(0);
   inHereAlready = FALSE;
}

/*****************************************************************************
**
**  getCurentValue
**
*****************************************************************************/
U32 getCurrentValue(HWND hDlg) {
   U8 tempEditVal[MAX_EDIT_TEXT];
   U32 lTmp;
   CHAR *endptr;
   S16 nChars;
   nChars = GetDlgItemText(hDlg, ER_VALUE_ID,
                           (LPSTR) tempEditVal, MAX_EDIT_TEXT);
   if (nChars <= 0) {
      return(savedValue);
   }
   lTmp = strtoul(tempEditVal, &endptr, 0);
   if (!((endptr != NULL && *endptr != '\0' && !isspace(*endptr)))) {
     return (lTmp);
   }
   sprintf(tempEditVal, "0x%lX", savedValue);
   SetDlgItemText(hDlg, ER_VALUE_ID, (LPSTR) tempEditVal);
   MessageBeep(0);
   return (savedValue);
}

/*****************************************************************************
**
**  EditGotAddr
**
*****************************************************************************/
RETCODE EditGotoAddr(HINSTANCE module, HWND parent) {
   U16 helpIndex;
   WORD helpEntry;
   HANDLE helpWnd;
   HWND tmp;
   U16 rval;
   PRIVATE DLGPROC lpfnGotoDlgProc;

   RegErr = GOOD; // PRIVATE global for convenience
   helpIndex = HI_PERIPHERAL;
   helpEntry = HE_PERIPHGOTOADDRESS;
   RegisterHelpEntry(helpIndex, (long) parent, helpEntry);

   if ((lpfnGotoDlgProc = (DLGPROC)MakeProcInstance((FARPROC)GotoAddrDlgProc,
                          module)) != NULL) {  
      tmp = parent;
      DialogBox (module, DIA_GO2ADDR, tmp, lpfnGotoDlgProc);
      FreeProcInstance((FARPROC)lpfnGotoDlgProc);
   }
   return(RegErr);
}

/*****************************************************************************
**
**  EditGotoReg
**
*****************************************************************************/
RETCODE EditGotoReg(HINSTANCE module, HWND parent) {
   U16 helpIndex;
   WORD helpEntry;
   HANDLE helpWnd;
   HWND tmp;
   U16 rval;
   PRIVATE DLGPROC lpfnGotoDlgProc;

   RegErr = GOOD; // PRIVATE global for convenience
   helpIndex = HI_PERIPHERAL;
   helpEntry = HE_EDITPERIPHREG;
   RegisterHelpEntry(helpIndex, (long) parent, helpEntry);

   if ((lpfnGotoDlgProc = (DLGPROC) MakeProcInstance ((FARPROC)GotoRegDlgProc,
                     module)) != NULL) {
      tmp = parent;
      DialogBox (module, DIA_GO2PER, tmp, lpfnGotoDlgProc);
      FreeProcInstance((FARPROC)lpfnGotoDlgProc);
   }
   return (RegErr);
}

/*****************************************************************************
**
**  EditGotoPeri
**
*****************************************************************************/
RETCODE EditGotoPeri(HINSTANCE module, HWND parent) {
   U16 helpIndex;
   WORD helpEntry;
   HANDLE helpWnd;
   HWND tmp;
   U16 rval;
   PRIVATE DLGPROC lpfnGotoDlgProc;

   RegErr = GOOD; // PRIVATE global for convenience
   helpIndex = HI_PERIPHERAL;
   helpEntry = HE_PERIPHGOTOPERIPH;
   RegisterHelpEntry(helpIndex, (long) parent, helpEntry);
   if ((lpfnGotoDlgProc = (DLGPROC)MakeProcInstance ((FARPROC)GotoPeriDlgProc,
                          module)) != NULL) {
      tmp = parent;
      DialogBox (module, DIA_GO2PER, tmp, lpfnGotoDlgProc);
      FreeProcInstance((FARPROC)lpfnGotoDlgProc);
   }
   return (RegErr);
}

/*****************************************************************************
**
**  GotoRegDlgProc
**
*****************************************************************************/
BOOL EXPORT GotoRegDlgProc (HWND hDlg, UINT Message,
                            UINT wParam, LONG lParam) {
   PTRegister reg;
   S16 nChars;
   CHAR tempEditVal[MAX_EDIT_TEXT];
   S16 buttonValue;
   U32 which;

   reg = RegPtr;
   switch (Message) {
      case WM_INITDIALOG:
         SetWindowText(hDlg, "Go To Register");
         SetDlgItemText(hDlg, STATIC_ID, (LPSTR) "Register Name:");
         return (TRUE);

      case WM_COMMAND:
         switch (wParam) {
            case IDCANCEL:
               EndDialog (hDlg, 0);
               return (TRUE);
            case IDOK:
               nChars = GetDlgItemText(hDlg, ER_VALUE_ID, 
                  (LPSTR) tempEditVal, MAX_EDIT_TEXT);
               if (nChars > 0) {
                  reg = PeriServer->GetRegByName((LPSTR)tempEditVal);
                  if (reg != NULL) {
                     if (!reg->parent->expanded) {
                        reg->parent->expanded = TRUE;
                        reg->parent->nLinesDirty = TRUE;
                        SendMessage(hwndPeriList, VLB_RESETCONTENT, 0, 0L);
                     }
                     which = PeriServer->RegToLine(reg);
                     SendMessage(hwndPeriList, VLB_SETCURSEL,
                                 (WORD)VLB_FINDITEM, (LONG) which);
                     PeriLastLineSelected = which;
                     EndDialog (hDlg, 0);
                  }
                  else {
                     SetFocus(hDlg);
                     ErrMessageBox((LPSTR) "Search Failed", 
                        (LPSTR) "Register Name Not Found", 
                        MB_OK | MB_ICONEXCLAMATION,
                        HE_EDITPERIPHREG, (S16 FAR *) &buttonValue);
                     SetFocus(hDlg);
                  }
               }
               return (TRUE);
            case IDHELP:
               WinHelp(hDlg, "PWRVIEWS.HLP",
                  HELP_CONTEXT, HE_EDITPERIPHREG);
               return TRUE;
      }
      break;
   }
   return (FALSE);
}

/*****************************************************************************
**
**  GotoAddrDlgProc
**
*****************************************************************************/
BOOL EXPORT GotoAddrDlgProc (HWND hDlg, UINT Message,
                             UINT wParam, LONG lParam) {
   CHAR tempEditVal[MAX_EDIT_TEXT];
   S32 which;
   S16 buttonValue, buttonID;
   PTRegister reg = NULL;
   PTGroup group = NULL;
   DESCRIPTOR go2AddrDesc;
   RETCODE err;

   switch (Message) {
      case WM_INITDIALOG:
         // SetWindowText(hDlg, "Go To Address");
         // SetDlgItemText(hDlg, PRIVATE_ID, (LPSTR) "Peripheral Name:");
         memset(tempEditVal,'\0',MAX_EDIT_TEXT);
         return (TRUE);

      case WM_COMMAND:
         switch (wParam) {
            case IDCANCEL:
               EndDialog (hDlg, 0);
               return (TRUE);
            case IDOK:
               if (!GetDlgItemText(hDlg, G2A_EDIT_ID, (LPSTR) tempEditVal,
                                  MAX_EDIT_TEXT)) {
                  MessageBeep(0);
                  return TRUE; // nothing to goto address
               }
               // nChars > 0 - convert the input text to address
               if ((err = AdrCreateAddress(&go2AddrDesc)) != GOOD) {
                  // report error
                  ErrDisplayFormattedError(err, FORCE_POPUP, NULL,NULL,
                                           NULL,MB_OK,(S16 FAR *) &buttonID);
                  return TRUE;  // continue
               }
               // convert text to address
               if ((err = AdrConvTextToAddress(go2AddrDesc, tempEditVal))
                  != GOOD) {
                  // report error
                  ErrDisplayFormattedError(err, FORCE_POPUP, NULL,NULL,
                                           NULL,MB_OK,(S16 FAR *) &buttonID);
                  AdrDestroyAddress(go2AddrDesc);
                  return TRUE;
               }
               if ((err = AdrSetAddrSpace(go2AddrDesc, SPACE_SD)) != GOOD) {
                  // report error
                  ErrDisplayFormattedError(err, FORCE_POPUP, NULL,NULL,
                                           NULL,MB_OK,(S16 FAR *) &buttonID);
                  AdrDestroyAddress(go2AddrDesc);
                  return TRUE;  // continue
               }
               // first look through the group list for a range that matches
               // the given address.
               reg = NULL;
               group = PeriServer->GetGroupByAddress(go2AddrDesc);
               if (group != NULL && *group != NOOBJECT) {
                  // we found a matching group so now find the closest
                  // register
                  reg = group->FindClosestRegByAddress(go2AddrDesc);
               }
               else {
                  // we don't have a group that matches the address so
                  // try this find first group where
                  // go2Addr < groupRange start addr
                  group = PeriServer->GetGroupGTAddress(go2AddrDesc);
                  if (group != NULL && *group == NOOBJECT) {
                     // last group, last address
                     group = PeriServer->GetGroupInfo(PeriServer->
                                                      GetGroupCount()-1);
                     reg = group->FindClosestRegByAddress(go2AddrDesc);
                  }
                  // 04/18/94 - Nghia
                  // Do not need to look any further.
                  // reg is NULL and group is NULL
               }
               AdrDestroyAddress(go2AddrDesc);
               if (reg != NULL) {
                  if (!reg->parent->expanded) {
                     reg->parent->expanded = TRUE;
                     reg->parent->nLinesDirty = TRUE;
                     SendMessage(hwndPeriList, VLB_RESETCONTENT, 0, 0L);
                  }
                  which = PeriServer->RegToLine(reg);
                  SendMessage(hwndPeriList, VLB_SETCURSEL,
                              (WORD) VLB_FINDITEM, (LONG) which);
                  PeriLastLineSelected = which;
                  EndDialog (hDlg, 0);
               }
               else {
                  SetFocus(hDlg);
                  ErrMessageBox((LPSTR) "Search Failed", 
                  (LPSTR) "No Register At That Address", 
                  MB_OK | MB_ICONEXCLAMATION,
                  HE_EDITPERIPHREG, (S16 FAR *) &buttonValue);
                  SetFocus(hDlg);
               }
               return (TRUE);
               
            case IDHELP:
               WinHelp(hDlg, "PWRVIEWS.HLP",
                  HELP_CONTEXT, HE_EDITPERIPHREG);
               return TRUE;
      }
      break;
   }
   return (FALSE);
}

/*****************************************************************************
**
**  GotoPeriDlgProc
**
*****************************************************************************/
BOOL EXPORT GotoPeriDlgProc (HWND hDlg, UINT Message,
                             UINT wParam, LONG lParam) {
   PTGroup group;
   S16 nChars;
   CHAR tempEditVal[MAX_EDIT_TEXT];
   S32 which;
   S16 buttonValue;

   switch (Message) {
      case WM_INITDIALOG:
         SetWindowText(hDlg, "Go To Peripheral");
         SetDlgItemText(hDlg, STATIC_ID, (LPSTR) "Peripheral Name:");
         return (TRUE);

      case WM_COMMAND:
         switch (wParam) {
            case IDCANCEL:
               EndDialog (hDlg, 0);
               return (TRUE);
            case IDOK:
               nChars = GetDlgItemText(hDlg, ER_VALUE_ID, 
                  (LPSTR) tempEditVal, MAX_EDIT_TEXT);
               if (nChars > 0) {
                  group = PeriServer->GetGroupByName((LPSTR)tempEditVal);
                  if (group != NULL) {
                     which = PeriServer->GroupToLine(group);
                     SendMessage(hwndPeriList, VLB_SETCURSEL,
                                 (WORD) VLB_FINDITEM, (LONG) which);
                     PeriLastLineSelected = which;
                     EndDialog (hDlg, 0);
                  }
                  else {
                     SetFocus(hDlg);
                     ErrMessageBox((LPSTR) "Search Failed", 
                        (LPSTR) "Peripheral Name Not Found", 
                        MB_OK | MB_ICONEXCLAMATION,
                        HE_PERIPHGOTOPERIPH, (S16 FAR *) &buttonValue);
                     SetFocus(hDlg);
                  }
               }
               return (TRUE);
            case IDHELP:
               WinHelp(hDlg, "PWRVIEWS.HLP",
                  HELP_CONTEXT, HE_PERIPHGOTOPERIPH);
               return TRUE;
      }
      break;
   }
   return (FALSE);
}

//************************** E O F ******************************************
