/*
 *                              M A P . C
 *
 *  Implements the map command.
 *  -  initialize and show popup
 *  -  send command
 *  -  process answer
 *
 *  Version      : $Revision: 1.10 $
 *
 *  Created      : Fri Jun 17 01:27:17 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  Last modified: Thu Jul 14 22:47:58 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
#if !defined(lint)
static const char *vcid = "$Id: map.c,v 1.10 1994/07/15 00:45:33 drepper Exp $";
#endif /* lint */

#include <assert.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>

#include "empire.h"

/*
 * local type definitions
 */
typedef struct _MapRegion {
    int xMin;
    int xMax;
    int yMin;
    int yMax;
    Bool redisplay;
} MapRegion;

/*
 * prototypes of local functions
 */
static void commandInitMap(void);
static void mapEditAdd(Bool active, XawTextBlock *textBlock, Bool async);
static void callbackMap(Widget widget, XtPointer closure,
			XtPointer callData);
static void mapNotify(Widget w, XEvent *event, String *params,
		      Cardinal *numParams);
static Bool processMap(Bool first, Bool last, char *str, void *data);

/*
 * local variables
 */
static Widget mapPopup;
static Widget form;
static Widget sectorText;
static Widget okButton;
static void (*oldEditAdd)(Bool, XawTextBlock *, Bool);

/*
 * exported functions
 */
void
queryCommandMap(void)
{
    static Bool firstCall = True;
    Position fx, fy;
    Position x, y;

    if (firstCall) {
	commandInitMap();
	firstCall = False;
    }

    XtVaGetValues(
	commandForm,
	XtNx, &fx,
	XtNy, &fy,
	NULL);

    XtVaGetValues(
	horizPane,
	XtNx, &x,
	XtNy, &y,
	NULL);

    XtTranslateCoords(
	topLevel,
	x+fx, y+fy,
	&x, &y);

    XtVaSetValues(
	mapPopup,
	XtNx, x,
	XtNy, y,
	NULL);

    /* prepare edit widget communication */
    oldEditAdd = currentEditAdd;
    oldEditAdd(False, NULL, False);

    currentEditAdd = mapEditAdd;
    currentEditAdd(True, NULL, False);
    
    XawTextSetInsertionPoint(sectorText, 0);
    XtVaSetValues(
	sectorText,
        XtNstring, "",
        NULL);

    XtPopup(mapPopup, XtGrabNonexclusive);
    XtAddGrab(showViewport, False, False);
}

Bool
mapCommand(int xMin, int yMin, int xMax, int yMax, Bool redisplay)
{
    MapRegion *reg = (MapRegion*)malloc(sizeof(MapRegion));

    if (!reg) return False;

    reg->xMin = xMin;
    reg->xMax = xMax;
    reg->yMin = yMin;
    reg->yMax = yMax;
    reg->redisplay = redisplay;

    return sendCmdStr(processMap, reg, NULL, "map %d:%d,%d:%d\n", 
		      xMin, xMax, yMin, yMax);
}

/*
 * local functions
 */
static void
commandInitMap(void)
{
    static String textTranslations = 
	"#override\n"
	"<Key>Return: mapNotify()\n"
	"<Key>Linefeed: mapNotify()\n"
	"Ctrl<Key>M: mapNotify()\n"
	"Ctrl<Key>J: mapNotify()\n";
    static XtActionsRec defaultAction[1] = {
	{ "mapNotify", mapNotify },
    };
    XtTranslations textTrans;
    Widget tmp;

    XtAppAddActions(appContext, defaultAction, 1);
    textTrans = XtParseTranslationTable(textTranslations);

    mapPopup =  XtVaCreatePopupShell(
	"mappopupshell",
        topLevelShellWidgetClass,
	topLevel,
	NULL);
    form = XtVaCreateManagedWidget(
	"form",
	formWidgetClass,
	mapPopup,
	NULL);
    tmp = XtVaCreateManagedWidget(
	"map",
	labelWidgetClass,
	form,
	NULL);
    tmp = XtVaCreateManagedWidget(
	"sectorlabel",
	labelWidgetClass,
	form,
	NULL);
    sectorText = XtVaCreateManagedWidget(
	"sectortext",
	asciiTextWidgetClass,
	form,
	XtNeditType, XawtextEdit,
	XtNtranslations, textTrans,
	NULL);

    okButton = XtVaCreateManagedWidget(
	"OK",
	commandWidgetClass,
	form,
	NULL);
    XtAddCallback(
	okButton,
	XtNcallback, callbackMap,
	(XtPointer)True);
    tmp = XtVaCreateManagedWidget(
	"Cancel",
	commandWidgetClass,
	form,
	NULL);
    XtAddCallback(
	tmp,
	XtNcallback, callbackMap,
	(XtPointer)False);

    XtRealizeWidget(mapPopup);
}

/* ASRGUSED */
static void
mapEditAdd(Bool active, XawTextBlock *textBlock, Bool async)
{
    assert(async==False);
    if (textBlock) {
	XtVaSetValues(
	    sectorText,
	    XtNstring, textBlock->ptr,
	    NULL);
	XawTextSetInsertionPoint(sectorText, strlen(textBlock->ptr));
    } else {
	XawTextDisplayCaret(sectorText, active);
	if (active) {
	    XtSetKeyboardFocus(form, sectorText);
	    XtSetKeyboardFocus(vertPane, sectorText);
	}
    }
}

static void
callbackMap(Widget widget, XtPointer closure, XtPointer callData)
{
    XtPopdown(mapPopup);

    currentEditAdd(False, NULL, False);
    currentEditAdd = oldEditAdd;
    oldEditAdd(True, NULL, False);
    
    if ((Bool)closure) {
	char *sector;
	int x1, y1, x2, y2;
	
	XtVaGetValues(
	    sectorText,
	    XtNstring, &sector,
	    NULL);

	if (strToRange(&sector, &x1, &y1, &x2, &y2)) {
	    mapCommand(x1, y1, x2, y2, True);
	}
    }
}

/* ARGSUSED */
static void
mapNotify(Widget w, XEvent *event, String *params, Cardinal *numParams)
{
    XtCallActionProc(okButton, "set", NULL, NULL, 0);
    XtCallActionProc(okButton, "notify", NULL, NULL, 0);
    XtCallActionProc(okButton, "unset", NULL, NULL, 0);
}

/* ARGSUSED */
static Bool
processMap(Bool first, Bool last, char *str, void *data)
{
    static int headerCol = 0;
    static int dataLine  = 0;
    MapRegion *reg       = data;
    char      *cp        = str;
    int        thisCol;

    /* if we do not need the structure anymore free it */
    if (last) {
	if (!first && reg->redisplay) {
	    redisplaySectors(mapWidget,
			     reg->xMin, reg->yMin, reg->xMax, reg->yMax);
	}
	free(reg);
	return True;
    }

    gotMap = True;

    while (isspace(*cp)) cp++;
    thisCol = cp-str;

    if (first) {
	headerCol = thisCol;
	dataLine  = 0;
    } else {
	int colCnt = reg->xMin;
	int rowCnt = reg->yMin+dataLine;

	if (thisCol == headerCol) {
	    if (dataLine > 0) {
		dataLine = 0;
	    }
	    return True;
	}

	/* 
	 * this is a real data line
	 * the format is:    ^  coord x x x x x x coord$
	 */
	/* skip the first coordinate */
	while (!isspace(*cp)) cp++;
	/* now skip one blank */
	cp++;
	/* 
	 * only if both the line and the row number are odd/even
	 * the first data has no further offset
	 */
	if ((colCnt^rowCnt)&1) {
	    cp++;
	    colCnt++;
	}

	while (colCnt <= reg->xMax) {
	    if (*cp == '?') {
		empire.map[MAP2ARR(colCnt,rowCnt)].status = EnemySector;
		if (empire.map[MAP2ARR(colCnt,rowCnt)].typeChar == ' ') {
		    empire.map[MAP2ARR(colCnt,rowCnt)].typeChar = *cp;
		    empire.map[MAP2ARR(colCnt,rowCnt)].typePixmap = 
		    getTypePixmap(MAP2ARRX(colCnt), MAP2ARRY(rowCnt), 
				  EnemySector, False);
		}
	    } else if (*cp != ' ' &&
		       empire.map[MAP2ARR(colCnt,rowCnt)].typeChar != *cp) {
		empire.map[MAP2ARR(colCnt,rowCnt)].typeChar = *cp;
		empire.map[MAP2ARR(colCnt,rowCnt)].typePixmap = 
		    getTypePixmap(MAP2ARRX(colCnt), MAP2ARRY(rowCnt), 
				  empire.map[MAP2ARR(colCnt,rowCnt)].status,
				  False);
	    }
	    cp     += 2;
	    colCnt += 2;
	}

	dataLine++;
    }

    return True;
}


/*
 * Local Variables:
 *  mode:c
 *  c-indent-level:4
 *  c-continued-statement-offset:4
 *  c-continued-brace-offset:0
 *  c-brace-offset:0
 *  c-imaginary-offset:0
 *  c-argdecl-indent:4
 *  c-label-offset:-2
 * End:
 */
