/*
 *                             D U M P . C
 *
 *  Implements the dump command
 *  -  init and show dialog
 *  -  send command
 *  -  interpret answer 
 *
 *  Version      : $Revision: 1.7 $
 *
 *  Created      : Sun Jul  3 19:26:29 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  Last modified: Thu Jul 14 21:25:46 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: dump.c,v 1.7 1994/07/15 00:46:24 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"

/*
 * prototypes of local functions
 */
static void commandInitDump(void);
static void dumpEditAdd(Bool active, XawTextBlock *textBlock, Bool async);
static void callbackDump(Widget widget, XtPointer closure,
			 XtPointer callData);
static void dumpNotify(Widget w, XEvent *event, String *params,
		       Cardinal *numParams);
static Bool processDump(Bool first, Bool last, char *str, void *data);

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

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

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

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

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

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

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

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

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

    dumpPopup =  XtVaCreatePopupShell(
        "dumppopupshell",
        topLevelShellWidgetClass,
        topLevel,
        NULL);
    form = XtVaCreateManagedWidget(
        "form",
        formWidgetClass,
        dumpPopup,
        NULL);
    tmp = XtVaCreateManagedWidget(
        "dump",
        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, callbackDump,
        (XtPointer)True);
    tmp = XtVaCreateManagedWidget(
        "Cancel",
        commandWidgetClass,
        form,
        NULL);
    XtAddCallback(
        tmp,
        XtNcallback, callbackDump,
        (XtPointer)False);

    XtRealizeWidget(dumpPopup);
}

/* ARGSUSED */
static void
dumpEditAdd(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
callbackDump(Widget widget, XtPointer closure, XtPointer callData)
{
    XtPopdown(dumpPopup);

    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)) {
            dumpCommand(x1, y1, x2, y2, True);
        }
    }
}

/* ARGSUSED */
static void
dumpNotify(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
processDump(Bool first, Bool last, char *str, void *data)
{
#define DUMPHEADERLINES 3
    static dataLine = 0;
    static XRectangle rectangle;
    Bool redisplay = (Bool)data;
    char *cp;
    int dummy;
    int x, y;
    EmpireSector *sector;
    char typeChar;
    int off;
    int eff;

    if (first) {
        dataLine = 0;
    }

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

    if (++dataLine<=DUMPHEADERLINES) return True;

    cp = str;
    while (isdigit(*cp)) cp++;
    while (isspace(*cp)) cp++;
    if (!strncmp(cp, "sector", 6)) return True;

    /* First info is coord */
    if (!strToInt(&str, &x) || !strToInt(&str, &y)) {
	message(WARN, "dump: strange format");
	return True;
    }

    /* combine to minimal rectangle */
    if (dataLine == DUMPHEADERLINES+1) {
        rectangle.x = x;
        rectangle.y = y;
        rectangle.width = x;
        rectangle.height = y;
    } else {
        rectangle.x = min(rectangle.x,x);
        rectangle.width = max(rectangle.width,x);
        rectangle.y = min(rectangle.y,y);
        rectangle.height = max(rectangle.height,y);
    }

    /* change to array base */
    x = MAP2ARRX(x);
    y = MAP2ARRY(y);

    sector = &empire.map[x+y*empire.rowBytes];

    sscanf(str, " %c %*c %d %d %*c %d %d %d %d %d %d %d %d %*d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %c %c %c %c %c %c %c %c %c %c %c %c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
	   &typeChar,
	   &eff,                            &sector->mobility,
	   &off,                            &sector->resource[resIdxMin],
	   &sector->resource[resIdxGold],   &sector->resource[resIdxFert],
	   &sector->resource[resIdxOil],    &sector->resource[resIdxUran],
	   &sector->work,                   &sector->avail,
	   &sector->product[commIdxCiv],    &sector->product[commIdxMil],
	   &sector->product[commIdxUW],     &sector->product[commIdxFood],
	   &sector->product[commIdxShell],  &sector->product[commIdxGun],
	   &sector->product[commIdxPetrol], &sector->product[commIdxIron],
	   &sector->product[commIdxDust],   &sector->product[commIdxBars],
	   &sector->product[commIdxOil],    &sector->product[commIdxLcm],
	   &sector->product[commIdxHcm],    &sector->product[commIdxRad],
	   &sector->path[commIdxUW],        &sector->path[commIdxFood],
	   &sector->path[commIdxShell],     &sector->path[commIdxGun],
	   &sector->path[commIdxPetrol],    &sector->path[commIdxIron],
	   &sector->path[commIdxDust],      &sector->path[commIdxBars],
	   &sector->path[commIdxOil],       &sector->path[commIdxLcm],
	   &sector->path[commIdxHcm],       &sector->path[commIdxRad],
	   &sector->cutoff[commIdxUW],      &sector->cutoff[commIdxFood],
	   &sector->cutoff[commIdxShell],   &sector->cutoff[commIdxGun],
	   &sector->cutoff[commIdxPetrol],  &sector->cutoff[commIdxIron],
	   &sector->cutoff[commIdxDust],    &sector->cutoff[commIdxBars],
	   &sector->cutoff[commIdxOil],     &sector->cutoff[commIdxLcm],
	   &sector->cutoff[commIdxHcm],     &sector->cutoff[commIdxRad],
	   &sector->dist_x,                 &sector->dist_y,
	   &sector->level[commIdxCiv],      &sector->level[commIdxMil],
	   &sector->level[commIdxUW],       &sector->level[commIdxFood],
	   &sector->level[commIdxShell],    &sector->level[commIdxGun],
	   &sector->level[commIdxPetrol],   &sector->level[commIdxIron],
	   &sector->level[commIdxDust],     &sector->level[commIdxBars],
	   &sector->level[commIdxOil],      &sector->level[commIdxLcm],
	   &sector->level[commIdxHcm],      &sector->level[commIdxRad]);

    if (!empire.isBroken && typeChar!='s') {
	XtVaSetValues(
	    breakCommandWidget,
	    XtNsensitive, False,
            NULL);
	empire.isBroken = True;
    }
    
    if (typeChar != sector->typeChar ||
	sector->status != OwnSector) {
	sector->typeChar = typeChar;
	sector->status = OwnSector;
	assert(typeChar != '?');
	sector->typePixmap = getTypePixmap(x, y, sector->status, False);
    }
    
    sector->eff = eff;
    
    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:
 */
