/***************************************************************************
**
**  Name: mapdlg.c
**
**  Description: This is the universal version of map presenter
**
**  Status: PRELIMINARY
**
**  $Log:   S:/tbird/mt2_68k/map/mapdlg.c_v  $
** 
**    Rev 1.0   13 Feb 1997 08:52:32   gene
** Initial revision.
** 
**    Rev 1.6   23 Jan 1997 16:10:06   kevin
** modified initpresenter
** 
**    Rev 1.5   19 Aug 1996 11:29:32   kevin
** None type always comes with all spaces
** 
**    Rev 1.4   21 Jun 1996 15:03:02   kevin
** In 302 case, UI can handle FC0, FC3, and FC4
** 
**    Rev 1.3   03 Jan 1996 16:03:10   kevin
** added 307 and 328 cases
** 
**    Rev 1.2   30 Nov 1995 11:28:12   kevin
** restored working directory after saving or restored process
** 
**    Rev 1.1   30 Nov 1995 10:25:42   gene
** added reset current directory in restore map/save map
** 
**    Rev 1.1   26 Sep 1995 15:04:36   kevin
** 9/26/95
** 
**    Rev 1.14   26 Jun 1995 16:43:30   marilyn
** Adde support for I80386EX_LC.
** 
**    Rev 1.13   29 Mar 1995 14:16:22   marilyn
** Replaced all occurrances of mulitiplying and dividing by gdwGranularity by
** equivalent bit operations to avoid divide by zero exception.  Also replaced
** all occurrances of %gdwGranularity by validating a non-zero gdwGranularity
** prior to the use of the modulus operator.  Fixes ppr 10166.
** 
**    Rev 1.12   10 Mar 1995 16:26:08   marilyn
** Merge 1.10.1.0 to the trunk (Kevin's changes).
** 
**    Rev 1.10.1.0   10 Mar 1995 16:22:48   marilyn
** Merge Kevin's changes.
** 
**    Rev 1.11   14 Nov 1994 11:45:00   tom
** Processor family-specific help support
** 
**    Rev 1.10   07 Oct 1994 11:23:30   steve
** set default space to be USER mode
** 
**    Rev 1.9   06 Oct 1994 10:55:40   ernie
** Restored PowerPack Intel space support; cleaned up compiler warnings.
** 
**    Rev 1.8   05 Oct 1994 15:25:00   steve
** change cursor during setting map.    modified by kevin
** 
**    Rev 1.7   13 Sep 1994 15:01:42   roy
** set gspaceType= SP_INTEL when connecting to 386SX probe.
** 
**    Rev 1.7   13 Sep 1994 10:12:14   roy
** assign gSpaceType = SP_INTEL when connecting to 386SX probe type.
** 
**    Rev 1.6   07 Sep 1994 10:20:04   roy
** new fix(s) from kevin
** 
**    Rev 1.5   11 Aug 1994 10:59:34   marilyn
** Kevin's bug fixes for pprs 9446 and 9496.
** 
**    Rev 1.4   29 Jun 1994 09:28:02   marilyn
** Kevin's fixes for build 6 plus Marilyn and Dennis's fixes for build 6.
** Target was not supported for PP.  Bug in writing out the access which
** included the target and overlay bit caused error in FW.
** 
**    Rev 1.3   10 Jun 1994 11:06:12   joyce
** Kevin modified:
** 1. Addresses are created as or converted to PHYSICAL addresses intead of 
**    VIRTUAL addresses.
** 2. Fix the problem about not synchronizing between CLI and dialog box setting
** 
**    Rev 1.2   02 Jun 1994 15:44:46   steve
** Kevin's changes for pv 2.2 beta 386 build 3
** 
**    Rev 1.1   24 May 1994 07:50:14   tom
** Fix type incompatibility.
** 
**    Rev 1.0   19 May 1994 10:27:56   tom
** Initial revision.
**
**    Rev 1.0   28 Jan 1994 13:19:12   kevin
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/map/mapdlg.c_v   1.0   13 Feb 1997 08:52:32   gene  $
**
**  Copyright (C) 1994 Microtek International.  All rights reserved.
**
****************************************************************************/

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

#ifndef __STDLIB_H
#include <stdlib.h>
#endif

#ifndef __STDIO_H
#include <stdio.h>
#endif

#ifndef __STRING_H
#include <string.h>
#endif

#ifndef __COMMDLG_H
#include <commdlg.h>
#endif

#ifndef __MEM_H
#include <mem.h>
#endif

#ifndef __DLGS_H
#include <dlgs.h>
#endif

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _CLIULIB_
#include "cliulib.h"
#endif

#ifndef _ADDR_
#include "addr.h"
#endif

#ifndef _PROC_
#include "proc.h"
#endif

#ifndef _MAPRC_
#include "maprc.h"
#endif

#ifndef _MAPDEF_
#include "mapdef.h"
#endif

#ifndef _MAPDLG_
#include "mapdlg.h"
#endif

#ifndef _MAP_
#include "map.h"
#endif

#ifndef _HLPENTRY__
#include "hlpentry.h"
#endif

#ifndef __DIR_H
#include "dir.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

BOOLEAN  bgSelEndAddr = FALSE;
CHAR  szFileName[MAX_NAME_LEN];
CHAR  szFileTitle[MAX_NAME_LEN];

DWORD   gdwGranularity;
MAPINFO gMapInfo;
HANDLE  ghInstance;
DWORD   gdwBlockSize;
WORD    gwBlockCount;
U32     gMaxOffset;
PROCESSOR_FAMILY gCpuFamily;
PROC_SYSTEM_TYPE gSystemType;
SPACE_TYPE gSpaceType; //the data type is only used by map server/presenter
PROBE_TYPE gProcessor;


// definitions for tabstop listbox

#define NUM_TABSTOPS 5

#define T_ENDADDR   51
#define T_SIZE     102
#define T_TYPE     137
#define T_ACCESS   167
#define T_SPACE    210

S16 TabStops[NUM_TABSTOPS] = {T_ENDADDR, T_SIZE, T_TYPE, T_ACCESS, T_SPACE};

// end of definitions for tabstop listbox


                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
                        ****************************/

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/

RETCODE CreateAddress(DESCRIPTOR *);
BOOL FAR PASCAL DlgMapProc(HWND, UINT, WPARAM, LPARAM);
BOOL FAR PASCAL DlgEditProc(HWND, UINT, WPARAM, LPARAM);
BOOL FAR PASCAL DlgHlpHookProc(HWND, UINT, WPARAM, LPARAM);
RETCODE PRIVATE UpdateCurrentStatus(HWND, HANDLE, DWORD *);
RETCODE PRIVATE MapDisplayError(HWND hWnd, RETCODE err);
RETCODE PRIVATE UpdateLenBox(HWND hDlg, WORD SBtype);
RETCODE PRIVATE bDialog(HWND, U16, FARPROC, DWORD);
RETCODE PRIVATE ResAddStrings(HWND, U16, U16, LPSTR, ...);
RETCODE PRIVATE ResSetDefault(HWND, U16, U16, U16);
RETCODE PRIVATE GetItemVal(HWND, U16, DWORD *);
RETCODE PRIVATE MapToStr(MAPINFO, LPSTR);
RETCODE PRIVATE SetItemVal(HWND, U16, LPSTR, DWORD);
RETCODE PRIVATE LoadWholeMap(HWND, U16, U16);
RETCODE PRIVATE GetSpaceStr(U16, LPSTR);

RETCODE PRIVATE InitFileStruct(HWND, OPENFILENAME*);
RETCODE PRIVATE OpenMapFile(OPENFILENAME *);
RETCODE PRIVATE SaveMapFile(OPENFILENAME *);


                       /****************************
                        *                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/

/**************************************************************************
**
**  InitPresenter
**
***************************************************************************/

RETCODE EXPORT InitPresenter(HANDLE hInstance)
{
   RETCODE err;
   DESCRIPTOR desc;

   ghInstance = hInstance;
   ProcReturnProcFamily(&gCpuFamily);
   ProcReturnSpecificProcessor(&gProcessor);
   ProcReturnSystemType(&gSystemType);
   gSpaceType = SP_GENERIC;  // without space mode
   switch (gSystemType) {
      case PROC_POWERSCOPE:  // no overlay memory
         gSpaceType = SP_NONE;
         break;
      case PROC_POWERPACK:
         if (gCpuFamily == FAMILY_68K)
            gSpaceType = SP_MOTOROLA;
            // There are some models without space modes
         else {
            if ((gProcessor==I80386CX_TB) || (gProcessor==I80386SX_TB) ||
                (gProcessor==I80386EX_TB)) {
               gSpaceType = SP_INTEL;
            }
         }
         break;
      case PROC_MICEPACK:
         if (gProcessor == M68306_MP || gProcessor == M68307_MP || 
             gProcessor == M68328_MP || gProcessor == M68302_MP)
            gSpaceType = SP_MOTOROLA;
         break;
      default:
         break;
   }
   if ((err = CreateAddress(&desc)) != GOOD)
      return(err);
   if ((err = AdrGetMaxInputAddrOffset(desc, &gMaxOffset)) != GOOD) {
      AdrDestroyAddress(desc);
      return(err);
   }
   err = AdrDestroyAddress(desc);

   return(err);
}

/**************************************************************************
**
**  MapPresenter
**
***************************************************************************/
RETCODE EXPORT MapPresenter(HWND hWnd)
{
   if (gSpaceType == SP_NONE) {
      MapDisplayError(hWnd, ER_NO_MEMORY_PRESENT);
      return(ER_NO_MEMORY_PRESENT);
   }
   else
      // to invoke map presenter
      return(bDialog(hWnd, IDD_MAPDLG, (FARPROC) DlgMapProc, NULL));
}


/**************************************************************************
**
**  DlgMapProc
**  Description: the main function for map presenter to deal with messages
**
**  hDlg    (in): handle of the dialog box
**  message (in): window message
**  wParam  (in): depends on window message
**  lParam  (in): depends on window message
**
***************************************************************************/
BOOL FAR PASCAL DlgMapProc(HWND hDlg, UINT message,
                           WPARAM wParam, LPARAM lParam)
{
   OPENFILENAME  ofn;
   CHAR szMapStr[MAX_MAPSTR_LEN];
   BOOLEAN bRetCode;
   DWORD dwIndex;
   U16  num;
   MAPINFO mapinfo;
   RETCODE err;
   HCURSOR hPrevCursor;

   STATIC HANDLE hListbox;
   STATIC U16    nNumMap;

   bRetCode = TRUE;
   switch (message) {
      case WM_INITDIALOG:
         RegisterHelpEntry(HI_MESSAGEBOXEX, hDlg, HE_MAP);
         hListbox = GetDlgItem(hDlg, IDC_LISTBOX);
         SendMessage(hListbox, LB_SETTABSTOPS, NUM_TABSTOPS,
                     (LPARAM)((S16 FAR*)TabStops));

         GetMapBlockGranularity(&gdwGranularity); // from map server
         GetMapBlockCount(&gwBlockCount);         // from map server
         GetMapBlockSize(&gdwBlockSize);          // from map server
         GetNumMapSetting(&nNumMap);              // from map server
         gMaxOffset &= (~gdwGranularity + 1);
         // gMaxOffset = (gMaxOffset/gdwGranularity)*gdwGranularity;
         if (nNumMap > 0)
            if (LoadWholeMap(hDlg, 0, nNumMap) != GOOD)
               bRetCode = FALSE;
         // update status of buttons
         UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
         break;
      case WM_ACTIVATE:
         if (wParam != 0) { // To use WA_INACTIVE(==0), the WIN 3.1 header
                            // file should be included.
            GetNumMapSetting(&num);
            dwIndex = SendMessage(hListbox, LB_GETCURSEL, NULL, NULL);
            LoadWholeMap(hDlg, nNumMap, num);
            if (nNumMap == num)
               SendMessage(hListbox, LB_SETCURSEL, (WPARAM)dwIndex, NULL);
            nNumMap = num;
            // update status of buttons
            UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
         }
         break;
      case WM_COMMAND:
         switch (wParam) {
            case IDCANCEL:
               // user can close the presenter by either 'ESC' or 'OK'
               EndDialog (hDlg, 1);
               break;
            case IDC_LISTBOX:
               if (HIWORD(lParam) == LBN_DBLCLK)
                  // invoke edit dialog box
                  SendMessage(hDlg, WM_COMMAND, IDC_MAPEDIT, NULL);
               if (HIWORD(lParam) == LBN_SELCHANGE) {
                  // update status of buttons
                  UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
               }
               break;

            case IDC_MAPADD:
               switch (gSpaceType) {
               /* three types -- basic, 68k, and Intel */
                  case SP_GENERIC:  // no space mode
                     if (bDialog(hDlg, IDD_MAPEDIT, (FARPROC) DlgEditProc,
                                 ADDMAP) != GOOD)
                        bRetCode = FALSE;
                     break;
                  case SP_INTEL:
                     if (bDialog(hDlg, IDD_MAPEDITINTEL,
                         (FARPROC)DlgEditProc, EDITINTEL|ADDMAP) != GOOD)
                        bRetCode = FALSE;
                     break;
                  case SP_MOTOROLA:
                     num = (gProcessor == M68302_MP) ?
                              IDD_MAPEDIT68K302 : IDD_MAPEDIT68K;
                     if (bDialog(hDlg, num, (FARPROC)DlgEditProc,
                                 EDIT68K|ADDMAP) != GOOD)
                        bRetCode = FALSE;
                     break;
               }
               if (bRetCode) {
                  if ((err=SetMapInfo(gMapInfo, TRUE, NULL)) == GOOD) {
                     MapToStr(gMapInfo, (LPSTR)szMapStr);
                     dwIndex = SendMessage(hListbox, LB_ADDSTRING, NULL,
                                           (LPARAM) szMapStr);
                     SendMessage(hListbox, LB_SETCURSEL, (WORD)dwIndex, NULL);
                     nNumMap++;
                     err = GetNumMapSetting(&num);
                     if (err==GOOD && nNumMap != num) {
                        // inconsistent information
                        LoadWholeMap(hDlg, nNumMap, num);
                        nNumMap = num;
                     }
                  }
                  else
                     MapDisplayError(hDlg, err);
               }
               // update status of buttons
               UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
               break;

            case IDC_MAPEDIT:
               dwIndex = SendDlgItemMessage(hDlg, IDC_LISTBOX,
                                            LB_GETCURSEL, NULL, NULL);
               if (dwIndex == (DWORD)LB_ERR) {
                  bRetCode = FALSE;
                  break;
               }
               GetMapInfo(dwIndex, &gMapInfo);
               mapinfo = gMapInfo;
               switch (gSpaceType) {
               /* three types -- basic, 68k, and Intel */
                  case SP_GENERIC:
                     if (bDialog(hDlg, IDD_MAPEDIT, (FARPROC) DlgEditProc,
                                 dwIndex) != GOOD)
                        bRetCode = FALSE;
                     break;
                  case SP_INTEL:
                     if (bDialog(hDlg, IDD_MAPEDITINTEL, (FARPROC)DlgEditProc,
                                 EDITINTEL|dwIndex) != GOOD)
                        bRetCode = FALSE;
                     break;
                  case SP_MOTOROLA:
                     num = (gProcessor == M68302_MP) ?
                              IDD_MAPEDIT68K302 : IDD_MAPEDIT68K;
                     if (bDialog(hDlg, num, (FARPROC) DlgEditProc,
                                 EDIT68K|(WORD)dwIndex) != GOOD)
                        bRetCode = FALSE;
                     break;
               }
               if (!bRetCode) break;

               // release the selection first
               if ((err=SetMapInfo(mapinfo, FALSE, dwIndex)) == GOOD) {
                  if ((err=SetMapInfo(gMapInfo, TRUE, NULL)) == GOOD) {
                     SendMessage(hListbox, LB_DELETESTRING, (WPARAM)dwIndex,
                                 NULL);
                     MapToStr(gMapInfo, (LPSTR)szMapStr);
                     dwIndex = SendMessage(hListbox, LB_ADDSTRING, NULL,
                                           (LPARAM) szMapStr);
                     SendMessage(hListbox, LB_SETCURSEL, (WPARAM)dwIndex,
                                 NULL);
                  }
                  else {
                     MapDisplayError(hDlg, err);
                     // restore the previous setting
                     SetMapInfo(mapinfo, TRUE, NULL);
                  }
               }
               else
                  MapDisplayError(hDlg, err);

               err = GetNumMapSetting(&num);
               if (err == GOOD && nNumMap != num) {
                  LoadWholeMap(hDlg, nNumMap, num);
                  nNumMap = num;
               }
               // update status of buttons
               UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
               break;

            case IDC_MAPDELETE:
               dwIndex = SendDlgItemMessage(hDlg, IDC_LISTBOX,
                                                  LB_GETCURSEL, NULL, NULL);
               if (dwIndex != (DWORD)LB_ERR) {
                  GetMapInfo(dwIndex, &gMapInfo);
                  SendMessage(hListbox, LB_DELETESTRING, (WPARAM)dwIndex,
                              NULL);
                  SendMessage(hListbox, LB_SETCURSEL, (WPARAM)dwIndex, NULL);
                  if ((err = SetMapInfo(gMapInfo, FALSE, dwIndex)) == GOOD) {
                     // remove the setting
                     nNumMap--;
                  }
                  else
                     MapDisplayError(hDlg, err);
                  
                  err = GetNumMapSetting(&num);
                  if (err==GOOD && nNumMap != num) {
                     /* didn't keep settings consistent between presenter
                        and server */
                     LoadWholeMap(hDlg, nNumMap, num);
                     nNumMap = num;
                  }
               }
               else
                  bRetCode = FALSE;
               // update status of buttons
               UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
               break;

            case IDC_CONFIGSAVE:
               InitFileStruct(hDlg, &ofn);
               if (SaveMapFile(&ofn) == GOOD)
                  MapSaveMap(ofn.lpstrFile);
               TFree(ofn.lpstrInitialDir);
               FreeProcInstance((FARPROC)ofn.lpfnHook);
               break;
            case IDC_CONFIGLOAD:
               InitFileStruct(hDlg, &ofn);
               if (OpenMapFile(&ofn) == GOOD) {
                  hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
                  if ((err=MapRestoreMap(ofn.lpstrFile)) != GOOD) {
                     SetCursor(hPrevCursor);
                     MapDisplayError(hDlg, err);
                  }
                  SetCursor(hPrevCursor);
                  GetNumMapSetting(&num);
                  LoadWholeMap(hDlg, nNumMap, num);
                  nNumMap = num;
               }
               TFree(ofn.lpstrInitialDir);
               FreeProcInstance((FARPROC)ofn.lpfnHook);
               // update status of buttons
               UpdateCurrentStatus(hDlg, hListbox, &dwIndex);
               break;
            case IDC_HELP:
               WinHelp(hDlg, "PWRVIEWS.HLP", HELP_CONTEXT, HE_MAP);
               bRetCode = FALSE;
               break;
            default:
                bRetCode = FALSE;
               break;
         }
          break;
      default:
          bRetCode = FALSE;
   }
   return(bRetCode);   // have done something if TRUE
}

/**************************************************************************
**
**  DlgEditProc
**  Description: major function for edit dialog box
**
**  hDlg    (in): handle of the dialog box
**  message (in): window message
**  wParam  (in): depends on window message
**  lParam  (in): depends on window message
**
***************************************************************************/
BOOL FAR PASCAL DlgEditProc(HWND hDlg, UINT message,
                            WPARAM wParam, LPARAM lParam)
{
   DWORD   dwDlgItemVal;
   BOOLEAN bRetCode;
   BOOLEAN bUD, bUP, bSD, bSP, bF0, bF3, bF4, bUSR, bSMM;

   bRetCode = TRUE;
   switch (message) {
      case WM_INITDIALOG:
         if (gSystemType == PROC_MICEPACK) {
            ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMTYPE,
                          (LPSTR)"Overlay", (LPSTR)"Target");
            ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                          (LPSTR)"RAM",
                          (LPSTR)"ROM break",
                          (LPSTR)"None");
         }
         else {
            ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMTYPE,
                          (LPSTR)"Overlay", (LPSTR)"Target");

            ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                          (LPSTR)"RAM",
                          (LPSTR)"ROM break",
                          (LPSTR)"ROM no break",
                          (LPSTR)"None");
         }
         SetItemVal(hDlg, IDC_EDITBASEADDR, (LPSTR)"%#lX", 0);
         if (bgSelEndAddr) {
            // show end address
             SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                        (DWORD)gdwGranularity-1);
             CheckRadioButton(hDlg, IDC_SELSIZE, IDC_SELADDR, IDC_SELADDR);
         }
         else {
            // size of overlay memory
             SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                        (DWORD)gdwGranularity);
            CheckRadioButton(hDlg, IDC_SELSIZE, IDC_SELADDR, IDC_SELSIZE);
         }

         bSMM = bUSR = bF0 = bF3 = bF4 = bUD = bUP = bSP = bSD = FALSE;
         if (ISADDDIALOG(lParam)) {
            SetWindowText(hDlg, "Add");
            ResSetDefault(hDlg, CB_SETCURSEL, IDC_CBMEMACCESS, 0);
            ResSetDefault(hDlg, CB_SETCURSEL, IDC_CBMEMTYPE, 0);
            switch (gSpaceType) {
               case SP_GENERIC:
                  break;
               case SP_MOTOROLA:
                  if (gSystemType == PROC_MICEPACK)
                     bUD = bUP = bSP = bSD = TRUE;
                  else
                     bSD = TRUE;
                  SendDlgItemMessage(hDlg, IDC_SPACEUP, BM_SETCHECK, bUP, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACEUD, BM_SETCHECK, bUD, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACESP, BM_SETCHECK, bSP, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACESD, BM_SETCHECK, bSD, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACE0, BM_SETCHECK, bF0, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACE3, BM_SETCHECK, bF3, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACE4, BM_SETCHECK, bF4, 0);
                  break;
               case SP_INTEL:
                  bUSR = TRUE;
                  SendDlgItemMessage(hDlg, IDC_SPACEUSER, BM_SETCHECK, 
                                     bUSR, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACESMM, BM_SETCHECK,
                                     bSMM, 0);
                  break;
            }

         }
         else {
            ResSetDefault(hDlg, CB_SETCURSEL, IDC_CBMEMTYPE,
                          GETTYPE(gMapInfo.type));
            if (gSystemType == PROC_MICEPACK)
               if (GETACCESS(gMapInfo.type) > 2) // NONE
                  gMapInfo.type--;
            if (GETTYPE(gMapInfo.type) > 0) { // target
               gMapInfo.type--;               // get rid of RAM case
            
               // clear out all the strings in the box
               SendDlgItemMessage(hDlg, IDC_CBMEMACCESS, CB_RESETCONTENT,
                                  NULL, NULL);

               // add correct settings to the box
               if (gSystemType == PROC_MICEPACK)
                  ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                                (LPSTR)"ROM break",
                                (LPSTR)"None");
               else
                  ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                                (LPSTR)"ROM break",
                                (LPSTR)"ROM no break",
                                (LPSTR)"None");
            }    
            
            ResSetDefault(hDlg, CB_SETCURSEL, IDC_CBMEMACCESS,
                          GETACCESS(gMapInfo.type));

            switch (gSpaceType) {
               case SP_GENERIC:
                  break;
               case SP_MOTOROLA:
                  if (HAS_UP(gMapInfo.space)) bUP = TRUE;
                  if (HAS_UD(gMapInfo.space)) bUD = TRUE;
                  if (HAS_SP(gMapInfo.space)) bSP = TRUE;
                  if (HAS_SD(gMapInfo.space)) bSD = TRUE;
                  if (HAS_SPC0(gMapInfo.space)) bF0 = TRUE;
                  if (HAS_SPC3(gMapInfo.space)) bF3 = TRUE;
                  if (HAS_SPC4(gMapInfo.space)) bF4 = TRUE;
                  SendDlgItemMessage(hDlg, IDC_SPACEUP, BM_SETCHECK, bUP, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACEUD, BM_SETCHECK, bUD, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACESP, BM_SETCHECK, bSP, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACESD, BM_SETCHECK, bSD, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACE0, BM_SETCHECK, bF0, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACE3, BM_SETCHECK, bF3, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACE4, BM_SETCHECK, bF4, 0);
                  break;
               case SP_INTEL:
                  if (HAS_USR(gMapInfo.space)) bUSR = TRUE;
                  if (HAS_SMM(gMapInfo.space))  bSMM = TRUE;
                  SendDlgItemMessage(hDlg, IDC_SPACEUSER, BM_SETCHECK,
                                     bUSR, 0);
                  SendDlgItemMessage(hDlg, IDC_SPACESMM, BM_SETCHECK,
                                     bSMM, 0);
                  break;
            }

            SetItemVal(hDlg, IDC_EDITBASEADDR, (LPSTR)"%#lX", gMapInfo.addr);
            if (bgSelEndAddr) {
               dwDlgItemVal = gMapInfo.addr - 1 + gMapInfo.size;
               SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                          (DWORD)dwDlgItemVal);
            }
            else
               SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                          (DWORD)gMapInfo.size);
         }
         break;
      case WM_VSCROLL:
         if (HIWORD(lParam) == GetDlgItem(hDlg, IDC_SPINBASEADDR)) {
            if (GetItemVal(hDlg, IDC_EDITBASEADDR, &gMapInfo.addr) != GOOD)
               gMapInfo.addr = 0;
            if (gMapInfo.addr > gMaxOffset)
               gMapInfo.addr = gMaxOffset;
            gMapInfo.addr &= (~gdwGranularity + 1);
            // gMapInfo.addr = (gMapInfo.addr/gdwGranularity)*gdwGranularity;
            switch(wParam) {
               case SB_LINEUP:
                  if (gMapInfo.addr < gMaxOffset)
                     gMapInfo.addr += gdwGranularity;
                  break;
               case SB_LINEDOWN:
                  if (gMapInfo.addr > 0)
                     gMapInfo.addr -= gdwGranularity;
                  break;
            }
            SetItemVal(hDlg, IDC_EDITBASEADDR, (LPSTR)"%#lX",
                       (DWORD)gMapInfo.addr);
            if (bgSelEndAddr)
               UpdateLenBox(hDlg, wParam);
         }
         else
            UpdateLenBox(hDlg, wParam);
         break;

      case WM_COMMAND:
         switch (wParam) {
            case IDOK:
               if (GetItemVal(hDlg, IDC_EDITBASEADDR, &gMapInfo.addr)
                  != GOOD) {
                  MapDisplayError(hDlg, ER_ADR_INVALID_ADDRESS_STR);
                  break;
               }
               gMapInfo.addr &= (~gdwGranularity + 1);
               // gMapInfo.addr = (gMapInfo.addr/gdwGranularity)*gdwGranularity;
               if (GetItemVal(hDlg, IDC_EDITBLOCKSIZE, &dwDlgItemVal)
                  != GOOD) {
                  if (bgSelEndAddr)
                     MapDisplayError(hDlg, ER_ADR_INVALID_ADDRESS_STR);
                  else
                     MapDisplayError(hDlg, ER_BLOCK_OUT_OF_RANGE);
                  break;
               }

               if (bgSelEndAddr) {
                  gMapInfo.size = dwDlgItemVal - gMapInfo.addr + 1;
                  if (dwDlgItemVal < gMapInfo.addr) {
                     bRetCode = FALSE;
                     MapDisplayError(hDlg, ER_ADR_END_ADDR_TOO_SMALL);
                     break;
                  }
               }
               else
                  gMapInfo.size = dwDlgItemVal;

               dwDlgItemVal = gMapInfo.size;
               gMapInfo.size &= (~gdwGranularity + 1);
               // gMapInfo.size = (gMapInfo.size/gdwGranularity)*gdwGranularity;
               if (gdwGranularity && (dwDlgItemVal%gdwGranularity))
                  gMapInfo.size += gdwGranularity;
               if (gMapInfo.size == 0)
                  bRetCode = FALSE;

               gMapInfo.type = SendDlgItemMessage(hDlg, IDC_CBMEMACCESS,
                                                     CB_GETCURSEL, 0, 0L);

               /* get memory type and access right */
               if (SendDlgItemMessage(hDlg, IDC_CBMEMTYPE, CB_GETCURSEL,
                                   NULL, NULL) > 0) {
                  gMapInfo.type++;  //!! adding RAM back
                  gMapInfo.type |= MAP_TARGET;
               }

               if (gSystemType == PROC_MICEPACK &&
                     GETACCESS(gMapInfo.type) == ACCESS_ROMNOBRK)
                  if (GETTYPE(gMapInfo.type) > 0) // target
                     gMapInfo.type = ACCESS_NONE|MAP_TARGET;
                  else
                     gMapInfo.type = ACCESS_NONE;

               bUSR = bSMM = bF0 = bF3 = bF4 = bUP = bUD = bSP = bSD = FALSE;
               switch (gSpaceType) {
                  case SP_GENERIC:
                     break;
                  case SP_MOTOROLA:
                     bUP = SendDlgItemMessage(hDlg, IDC_SPACEUP, BM_GETCHECK,
                                              0, 0L);
                     bUD = SendDlgItemMessage(hDlg, IDC_SPACEUD, BM_GETCHECK,
                                              0, 0L);
                     bSP = SendDlgItemMessage(hDlg, IDC_SPACESP, BM_GETCHECK,
                                              0, 0L);
                     bSD = SendDlgItemMessage(hDlg, IDC_SPACESD, BM_GETCHECK,
                                              0, 0L);
                     bF0 = SendDlgItemMessage(hDlg, IDC_SPACE0, BM_GETCHECK,
                                              0, 0L);
                     bF3 = SendDlgItemMessage(hDlg, IDC_SPACE3, BM_GETCHECK,
                                              0, 0L);
                     bF4 = SendDlgItemMessage(hDlg, IDC_SPACE4, BM_GETCHECK,
                                              0, 0L);
                     break;
                  case SP_INTEL:
                     bUSR = SendDlgItemMessage(hDlg, IDC_SPACEUSER,
                                               BM_GETCHECK, 0, 0L);
                     bSMM = SendDlgItemMessage(hDlg, IDC_SPACESMM,
                                               BM_GETCHECK, 0, 0L);
                     break;
               }
               /* get space */
               if (gSpaceType == SP_GENERIC)
                  gMapInfo.space = 0;
               else {
                  if (gSpaceType == SP_INTEL)
                     gMapInfo.space = GETSPACE(0,0,bUSR,bSMM,0,0,0,0);
                  else
                     gMapInfo.space = GETSPACE(0,bF4,bF3,bF0,bUP,bUD,bSP,bSD);
                  if (gMapInfo.space == 0) {
                     if (gSpaceType == SP_INTEL)
                        bUSR = TRUE;
                     else {    // SP_MOTOROLA case
                        if (gSystemType == PROC_MICEPACK)
                           bSD = bSP = bUD = bUP = TRUE;
                        else
                           bSD = TRUE;
                     }
                     if (gSpaceType == SP_INTEL)
                        gMapInfo.space = GETSPACE(0,0,bUSR,bSMM,0,0,0,0);
                     else
                        gMapInfo.space = GETSPACE(0,bF4,bF3,bF0,bUP,bUD,bSP,bSD);
                  }
               }
               EndDialog(hDlg, bRetCode);
               break;
            case IDCANCEL:
               bRetCode = FALSE;
               EndDialog(hDlg, bRetCode);
               break;
            case IDC_HELP:
               WinHelp(hDlg, "PWRVIEWS.HLP", HELP_CONTEXT, HE_MAP);
               bRetCode = FALSE;
               break;
            case IDC_CBMEMACCESS:
               if (gSystemType != PROC_MICEPACK)
                  break;
               else {
                  U8 access;

                  access = SendDlgItemMessage(hDlg, IDC_CBMEMACCESS, CB_GETCURSEL,
                           NULL, NULL);
                  if (SendDlgItemMessage(hDlg, IDC_CBMEMTYPE, CB_GETCURSEL,
                           NULL, NULL) > 0) access++;
                  if (access == 2) {  // none type
                     bSD = bSP = bUD = bUP = bF0 = bF3 = bF4 = TRUE;
                     SendDlgItemMessage(hDlg, IDC_SPACEUP, BM_SETCHECK, bUP, 0);
                     SendDlgItemMessage(hDlg, IDC_SPACEUD, BM_SETCHECK, bUD, 0);
                     SendDlgItemMessage(hDlg, IDC_SPACESP, BM_SETCHECK, bSP, 0);
                     SendDlgItemMessage(hDlg, IDC_SPACESD, BM_SETCHECK, bSD, 0);
                     SendDlgItemMessage(hDlg, IDC_SPACE0, BM_SETCHECK, bF0, 0);
                     SendDlgItemMessage(hDlg, IDC_SPACE3, BM_SETCHECK, bF3, 0);
                     SendDlgItemMessage(hDlg, IDC_SPACE4, BM_SETCHECK, bF4, 0);
                  }
               }
               break;
            case IDC_CBMEMTYPE:
                // clear out all the strings in the box
                SendDlgItemMessage(hDlg, IDC_CBMEMACCESS, CB_RESETCONTENT,
                   NULL, NULL);
               if (gSystemType == PROC_MICEPACK) {
                  // switching content
                  if (SendDlgItemMessage(hDlg, IDC_CBMEMTYPE, CB_GETCURSEL,
                                         NULL, NULL) > 0) // target
                     ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                                   (LPSTR)"ROM break",
                                   (LPSTR)"None");
                  else
                     ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                                   (LPSTR)"RAM",
                                   (LPSTR)"ROM break",
                                   (LPSTR)"None");
                  ResSetDefault(hDlg, CB_SETCURSEL, IDC_CBMEMACCESS, 0);
               }
               else {
                  // switching content
                  if (SendDlgItemMessage(hDlg, IDC_CBMEMTYPE, CB_GETCURSEL,
                                         NULL, NULL) > 0) // target
                     ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                                   (LPSTR)"ROM break",
                                   (LPSTR)"ROM no break",
                                   (LPSTR)"None");
                  else
                     ResAddStrings(hDlg, CB_ADDSTRING, IDC_CBMEMACCESS,
                                   (LPSTR)"RAM",
                                   (LPSTR)"ROM break",
                                   (LPSTR)"ROM no break",
                                   (LPSTR)"None");
                  ResSetDefault(hDlg, CB_SETCURSEL, IDC_CBMEMACCESS, 0);
               }
               break;
            case IDC_SELADDR:
            case IDC_SELSIZE:
               if (GetItemVal(hDlg, IDC_EDITBLOCKSIZE, &dwDlgItemVal)
                     != GOOD)
                  dwDlgItemVal = gdwGranularity;
               // make sure the start address is legal
               if (GetItemVal(hDlg, IDC_EDITBASEADDR, &gMapInfo.addr)
                     != GOOD)
                  gMapInfo.addr = 0;

               if (bgSelEndAddr) {
                  if (dwDlgItemVal < gMapInfo.addr)
                     gMapInfo.size = 0;
                  else
                     gMapInfo.size = dwDlgItemVal - gMapInfo.addr + 1;
               }
               else
                  gMapInfo.size = dwDlgItemVal;

               dwDlgItemVal = gMapInfo.size;
               gMapInfo.size &= (~gdwGranularity + 1);
               // gMapInfo.size = (gMapInfo.size/gdwGranularity)*gdwGranularity;
               if (gdwGranularity && (dwDlgItemVal%gdwGranularity))
                  gMapInfo.size += gdwGranularity;

               if (wParam == IDC_SELADDR) {
                  dwDlgItemVal = gMapInfo.addr - 1 + gMapInfo.size;
                  SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                             (DWORD)dwDlgItemVal);
                  bgSelEndAddr = TRUE;
               }
               else {
                  SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                             (DWORD)gMapInfo.size);
                  bgSelEndAddr = FALSE;
               }
               break;
            default:
               bRetCode = FALSE;
               break;
         }
         break;
      default:
         bRetCode = FALSE;
   }
   return(bRetCode);
}

/**************************************************************************
**
**  DlgHlpHookProc
**  Description: to hook help dialogbox on a common dialogbox
**
**  hDlg    (in): handle of the dialog box
**  message (in): window message
**  wParam  (in): depends on window message
**  lParam  (in): depends on window message
**
***************************************************************************/
#pragma argsused
BOOL FAR PASCAL DlgHlpHookProc(HWND hDlg, UINT message, WPARAM wParam,
   LPARAM lParam) {

   if (message == WM_COMMAND && wParam == pshHelp)
      WinHelp(hDlg, "PWRVIEWS.HLP", HELP_CONTEXT, HE_MAP);
   return(FALSE);
}

/**************************************************************************
**
**  UpdateLenBox
**  Description: to modify the content in the box of end address or block
**               size.
**
**  hDlg   (in): handle of the dialog box
**  SBtype (in): message type of scroll bar
**
***************************************************************************/
RETCODE PRIVATE UpdateLenBox(HWND hDlg, WORD SBtype)
{
   DWORD dwDlgItemVal;

   if (GetItemVal(hDlg, IDC_EDITBASEADDR, &dwDlgItemVal) != GOOD)
      dwDlgItemVal = 0;
   if (dwDlgItemVal > gMaxOffset)
      dwDlgItemVal = gMaxOffset;

   gMapInfo.addr = dwDlgItemVal & (~gdwGranularity + 1);
   // gMapInfo.addr = (dwDlgItemVal/gdwGranularity)*gdwGranularity;

   // update the content in the box of start address
   SetItemVal(hDlg,IDC_EDITBASEADDR,(LPSTR)"%#lX",(DWORD)gMapInfo.addr);

   if (GetItemVal(hDlg, IDC_EDITBLOCKSIZE, &dwDlgItemVal) != GOOD)
      dwDlgItemVal = gdwGranularity;

   if (bgSelEndAddr) {
      if (dwDlgItemVal < gMapInfo.addr) {
         if (SBtype == SB_LINEUP)
            gMapInfo.size = 0;  // it will be increased later
         else
            gMapInfo.size = gdwGranularity; // the smallest unit
      }
      else
         gMapInfo.size = dwDlgItemVal - gMapInfo.addr + 1;
   }
   else
      gMapInfo.size = dwDlgItemVal;

   dwDlgItemVal = gMapInfo.size;
   gMapInfo.size &= (~gdwGranularity + 1);
   // gMapInfo.size = (gMapInfo.size/gdwGranularity)*gdwGranularity;
   if (gdwGranularity && (dwDlgItemVal%gdwGranularity))
      gMapInfo.size += gdwGranularity;
   switch(SBtype) { // ignore the cases rather than SB_LINEUP and SB_LINEUP 
      case SB_LINEUP:
         if (gMapInfo.addr <= gMaxOffset-gMapInfo.size)
            gMapInfo.size += gdwGranularity;
         break;
      case SB_LINEDOWN:
         if (gMapInfo.size > gdwGranularity)
            gMapInfo.size -= gdwGranularity;
         break;
   }
   if (gMapInfo.addr > gMaxOffset-gMapInfo.size)
      gMapInfo.size = gMaxOffset-gMapInfo.addr+gdwGranularity;

   if (bgSelEndAddr) {
      dwDlgItemVal = gMapInfo.addr - 1 + gMapInfo.size;
      SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                 (DWORD)dwDlgItemVal);
   }
   else
      SetItemVal(hDlg, IDC_EDITBLOCKSIZE, (LPSTR)"%#lX",
                 (DWORD)gMapInfo.size);
   return(GOOD);
}

/**************************************************************************
**
**  bDialog
**
**  hDlg   (in): handle of the dialog box
**  nDlgID (in): ID of the dialog box
**  fpProc (in): message processor of the dialog
**  lParam (in): long parameter for the dialog
**
***************************************************************************/
RETCODE PRIVATE bDialog(HWND hWnd, U16 nDlgID, FARPROC fpProc, DWORD lParam)
{
   BOOLEAN bRetCode;
   FARPROC fpFunction;

   fpFunction = MakeProcInstance(fpProc, ghInstance);
   bRetCode = DialogBoxParam(ghInstance, MAKEINTRESOURCE(nDlgID), hWnd,
                             fpFunction, lParam);
   FreeProcInstance(fpFunction);
   if (bRetCode)
      return(GOOD);
   else
      return(!GOOD);
}

/**************************************************************************
**
**  UpdateCurrentStatus(hDlg, hListbox, dwIndex)
**  Description: Get current selection in listbox and update the status of
**               edit and delete buttons.
**
**  hDlg  (in): handle of the parent window
**  hListbox (in): handle of list box
**  dwIndex (out): position of selection in list box
**
***************************************************************************/
RETCODE PRIVATE UpdateCurrentStatus(HWND hDlg, HANDLE hListbox,
      DWORD *dwIndex) {
HANDLE  hBEdit, hBDelete;
BOOLEAN bEnable;

   hBEdit   = GetDlgItem(hDlg, IDC_MAPEDIT);
   hBDelete = GetDlgItem(hDlg, IDC_MAPDELETE);
   *dwIndex = SendMessage(hListbox, LB_GETCURSEL, NULL, NULL);
   bEnable = TRUE;
   if (*dwIndex == (DWORD)LB_ERR) {
      *dwIndex = 0;
      bEnable = FALSE;
   }
   EnableWindow(hBEdit, bEnable);
   EnableWindow(hBDelete, bEnable);

   return(GOOD);
}

/**************************************************************************
**
**  MapDisplayError
**  Description: pop up a message box to display error message
**               using message server.
**
**  hWnd  (in): handle of the parent window
**  err   (in): error code
**
** if hWnd == NULL, it means we were called from CLI
**
**  note that NULL passed in hDlg will have it call Ex.
**  this means DLG vs CLI calls differ.
***************************************************************************/
#pragma argsused
RETCODE PRIVATE MapDisplayError(HWND hWnd, RETCODE err)
{
   S16  buttonID;

   ErrDisplayErrorEx(err, FORCE_POPUP, MB_TYPE_OK, (S16 FAR *)&buttonID );
   return(GOOD);
}

/**************************************************************************
**
**  ResAddStrings
**
**  Purpose: add strings into combo box
**
**  hDlg    (in): handle of the dialog box
**  uMsg    (in): control message
**  nCltID  (in): ID of item
**  lpszStr (in): list of strings
**
***************************************************************************/
RETCODE PRIVATE ResAddStrings(HWND hDlg, U16 uMsg, U16 nCltID,
                              LPSTR lpszStr, ...)
{
   HWND hItem;
   U16  i;

   hItem = GetDlgItem(hDlg, nCltID);
   for (i=0; lstrlen(*(&lpszStr+i)); i++)
      SendMessage(hItem, uMsg, NULL, (LPARAM)*(&lpszStr+i));
   return (GOOD);
}

/**************************************************************************
**
**  ResSetDefault
**
**  Purpose: set the default item for a combo box
**
**  hDlg   (in): handle of the dialog box
**  uMsg   (in): control message
**  nCltID (in): ID of item
**  nSel   (in): specified item
**
***************************************************************************/
RETCODE PRIVATE ResSetDefault(HWND hDlg, U16 uMsg, U16 nCltID, U16 nSel)
{
   HWND hItem;

   hItem = GetDlgItem(hDlg, nCltID);
   SendMessage(hItem, uMsg, (WPARAM)nSel, NULL);

   return (GOOD);
}

/**************************************************************************
**
**  InitFileStruct
**
**  Purpose: initialize the structure of the OPENFILENAME
**
**  hDlg (in): handle of the dialog box
**  ofn  (out): with OPENFILENAME data structure
**
***************************************************************************/
RETCODE PRIVATE InitFileStruct(HWND hDlg, OPENFILENAME *ofn)
{
   memset(ofn, 0, sizeof(OPENFILENAME));

   ofn->lStructSize       = sizeof(OPENFILENAME);
   ofn->hwndOwner         = hDlg;
   ofn->lpstrFilter       = "Map files (*.map)\0*.map\0";
   ofn->lpstrFile         = szFileName;
   ofn->nMaxFile          = sizeof(szFileName);
   ofn->lpstrInitialDir   = (LPSTR)TMalloc(80*sizeof(char));
   getcwd(ofn->lpstrInitialDir,80);
   ofn->lpstrFileTitle    = szFileTitle;
   ofn->nMaxFileTitle     = sizeof(szFileTitle);
   ofn->lpfnHook = (UINT (CALLBACK *)(HWND,UINT,WPARAM,LPARAM))
      MakeProcInstance((FARPROC)DlgHlpHookProc, ghInstance);
   return(GOOD);
}

/**************************************************************************
**
**  OpenMapFile
**
**  Purpose: invoke a standard open-file dialog box to get a filename
**
**  ofn  (in/out): with OPENFILENAME data structure
**
***************************************************************************/
RETCODE PRIVATE OpenMapFile(OPENFILENAME *ofn)
{
   HFILE hFile;

   ofn->lpstrTitle = "Restore Map File";
   ofn->Flags = OFN_FILEMUSTEXIST|OFN_SHOWHELP|OFN_HIDEREADONLY|OFN_ENABLEHOOK;
   if (GetOpenFileName(ofn)) {
      hFile = _lopen(ofn->lpstrFile, READ);
      // if (hFile == HFILE_ERROR)  <== should include windows.h v3.1
      if (hFile == (HFILE)-1)
         return (ER_MAP_CANNOT_OPEN_FILE);
      _lclose(hFile);
      chdir(ofn->lpstrInitialDir);
   }
   else
      return (ER_MAP_CANNOT_OPEN_FILE);
   return(GOOD);
}

/**************************************************************************
**
**  SaveMapFile
**
**  Purpose: invoke a standard common dialog box to get a save filename
**
**  ofn  (in/out): with OPENFILENAME data structure
**
***************************************************************************/
RETCODE PRIVATE SaveMapFile(OPENFILENAME *ofn)
{
   OFSTRUCT ofs;
   HFILE hFile;

   ofn->Flags = OFN_OVERWRITEPROMPT|OFN_SHOWHELP|OFN_HIDEREADONLY|OFN_ENABLEHOOK;
   ofn->lpstrTitle = "Save Map File";
   if (GetSaveFileName(ofn)) {
      hFile = OpenFile(ofn->lpstrFile, &ofs, OF_CREATE|OF_WRITE);
      // if (hFile == HFILE_ERROR)  <== should include windows.h v3.1
      if (hFile == (HFILE)-1)
         return (ER_MAP_CANNOT_OPEN_FILE);
      _lclose(hFile);
      chdir(ofn->lpstrInitialDir);
   }
   else
      return (ER_MAP_CANNOT_OPEN_FILE);
   return (GOOD);
}

/**************************************************************************
**
**  MapToStr
**
**  Purpose: convert map information into a string
**
**  hDlg   (in): handle of the dialog box
**  Map    (in): map information
**  lpszMap(out): result
**
***************************************************************************/
RETCODE PRIVATE MapToStr(MAPINFO Map, LPSTR lpszMap)
{
   CHAR   szStrBuff[80];


   wsprintf(lpszMap, "%#08lX\t%#08lX\t%lu\t",
            Map.addr, Map.addr-1+Map.size, Map.size/1024);
   //!!  0X08FE... => 0x08FE...
   lpszMap[1] = lpszMap[12] = 'x';

   if (GETTYPE(Map.type) == 0)  /* 0: overlay, 1: target */
      lstrcat(lpszMap, "Overlay\t");
   else
      lstrcat(lpszMap, "Target\t");

   switch (GETACCESS(Map.type)) {
      case 0:
         lstrcat(lpszMap, "RAM\t");
         break;
      case 1:
         lstrcat(lpszMap, "ROM break\t");
         break;
      case 2:
         lstrcat(lpszMap, "ROM no break\t");
         break;
      case 3:
         lstrcat(lpszMap, "None\t");
         break;
/*
      default:
         MapDisplayError(hDlg, ER_ASSERTION);
         return(ER_ASSERTION);
         break;
*/
   }

   GetSpaceStr(Map.space, (LPSTR)szStrBuff);
   lstrcat(lpszMap, szStrBuff);

   return GOOD;
}

/**************************************************************************
**
**  GetSpaceStr
**
**  Purpose: append space modes to a string
**
**  nSpace  (in): space modes
**  lpszStr (in): string
**
***************************************************************************/
RETCODE PRIVATE GetSpaceStr(U16 nSpace, LPSTR lpszStr)
{
   lpszStr[0] = '\0';
   if (nSpace > 0) {
      // the order of following code is according to the appended string
      // because the list box is gonna sort these settings by the strings
      if (HAS_SD(nSpace)) lstrcat(lpszStr, "SD ");
      if (HAS_SP(nSpace)) lstrcat(lpszStr, "SP ");
      if (HAS_UD(nSpace)) lstrcat(lpszStr, "UD ");
      if (HAS_UP(nSpace)) lstrcat(lpszStr, "UP ");

      if (gSpaceType == SP_INTEL) {
         if (HAS_SMM(nSpace)) lstrcat(lpszStr, "SMM ");
         if (HAS_USR(nSpace)) lstrcat(lpszStr, "User ");
      }
      else {
         if (HAS_SPC0(nSpace)) lstrcat(lpszStr, "F0 ");
         if (HAS_SPC3(nSpace)) lstrcat(lpszStr, "F3 ");
         if (HAS_SPC4(nSpace)) lstrcat(lpszStr, "F4 ");
      }
   }
   return(GOOD);
}

/**************************************************************************
**
**  GetItemVal
**
**  Purpose: get value from a item
**
**  hDlg (in): handle of the dialog box
**  CtlID (in): ID of the item to be set focus
**  dwVal (out)
**
***************************************************************************/
RETCODE PRIVATE GetItemVal(HWND hDlg, U16 CtlID, DWORD *dwVal)
{
   CHAR szVal[MAX_STR_LEN];
   CHAR *endptr;

   if (GetDlgItemText(hDlg, CtlID, szVal, MAX_STR_LEN) == NULL) {
      *dwVal = 0;
      return(!GOOD);
   }

   *dwVal = strtoul(szVal, &endptr, 0);
   if (*endptr != '\0')
      return(!GOOD);

   return(GOOD);
}

/**************************************************************************
**
**  SetItemVal
**
**  Purpose: set value in the item
**
**  hDlg (in): handle of the dialog box
**  CtlID (in): ID of the item to be set focus
**  format (in): format for the output value
**  dwVal (in)
**
***************************************************************************/
RETCODE PRIVATE SetItemVal(HWND hDlg, U16 ItemID, LPSTR format, DWORD dwVal)
{
   CHAR szStrBuff[100];

   wsprintf(szStrBuff, format, dwVal);
   if (strcmp(format, "%#lX") == 0)
      szStrBuff[1] = 'x';
   SetDlgItemText(hDlg, ItemID, szStrBuff);
   return GOOD;
}

/**************************************************************************
**
**  GetMapInfo
**
**  Purpose: get map information from map server
**
**  nIndex (in): bank number
**  pMapInfo (out): map information
**
***************************************************************************/
RETCODE GetMapInfo(U16 nIndex, MAPINFO *pMapInfo)
{
   RETCODE err;
   MEMORY_MAP_DATA map;

   memset(pMapInfo, 0, sizeof(MAPINFO));
   if (!GetMapPresent()) return(ER_NO_MEMORY_PRESENT);
   if ((err=CreateAddress(&map.address)) != GOOD)
      return(err);

   if((err=MapGetWithIndex(&map, nIndex))!=GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }

   if ((err=AdrGetAddrOffset(map.address, &pMapInfo->addr)) != GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }
   pMapInfo->size = map.blockSize;
   pMapInfo->type = map.accessRights&0x00ff;
   pMapInfo->space = (map.accessRights&0xff00)>>8;

   AdrDestroyAddress(map.address);
   return (GOOD);
}

/**************************************************************************
**
**  SetMapInfo
**
**  Purpose: send map information to map server
**
***************************************************************************/
RETCODE SetMapInfo(MAPINFO MapInfo, BOOLEAN bEnable, U32 IndexNo)
{
   RETCODE err;
   MEMORY_MAP_DATA map;
   HCURSOR hPrevCursor;

   if (!GetMapPresent()) return(ER_NO_MEMORY_PRESENT);
   if ((err=CreateAddress(&map.address)) != GOOD)
      return(err);
   if ((err=AdrSetAddrOffset(map.address, MapInfo.addr)) != GOOD) {
      AdrDestroyAddress(map.address);
      return(err);
   }
   map.blockSize = MapInfo.size;
   map.accessRights = MapInfo.type|((MapInfo.space)<<8);
   hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
   if (bEnable) {
      map.enabled = MAP_ENABLE;
      err = MapSet(&map);
   }
   else {
      map.enabled = MAP_DISABLE;
      err = MapSetWithIndex(&map, IndexNo);
   }
   SetCursor(hPrevCursor);

   AdrDestroyAddress(map.address);
   return (err);
}

/**************************************************************************
**
**  LoadWholeMap
**
**  Purpose: if map setting of map presenter is not consistent with map
**           server, reset the setting in presenter and load them from
**           server.
**
**  hDlg (in): handle of the dialog
**  nNumList (in): number of map setting in presenter
**  nNumMap (in): number of map setting in server
**
***************************************************************************/
RETCODE PRIVATE LoadWholeMap(HWND hDlg, U16 nNumList, U16 nNumMap)
{
   U16 i;
   HANDLE hListbox;
   MAPINFO MapInfo;
   CHAR szMapStr[MAX_MAPSTR_LEN];

   hListbox = GetDlgItem(hDlg, IDC_LISTBOX);
   for (i=0; i<nNumList; i++)
      SendMessage(hListbox, LB_DELETESTRING, (WPARAM)0, NULL);
   for (i=0; i<nNumMap; i++) {
      GetMapInfo(i, &MapInfo);
      MapToStr(MapInfo, (LPSTR)szMapStr);
      SendMessage(hListbox, LB_ADDSTRING, NULL, (LPARAM) szMapStr);
   }
   return (GOOD);
}

/**************************************************************************
**
**   CreateAddress
**
***************************************************************************/
RETCODE CreateAddress(DESCRIPTOR *desc) {
   RETCODE err;

   if (gCpuFamily == FAMILY_X86) {
      if ((err = AdrCreateAddressWithType(ADDR_PHYSICAL, desc)) != GOOD)
         return(err);
   }
   else
      if ((err = AdrCreateAddress(desc)) != GOOD) return(err);

   return(GOOD);
}

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