/****************************************************************************************************************
 *
 *  Copyright (c) 1992 by Antoine Dumesnil de Maricourt. All rights reserved.
 *
 *  This program is distributed in the hope that it will be useful.
 *  Use and copying of this software and preparation of derivative works
 *  based upon this software are permitted, so long as the following
 *  conditions are met:
 *       o credit to the authors is acknowledged following current
 *         academic behaviour
 *       o no fees or compensation are charged for use, copies, or
 *         access to this software
 *       o this copyright notice is included intact.
 *  This software is made available AS IS, and no warranty is made about 
 *  the software or its performance. 
 * 
 *  Bug descriptions, use reports, comments or suggestions are welcome.
 *  Send them to    dumesnil@etca.fr   or to:
 *       
 *       Antoine de Maricourt
 *       ETCA CREA-SP
 *       16 bis, avenue Prieur de la Cote d'Or
 *       94114 Arcueil Cedex
 *       France
 */

#include <stdio.h>
#include <ctype.h>

#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>

#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/AsciiText.h>

#include "Goban.h"
#include "xgoban.h"

static Widget   i_top;
static Widget   form;

static Widget   w_GN;
static Widget   w_PW;
static Widget   w_PB;
static Widget   w_WR;
static Widget   w_BR;
static Widget   w_WS;
static Widget   w_BS;
static Widget   w_EV;
static Widget   w_PC;
static Widget   w_DT;
static Widget   w_RO;
static Widget   w_HA;
static Widget   w_KM;
static Widget   w_TM;
static Widget   w_RE;
static Widget   w_US;
static Widget   w_SO;
static Widget   w_GC;

/*******************************************************************************************************
 */

static void SetEventProperty (w, id, node)
Widget      w;
int         id;
SG_NodePtr  node;
{
  Arg             arg;
  String          text;
  SG_PropertyPtr  property;

  XtSetArg (arg, XtNstring, &text); XtGetValues (w, &arg, 1);

  if (node != NULL) {
    property = SG_GetProperty (node, id);

    if (property != NULL && strcmp (property->data.pvalue, text) != 0) {
      SG_strcpy (&property->data.pvalue, text, '\0');
      modified = True;
    }

    else if (strcmp (text, "") != 0 && property == NULL) {
      SG_MakeProperty (node, id, text);
      modified = True;
    }
  }
}

/*******************************************************************************************************
 */

static void infoCancel   (w, event) 
Widget    w;
XEvent   *event;
{ 
  XtPopdown (i_top);
}

/*******************************************************************************************************
 */

static void highlightText  (w, event) 
Widget    w;
XEvent   *event;
{ 
  Arg args[1];

  if (edit == True) {
    XtSetArg (args[0], XtNdisplayCaret,  True);
    XtSetValues (w, args, 1);
  }
}

/*******************************************************************************************************
 */

static void unhighlightText  (w, event) 
Widget    w;
XEvent   *event;
{ 
  Arg args[1];

  if (edit == True) {
    XtSetArg (args[0], XtNdisplayCaret,  False);
    XtSetValues (w, args, 1);
  }
}

/*******************************************************************************************************
 */

static void infoConfirm  (w, event) 
Widget    w;
XEvent   *event;
{ 
  SG_NodePtr node = current_node;

  if (edit == True) {
    while (node->type != SG_EventType) {
      while (node->left != NULL)
        node = node->left;
      while (node->up != NULL)
        node = node->up;
    }
    
    SetEventProperty (w_PB, SG_PlayerBlack, node);
    SetEventProperty (w_PW, SG_PlayerWhite, node);
    SetEventProperty (w_BS, SG_BlackSpec  , node);
    SetEventProperty (w_WS, SG_WhiteSpec  , node);
    SetEventProperty (w_BR, SG_BlackRank  , node);
    SetEventProperty (w_WR, SG_WhiteRank  , node);
    SetEventProperty (w_EV, SG_EVent      , node);
    SetEventProperty (w_RO, SG_ROund      , node);
    SetEventProperty (w_PC, SG_PlaCe      , node);
    SetEventProperty (w_DT, SG_DaTe       , node);
    SetEventProperty (w_HA, SG_HAndicap   , node);
    SetEventProperty (w_KM, SG_KoMi       , node);
    SetEventProperty (w_TM, SG_TiMe       , node);
    SetEventProperty (w_RE, SG_REsult     , node);
    SetEventProperty (w_US, SG_USer       , node);
    SetEventProperty (w_SO, SG_SOurce     , node);
    SetEventProperty (w_GN, SG_GameName   , node);
    SetEventProperty (w_GC, SG_GameComment, node);
  }
   
  XtPopdown (i_top);
}

void EventInfo (w, event)
Widget    w;
XEvent   *event;
{
  SG_NodePtr     node = current_node;
  SG_PropertyPtr property;
  Arg            args[4];
  int            xtargc;
  Widget         text;

  while (node->type != SG_EventType) {
    while (node->left != NULL)
      node = node->left;
    while (node->up != NULL)
      node = node->up;
  }

  if (node->type == SG_EventType) {
    CenterWindow (i_top, NULL);

    xtargc = 0;
    XtSetArg (args[xtargc], XtNstring, (XtArgVal) ""); xtargc++;
    XtSetArg (args[xtargc], XtNeditType, 
              (XtArgVal) (edit == True) ? XawtextEdit : XawtextRead); xtargc++;

    
    XtSetValues (w_PB, args, xtargc);
    XtSetValues (w_PW, args, xtargc);
    XtSetValues (w_BS, args, xtargc);
    XtSetValues (w_WS, args, xtargc);
    XtSetValues (w_BR, args, xtargc);
    XtSetValues (w_WR, args, xtargc);
    XtSetValues (w_EV, args, xtargc);
    XtSetValues (w_RO, args, xtargc);
    XtSetValues (w_PC, args, xtargc);
    XtSetValues (w_DT, args, xtargc);
    XtSetValues (w_HA, args, xtargc);
    XtSetValues (w_KM, args, xtargc);
    XtSetValues (w_TM, args, xtargc);
    XtSetValues (w_RE, args, xtargc);
    XtSetValues (w_US, args, xtargc);
    XtSetValues (w_SO, args, xtargc);
    XtSetValues (w_GC, args, xtargc);
    XtSetValues (w_GN, args, xtargc);

    property = node->property;
    
    while (property != NULL) {
      switch (property->id) {
      case SG_PlayerBlack : text = w_PB; break;
      case SG_PlayerWhite : text = w_PW; break;
      case SG_BlackSpec   : text = w_BS; break;
      case SG_WhiteSpec   : text = w_WS; break;
      case SG_BlackRank   : text = w_BR; break;
      case SG_WhiteRank   : text = w_WR; break;
      case SG_EVent       : text = w_EV; break;
      case SG_ROund       : text = w_RO; break;
      case SG_PlaCe       : text = w_PC; break;
      case SG_DaTe        : text = w_DT; break;
      case SG_HAndicap    : text = w_HA; break;
      case SG_KoMi        : text = w_KM; break;
      case SG_TiMe        : text = w_TM; break;
      case SG_REsult      : text = w_RE; break;
      case SG_USer        : text = w_US; break;
      case SG_SOurce      : text = w_SO; break;
      case SG_GameName    : text = w_GN; break;
      case SG_GameComment : text = w_GC; break;
      default             : text = NULL;
      }

      if (text != NULL && property->data.pvalue != NULL)
	{ XtSetArg (args[0], XtNstring, property->data.pvalue);	XtSetValues (text, args, 1); }

      property = property->next;
    }

    XtPopup (i_top, XtGrabNonexclusive);
  }
}

/*******************************************************************************************************
 */

static Widget make_label (form, name, label, horiz, vert, width, justify)
Widget    form;
String    name;
String    label;
Widget    horiz;
Widget    vert;
Dimension width;
XtArgVal  justify;
{
  Arg args[8];
  int xtargc;

  xtargc = 0;
  if (horiz != NULL) { XtSetArg (args[xtargc], XtNfromHoriz, horiz); xtargc++; } 
  if (vert  != NULL) { XtSetArg (args[xtargc], XtNfromVert , vert ); xtargc++; }

  XtSetArg (args[xtargc], XtNjustify       , justify  ); xtargc++;
  XtSetArg (args[xtargc], XtNlabel         , label    ); xtargc++;
  XtSetArg (args[xtargc], XtNwidth         , width + 2); xtargc++;
  XtSetArg (args[xtargc], XtNborderWidth   , 0        ); xtargc++;
  XtSetArg (args[xtargc], XtNinternalHeight, 3        ); xtargc++;

  return XtCreateManagedWidget (name, labelWidgetClass, form, args, xtargc);
}

/*******************************************************************************************************
 */

static XtTranslations translations;

static Widget make_text (form, name, horiz, vert, width)
Widget    form;
String    name;
Widget    horiz;
Widget    vert;
Dimension width;
{
  Arg args[8];
  int xtargc;

  xtargc = 0;
  if (horiz != NULL) { XtSetArg (args[xtargc], XtNfromHoriz, (XtArgVal) horiz); xtargc++; } 
  if (vert  != NULL) { XtSetArg (args[xtargc], XtNfromVert , (XtArgVal) vert ); xtargc++; }

  XtSetArg (args[xtargc], XtNwidth       , (XtArgVal) width       ); xtargc++;
  XtSetArg (args[xtargc], XtNeditType    , (XtArgVal) XawtextEdit ); xtargc++;
  XtSetArg (args[xtargc], XtNtranslations, (XtArgVal) translations); xtargc++;
  XtSetArg (args[xtargc], XtNdisplayCaret, (XtArgVal) False       ); xtargc++;

  return XtCreateManagedWidget (name, asciiTextWidgetClass, form, args, xtargc);
}

/*******************************************************************************************************
 */

void makeEventWindow (toplevel, app_context)
Widget        toplevel;
XtAppContext  app_context;

{
  static XtActionsRec   actions[] = {
    { "infoConfirm"      , infoConfirm     , },
    { "infoCancel"       , infoCancel      , },
    { "highlightText"    , highlightText   , },
    { "unhighlightText"  , unhighlightText , },
  }; 

  Arg    args[10];
  int    xtargc;

  Widget game;
  Widget name, rank, species, white, black;
  Widget event, place, date, round;
  Widget handicap, komi, time, result;
  Widget user, source;
  Widget cancel, confirm;
   
  XtAppAddActions (app_context, actions, XtNumber(actions));

  translations = XtParseTranslationTable 
    ("#override                            \
      <EnterWindow>  : highlightText()   \n\
      <LeaveWindow>  : unhighlightText() \n\
      <Key> Escape   : infoCancel()      \n\
      <Key> Linefeed : infoConfirm()     \n\
      <Key> Return   : infoConfirm()     \n\
      Ctrl <Key> J   : infoConfirm()     \n\
      Ctrl <Key> M   : infoConfirm()");
 
  i_top    = XtCreatePopupShell    ("event"        , transientShellWidgetClass, toplevel , NULL, 0);

  xtargc = 0;
  XtSetArg (args[xtargc], XtNtranslations, (XtArgVal) translations); xtargc++;

  form     = XtCreateManagedWidget ("eventForm"    , formWidgetClass          , i_top      , args, xtargc);

  
  game     = make_label (form, "game"    , "Game"    , NULL   , NULL    , (Dimension) 66 , XtJustifyLeft);

  w_GN     = make_text  (form, "GN"      , game      , NULL   , (Dimension) 200);

  name     = make_label (form, "name"    , "Name"    , game   , game    , (Dimension) 200, XtJustifyCenter);
  rank     = make_label (form, "rank"    , "Rank"    , name   , game    , (Dimension) 80 , XtJustifyCenter);
  species  = make_label (form, "species" , "Species" , rank   , game    , (Dimension) 80 , XtJustifyCenter);

  white    = make_label (form, "white"   , "White"   , NULL   , name    , (Dimension) 66 , XtJustifyLeft);
  black    = make_label (form, "black"   , "Black"   , NULL   , white   , (Dimension) 66 , XtJustifyLeft);

  w_PW     = make_text  (form, "PW"      , white     , name   , 200);
  w_PB     = make_text  (form, "PB"      , black     , w_PW   , 200);
  w_WR     = make_text  (form, "WR"      , w_PW      , rank   , 80 );
  w_BR     = make_text  (form, "BR"      , w_PB      , w_WR   , 80 );
  w_WS     = make_text  (form, "WS"      , w_WR      , species, 80 );
  w_BS     = make_text  (form, "BS"      , w_BR      , w_WS   , 80 );

  event    = make_label (form, "event"   , "Event"   , NULL   , black   , (Dimension) 66 , XtJustifyLeft);
  place    = make_label (form, "place"   , "Place"   , NULL   , event   , (Dimension) 66 , XtJustifyLeft);
  date     = make_label (form, "date"    , "Date"    , NULL   , place   , (Dimension) 66 , XtJustifyLeft);
  round    = make_label (form, "round"   , "Round"   , NULL   , date    , (Dimension) 66 , XtJustifyLeft);

  w_EV     = make_text  (form, "EV"      , event     , black  , (Dimension) 200);
  w_PC     = make_text  (form, "PC"      , place     , w_EV   , (Dimension) 200);
  w_DT     = make_text  (form, "DT"      , date      , w_PC   , (Dimension) 200);
  w_RO     = make_text  (form, "RO"      , round     , w_DT   , (Dimension) 200);

  handicap = make_label (form, "handicap", "Handicap", w_EV   , black   , (Dimension) 66 , XtJustifyLeft);
  komi     = make_label (form, "komi"    , "Komi"    , w_PC   , handicap, (Dimension) 66 , XtJustifyLeft);
  time     = make_label (form, "time"    , "Time"    , w_DT   , komi    , (Dimension) 66 , XtJustifyLeft);
  result   = make_label (form, "result"  , "Result"  , w_RO   , time    , (Dimension) 66 , XtJustifyLeft);

  w_HA     = make_text  (form, "HA"      , handicap  , black  , (Dimension) 80);
  w_KM     = make_text  (form, "KM"      , komi      , w_HA   , (Dimension) 80);
  w_TM     = make_text  (form, "TM"      , time      , w_KM   , (Dimension) 80);
  w_RE     = make_text  (form, "RE"      , result    , w_TM   , (Dimension) 80);

  user     = make_label (form, "user"    , "User"    , NULL   , round   , (Dimension) 66 , XtJustifyLeft);
  source   = make_label (form, "komi"    , "Source"  , NULL   , user    , (Dimension) 66 , XtJustifyLeft);

  w_US     = make_text  (form, "US"      , user      , round  , (Dimension) 200);
  w_SO     = make_text  (form, "SO"      , source    , w_US   , (Dimension) 200);
  
  xtargc = 0;
  XtSetArg (args[xtargc], XtNlabel          , (XtArgVal) CancelLabel ); xtargc++;  
  XtSetArg (args[xtargc], XtNfromVert       , (XtArgVal) round       ); xtargc++;  
  XtSetArg (args[xtargc], XtNfromHoriz      , (XtArgVal) w_US        ); xtargc++;  
  XtSetArg (args[xtargc], XtNwidth          , (XtArgVal) 100         ); xtargc++;  

#ifndef NO_EXTENSION
  XtSetArg (args[xtargc], XtNshapeStyle     , (XtArgVal) XmuShapeOval); xtargc++;  
#endif

  cancel   = XtCreateManagedWidget ("cancel"   , commandWidgetClass  , form   , args, xtargc);
  
  xtargc = 0;
  XtSetArg (args[xtargc], XtNlabel          , (XtArgVal) ConfirmLabel); xtargc++;  
  XtSetArg (args[xtargc], XtNfromVert       , (XtArgVal) cancel      ); xtargc++;  
  XtSetArg (args[xtargc], XtNfromHoriz      , (XtArgVal) w_US        ); xtargc++;  
  XtSetArg (args[xtargc], XtNwidth          , (XtArgVal) 100         ); xtargc++;  

#ifndef NO_EXTENSION
  XtSetArg (args[xtargc], XtNshapeStyle     , (XtArgVal) XmuShapeOval); xtargc++;  
#endif
  
  confirm  = XtCreateManagedWidget ("confirm"  , commandWidgetClass  , form   , args, xtargc);
  
  xtargc = 0;
  XtSetArg (args[xtargc], XtNtranslations   , (XtArgVal) translations); xtargc++;
  XtSetArg (args[xtargc], XtNfromVert       , (XtArgVal) source      ); xtargc++;  
  XtSetArg (args[xtargc], XtNwidth          , (XtArgVal) 444         ); xtargc++;  
  XtSetArg (args[xtargc], XtNheight         , (XtArgVal) 150         ); xtargc++;  
  XtSetArg (args[xtargc], XtNscrollVertical , (XtArgVal) XawtextScrollAlways); xtargc++;  
  XtSetArg (args[xtargc], XtNeditType       , (XtArgVal) XawtextEdit ); xtargc++;  
  XtSetArg (args[xtargc], XtNdisplayCaret   , (XtArgVal) False       ); xtargc++;

  w_GC = XtCreateManagedWidget ("GC" , asciiTextWidgetClass     , form     , args, xtargc);

  xtargc = 0;
  XtSetArg (args[xtargc], XtNvertDistance , (XtArgVal) 16); xtargc++;

  XtSetValues (event     , args, xtargc);
  XtSetValues (w_EV      , args, xtargc);
  XtSetValues (w_HA      , args, xtargc);
  XtSetValues (user      , args, xtargc);
  XtSetValues (w_US      , args, xtargc);
  XtSetValues (cancel    , args, xtargc);
  XtSetValues (w_GC      , args, xtargc);
  XtSetValues (handicap  , args, xtargc);

  xtargc = 0;
  XtSetArg (args[xtargc], XtNvertDistance , (XtArgVal) 8 ); xtargc++;

  XtSetValues (w_GN      , args, xtargc);
  XtSetValues (game      , args, xtargc);

  xtargc = 0;
  XtSetArg (args[xtargc], XtNhorizDistance, (XtArgVal) 18); xtargc++;

  XtSetValues (handicap  , args, xtargc);
  XtSetValues (komi      , args, xtargc);
  XtSetValues (time      , args, xtargc);
  XtSetValues (result    , args, xtargc);

  xtargc = 0;
  XtSetArg (args[xtargc], XtNhorizDistance, (XtArgVal) 37); xtargc++;

  XtSetValues (confirm   , args, xtargc);
  XtSetValues (cancel    , args, xtargc);

  XtAddCallback (confirm, XtNcallback, infoConfirm, NULL);
  XtAddCallback (cancel , XtNcallback, infoCancel , NULL);
}
