/*
 *                        D E S I G N A T E . C
 *
 *  Implements the designate command.
 *  -  popup for data
 *  -  send command
 *  -  process output of server
 *
 *  Version      : $Revision: 1.9 $
 *
 *  Created      : Sun Jun 12 11:26:20 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  Last modified: Fri Jul 15 21:40:51 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: designate.c,v 1.9 1994/07/15 21:47:54 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 <X11/Xaw/Toggle.h>

#include "empire.h"

#if defined(NEED_toupper)
int toupper(int c);
#endif /* NEED_toupper */

/*
 * local type declaration
 */
typedef struct {
    Widget widget;
    int idx;
} HexaButtons;

/*
 * local variables
 */
static Widget designatePopup;
static Widget form;
static Widget sectorText;
static HexaButtons hexaButtons[40];  /* not clean but should be enough */
static Widget okButton;
static Widget actToggleButton;
static void (*oldEditAdd)(Bool, XawTextBlock *, Bool);

/*
 * local function prototypes
 */
static void commandInitDesignate(void);
static void designateEditAdd(Bool active, XawTextBlock *textBlock, Bool async);
static void togglePixButton(Widget widget, XtPointer closure,
			    XtPointer callData);
static void callbackDesignate(Widget widget, XtPointer closure,
			      XtPointer callData);
static void designateNotify(Widget w, XEvent *event, String *params,
			    Cardinal *numParams);
static void designateShort(Widget w, XEvent *event, String *params,
			   Cardinal *numParams);

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

    if (firstCall) {
	commandInitDesignate();
	firstCall = True;
    }

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

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

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

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

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

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

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

Bool
designateCommand(int x, int y, char typeChar)
{
    EmpireSector *sector = &empire.map[MAP2ARR(x,y)];

    if (sector->status != OwnSector) return False;

    sector->typeChar   = typeChar;
    sector->typePixmap = getTypePixmap(MAP2ARRX(x), MAP2ARRY(y),
				       sector->status, False);
    
    redisplaySectors(mapWidget, x, y, x, y);

    return sendCmdStr(NULL, NULL, NULL, "designate %d,%d %c\n",
		      x, y, typeChar);
}

/*
 * local functions
 */
/* ARGSUSED */
static void
commandInitDesignate(void)
{
    static String textTranslations = 
	"#override\n"
	"<Key>Return: designateNotify()\n"
	"<Key>Linefeed: designateNotify()\n"
	"Ctrl<Key>M: designateNotify()\n"
	"Ctrl<Key>J: designateNotify()\n";
    static XtActionsRec defaultAction[2] = {
	{ "designateNotify", designateNotify },
	{ "designateShort", designateShort },
    };
    static String toggleTranslations =
	"<EnterWindow>: highlight(Always)\n"
	"<LeaveWindow>: unhighlight()\n"
	"<Btn1Down>,<Btn1Up>: set() notify()\n";
    static XtTranslations textTrans;
    static XtTranslations toggleTrans;
    char buffer[2048];
    Widget tmp;
    int i;
    int actIdx;

    strcpy(buffer, textTranslations);
    for (i=0, actIdx=0; hexaPixmap[i].name!=NULL; i++) {
	if (hexaPixmap[i].mayDesignate) {
	    char line[100];
	    sprintf(line, "Meta<Key>%c: designateShort(%d)\n",
		    toupper(hexaPixmap[i].typeChar), actIdx);
	    strcat(buffer, line);
	    actIdx++;
	}
    }
    
    XtAppAddActions(appContext, defaultAction, 2);
    textTrans = XtParseTranslationTable(buffer);
    toggleTrans = XtParseTranslationTable(toggleTranslations);
    
    designatePopup = XtVaCreatePopupShell(
	"designatepopupshell",
	topLevelShellWidgetClass,
	topLevel,
	NULL);
    form = XtVaCreateManagedWidget(
	"form",
	formWidgetClass,
	designatePopup,
	NULL);
    tmp = XtVaCreateManagedWidget(
	"designate",
	labelWidgetClass,
	form,
	NULL);
    tmp = XtVaCreateManagedWidget(
	"sectorlabel",
	labelWidgetClass,
	form,
	NULL);
    sectorText = XtVaCreateManagedWidget(
	"sectortext",
	asciiTextWidgetClass,
	form,
	XtNeditType, XawtextEdit,
	XtNtranslations, textTrans,
	NULL);

    for (i=0, actIdx=0; hexaPixmap[i].name!=NULL; i++) {
	if (hexaPixmap[i].mayDesignate) {
	    if (actIdx==0) {
		hexaButtons[actIdx].widget = XtVaCreateManagedWidget(
		    hexaPixmap[i].name,
	            toggleWidgetClass,
		    form,
		    XtNtranslations, toggleTrans,
	            XtNradioData, i+1,
		    XtNstate, True,
		    XtNbitmap, hexaPixmap[i].pixmap_hilit,
		    XtNwidth, 39,
		    XtNheight, 39,
		    XtNinternalWidth, 0,
		    XtNinternalHeight, 0,
		    XtNhighlightThickness, 0,
		    NULL);
		actToggleButton = hexaButtons[actIdx].widget;
	    } else {
		hexaButtons[actIdx].widget = XtVaCreateManagedWidget(
		    hexaPixmap[i].name,
	            toggleWidgetClass,
		    form,
		    XtNtranslations, toggleTrans,
	            XtNradioData, i+1,
		    XtNradioGroup, hexaButtons[0].widget,
		    XtNstate, False,
		    XtNbitmap, hexaPixmap[i].pixmap_normal,
		    XtNwidth, 39,
		    XtNheight, 39,
		    XtNinternalWidth, 0,
		    XtNinternalHeight, 0,
		    XtNhighlightThickness, 0,
		    NULL);
	    }
	    hexaButtons[actIdx].idx = i;
	    XtAddCallback(
		hexaButtons[actIdx].widget,
	        XtNcallback, togglePixButton,
	        NULL);
	    actIdx++;
	}
    }

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

    XtRealizeWidget(designatePopup);
}

/* ARGSUSED */
static void
designateEditAdd(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
togglePixButton(Widget widget, XtPointer closure, XtPointer callData)
{
    if (widget != actToggleButton) {
	int data;

	XtVaGetValues(
	    actToggleButton,
	    XtNradioData, &data,
	    NULL);

	XtVaSetValues(
	    actToggleButton,
	    XtNbitmap, hexaPixmap[data-1].pixmap_normal,
	    NULL);

	actToggleButton = widget;
	
	XtVaGetValues(
	    widget,
	    XtNradioData, &data,
	    NULL);

	XtVaSetValues(
	    widget,
	    XtNbitmap, hexaPixmap[data-1].pixmap_hilit,
	    NULL);
    }
}

static void
callbackDesignate(Widget widget, XtPointer closure, XtPointer callData)
{
    if ((Bool)closure) {
	char *sector;
	int x, y;
	int idx;

	idx = (int)XawToggleGetCurrent(actToggleButton);
	idx--;                  /* toggle value must be != 0, see init */
	
	XtVaGetValues(
	    sectorText,
	    XtNstring, &sector,
	    NULL);

	if (strToCoord(&sector, &x, &y)) {
	    designateCommand(x, y, hexaPixmap[idx].typeChar);

	    /* prepare for new input */
	    XtVaSetValues(
		sectorText,
                XtNstring, "",
                NULL);
	} else {
	    message(WARN, "designate: not a valid coord");
	}
    } else {
	XtPopdown(designatePopup);

	currentEditAdd(False, NULL, False);
	currentEditAdd = oldEditAdd;
	oldEditAdd(True, NULL, False);
    }
}

/* ARGSUSED */
static void
designateNotify(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);
}

static void
designateShort(Widget w, XEvent *event, String *params, Cardinal *numParams)
{
    int idx;
    
    if (*numParams != 1) {
	message(WARN, "designateShort: wrong number of args");
	return;
    }

    idx = atoi(params[0]);

    XtCallActionProc(hexaButtons[idx].widget, "set", NULL, NULL, 0);
    XtCallActionProc(hexaButtons[idx].widget, "notify", NULL, NULL, 0);
}

/*
 * 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:
 */
