90
90
static void ExposeMlink(Widget renew, XEvent * event, Region region);
91
91
static void HideMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
92
92
static void SelectMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
93
static void ReleaseMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
94
static void PracticeMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
95
static void PracticeMlinkMaybe(MlinkWidget w, XEvent * event, char **args, int nArgs);
96
static void PracticeMlink2(MlinkWidget w, XEvent * event, char **args, int nArgs);
97
static void RandomizeMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
98
static void RandomizeMlinkMaybe(MlinkWidget w, XEvent * event, char **args, int nArgs);
99
static void RandomizeMlink2(MlinkWidget w, XEvent * event, char **args, int nArgs);
93
static void MotionMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
94
static void ReleaseMlink(MlinkWidget w, XEvent * event,
95
char **args, int nArgs);
96
static void PracticeMlink(MlinkWidget w, XEvent * event,
97
char **args, int nArgs);
98
static void PracticeMlinkMaybe(MlinkWidget w, XEvent * event,
99
char **args, int nArgs);
100
static void PracticeMlink2(MlinkWidget w, XEvent * event,
101
char **args, int nArgs);
102
static void RandomizeMlink(MlinkWidget w, XEvent * event,
103
char **args, int nArgs);
104
static void RandomizeMlinkMaybe(MlinkWidget w, XEvent * event,
105
char **args, int nArgs);
106
static void RandomizeMlink2(MlinkWidget w, XEvent * event,
107
char **args, int nArgs);
100
108
static void GetMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
101
109
static void WriteMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
102
110
static void ClearMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
103
111
static void UndoMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
104
112
static void SolveMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
105
static void OrientizeMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
113
static void OrientizeMlink(MlinkWidget w, XEvent * event,
114
char **args, int nArgs);
106
115
static void MiddleMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
107
116
static void SpeedMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
108
117
static void SlowMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
109
118
static void SoundMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
110
119
static void EnterMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
111
120
static void LeaveMlink(MlinkWidget w, XEvent * event, char **args, int nArgs);
112
static void MoveMlinkTop(MlinkWidget w, XEvent * event, char **args, int nArgs);
113
static void MoveMlinkLeft(MlinkWidget w, XEvent * event, char **args, int nArgs);
114
static void MoveMlinkRight(MlinkWidget w, XEvent * event, char **args, int nArgs);
115
static void MoveMlinkBottom(MlinkWidget w, XEvent * event, char **args, int nArgs);
121
static void MoveMlinkTop(MlinkWidget w, XEvent * event,
122
char **args, int nArgs);
123
static void MoveMlinkBottom(MlinkWidget w, XEvent * event,
124
char **args, int nArgs);
125
static void MoveMlinkLeft(MlinkWidget w, XEvent * event,
126
char **args, int nArgs);
127
static void MoveMlinkRight(MlinkWidget w, XEvent * event,
128
char **args, int nArgs);
117
130
static char defaultTranslationsMlink[] =
118
131
"<KeyPress>q: Quit()\n\
833
851
for (i = 0; i < THICKNESS; i++) {
834
852
sizex = w->mlink.offset.x * 3 / 2 - i;
835
853
sizey = w->mlink.offset.y * 3 / 4 - i;
836
Cartesian(w, pos, &dx, &dy);
837
dx += -sizex / 2 + offsetX;
838
dy += w->mlink.tileSize.y / 2 - sizey / 2 + offsetY;
839
if (tile % w->mlink.tiles == 0 || tile == w->mlink.tileFaces - 1) }
854
dx = CartesianX(w, pos) - sizex / 2 + offsetX;
855
dy = CartesianY(w, pos) + w->mlink.tileSize.y / 2 - sizey / 2 +
857
if (tile % w->mlink.tiles == 0 ||
858
tile == w->mlink.tileFaces - 1) {
840
859
DRAWARC(w, dr, gc, 1, gc, dx, dy,
841
860
sizex, sizey, 89 * MULT, -179 * MULT);
842
861
} else if (tile % w->mlink.tiles == 1) {
843
DRAWARC(w, dr, gc, 1, gc, dx + w->mlink.tileSize.x - 1, dy,
844
sizex, sizey, 90 * MULT, 180 * MULT);
862
DRAWARC(w, dr, gc, 1, gc,
863
dx + w->mlink.tileSize.x - 1, dy,
864
sizex, sizey, 90 * MULT, 180 * MULT);
846
866
DRAWARC(w, dr, gc, 1, gc, dx, dy,
847
867
sizex, sizey, 89 * MULT, -32 * MULT);
1057
1078
if (aTile < numTiles - 1) {
1060
FILLRECTANGLE(w, dr,
1062
ix - gapI, iy, gapI, w->mlink.tileSize.y);
1065
FILLRECTANGLE(w, dr,
1067
ix + w->mlink.tileSize.x, iy,
1068
gapI, w->mlink.tileSize.y);
1081
FILLRECTANGLE(w, dr,
1083
ix - gapI, iy, gapI, w->mlink.tileSize.y);
1086
FILLRECTANGLE(w, dr,
1088
ix + w->mlink.tileSize.x, iy,
1089
gapI, w->mlink.tileSize.y);
1074
FILLRECTANGLE(w, dr,
1077
ix - fillBeginI, w->mlink.tileSize.y);
1080
FILLRECTANGLE(w, dr,
1082
ix + w->mlink.tileSize.x, iy,
1083
fillBeginI - ix, w->mlink.tileSize.y);
1095
FILLRECTANGLE(w, dr,
1098
ix - fillBeginI, w->mlink.tileSize.y);
1101
FILLRECTANGLE(w, dr,
1103
ix + w->mlink.tileSize.x, iy,
1104
fillBeginI - ix, w->mlink.tileSize.y);
1220
ResetTiles(MlinkWidget w)
1224
w->mlink.tileFaces = w->mlink.tiles * w->mlink.faces;
1225
if (w->mlink.tileOfPosition)
1226
free(w->mlink.tileOfPosition);
1227
if (!(w->mlink.tileOfPosition = (int *)
1228
malloc(sizeof (int) * w->mlink.tileFaces))) {
1229
DISPLAY_ERROR("Not enough memory, exiting.");
1233
free(startPosition);
1234
if (!(startPosition = (int *)
1235
malloc(sizeof (int) * w->mlink.tileFaces))) {
1236
DISPLAY_ERROR("Not enough memory, exiting.");
1239
w->mlink.spacePosition = w->mlink.tileFaces - 1;
1240
w->mlink.tileOfPosition[w->mlink.tileFaces - 1] = 0;
1241
for (i = 1; i < w->mlink.tileFaces; i++)
1242
w->mlink.tileOfPosition[i - 1] = i;
1244
w->mlink.currentRef = -w->mlink.tileFaces;
1245
w->mlink.started = False;
1249
EraseFrame(const MlinkWidget w, Pixmap dr)
1251
FILLRECTANGLE(w, dr, w->mlink.inverseGC,
1252
0, 0, w->core.width, w->core.height);
1256
1241
DrawFrame(MlinkWidget w, Pixmap dr, Boolean focus)
1258
1243
int sumX, sumY, offsetX, offsetY, k;
1498
MoveShift(MlinkWidget w, int direction, int fast)
1500
(void) MoveTilesDir(w, direction, 0, True, fast);
1501
SetMlink(w, MLINK_CONTROL);
1497
MoveMlink(MlinkWidget w, const int direction, const int tile, const int shift,
1498
const Boolean motion, const int fast)
1500
if (shift != 0 && (direction == TOP || direction == BOTTOM)) {
1501
MoveShift(w, direction, fast);
1503
PutMove(direction, tile, 1);
1506
} else if (MoveTilesDir(w, direction, tile, False, fast)) {
1508
SetMlink(w, MLINK_MOVED);
1509
PutMove(direction, tile, 0);
1517
DiffMove(MlinkWidget w, int diff, int j, int shift)
1521
if (diff > w->mlink.faces / 2 ||
1522
(diff == (w->mlink.faces + 1) / 2 && j > w->mlink.currentFace))
1523
for (k = 0; k < w->mlink.faces - diff; k++)
1524
(void) MoveMlink(w, BOTTOM, w->mlink.currentTile,
1525
shift, True, NORMAL);
1527
for (k = 0; k < diff; k++)
1528
(void) MoveMlink(w, TOP, w->mlink.currentTile,
1529
shift, True, NORMAL);
1533
MoveRecord(MlinkWidget w, const int direction, const int tile, const int shift)
1535
if (shift != 0 && (direction == TOP || direction == BOTTOM)) {
1536
PutMove(direction, tile, 1);
1538
SetMlink(w, MLINK_MOVED);
1539
PutMove(direction, tile, 0);
1544
DiffRecord(MlinkWidget w, int diff, int j, int shift)
1548
if (diff > w->mlink.faces / 2 ||
1549
(diff == (w->mlink.faces + 1) / 2 && j > w->mlink.currentFace))
1550
for (k = 0; k < w->mlink.faces - diff; k++)
1551
(void) MoveRecord(w, BOTTOM,
1552
w->mlink.currentTile, shift);
1554
for (k = 0; k < diff; k++)
1555
(void) MoveRecord(w, TOP,
1556
w->mlink.currentTile, shift);
1560
MoveMlinkDelay(MlinkWidget w,
1561
const int direction, const int tile, const Boolean all)
1565
if (direction == RIGHT) {
1566
pos = tile - w->mlink.spacePosition;
1567
for (n = (-pos) % w->mlink.tiles - 1; n >= 0; n--) {
1568
SetMlink(w, MLINK_MOVED);
1569
PutMove(direction, tile + n, False);
1571
} else if (direction == LEFT) {
1572
pos = tile - w->mlink.spacePosition;
1573
for (n = pos % w->mlink.tiles - 1; n >= 0; n--) {
1574
SetMlink(w, MLINK_MOVED);
1575
PutMove(direction, tile - n, False);
1578
SetMlink(w, MLINK_MOVED);
1579
PutMove(direction, tile, all);
1581
(void) MoveTilesDir(w, direction, tile, all, NORMAL);
1582
Sleep((unsigned int) w->mlink.delay);
1567
MoveMlinkDelay(MlinkWidget w,
1568
const int direction, const int tile, const Boolean all)
1572
if (direction == RIGHT) {
1573
pos = tile - w->mlink.spacePosition;
1574
for (n = (-pos) % w->mlink.tiles - 1; n >= 0; n--) {
1575
SetMlink(w, MLINK_MOVED);
1576
PutMove(direction, tile + n, False);
1578
} else if (direction == LEFT) {
1579
pos = tile - w->mlink.spacePosition;
1580
for (n = pos % w->mlink.tiles - 1; n >= 0; n--) {
1581
SetMlink(w, MLINK_MOVED);
1582
PutMove(direction, tile - n, False);
1585
SetMlink(w, MLINK_MOVED);
1586
PutMove(direction, tile, all);
1588
(void) MoveTilesDir(w, direction, tile, all, NORMAL);
1589
Sleep((unsigned int) w->mlink.delay);
1593
MoveMlink(MlinkWidget w, const int direction, const int tile, const int shift,
1596
if (shift && (direction == TOP || direction == BOTTOM)) {
1597
MoveShift(w, direction, fast);
1598
PutMove(direction, tile, 1);
1600
} else if (MoveTilesDir(w, direction, tile, False, fast)) {
1601
SetMlink(w, MLINK_MOVED);
1602
PutMove(direction, tile, 0);
1609
1648
SelectTiles(MlinkWidget w, int x, int y, int *i, int *j)
1650
int temp = w->mlink.faces * w->mlink.offset.y + w->mlink.delta.y - 1;
1611
1652
*i = (x - w->mlink.delta.x / 2 - w->mlink.puzzleOffset.x) /
1612
1653
w->mlink.offset.x;
1613
*j = ((y - w->mlink.delta.y / 2 - w->mlink.puzzleOffset.y) %
1614
(w->mlink.faces * w->mlink.offset.y + w->mlink.delta.y - 1)) /
1654
*j = ((y - w->mlink.delta.y / 2 - w->mlink.puzzleOffset.y + temp) %
1655
temp) / w->mlink.offset.y;
1616
1656
if (*i >= 0 && *j >= 0 &&
1617
1657
*i < w->mlink.tiles && *j < w->mlink.faces)
1618
1658
return (*i + w->mlink.tiles * *j -
1700
ResetTiles(MlinkWidget w)
1704
w->mlink.tileFaces = w->mlink.tiles * w->mlink.faces;
1705
if (w->mlink.tileOfPosition)
1706
free(w->mlink.tileOfPosition);
1707
if (!(w->mlink.tileOfPosition = (int *)
1708
malloc(sizeof (int) * w->mlink.tileFaces))) {
1709
DISPLAY_ERROR("Not enough memory, exiting.");
1713
free(startPosition);
1714
if (!(startPosition = (int *)
1715
malloc(sizeof (int) * w->mlink.tileFaces))) {
1716
DISPLAY_ERROR("Not enough memory, exiting.");
1719
w->mlink.spacePosition = w->mlink.tileFaces - 1;
1720
w->mlink.tileOfPosition[w->mlink.tileFaces - 1] = 0;
1721
for (i = 1; i < w->mlink.tileFaces; i++)
1722
w->mlink.tileOfPosition[i - 1] = i;
1724
w->mlink.currentRef = -w->mlink.tileFaces;
1725
w->mlink.started = False;
1660
1729
GetTiles(MlinkWidget w)
2815
MotionMlink(MlinkWidget w
2817
, const int x, const int y, const int shift
2819
, XEvent * event, char **args, int nArgs
2823
int i, j, pos, diff;
2825
int x = event->xbutton.x, y = event->xbutton.y;
2826
int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
2829
if (w->mlink.currentRef == -w->mlink.tileFaces)
2831
if (shift == 0 && !w->mlink.practice && CheckSolved(w)) {
2833
w->mlink.currentRef = -w->mlink.tileFaces;
2836
pos = SelectTiles(w, x, y, &i, &j);
2837
if (w->mlink.currentTile != i) {
2838
int k = w->mlink.currentTile +
2839
w->mlink.currentFace * w->mlink.tiles;
2841
DrawTile(w, k, True, True, TRUE, 0, 0);
2842
DrawTile(w, k, (w->mlink.tileOfPosition[k] <= 0),
2843
(w->mlink.tileOfPosition[k] <= 0), FALSE, 0, 0);
2844
DiffRecord(w, w->mlink.motionDiff, j, FALSE);
2845
DiffRecord(w, w->mlink.shiftDiff, j, TRUE);
2846
if (shift == 0 && CheckSolved(w)) {
2847
SetMlink(w, MLINK_SOLVED);
2849
w->mlink.currentTile = i;
2850
w->mlink.currentFace = j;
2851
w->mlink.currentRef = pos;
2852
w->mlink.motionDiff = 0;
2853
w->mlink.shiftDiff = 0;
2855
if (-w->mlink.tileFaces != pos) {
2856
if (j != w->mlink.currentFace) {
2857
diff = (w->mlink.currentFace - j + w->mlink.faces) %
2859
DiffMove(w, diff, j, shift);
2860
if (shift == 0 && CheckSolved(w)) {
2861
SetMlink(w, MLINK_SOLVED);
2863
w->mlink.motion = True;
2865
w->mlink.motionDiff = (diff +
2866
w->mlink.motionDiff) % w->mlink.faces;
2868
w->mlink.shiftDiff = (diff +
2869
w->mlink.shiftDiff) % w->mlink.faces;
2871
w->mlink.currentTile = i;
2872
w->mlink.currentFace = j;
2873
w->mlink.currentRef = pos;
2874
if (shift != 0 || w->mlink.practice || !CheckSolved(w)) {
2875
pos = w->mlink.currentTile +
2876
w->mlink.currentFace * w->mlink.tiles;
2877
DrawTile(w, pos, (w->mlink.tileOfPosition[i + j * w->mlink.tiles] <= 0),
2881
w->mlink.currentRef = -w->mlink.tileFaces;
2741
2888
ReleaseMlink(MlinkWidget w
2743
2890
, const int x, const int y, const int shift
2759
2906
if (w->mlink.tileOfPosition[pos] > 0) {
2760
2907
DrawTile(w, pos, False, False, FALSE, 0, 0);
2762
if (!shift && !w->mlink.practice && CheckSolved(w))
2909
if (shift == 0 && !w->mlink.practice && CheckSolved(w)) {
2763
2910
MoveNoTiles(w);
2765
pos = SelectTiles(w, x, y, &i, &j);
2766
if (-w->mlink.tileFaces != pos) {
2767
if (j == w->mlink.currentFace) {
2768
pos = w->mlink.currentRef;
2769
if (pos / w->mlink.tiles == 0 &&
2770
j == Row(w, w->mlink.spacePosition) && pos != 0) {
2771
if (shift && CheckSolved(w))
2774
SelectSlideTiles(w, pos);
2775
w->mlink.currentTile = w->mlink.tiles;
2776
if (CheckSolved(w)) {
2777
SetMlink(w, MLINK_SOLVED);
2911
w->mlink.currentRef = -w->mlink.tileFaces;
2914
pos = SelectTiles(w, x, y, &i, &j);
2915
if (-w->mlink.tileFaces != pos) {
2916
if (j == w->mlink.currentFace && !w->mlink.motion) {
2917
pos = w->mlink.currentRef;
2918
if (pos / w->mlink.tiles == 0 &&
2919
j == Row(w, w->mlink.spacePosition) && pos != 0) {
2920
if (shift != 0 && CheckSolved(w))
2923
SelectSlideTiles(w, pos);
2924
w->mlink.currentTile = w->mlink.tiles;
2925
if (CheckSolved(w)) {
2926
SetMlink(w, MLINK_SOLVED);
2782
diff = (w->mlink.currentFace - j + w->mlink.faces) % w->mlink.faces;
2783
if (diff > w->mlink.faces / 2 || (diff == (w->mlink.faces + 1) / 2 &&
2784
j > w->mlink.currentFace))
2785
for (i = 0; i < w->mlink.faces - diff; i++)
2786
(void) MoveMlink(w, BOTTOM, w->mlink.currentTile, shift, NORMAL);
2788
for (i = 0; i < diff; i++)
2789
(void) MoveMlink(w, TOP, w->mlink.currentTile, shift, NORMAL);
2790
if (!shift && CheckSolved(w)) {
2791
SetMlink(w, MLINK_SOLVED);
2931
diff = (w->mlink.currentFace - j + w->mlink.faces) %
2933
DiffMove(w, diff, j, shift);
2935
w->mlink.motionDiff = (diff +
2936
w->mlink.motionDiff) %
2939
w->mlink.shiftDiff = (diff +
2940
w->mlink.shiftDiff) % w->mlink.faces;
2941
DiffRecord(w, w->mlink.motionDiff, j, FALSE);
2942
DiffRecord(w, w->mlink.shiftDiff, j, TRUE);
2943
if (shift == 0 && CheckSolved(w)) {
2944
SetMlink(w, MLINK_SOLVED);
3048
MoveMlinkTop(MlinkWidget w, XEvent * event, char **args, int nArgs)
3050
MoveMlinkInput(w, event->xbutton.x, TOP,
3051
(int) (event->xkey.state & (ShiftMask | LockMask)),
3052
(int) (event->xkey.state & ControlMask));
3200
MoveMlinkTop(MlinkWidget w , XEvent * event, char **args, int nArgs
3203
int x = event->xbutton.x;
3204
int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
3205
int control = (int) (event->xkey.state & ControlMask);
3207
MoveMlinkInput(w, x, TOP, shift, control);
3211
MoveMlinkBottom(MlinkWidget w , XEvent * event, char **args, int nArgs
3214
int x = event->xbutton.x;
3215
int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
3216
int control = (int) (event->xkey.state & ControlMask);
3218
MoveMlinkInput(w, x, BOTTOM, shift, control);