/*
 *                            L E V E L . C
 *
 *  Implements the level command
 *  -  initialize and show popup
 *  -  send command
 *  -  process answer
 *
 *  Version      : $Revision: 1.4 $
 *
 *  Created      : Sun Jul  3 14:43:02 1994
 *  Author       : Ulrich Drepper <drepper@mydec>
 *
 *  Last modified: Mon Jul 11 17:00: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: level.c,v 1.4 1994/07/11 16:37:18 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 commandInitLevel(void);
static void levelEditAdd(Bool active, XawTextBlock *textBlock, Bool async);
static void callbackLevel(Widget widget, XtPointer closure,
			  XtPointer callData);
static void levelNotify(Widget w, XEvent *event, String *params,
			Cardinal *numParams);
static Bool processLevel(Bool first, Bool last, char *str, void *data);

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

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

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

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

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

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

Bool
levelCommand(int xMin, int yMin, int xMax, int yMax)
{
    return sendCmdStr(processLevel, NULL, NULL, "level %d:%d,%d:%d\n", 
                      xMin, xMax, yMin, yMax);
}

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

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

    levelPopup =  XtVaCreatePopupShell(
        "levelpopupshell",
        topLevelShellWidgetClass,
        topLevel,
        NULL);
    form = XtVaCreateManagedWidget(
        "form",
        formWidgetClass,
        levelPopup,
        NULL);
    tmp = XtVaCreateManagedWidget(
        "level",
        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, callbackLevel,
        (XtPointer)True);
    tmp = XtVaCreateManagedWidget(
        "Cancel",
        commandWidgetClass,
        form,
        NULL);
    XtAddCallback(
        tmp,
        XtNcallback, callbackLevel,
        (XtPointer)False);

    XtRealizeWidget(levelPopup);
}

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

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

/* ARGSUSED */
static void
levelNotify(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
processLevel(Bool first, Bool last, char *str, void *data)
{
#define LEVELHEADERLINES 3
    static Bool ignore = False;
    static int dataLine = 0;
    int x, y;
    char *pStart = &str[18];
    EmpireSector *sector;
    char save;
    int i;

    if (first) {
	ignore = False;
	dataLine = 0;
    }
    
    if (last) {
	return True;
    }

    if (++dataLine<=LEVELHEADERLINES || !isspace(str[0])) return True;

    if (!strToCoord(&str, &x, &y)) {
	message(WARN, "level: strange format");
	ignore = True;
	return True;
    }

    sector = &empire.map[MAP2ARR(x,y)];

    while (isspace(*str)) str++;
    if (*str != sector->typeChar) {
	sector->typeChar = *str;
	sector->typePixmap = getTypePixmap(MAP2ARRX(x), MAP2ARRY(y),
					   sector->status, False);
    }
    str++;

    if (!strToCoord(&str, &sector->dist_x, &sector->dist_y)) {
	message(WARN, "level: strange format");
	ignore = True;
	return True;
    }

    for (i=commIdxCiv; i<=commIdxRad; i++) {
	char len =
	    (i==commIdxFood || i==commIdxIron || i==commIdxDust) ? 5 : 4;
	char save = pStart[len];

	pStart[len] = '\0';
	sector->level[i] = atoi(pStart);
	pStart[len] = save;
	pStart += len;
    }

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