/*
 * @(#)OctP.h
 *
 * Copyright 1994 - 2023  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 Oct */

#ifndef _OctP_h
#define _OctP_h

#include "xwin.h"
#include "timer.h"
#include "Oct.h"

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

#else

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

typedef struct _OctClassRec {
	CoreClassPart coreClass;
	OctClassPart octClass;
} OctClassRec;

extern OctClassRec octClassRec;
extern void quitPuzzle(OctWidget w, XEvent *event, char **args, int nArgs);
extern void movePuzzleCw(OctWidget w, XEvent *event, char **args, int nArgs);
extern void movePuzzleCcw(OctWidget w, XEvent *event, char **args,
	int nArgs);
#endif
extern void hidePuzzle(
#ifdef WINVER
const OctWidget w
#else
OctWidget w, XEvent *event, char **args, int nArgs
#endif
);
extern void selectPuzzle(OctWidget w
#ifdef WINVER
, const int x, const int y, const int control
#else
, XEvent *event, char **args, int nArgs
#endif
);
extern void releasePuzzle(OctWidget 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(OctWidget w
, XEvent *event, char **args, int nArgs
);
extern void practicePuzzleWithDoubleClick(OctWidget w
, XEvent *event, char **args, int nArgs
);
extern void randomizePuzzleWithQuery(OctWidget w
, XEvent *event, char **args, int nArgs
);
extern void randomizePuzzleWithDoubleClick(OctWidget w
, XEvent *event, char **args, int nArgs
);
#endif
extern void getPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void writePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void undoPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void redoPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void clearPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void randomizePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void solvePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void findPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void practicePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void incrementPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern
#ifdef WINVER
Boolean
#else
void
#endif
decrementPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void orientizePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void stickyModePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void period3ModePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void period4ModePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void bothModePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void viewPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void speedUpPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void slowDownPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void toggleSoundPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void enterPuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void leavePuzzle(OctWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);

#ifndef MOVESOUND
#define MOVESOUND "move"
#endif

#define SYMBOL ':'

#define TOP 0
#define TR 1
#define RIGHT 2
#define BR 3
#define BOTTOM 4
#define BL 5
#define LEFT 6
#define TL 7
#define COORD 8
#define CW 9
#define CCW 15

#define SAME 0
#define OPPOSITE 1
#define DOWN 0
#define UP 1
#define MAX_VIEWS 2
#define MAX_SIDES (MAX_FACES/MAX_VIEWS)
#define MAX_ORIENT (3*MAX_SIDES)
#define NORMAL 1
#define DOUBLE 2
#define INSTANT 3

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

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

typedef struct _OctStack {
	MoveStack *currMove, *lastMove, *firstMove;
	int count;
} OctStack;

typedef struct _OctLoc {
	int face, rotation;
} OctLoc;

typedef struct _RTT {
	int row, trbl, tlbr;
} RTT;

typedef struct _OctPart {
	OctLoc     *facetLoc[MAX_FACES];
	OctLoc     *faceLoc;
	OctLoc     *rowLoc[MAX_ORIENT / 2];
	int	    currentFace, currentPosition, currentDirection;
	int	    currentStyle, currentFast, currentControl;
	Boolean     started, cheat, sound;
	Boolean     practice, orient, vertical, mono, reverse, sticky, focus;
	Boolean     scoreOnly, versionOnly;
	int	    dim; /* This allows us to reuse code between 2d and 3d */
	int	    degreeTurn, view;
	int	    size, sizeSize, mode;
	int	    delay;
	Position    delta;
	Position    facetLength;
	Position    faceLength;
	Position    viewLength, viewMiddle;
	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
} OctPart;

typedef struct _OctRec {
	CorePart    core;
	OctPart     oct;
} OctRec;

extern OctLoc *startLoc[MAX_FACES];

extern void movePuzzleInput(OctWidget w, int x, int y, int direction,
	int shift, int control);
extern void setPuzzle(OctWidget w, int reason);
extern void movePuzzle(OctWidget w, int face, int position,
	int direction, int style, int control, int fast);
extern void movePuzzleDelay(OctWidget w, int face, int position,
	int direction, int style, int control);
extern void setAllColors(OctWidget w);
extern void resetPieces(OctWidget w);
extern void clearPieces(OctWidget w);
extern void solveSomePieces(OctWidget w);
extern void findSomeMoves(OctWidget w);
extern void drawAllPieces(OctWidget w);
extern Boolean checkSolved(OctWidget w);
extern void newMoves(OctStack *s);
extern void deleteMoves(OctStack *s);
extern void setMove(OctStack *s,
	int direction, int style, int control, int face, int position);
extern void getMove(OctStack *s,
	int *direction, int *style, int *control, int *face, int *position);
extern int madeMoves(OctStack *s);
extern void flushMoves(OctWidget w, OctStack *s, Boolean undo);
extern int numMoves(OctStack *s);
extern Boolean scanMoves(FILE *fp, OctWidget w, int moves);
extern void printMoves(FILE *fp, OctStack *s);
extern Boolean scanStartPosition(FILE *fp, OctWidget w);
extern void printStartPosition(FILE *fp, OctWidget w);
extern void setStartPosition(OctWidget w);
extern int SQRT(int i);
extern void toRTT(int position, RTT * rtt);
extern int toPosition(RTT rtt);

#endif /* _OctP_h */
