/*
 * @(#)MballP.h
 *
 * Copyright 1994 - 2024  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 Mball */

#ifndef _MballP_h
#define _MballP_h

#include "xwin.h"
#include "timer.h"
#include "Mball.h"

#ifdef WINVER
extern void destroyPuzzle(HBRUSH brush);
extern void resizePuzzle(MballWidget w);
extern void sizePuzzle(MballWidget w);
extern void initializePuzzle(MballWidget w, HBRUSH brush);
extern void exposePuzzle(MballWidget w);
extern void hidePuzzle(MballWidget w);
extern void selectPuzzle(MballWidget w,
	const int x, const int y, const int control);
extern void releasePuzzle(MballWidget w,
	const int x, const int y, const int shift, const int control);
extern void practicePuzzle(MballWidget w);
extern void randomizePuzzle(MballWidget w);
extern void getPuzzle(MballWidget w);
extern void writePuzzle(MballWidget w);
extern void undoPuzzle(MballWidget w);
extern void redoPuzzle(MballWidget w);
extern void clearPuzzle(MballWidget w);
extern void solvePuzzle(MballWidget w);
extern void incrementPuzzle(MballWidget w);
extern Boolean decrementPuzzle(MballWidget w);
extern void wedgePuzzle(MballWidget w, const int mode);
extern void wedge2ModePuzzle(MballWidget w);
extern void wedge4ModePuzzle(MballWidget w);
extern void wedge6ModePuzzle(MballWidget w);
extern void wedge8ModePuzzle(MballWidget w);
extern void wedge10ModePuzzle(MballWidget w);
extern void wedge12ModePuzzle(MballWidget w);
extern void orientizePuzzle(MballWidget w);
extern void middlePuzzle(MballWidget w);
extern void speedUpPuzzle(MballWidget w);
extern void slowDownPuzzle(MballWidget w);
extern void toggleSoundPuzzle(MballWidget w);
extern void perspectivePuzzle(MballWidget w);
extern void enterPuzzle(MballWidget w);
extern void leavePuzzle(MballWidget w);
extern void dimPuzzle(MballWidget w);
extern int  movePuzzleDir(MballWidget w, const int direction);
extern void setPuzzleMove(MballWidget w, int reason, int wedges, int bands,
	int direction, Boolean control, int fast);

#else

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

typedef struct _MballClassRec {
	CoreClassPart coreClass;
	MballClassPart mballClass;
} MballClassRec;

extern MballClassRec mballClassRec;
extern void quitPuzzle(MballWidget w, XEvent *event, char **args, int nArgs);
extern void movePuzzleCw(MballWidget w, XEvent *event, char **args, int nArgs);
extern void movePuzzleCcw(MballWidget w, XEvent *event, char **args, int nArgs);
#endif
extern void hidePuzzle(
#ifdef WINVER
const MballWidget w
#else
MballWidget w, XEvent *event, char **args, int nArgs
#endif
);
extern void selectPuzzle(MballWidget w
#ifdef WINVER
, const int x, const int y, const int control
#else
, XEvent *event, char **args, int nArgs
#endif
);
extern void releasePuzzle(MballWidget 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(MballWidget w
, XEvent *event, char **args, int nArgs
);
extern void practicePuzzleWithDoubleClick(MballWidget w
, XEvent *event, char **args, int nArgs
);
extern void randomizePuzzleWithQuery(MballWidget w
, XEvent *event, char **args, int nArgs
);
extern void randomizePuzzleWithDoubleClick(MballWidget w
, XEvent *event, char **args, int nArgs
);
#endif
extern void getPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void writePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void undoPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void redoPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void clearPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void randomizePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void solvePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void practicePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void incrementPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern
#ifdef WINVER
Boolean
#else
void
#endif
decrementPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void orientizePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void wedge2ModePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void wedge4ModePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void wedge6ModePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void wedge8ModePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void wedge10ModePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void wedge12ModePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void viewPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void speedUpPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void slowDownPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void toggleSoundPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void perspectivePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void enterPuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);
extern void leavePuzzle(MballWidget w
#ifndef WINVER
, XEvent *event, char **args, int nArgs
#endif
);

#ifndef MOVESOUND
#define MOVESOUND "move"
#endif

#define SYMBOL ':'

#define IGNORE_DIR (-1)
#define TOP 0
#define TTR 1
#define TR 2
#define RIGHT 3
#define BR 4
#define BBR 5
#define BOTTOM 6
#define BBL 7
#define BL 8
#define LEFT 9
#define TL 10
#define TTL 11
#define COORD 12
#define CW 13
#define CCW 23
#define CUTS (COORD / 2)
#define SAME 0
#define OPPOSITE 1
#define DOWN 0
#define UP 1
#define MAX_VIEWS 2
#define NORMAL 1
#define DOUBLE 2
#define INSTANT 3

#define ST_ANG  (NUM_DEGREES/2)
#define RT_ANG  (NUM_DEGREES/4)
#define DEGREES(x) ((x)/M_PI*ST_ANG)
#define RADIANS(x) (M_PI*(x)/ST_ANG)
#define CIRCLE_2  (FULL_CIRCLE/2)
#define CIRCLE_4  (FULL_CIRCLE/4)

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

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

typedef struct _MballStack {
	MoveStack *currMove, *lastMove, *firstMove;
	int count;
} MballStack;

typedef struct _MballLoc {
	int wedge, direction;
} MballLoc;

typedef struct _MballPart {
	MballLoc   *mballLoc[MAX_WEDGES];
	int         currentSector;
	int         currentWedge, currentBand, currentDirection;
	int         currentFast, currentControl;
	Boolean     started, cheat, sound, perspective;
	Boolean     practice, orient, vertical, mono, reverse, focus;
	Boolean     scoreOnly, versionOnly;
	int         dim; /* This allows us to reuse code between 2d and 3d */
	int         view;
	int         base;
	int         wedges, bands;
	int         delay;
	Position    delta, dr;
	Position    mballLength;
	Position    wedgeLength;
	Position    viewLength, viewMiddle;
	Point       puzzleSize;
	Point       puzzleOffset, letterOffset;
	GC          frameGC, borderGC, inverseGC;
	GC          wedgeGC[MAX_WEDGES];
#ifdef WINVER
	char        userName[81], scoreFile[81], moveSound[81];
	char        wedgeChar[MAX_WEDGES];
#else
	int         menu, pixmapSize;
	char       *userName, *scoreFile, *moveSound, *font;
	XFontStruct *fontInfo;
	char       *wedgeName[MAX_WEDGES];
	Pixel       foreground, background;
	Pixel       frameColor, borderColor;
	Pixel       wedgeColor[MAX_WEDGES];
	XtCallbackList select;
#endif
} MballPart;

typedef struct _MballRec {
	CorePart    core;
	MballPart   mball;
} MballRec;

extern MballLoc *startLoc[MAX_WEDGES];
extern void movePuzzleInput(MballWidget w,
	int x, int direction, int shift, int control);
extern void setPuzzle(MballWidget w, int reason);
extern void movePuzzle(MballWidget w, int wedge, int band,
	int direction, int control, int fast);
extern void movePuzzleDelay(MballWidget w, int wedge, int band,
	int direction, int control);
extern void setAllColors(MballWidget w);
extern void resetPieces(MballWidget w);
extern void clearPieces(MballWidget w);
extern void solveSomePieces(MballWidget w);
extern void drawAllWedges(MballWidget w);
extern Boolean checkSolved(MballWidget w);
extern void newMoves(MballStack *s);
extern void deleteMoves(MballStack *s);
extern void setMove(MballStack *s,
	int direction, int control, int sector);
extern void getMove(MballStack *s,
	int *direction, int *control, int *sector);
extern int madeMoves(MballStack *s);
extern void flushMoves(MballWidget w, MballStack *s, Boolean undo);
extern int numMoves(MballStack *s);
extern Boolean scanMoves(FILE *fp, MballWidget w, int moves);
extern void printMoves(FILE *fp, MballStack *s);
extern Boolean scanStartPosition(FILE *fp, MballWidget w);
extern void printStartPosition(FILE *fp, MballWidget w);
extern void setStartPosition(MballWidget w);

extern int mapWedgeToDir[(MAX_WEDGES - MIN_WEDGES) / 2 + 1][MAX_WEDGES];
#endif /* _MballP_h */
