/*
 *                            R A D A R . C
 *
 *  Implements the radar command
 *  - init and show dialog
 *  - send command
 *  - interpret answer
 *
 *  Version      : $Revision: 1.4 $
 *
 *  Created      : Wed Jul 13 10:27:47 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: radar.c,v 1.4 1994/07/15 21:47:08 drepper Exp $";
#endif /* lint */

#include <assert.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"

/*
 * prototypes of local functions
 */
static void commandInitRadar(void);
static void radarEditAdd(Bool active, XawTextBlock *textBlock, Bool async);
static void callbackRadar(Widget widget, XtPointer closure,
			  XtPointer callData);
static void radarNotify(Widget w, XEvent *event, String *params,
			Cardinal *numParams);
static Bool processRadarStation(Bool first, Bool last, char *str, void *data);
static Bool processRadarShip(Bool first, Bool last, char *str, void *data);

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

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

    if (firstCall) {
        commandInitRadar();
        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(
        radarPopup,
        XtNx, x,
        XtNy, y,
        NULL);

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

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

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

Bool
radarStationCommand(int xMin, int yMin, int xMax, int yMax, Bool redisplay)
{
    return sendCmdStr(processRadarStation, (void*)redisplay, NULL,
                      "radar %d:%d,%d:%d\n", xMin, xMax, yMin, yMax);
}

Bool
radarShipCommand(int shipNr, Bool redisplay)
{
    return sendCmdStr(processRadarShip, (void*)redisplay, NULL,
                      "radar %d\n", shipNr);
}

/*
 * local functions
 */
static void
commandInitRadar(void)
{
    static String textTranslations = 
        "#override\n"
        "<Key>Return: radarNotify()\n"
        "<Key>Linefeed: radarNotify()\n"
        "Ctrl<Key>M: radarNotify()\n"
        "Ctrl<Key>J: radarNotify()\n";
    static String toggleTranslations =
        "<EnterWindow>: highlight(Always)\n"
        "<LeaveWindow>: unhighlight()\n"
        "<Btn1Down>,<Btn1Up>: set() notify()\n";
    static XtActionsRec defaultAction[1] = {
        { "radarNotify", radarNotify },
    };
    XtTranslations textTrans;
    XtTranslations toggleTrans;
    Widget tmp;

    XtAppAddActions(appContext, defaultAction, 1);
    textTrans = XtParseTranslationTable(textTranslations);
    toggleTrans = XtParseTranslationTable(toggleTranslations);
    
    /* explore command */
    radarPopup = XtVaCreatePopupShell(
        "radarpopupshell",
        topLevelShellWidgetClass,
        topLevel,
        NULL);
    form = XtVaCreateManagedWidget(
        "form",
        formWidgetClass,
        radarPopup,
        NULL);
    tmp = XtVaCreateManagedWidget(
        "radar",
        labelWidgetClass,
        form,
        NULL);
    tmp = XtVaCreateManagedWidget(
        "radarlabel",
        labelWidgetClass,
        form,
        NULL);
    sectorText = XtVaCreateManagedWidget(
        "radartext",
        asciiTextWidgetClass,
        form,
        XtNeditType, XawtextEdit,
        XtNtranslations, textTrans,
        NULL);
    stationToggle = XtVaCreateManagedWidget(
        "station",
        toggleWidgetClass,
        form,
        XtNradioData, (int)'l',
        XtNtranslations, toggleTrans,
        XtNstate, True,
        NULL);
    tmp = XtVaCreateManagedWidget(
        "ship",
        toggleWidgetClass,
        form,
        XtNradioGroup, stationToggle,
        XtNradioData, (int)'s',
        XtNtranslations, toggleTrans,
        NULL);
    okButton = XtVaCreateManagedWidget(
        "OK",
        commandWidgetClass,
        form,
        NULL);
    XtAddCallback(
        okButton,
        XtNcallback, callbackRadar,
        (XtPointer)True);
    tmp = XtVaCreateManagedWidget(
        "Cancel",
        commandWidgetClass,
        form,
        NULL);
    XtAddCallback(
        tmp,
        XtNcallback, callbackRadar,
        (XtPointer)False);

    XtRealizeWidget(radarPopup);
}

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

/* ARGSUSED */
static void
callbackRadar(Widget widget, XtPointer closure, XtPointer callData)
{
    XtPopdown(radarPopup);

    currentEditAdd(False, NULL, False);
    currentEditAdd = oldEditAdd;
    oldEditAdd(True, NULL, False);
    
    if ((Bool)closure) {
	char isStation = (char)(int)XawToggleGetCurrent(stationToggle);
        char *sector;

	XtVaGetValues(
	    sectorText,
	    XtNstring, &sector,
	    NULL);

	if (isStation == 'l') {
	    /* is radar station */
	    int x1, y1, x2, y2;
	    
	    if (strToRange(&sector, &x1, &y1, &x2, &y2)) {
		radarStationCommand(x1, y1, x2, y2, True);
            } else {
	        message(WARN, "radar: invalid sector range");
            }
        } else {
	    /* is ship radar */
    	    int nr;

            if (strToInt(&sector, &nr) && !*sector) {
	        radarShipCommand(nr, True);
            } else {
	        message(WARN, "radar: invalid ship number");
            }
	}
    }
}
/* ARGSUSED */
static void
radarNotify(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 Bool
processRadarStation(Bool first, Bool last, char *str, void *data)
{
    static int dataLine = -1;
    static Bool ignore = False;
    static XRectangle rectangle;
    static int xCenter, yCenter;
    static int range;
    Bool redisplay = (Bool)data;
    int i;

    if (first) {
	dataLine = -1;
	ignore = False;
    }

    if (last) {
	if (redisplay && !ignore && dataLine>=0) {
	    redisplaySectors(mapWidget, rectangle.x, rectangle.y,
			     rectangle.width, rectangle.height);
	}
	return True;
    }

    if (ignore) return True;

    if (dataLine == -1) {
	int eff;

	if (str[0] == '\n' && !str[1]) return True; /* seperating line */
	
	if (!strToCoord(&str, &xCenter, &yCenter) ||
	    sscanf(str, " efficiency %d%%, max range %d", &eff, &range)!=2) {
	    ignore = True;
	    return True;
	}
        empire.map[MAP2ARR(xCenter,yCenter)].eff = eff;

	if (redisplay) {
	    if (first) { 
		rectangle.x = xCenter-range;
		rectangle.y = yCenter-range;
		rectangle.width = xCenter+range;
		rectangle.height = yCenter+range;
	    } else {
		rectangle.x = min(rectangle.x, xCenter-range);
		rectangle.width = max(rectangle.width, xCenter+range);
		rectangle.y = min(rectangle.y, yCenter-range);
		rectangle.height = max(rectangle.height, yCenter+range);
	    }
	}
	
        dataLine++;
	return True;
    }

    assert(dataLine<1+2*range);

    for (i=0; i<abs(dataLine-range); i++) {
	assert(*str==' ');
	str++;
    }
    for (i=0; i<2*range+1-abs(dataLine-range) && *str!='\n'; i++, str+=2) {
	Bool new = False;
	int x = MAP2ARRX(xCenter-2*range+abs(dataLine-range)+2*i);
	int y = MAP2ARRY(yCenter-range+dataLine);
	EmpireSector *sector = &empire.map[x+empire.rowBytes*y];

	if (*str>='A' && *str<='Z') continue;  /* FIX ME: unit processing */

	if (dataLine == range && i == range) continue; /* station itself */

	if (*str == ' ') continue; /* sometimes it's a ' ' */
	
	if (sector->typeChar == ' ') {
	    sector->typeChar = *str;
	    if (*str != '.' && *str != '-' && *str != '^') {
		sector->status = EnemySector;
	    }
	    new = True;
	} else {
	    if (*str == '?') {
		if (sector->status != EnemySector) {
		    sector->status = EnemySector;
		    new = True;
		}
	    } else {
		if (*str != sector->typeChar) {
		    sector->typeChar = *str;
		    new = True;
		}
	    }
	}

	if (new) {
	    sector->typePixmap = getTypePixmap(x, y, sector->status, False);
	}

	if (str[1]=='\n') break;
    }
    
    if (++dataLine == 1+2*range) {
	dataLine = -1;
    }
    return True;
}

static Bool
processRadarShip(Bool first, Bool last, char *str, void *data)
{
    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:
 */
