/*
 * @(#)SkewbP.h
 *
 * Copyright 1994 - 2010  David A. Bagley, bagleyd AT verizon.net
 *
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of the author not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * 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.
 */

/* Private header file for Skewb */

#ifndef _SkewbP_h
#define _SkewbP_h

#include "xwin.h"
#include "timer.h"
#include "Skewb.h"

#ifdef WINVER
extern void destroyPuzzle(HBRUSH brush);
extern void resizePuzzle(SkewbWidget w);
extern void sizePuzzle(SkewbWidget w);
extern void initializePuzzle(SkewbWidget w, HBRUSH brush);
extern void exposePuzzle(SkewbWidget w);
extern void dimPuzzle(SkewbWidget w);
extern int  movePuzzleDir(SkewbWidget w, const int direction);
extern void setPuzzle(SkewbWidget w, int reason);
extern void setPuzzleMove(SkewbWidget w, int reason, int face, int position,
	int direction, int control, int fast);

#else

/* This gets around C's inability to do inheritance */
typedef struct _SkewbClassPart {
	int         ignore;
} SkewbClassPart;

typedef struct _SkewbClassRec {
	CoreClassPart coreClass;
	SkewbClassPart skewbClass;
} SkewbClassRec;

extern SkewbClassRec skewbClassRec;

extern void quitPuzzle(SkewbWidget w, XEvent *event, char **args, int nArgs);
extern void movePuzzleCw(SkewbWidget w, XEvent *event, char **args, int nArgs);
extern void movePuzzleCcw(SkewbWidget w, XEvent *event, char **args,
	int nArgs);
#endif

#ifndef MOVESOUND
#define MOVESOUND "move"
#endif

#define SYMBOL ':'

#define TR 0
#define BR 1
#define BL 2
#define TL 3
#define STRT 4
#define CW 5
#define HALF 6
#define CCW 7
#define TOP 8
#define RIGHT 9
#define BOTTOM 10
#define LEFT 11
#define MAX_ORIENT 4
#define MAX_ROTATE 3
#define MAX_CUBES (MAX_ORIENT+1)
#define MINOR 0
#define MAJOR 1

#define NORMAL 1
#define DOUBLE 2
#define INSTANT 3

typedef struct _SkewbLocPos {
	int         face, position, direction;
} SkewbLocPos;

typedef struct _moveRecord {
#if 0
	int face, position, direction, control;
#endif
	unsigned short int packed;  /* This makes assumptions on the data. */
} moveRecord;

typedef struct _MoveStack {
	moveRecord move;
	struct _MoveStack *previous, *next;
} MoveStack;

typedef struct _SkewbStack {
	MoveStack *currMove, *lastMove, *firstMove;
	int count;
} SkewbStack;

typedef struct _SkewbLoc {
	int face, rotation;
} SkewbLoc;

typedef struct _SkewbPart {
	SkewbLoc    cubeLoc[MAX_FACES][MAX_CUBES];
	SkewbLoc    faceLoc[MAX_CUBES];
	SkewbLoc    rowLoc[MAX_ORIENT][MAX_CUBES];
	SkewbLoc    minorLoc[MAX_ORIENT], majorLoc[MAX_ORIENT][MAX_ORIENT];
	SkewbLoc    skewbLoc[MAX_FACES][MAX_CUBES];
	int         currentFace, currentPosition, currentDirection, currentFast;
	int         currentControl;
	Boolean     started, cheat, sound;
	Boolean     practice, orient, vertical, mono, reverse, focus;
	Boolean     scoreOnly, versionOnly;
	int         dim; /* This allows us to reuse code between 2d and 3d */
	int         degreeTurn, view;
	int         delay;
	Position    delta;
	Position    orientLineLength;
	Point       puzzleSize;
	Point       puzzleOffset, letterOffset;
	GC          frameGC, borderGC, inverseGC;
	GC          faceGC[MAX_FACES];
#ifdef WINVER
	char        userName[81], scoreFile[81], moveSound[81];
	char        faceChar[MAX_FACES];
#else
	int         menu, pixmapSize;
	char       *userName, *scoreFile, *moveSound, *font;
	XFontStruct *fontInfo;
	char       *faceName[MAX_FACES];
	Pixel       foreground, background;
	Pixel       frameColor, borderColor;
	Pixel       faceColor[MAX_FACES];
	XtCallbackList select;
#endif
} SkewbPart;

typedef struct _SkewbRec {
	CorePart    core;
	SkewbPart   skewb;
} SkewbRec;

typedef struct _RowNext {
	int         face, direction, sideFace;
} RowNext;

extern void hidePuzzle(
#ifdef WINVER
const SkewbWidget w
#else
SkewbWidget w, XEvent *event, char **args, int nArgs
#endif
);
extern void selectPuzzle(SkewbWidget w
#ifdef WINVER
, const int x, const int y, const int control, const int alt
#else
, XEvent *event, char **args, int nArgs
#endif
);
extern void releasePuzzle(SkewbWidget w
#ifdef WINVER
, const int x, const int y, const int control, const int alt
#else
, XEvent *event, char **args, int nArgs
#endif
);
#ifndef WINVER
extern void practicePuzzleWithQuery(SkewbWidget w
, XEvent *event, char **args, int nArgs
);
extern void practicePuzzleWithDoubleClick(SkewbWidget w
, XEvent *event, char **args, int nArgs
);
extern void randomizePuzzleWithQuery(SkewbWidget w
, XEvent *event, char **args, int nArgs
);
extern void randomizePuzzleWithDoubleClick(SkewbWidget w
, XEvent *event, char **args, int nArgs
);
#endif
extern void readPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void writePuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void undoPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void redoPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void clearPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void randomizePuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void solvePuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void practicePuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void orientizePuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void viewPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void speedUpPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void slowDownPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void toggleSoundPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void enterPuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void leavePuzzle(SkewbWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);

extern void movePuzzleInput(SkewbWidget w, int x, int y, int direction,
	int control, int alt);
extern void setPuzzle(SkewbWidget w, int reason);
extern void movePuzzle(SkewbWidget w, int face, int position, int direction,
	int control, int speed);
extern void movePuzzleDelay(SkewbWidget w,
	int face, int position, int direction, int control);
extern void setAllColors(SkewbWidget w);
extern void solveSomePieces(SkewbWidget w);
extern void drawAllPieces(SkewbWidget w);
extern Boolean checkSolved(SkewbWidget w);
extern void newMoves(SkewbStack *s);
extern void deleteMoves(SkewbStack *s);
extern void setMove(SkewbStack *s,
	int face, int position, int direction, int control);
extern void getMove(SkewbStack *s,
	int *face, int *position, int *direction, int *control);
extern int madeMoves(SkewbStack *s);
extern void flushMoves(SkewbWidget w, SkewbStack *s, Boolean undo);
extern int numMoves(SkewbStack *s);
extern void scanMoves(FILE *fp, SkewbWidget w, int moves);
extern void printMoves(FILE *fp, SkewbStack *s);
extern void scanStartPosition(FILE *fp, SkewbWidget w);
extern void printStartPosition(FILE *fp, SkewbWidget w);
extern void setStartPosition(SkewbWidget w);

#ifdef DEBUG
extern void printCube(SkewbWidget w);

#endif

#endif /* _SkewbP_h */
