/*
 * @(#)MlinkP.h
 *
 * Copyright 1994 - 2020  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 Mlink */

#ifndef _MlinkP_h
#define _MlinkP_h

#include "xwin.h"
#include "timer.h"
#include "Mlink.h"

#ifdef WINVER
extern void destroyPuzzle(MlinkWidget w, HBRUSH brush);
extern void resizePuzzle(MlinkWidget w);
extern void sizePuzzle(MlinkWidget w);
extern void initializePuzzle(MlinkWidget w, HBRUSH brush);
extern void exposePuzzle(MlinkWidget w);
extern void hidePuzzle(MlinkWidget w);
extern void selectPuzzle(MlinkWidget w,
	const int x, const int y, const int shift);
extern void motionPuzzle(MlinkWidget w,
	const int x, const int y, const int shift);
extern void releasePuzzle(MlinkWidget w,
	const int x, const int y, const int shift);
extern void practicePuzzle(MlinkWidget w);
extern void randomizePuzzle(MlinkWidget w);
extern void getPuzzle(MlinkWidget w);
extern void writePuzzle(MlinkWidget w);
extern void undoPuzzle(MlinkWidget w);
extern void redoPuzzle(MlinkWidget w);
extern void clearPuzzle(MlinkWidget w);
extern void solvePuzzle(MlinkWidget w);
extern void orientizePuzzle(MlinkWidget w);
extern void middlePuzzle(MlinkWidget w);
extern void speedUpPuzzle(MlinkWidget w);
extern void slowDownPuzzle(MlinkWidget w);
extern void toggleSoundPuzzle(MlinkWidget w);
extern void enterPuzzle(MlinkWidget w);
extern void leavePuzzle(MlinkWidget w);
extern void movePuzzleInput(MlinkWidget w,
	int x, int direction, int shift, int control);
extern int  movePuzzleDir(MlinkWidget w, const int direction);

#else

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

typedef struct _MlinkClassRec {
	CoreClassPart coreClass;
	MlinkClassPart mlinkClass;
} MlinkClassRec;

extern MlinkClassRec mlinkClassRec;
#endif

#ifndef BUMPSOUND
#define BUMPSOUND "bump"
#endif
#ifndef MOVESOUND
#define MOVESOUND "move"
#endif

#define SYMBOL ':'

#define TOP 0
#define RIGHT 1
#define BOTTOM 2
#define LEFT 3
#define COORD 4
#define FG_SHADES 3
#define MAX_SLICES 10

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

typedef struct _MoveRecord {
#if 0
	int direction, control;
#endif
	unsigned char packed;	/* This makes assumptions on the data. */
	int tile;		/* Do not make assumptions on this one. */
} MoveRecord;

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

typedef struct _MlinkStack {
	MoveStack *currMove, *lastMove, *firstMove;
	int count;
} MlinkStack;

typedef struct _MlinkPart {
	int        *tileOfPosition, spacePosition;
	int         currentTile, currentFace, currentRef;
	Boolean     started, cheat, sound, motion;
	Boolean     practice, orient, mono, reverse, middle, focus;
	Boolean     scoreOnly, versionOnly;
	int         delay, numSlices, motionDiff, shiftDiff;
	int         base;
	int         tiles, faces, tileFaces;
	Point       offset, tileSize, faceSize, puzzleSize;
	Point       delta, puzzleOffset, digitOffset;
	GC          frameGC, borderGC, inverseGC;
	GC          tileGC[FG_SHADES];
	GC          faceGC[MAX_FACES];
	Pixmap      bufferTiles[2];
	TimeVal     oldTime;
#ifdef WINVER
	char        userName[81], scoreFile[81], bumpSound[81], moveSound[81];
	char        picture[81];
	char        faceChar[MAX_FACES];
#else
	int         menu, graphicsFormat, pixmapSize;
	char       *userName, *scoreFile, *bumpSound, *moveSound;
	char       *picture, *font;
	Boolean     install;
	Colormap    colormap, oldColormap;
	XImage     *image;
	XFontStruct *fontInfo;
	char       *faceName[MAX_FACES];
	Pixel       foreground, background;
	Pixel       frameColor, tileColor, borderColor;
	Pixel       faceColor[MAX_FACES];
	XtCallbackList select;
#endif
} MlinkPart;

typedef struct _MlinkRec {
	CorePart    core;
	MlinkPart   mlink;
} MlinkRec;

extern int *startPosition;
extern void setPuzzle(MlinkWidget w, int reason);
extern Boolean movePuzzle(MlinkWidget w,
	const int direction, const int tile, const int shift,
	const Boolean motion, const int fast);
extern void movePuzzleDelay(MlinkWidget w,
	const int direction, const int tile, const Boolean all);

extern void solveSomeTiles(MlinkWidget w);
extern void drawAllTiles(const MlinkWidget w);
extern Boolean checkSolved(const MlinkWidget w);
extern void newMoves(MlinkStack *s);
extern void deleteMoves(MlinkStack *s);
extern void setMove(MlinkStack *s, int direction, int tile, int control);
extern void getMove(MlinkStack *s, int *direction, int *tile, int *control);
extern int madeMoves(MlinkStack *s);
extern void flushMoves(MlinkWidget w, MlinkStack *s, Boolean undo);
extern int numMoves(MlinkStack *s);
extern Boolean scanMoves(FILE *fp, MlinkWidget w, int moves);
extern void printMoves(FILE *fp, MlinkStack *s);
extern Boolean scanStartPosition(FILE *fp, MlinkWidget w);
extern void printStartPosition(FILE *fp, MlinkWidget w);
extern void setStartPosition(MlinkWidget w);

#endif /* _MlinkP_h */
