#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include "TableP.h"

#define offset(field) XtOffset(AtTableObject, field)
static XtResource resources[] = {
{XtNnumRows, XtCNumRows, XtRShort,
     sizeof(short), offset(table.numRows), XtRImmediate, 0},
{XtNnumColumns, XtCNumColumns, XtRShort,
     sizeof(short), offset(table.numColumns), XtRImmediate, 0},
{XtNvalueChangedCallback, XtCCallback, XtRCallback,
     sizeof(XtCallbackList), offset(table.valueChangedCallback),
     XtRImmediate, NULL},
{XtNsizeChangedCallback, XtCCallback, XtRCallback,
     sizeof(XtCallbackList), offset(table.sizeChangedCallback),
     XtRImmediate, NULL},
};
#undef offset

static void ClassPartInitialize(WidgetClass);
static void Initialize(AtTableObject, AtTableObject);
static void Destroy(AtTableObject);
static char *GetCellValue(AtTableObject, int, int);
static void SetCellValue(AtTableObject, int, int , char *);
static char *GetRowName(AtTableObject, int);
static char *GetColName(AtTableObject, int);

AtTableClassRec atTableClassRec = {
{ /* core part */
    /* superclass         */    (WidgetClass) &objectClassRec,
    /* class_name         */    "AtTable",
    /* widget_size        */    sizeof(AtTableRec),
    /* class_initialize   */    NULL,
    /* class_part_initialize*/  ClassPartInitialize,
    /* class_inited       */    FALSE,
    /* initialize         */    (XtInitProc) Initialize,
    /* initialize_hook    */    NULL,
    /* pad                */    NULL,
    /* pad                */    NULL,
    /* pad                */    0,
    /* resources          */    resources,
    /* num_resources      */    XtNumber(resources),
    /* xrm_class          */    NULLQUARK,
    /* pad                */    FALSE,
    /* pad                */    FALSE,
    /* pad                */    FALSE,
    /* pad                */    FALSE,
    /* destroy            */    (XtWidgetProc)Destroy,
    /* pad                */    NULL,
    /* pad                */    NULL,
    /* set_values         */    (XtSetValuesFunc)NULL,
    /* set_values_hook    */    NULL,
    /* pad                */    NULL,
    /* get_values_hook    */    NULL,
    /* pad                */    NULL,
    /* version            */    XtVersion,
    /* callback_offsets   */    NULL,
    /* pad                */    NULL,
    /* pad                */    NULL,
    /* pad                */    NULL,
    /* extension            */  NULL
},
/* AtTableClassPart initialization */
{
    /* GetCellValue()     */    GetCellValue,
    /* SetCellValue()     */    SetCellValue,
    /* GetRowName()       */    GetRowName,
    /* GetColumnName()    */    GetColName,
}
};

WidgetClass atTableObjectClass = (WidgetClass)&atTableClassRec;

static void ClassPartInitialize(WidgetClass class)
{
    AtTableObjectClass table, super;

    table = (AtTableObjectClass) class;
    super = (AtTableObjectClass) table->object_class.superclass;

#define CheckInherit(proc) \
    if ((XtProc)table->table_class.proc == (XtProc)_XtInherit)\
        table->table_class.proc = super->table_class.proc

    CheckInherit(GetCellValue);
    CheckInherit(SetCellValue);
    CheckInherit(GetRowName);
    CheckInherit(GetColumnName);

#undef CheckInherit
}

				    

static void Initialize(AtTableObject req, AtTableObject new)
{
  new->table.data = (char **)XtCalloc(new->table.numRows * 
				      new->table.numColumns,
				      sizeof(char *));
}

static void Destroy(AtTableObject w)
{
  int i;

  for(i=0; i < w->table.numRows * w->table.numColumns; i++) 
    XtFree(w->table.data[i]);
  XtFree(w->table.data);
}

static char *GetCellValue(AtTableObject w, int x, int y)
{
    return w->table.data[y*w->table.numColumns + x];
}

static void SetCellValue(AtTableObject w, int x, int y, char *val)
{
    XtFree(w->table.data[y*w->table.numColumns + x]);
    w->table.data[y*w->table.numColumns+x] = XtNewString(val);
}

static char namebuf[25];

static char *GetRowName(AtTableObject w, int i)
{
    sprintf(namebuf, "Row@-(%d)", i);
    return namebuf;
}

static char *GetColName(AtTableObject w, int col)
{
  int i,j,k;
  char buf[2];

  i = (col - 26) / (26 * 26);
  if (i)
    col = (col - 26) % (26 * 26);

  j = col / 26;
  k = col % 26;

  strcpy(namebuf, "Col@-(");
  if (i)
    {
      sprintf(buf, "%c%c", (char)('A' + i - 1), (char)('A' + j));
      strcat(namebuf, buf);
    }
  else if (j)
    {
      sprintf(buf, "%c", (char)('A' + j - 1));
      strcat(namebuf, buf);
    }
  sprintf(buf, "%c)", (char)('A' + k));
  strcat(namebuf, buf);
  return namebuf;
}



char *AtTableGetCellValue(AtTableObject t, int x, int y)
{
    return (*((AtTableObjectClass)t->object.widget_class)->table_class.GetCellValue)(t, x, y);
}

void AtTableSetCellValue(AtTableObject t, int x, int y, char *value)
{
    (*((AtTableObjectClass)t->object.widget_class)->table_class.SetCellValue)(t, x, y, value);
}

char *AtTableGetRowName(AtTableObject t, int x)
{
    return (*((AtTableObjectClass)t->object.widget_class)->table_class.GetRowName)(t, x);
}

char *AtTableGetColumnName(AtTableObject t, int x)
{
    return (*((AtTableObjectClass)t->object.widget_class)->table_class.GetColumnName)(t, x);
}

void AtTableGetSize(AtTableObject t, int *x, int *y)
{
    Arg a[2];
    short width, height;
    XtSetArg(a[0], XtNnumColumns, &width);
    XtSetArg(a[1], XtNnumRows, &height);
    XtGetValues(t, a, 2);
    *x = width;
    *y = height;
}
