/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 1993, 1994, 1995, Elan Feingold (feingold@zko.dec.com)     *
 *                                                                           *
 *     PERMISSION TO USE, COPY, MODIFY, AND TO DISTRIBUTE THIS SOFTWARE      *
 *     AND ITS DOCUMENTATION FOR ANY PURPOSE IS HEREBY GRANTED WITHOUT       *
 *     FEE, PROVIDED THAT THE ABOVE COPYRIGHT NOTICE APPEAR IN ALL           *
 *     COPIES AND MODIFIED COPIES AND THAT BOTH THAT COPYRIGHT NOTICE AND    *
 *     THIS PERMISSION NOTICE APPEAR IN SUPPORTING DOCUMENTATION.  THERE     *
 *     IS NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR      *
 *     ANY PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS       *
 *     OR IMPLIED WARRANTY.                                                  *
 *                                                                           *
 *****************************************************************************/

#include <X11/X.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>

#include <X11/Xaw/Form.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Box.h>

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include "gui-vars.h"
#include "gui-func.h"
#include "callbacks.h"
#include "dice.h"
#include "cards.h"
#include "colormap.h"
#include "utils.h"
#include "debug.h"
#include "types.h"
#include "version.h"

/* Main stuff */
XtAppContext  appContext;

/* All of the widgets */
Widget wToplevel, wForm;
Widget wMap, wControls;
Widget wAttackLabel, wAttackList;
Widget wActionLabel, wActionList;
Widget wMsgDestLabel, wMsgDestList, wMsgDestViewport;
Widget wSendMsgText;
Widget wMsgText;
Widget wPlayField;
Widget wCommentLabel, wQuitButton, wRepeatButton, wCancelAttackButton;
Widget wHelpButton, wShowCardsButton;
Widget wEndTurnButton, wDiceBox;
Widget wCurrentPlayer, wErrorLabel;
Widget wAboutButton;

/* The register popup shell */
Widget wRegisterShell, wRegisterForm;
Widget wNameLabel, wNameText;
Widget wColorLabel, wColorText;
Widget wRegisterButton, wStartGameButton;

/* The view cards popup shell */
Widget wCardShell, wCardForm, wCardTableBox;
Widget wCardViewport, wCardToggle[MAX_CARDS];
Widget wExchangeButton, wCancelCardsButton;

/* The "place armies" popup shell */
Widget wArmiesShell, wArmiesForm, wArmiesLabel, wArmiesText;
Widget wFinishArmiesButton, wCancelArmiesButton;

/* The "help" popup shell */
Widget wHelpShell, wHelpForm, wHelpTopicViewport, wHelpTopicList, wHelpLabel; 
Widget wHelpTopicLabel, wHelpText, wHelpOkButton;

/* The "generic popup" dialog */
Widget wDialogLabel, wDialogButton[3];
Widget wDialogShell, wDialogForm;

/* Translation & action tables */
static CString registerTranslations = "<Key>Return:   register()\n\
                                      Ctrl<Key>M:    no-op()\n\
                                      Ctrl<Key>J:    no-op()\n\
                                      <Key>Linefeed: no-op()\n\
                                      <Key>Tab:      no-op()";

static XtActionsRec registerActionTable[] =
{
  { "register", (XtActionProc)CBK_Register },
  { NULL, NULL },
};

static CString armiesTranslations = "<Key>Return:    popuparmies()\n\
                                     Ctrl<Key>M:    no-op()\n\
                                     Ctrl<Key>J:    no-op()\n\
                                     <Key>Linefeed:  no-op()\n\
                                     <Key>Tab:      no-op()";
static XtActionsRec armiesActionTable[] =
{
  { "popuparmies", (XtActionProc)UTIL_QueryYes },
  { NULL, NULL },
};

static CString messageTranslations = "<Key>Return:   sendmessage()\n\
                                     Ctrl<Key>M:    no-op()\n\
                                     Ctrl<Key>J:    no-op()\n\
                                     <Key>Linefeed:  no-op()\n\
                                     <Key>Tab:      no-op()";
static XtActionsRec messageActionTable[] =
{
  { "sendmessage", (XtActionProc)CBK_SendMessage },
  { NULL, NULL }
};

char *pstrAttackDice[] = 
{
  "1 die", 
  "2 dice",
  "3 dice",
  "Auto",
};

char *pstrActions[] = 
{
  "Place Armies", 
  "Single Attack", 
  "Do-or-Die Attack",
  "Free Move",
};

/* Fallback resources */
CString strResources[] =
{
#include "resources.h"
 NULL
};

/* Private functions */
static Int32 GUI_GetNumColorsInMap(CString strMapFile);

Display        *hDisplay;
Window          hWindow;
GC              hGC, hGC_XOR;
Int32           iScreen;
XFontStruct    *pFont;
Pixmap          pixMapImage;
XImage         *pMapImage;
Visual         *pVisual;

/************************************************************************ 
 *  FUNCTION: GUI_Setup
 *  HISTORY: 
 *     01.25.94  ESF  Created.
 *     02.19.94  ESF  Added Card UI stuff.
 *     03.03.94  ESF  Added callbacks for the remaining buttons.
 *     03.03.94  ESF  Changed so `Number of Armies?' starts unmanaged.
 *     03.04.94  ESF  Added another comment widget for error messages.
 *     03.06.94  ESF  Added an army placement shell.
 *     03.14.94  ESF  Changed shells to be transient.
 *     04.01.94  ESF  Added help popup.
 *     04.02.94  ESF  Added generic dialog with three possible answers.
 *     05.19.94  ESF  Added TrueColor display patches.
 *     09.14.94  ESF  Fixed so that it works with more TrueColor visuals.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
void GUI_Setup(Int32 argc, CString *argv)
{
  Int32         iCount, i, iVisualCount;
  Arg           pArgs[10], pVisualArgs[3];

  /* Setup a colormap for the application */
  COLOR_GetColormap(pVisualArgs, &iVisualCount, 
		    GUI_GetNumColorsInMap(MAPFILE) + 
		    MAX_PLAYERS + NUM_OTHERCOLORS, argc, argv);

  /* Create the application's main window */
  wToplevel = XtAppCreateShell(NULL, "XFrisk", applicationShellWidgetClass,
			       hDisplay, pVisualArgs, iVisualCount);

  /* Make sure to set the arguments from the command line */
  XtVaSetValues(wToplevel, 
		XtNargc, argc,
 		XtNargv, argv,
 		NULL); 

  /****************************/
  /* The main window UI stuff */
  /****************************/
  wForm = XtCreateManagedWidget("wForm", formWidgetClass, wToplevel, 
				NULL, 0);
  wMap = XtCreateManagedWidget("wMap", formWidgetClass, wForm, 
			       NULL, 0);
  wPlayField = XtCreateManagedWidget("wPlayField", formWidgetClass, wForm, 
                                    NULL, 0);
  wControls = XtCreateManagedWidget("wControls", formWidgetClass, wForm, 
                                    NULL, 0);
  
  /* Holds the number of attack dice to use (1, 2, or 3) */
  wAttackLabel = XtCreateManagedWidget("wAttackLabel", labelWidgetClass, 
				       wControls, NULL, 0);
  iCount=0;
  XtSetArg(pArgs[iCount], XtNlist, pstrAttackDice); iCount++;
  XtSetArg(pArgs[iCount], XtNnumberStrings, 4); iCount++;
  wAttackList = XtCreateManagedWidget("wAttackList", listWidgetClass, 
				      wControls, pArgs, iCount);
  XtAddCallback(wAttackList, XtNcallback, CBK_Attack, NULL); 
  
  /* Holds the action to perform (Place Armies, Attack, Free Move) */
  wActionLabel = XtCreateManagedWidget("wActionLabel", labelWidgetClass, 
				       wControls, NULL, 0);
  iCount=0;
  XtSetArg(pArgs[iCount], XtNlist, pstrActions); iCount++;
  XtSetArg(pArgs[iCount], XtNnumberStrings, 4); iCount++;
  wActionList = XtCreateManagedWidget("wActionList", listWidgetClass, 
				      wControls, pArgs, iCount);
  XtAddCallback(wActionList, XtNcallback, CBK_Action, NULL); 

  /* Holds the destination of a message (All, [players...]) */
  wMsgDestLabel = XtCreateManagedWidget("wMsgDestLabel", labelWidgetClass, 
					wControls, NULL, 0);
  wMsgDestViewport = XtCreateManagedWidget("wMsgDestViewport", 
					   viewportWidgetClass, wControls, 
					   NULL, 0);

  pstrMsgDstCString[0] = "All Players";
  wMsgDestList = XtVaCreateManagedWidget("wMsgDestList", listWidgetClass, 
					 wMsgDestViewport, 
					 XtNlist, pstrMsgDstCString,
					 XtNnumberStrings, 1, 
					 NULL);
  XtAddCallback(wMsgDestList, XtNcallback, CBK_MsgDest, NULL); 

  /* Holds the message to send */
  iCount=0;
  XtSetArg(pArgs[iCount], XtNeditType, XawtextEdit); iCount++;  
  wSendMsgText = XtCreateManagedWidget("wSendMsgText", asciiTextWidgetClass, 
				       wControls, pArgs, iCount);
  XtAppAddActions(appContext, messageActionTable, 
		  XtNumber(messageActionTable));
  XtOverrideTranslations(wSendMsgText, 
			 XtParseTranslationTable(messageTranslations));

  /* Holds all of the messages */
  iCount=0;
  XtSetArg(pArgs[iCount], XtNstring, ""); iCount++;
  XtSetArg(pArgs[iCount], XtNscrollVertical, XawtextScrollAlways); iCount++; 
  wMsgText = XtCreateManagedWidget("wMsgText", asciiTextWidgetClass, 
				   wControls, pArgs, iCount);

  /* Turns the color of the player who's turn it is */
  wCurrentPlayer = XtCreateManagedWidget("wCurrentPlayer", formWidgetClass, 
					 wPlayField, NULL, 0);
  
  /* Running commentary on the game, one liners, rules */
  wCommentLabel = XtCreateManagedWidget("wCommentLabel", labelWidgetClass, 
					wPlayField, NULL, 0);

  /* Tells about the game version */
  wAboutButton = XtCreateManagedWidget("wAboutButton", 
				       commandWidgetClass, wPlayField, 
				       NULL, 0);
  XtAddCallback(wAboutButton, XtNcallback, CBK_About, NULL); 

  /* Cancel an attack */
  wCancelAttackButton = XtCreateManagedWidget("wCancelAttackButton", 
					      commandWidgetClass, wPlayField, 
					      NULL, 0);
  XtAddCallback(wCancelAttackButton, XtNcallback, CBK_CancelAttack, NULL); 

  /* Repeat a single attack */
  wRepeatButton = XtCreateManagedWidget("wRepeatButton", commandWidgetClass, 
					wPlayField, NULL, 0);
  XtAddCallback(wRepeatButton, XtNcallback, CBK_Repeat, NULL); 

  /* End a turn */
  wEndTurnButton = XtCreateManagedWidget("wEndTurnButton", commandWidgetClass, 
					 wPlayField, NULL, 0);
  XtAddCallback(wEndTurnButton, XtNcallback, CBK_EndTurn, NULL);

  /* Show the cards */
  wShowCardsButton = XtCreateManagedWidget("wShowCardsButton", 
					   commandWidgetClass, wPlayField, 
					   NULL, 0);
  XtAddCallback(wShowCardsButton, XtNcallback, CBK_ShowCards, NULL);

  /* Help */
  wHelpButton = XtCreateManagedWidget("wHelpButton", commandWidgetClass, 
				      wPlayField, NULL, 0);
  XtAddCallback(wHelpButton, XtNcallback, CBK_Help, NULL); 

  /* The Quit button */
  wQuitButton = XtCreateManagedWidget("wQuitButton", commandWidgetClass, 
					 wPlayField, NULL, 0);
  XtAddCallback(wQuitButton, XtNcallback, CBK_Quit, NULL);  

  /* Error messages */
  wErrorLabel = XtCreateManagedWidget("wErrorLabel", labelWidgetClass, 
				      wPlayField, NULL, 0);

  /* Holds the rolled dice bitmaps */
  wDiceBox = XtCreateManagedWidget("wDiceBox", formWidgetClass, 
				   wPlayField, NULL, 0);

  /* Finished */
  XtRealizeWidget(wToplevel);

  /**********************************/
  /* Build the Register popup shell */
  /**********************************/
  wRegisterShell = XtCreatePopupShell("Register", transientShellWidgetClass,
					 wToplevel, pVisualArgs, iVisualCount);
  wRegisterForm = XtCreateManagedWidget("wRegisterForm", formWidgetClass, 
					wRegisterShell, NULL, 0);
  wNameLabel = XtCreateManagedWidget("wNameLabel", labelWidgetClass, 
				     wRegisterForm, NULL, 0);
  wNameText = XtVaCreateManagedWidget("wNameText", asciiTextWidgetClass, 
				      wRegisterForm, 
				      XtNeditType, XawtextEdit, NULL);
  XtAppAddActions(appContext, registerActionTable, 
		  XtNumber(registerActionTable));
  XtOverrideTranslations(wNameText, 
			 XtParseTranslationTable(registerTranslations));

  wColorLabel = XtCreateManagedWidget("wColorLabel", labelWidgetClass, 
				      wRegisterForm, NULL, 0);

  wColorText = XtVaCreateManagedWidget("wColorText", asciiTextWidgetClass, 
				     wRegisterForm, 
				       XtNeditType, XawtextEdit, NULL);
  XtAppAddActions(appContext, registerActionTable, 
		  XtNumber(registerActionTable));
  XtOverrideTranslations(wColorText, 
			 XtParseTranslationTable(registerTranslations));

  wRegisterButton = XtCreateManagedWidget("wRegisterButton", 
					  commandWidgetClass, wRegisterForm, 
					  NULL, 0);
  XtAddCallback(wRegisterButton, XtNcallback, CBK_Register, NULL);
  wStartGameButton = XtCreateManagedWidget("wStartGameButton", 
					   commandWidgetClass, wRegisterForm, 
					   NULL, 0);
  XtAddCallback(wStartGameButton, XtNcallback, CBK_StartGame, NULL);
  
  /******************************/
  /* Build the card popup shell */
  /******************************/
  wCardShell = XtCreatePopupShell("Cards", transientShellWidgetClass,
				  wToplevel, pVisualArgs, iVisualCount);
  wCardForm = XtCreateManagedWidget("wCardForm", formWidgetClass, 
				    wCardShell, NULL, 0);
  wCardViewport = XtCreateManagedWidget("wCardViewport", viewportWidgetClass, 
					wCardForm, NULL, 0);
  wCardTableBox = XtCreateManagedWidget("wCardTableBox", boxWidgetClass, 
					 wCardViewport, NULL, 0);
  
  for (i=0; i!=MAX_CARDS; i++)
    {
      sprintf(strScratch, "wCardToggle%d", i);
      wCardToggle[i] = XtVaCreateWidget(strScratch, toggleWidgetClass,
					wCardTableBox, 
					XtNwidth, CARD_WIDTH,
					XtNheight, CARD_HEIGHT,
					XtNborderWidth, 0,
					XtNhighlightThickness, 0,
					XtNlabel, "",
					NULL);
    }
  
  wExchangeButton = XtCreateManagedWidget("wExchangeButton", 
					  commandWidgetClass, wCardForm, 
					  NULL, 0);
  XtAddCallback(wExchangeButton, XtNcallback, CBK_ExchangeCards, NULL); 
  wCancelCardsButton = XtCreateManagedWidget("wCancelCardsButton", 
					     commandWidgetClass, wCardForm, 
					     NULL, 0);
  XtAddCallback(wCancelCardsButton, XtNcallback, CBK_CancelCards, NULL);

  /**********************************/
  /* Build the army placement shell */
  /**********************************/
  wArmiesShell = XtCreatePopupShell("Armies", transientShellWidgetClass,
				      wToplevel, pVisualArgs, iVisualCount);
  wArmiesForm = XtCreateManagedWidget("wArmiesForm", formWidgetClass, 
				      wArmiesShell, NULL, 0);
  wArmiesLabel = XtCreateManagedWidget("wArmiesLabel", labelWidgetClass, 
				       wArmiesForm, NULL, 0);
  wArmiesText = XtVaCreateManagedWidget("wArmiesText", asciiTextWidgetClass, 
					wArmiesForm, XtNeditType, XawtextEdit,
					NULL);
  XtAppAddActions(appContext, armiesActionTable, 
		  XtNumber(armiesActionTable));
  XtOverrideTranslations(wArmiesText, 
			 XtParseTranslationTable(armiesTranslations));
  
  wFinishArmiesButton = XtCreateManagedWidget("wFinishArmiesButton", 
					      commandWidgetClass, wArmiesForm, 
					      NULL, 0);
  XtAddCallback(wFinishArmiesButton, XtNcallback, 
		(XtCallbackProc)UTIL_QueryYes, NULL);

  wCancelArmiesButton = XtCreateManagedWidget("wCancelArmiesButton", 
					      commandWidgetClass, wArmiesForm, 
					      NULL, 0);
  XtAddCallback(wCancelArmiesButton, XtNcallback, 
		(XtCallbackProc)UTIL_QueryNo, NULL);

  /************************/
  /* Build the help shell */
  /************************/
  wHelpShell = XtCreatePopupShell("Help", transientShellWidgetClass,
				    wToplevel, pVisualArgs, iVisualCount);
  wHelpForm = XtCreateManagedWidget("wHelpForm", formWidgetClass, 
				    wHelpShell, NULL, 0);
  wHelpTopicLabel = XtCreateManagedWidget("wHelpTopicLabel", labelWidgetClass, 
					  wHelpForm, NULL, 0);
  wHelpLabel = XtCreateManagedWidget("wHelpLabel", labelWidgetClass, 
				     wHelpForm, NULL, 0);
  wHelpTopicViewport = XtCreateManagedWidget("wHelpTopicViewport", 
					     viewportWidgetClass, 
					     wHelpForm, NULL, 0);
  wHelpTopicList = XtCreateManagedWidget("wHelpTopicList", listWidgetClass, 
					 wHelpTopicViewport, NULL, 0);
  XtAddCallback(wHelpTopicList, XtNcallback, CBK_HelpSelectTopic, NULL); 
  wHelpText = XtVaCreateManagedWidget("wHelpText", asciiTextWidgetClass, 
				      wHelpForm,
				      XtNwrap, XawtextWrapWord,
				      XtNdisplayCaret, False,
				      XtNscrollVertical, XawtextScrollAlways,
				      NULL);
  wHelpOkButton = XtCreateManagedWidget("wHelpOkButton", 
					commandWidgetClass, wHelpForm, 
					NULL, 0);
  XtAddCallback(wHelpOkButton, XtNcallback, CBK_HelpOk, NULL);

  /***********************************/
  /* Build the generic dialog shells */
  /***********************************/
  wDialogShell = XtCreatePopupShell("Dialog", transientShellWidgetClass,
				      wToplevel, pVisualArgs, iVisualCount);
  wDialogForm = XtCreateManagedWidget("wDialogForm", formWidgetClass, 
				      wDialogShell, NULL, 0);
  wDialogLabel = XtCreateManagedWidget("wDialogLabel", labelWidgetClass, 
				       wDialogForm, NULL, 0);
  wDialogButton[0] = XtCreateManagedWidget("wDialogButton1", 
					   commandWidgetClass, wDialogForm, 
					   NULL, 0);
  XtAddCallback(wDialogButton[0], XtNcallback, (XtCallbackProc)UTIL_QueryYes, 
		NULL);
  wDialogButton[1] = XtCreateManagedWidget("wDialogButton2", 
					   commandWidgetClass, wDialogForm, 
					   NULL, 0);
  XtAddCallback(wDialogButton[1], XtNcallback, (XtCallbackProc)UTIL_QueryNo, 
		NULL);
  wDialogButton[2] = XtCreateManagedWidget("wDialogButton3", 
					   commandWidgetClass, wDialogForm, 
					   NULL, 0);
  XtAddCallback(wDialogButton[2], XtNcallback, 
		(XtCallbackProc)UTIL_QueryCancel, NULL);

  /* Get a couple globals for the future */
  hDisplay = XtDisplay(wMap);
  hWindow  = XtWindow(wMap);
  iScreen  = DefaultScreen(hDisplay);
  hGC      = XCreateGC(hDisplay, hWindow, 0, NULL);
  hGC_XOR  = XCreateGC(hDisplay, hWindow, 0, NULL);  

  /* Set the XOR GC appropriately */
  XSetFunction(hDisplay, hGC_XOR, GXinvert); 
  XSetLineAttributes(hDisplay, hGC_XOR, 2, LineSolid, CapButt, JoinMiter);

  /* Get the font */
  if ((pFont=XLoadQueryFont(hDisplay, "fixed")) == NULL)
    {
      (void)UTIL_PopupDialog("Fatal Error", 
			     "GUI: Couldn't get font 'fixed'!\n", 1,
			     "Ok", NULL, NULL);
      UTIL_ExitProgram(-1);
    }
  
  /* Print a welcome message */
  sprintf(strScratch, "Welcome to %s", FRISK_VERSION);
  UTIL_DisplayComment(strScratch);
}


/************************************************************************ 
 *  FUNCTION: GUI_Start
 *  HISTORY: 
 *     01.25.94  ESF  Created.
 *     01.29.94  ESF  Added Registration popup.
 *     03.16.94  ESF  Centering and automatic placement of wRegisterShell.
 *     04.01.94  ESF  Fixed bug, XtNy had an x by it.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
void GUI_Start(void)
{
  Int32 x, y;

  UTIL_CenterShell(wRegisterShell, wToplevel, &x, &y);
  XtVaSetValues(wRegisterShell, 
		XtNallowShellResize, False,
		XtNx, x, 
		XtNy, y, 
		XtNborderWidth, 1,
		XtNtitle, "Frisk Registration",
		NULL);

  XtAppMainLoop(appContext);
}



/************************************************************************ 
 *  FUNCTION: GUI_AddCallbacks
 *  HISTORY: 
 *     01.25.94  ESF  Created 
 *     04.11.94  ESF  Added event handler for dice region.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
void GUI_AddCallbacks(Int32 iReadSock)
{
  /* Add the input to receive messages from */
  (void)XtAppAddInput (appContext, iReadSock, (XtPointer)XtInputReadMask, 
		       CBK_XIncomingMessage, NULL); 

  /* Add event handlers */
  XtAddEventHandler(wMap, ExposureMask, False, (XtEventHandler)CBK_RefreshMap,
		    NULL);
  XtAddEventHandler(wMap, ExposureMask, False, (XtEventHandler)CBK_RefreshDice,
		    NULL);
  XtAddEventHandler(wMap, ButtonPressMask, False, 
		    (XtEventHandler)CBK_MapClick, NULL);
}


/************************************************************************ 
 *  FUNCTION: GUI_LoadMap
 *  HISTORY: 
 *     01.26.94  ESF  Created.
 *     01.27.94  ESF  Added palette code.
 *     01.28.94  ESF  Changed to allocate pixmap as well as image.
 *     02.03.94  ESF  Don't allocate colors in order, use mapping.
 *     02.23.94  ESF  Started adding 24 bit server support.
 *     04.01.94  ESF  Fixed free on bogus pointer.
 *     05.12.94  ESF  Moved world colors to colormap.c.
 *     05.19.94  ESF  Added TrueColor display patches.
 *     09.09.94  ESF  Fixed small bug in initializing player turn indicator.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
void GUI_LoadMap(CString strMapFile)
{
  Int32   iHeight, iWidth;
  FILE   *hMap;
  Int32   iPixels;
  Byte    bColor, bLength, *pMapData, *pDataStream, *pBuffer, *pTemp;
  Int32   lCurrent, lEnd; 

  /* Open file and get dimensions */
  if ((hMap=UTIL_OpenFile(strMapFile, "r"))==NULL)
    {
      sprintf(strScratch, "GUI: Could not load %s.\n", strMapFile);
      (void)UTIL_PopupDialog("Fatal Error", strScratch, 1, "Ok", NULL, NULL);
      UTIL_ExitProgram(-1);
    }
  fscanf(hMap, "%d%d%d\n", &iWidth, &iHeight, &iNumColors);

  /* Allocate memory for the map data */
  pMapData = (unsigned char *)MEM_Alloc(iWidth*iHeight);
  
  /* Allocate memory for the buffer; first find out size of file */
  lCurrent = ftell(hMap);
  fseek(hMap, 0, SEEK_END);
  lEnd = ftell(hMap);
  fseek(hMap, lCurrent, SEEK_SET);
  pTemp = pBuffer = (unsigned char *)MEM_Alloc(lEnd-lCurrent);

  /* Read in the rest of the file */
  fread(pBuffer, 1, lEnd-lCurrent, hMap);
  
  for (iPixels=0,pDataStream=pMapData; 
       iPixels!=iWidth*iHeight; 
       iPixels+=bLength)
    {
      /* Get a color segment */
      bLength = *pBuffer++;
      bColor  = *pBuffer++;
     
      /* Adjust for black/white */
      if (bColor == BLACK)
	bColor = iNumColors-2;
      else if (bColor == WHITE)
	bColor = iNumColors-1;

      /* Put it in the map image */
      memset(pDataStream, plCountryToColor[bColor], bLength);
      pDataStream += bLength; 
    }
  
  /* Create an image to hold the map */
  pMapImage = XCreateImage(hDisplay, pVisual,
			   8, ZPixmap, 0, (char *)pMapData, iWidth, iHeight, 
			   8, iWidth);

  /* Create a pixmap to hold the image server-side */
  pixMapImage = XCreatePixmap(hDisplay, 
			      RootWindowOfScreen(XtScreen(wMap)),
			      iWidth, iHeight, 
			      8);

  /* Save the world colormap */
  COLOR_SetWorldColormap((Color*)pBuffer);
  COLOR_SetWorldColors();

  /* Finally write map image to pixmap and window */
  XPutImage(hDisplay, hWindow, hGC, pMapImage, 0, 0, 0, 0, iWidth,iHeight);
  XPutImage(hDisplay, pixMapImage, hGC, pMapImage, 0, 0, 0, 0, iWidth,iHeight);

  /* After colormap is established we want to do this (move it elsewhere!) */
  XtVaSetValues(wCurrentPlayer, XtNbackground, COLOR_DieToColor(2), NULL);

  /* Free up memory we were using */
  MEM_Free(pTemp);
}


/************************************************************************ 
 *  FUNCTION: 
 *  HISTORY: 
 *     09.14.94  ESF  Created.
 *     10.02.94  ESF  Fixed to not call UTIL_PopupDialog.
 *  PURPOSE: 
 *  NOTES: 
 ************************************************************************/
static Int32 GUI_GetNumColorsInMap(CString strMapFile)
{
  FILE   *hMap;
  Int32   iWidth, iHeight, iNumColors;

  /* Open file and get dimensions */
  if ((hMap=UTIL_OpenFile(strMapFile, "r"))==NULL)
    {
      printf("CLIENT: Fatal error, could not load %s.\n", strMapFile);
      UTIL_ExitProgram(-1);
    }

  /* Read the header and close the file */
  fscanf(hMap, "%d%d%d\n", &iWidth, &iHeight, &iNumColors);
  fclose(hMap);

  return iNumColors;
}
