~ubuntu-branches/ubuntu/karmic/xpuzzles/karmic

« back to all changes in this revision

Viewing changes to xmlink/Mlink.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-22 16:29:42 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050822162942-tdtf178zkpd3xxdg
Tags: 7.1.3-1ubuntu1
Update {build-,}depends for xorg -> mesa transition.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
#
6
6
###
7
7
#
8
 
#  Copyright (c) 1994 - 2004    David Albert Bagley, bagleyd@tux.org
 
8
#  Copyright (c) 1994 - 2005    David Albert Bagley, bagleyd@tux.org
9
9
#
10
10
#                   All Rights Reserved
11
11
#
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);
116
129
 
117
130
static char defaultTranslationsMlink[] =
118
131
"<KeyPress>q: Quit()\n\
143
156
 <KeyPress>KP_2: MoveBottom()\n\
144
157
 <KeyPress>R14: MoveBottom()\n\
145
158
 <Btn1Down>: Select()\n\
 
159
 <Btn1Motion>: Motion()\n\
146
160
 <Btn1Up>: Release()\n\
147
161
 <KeyPress>p: Practice()\n\
148
162
 <KeyPress>r: Randomize()\n\
161
175
 <KeyPress>0x3E: Speed()\n\
162
176
 <KeyPress>0x3C: Slow()\n\
163
177
 <KeyPress>0x2C: Slow()\n\
164
 
 <KeyPress>2: Sound()\n\
165
178
 <KeyPress>@: Sound()\n\
166
179
 <EnterWindow>: Enter()\n\
167
180
 <LeaveWindow>: Leave()";
175
188
        {(char *) "MoveRight", (XtActionProc) MoveMlinkRight},
176
189
        {(char *) "MoveBottom", (XtActionProc) MoveMlinkBottom},
177
190
        {(char *) "Select", (XtActionProc) SelectMlink},
 
191
        {(char *) "Motion", (XtActionProc) MotionMlink},
178
192
        {(char *) "Release", (XtActionProc) ReleaseMlink},
179
193
        {(char *) "Practice", (XtActionProc) PracticeMlink},
180
194
        {(char *) "PracticeMaybe", (XtActionProc) PracticeMlinkMaybe},
498
512
#endif
499
513
}
500
514
 
501
 
 
502
515
static void
503
516
useTimer(MlinkWidget w, int delay)
504
517
{
615
628
        return (pos / w->mlink.tiles);
616
629
}
617
630
 
618
 
static void
619
 
Cartesian(MlinkWidget w, int pos, int * x, int * y)
 
631
static int
 
632
CartesianX(MlinkWidget w, int pos)
620
633
{
621
 
        *x = Column(w, pos) * w->mlink.offset.x + w->mlink.delta.x +
 
634
        return Column(w, pos) * w->mlink.offset.x + w->mlink.delta.x +
622
635
                w->mlink.puzzleOffset.x;
623
 
        *y = Row(w, pos) * (w->mlink.offset.y + 1) + w->mlink.delta.y +
 
636
}
 
637
 
 
638
static int
 
639
CartesianY(MlinkWidget w, int pos)
 
640
{
 
641
        return Row(w, pos) * (w->mlink.offset.y + 1) + w->mlink.delta.y +
624
642
                w->mlink.puzzleOffset.y;
625
643
}
626
644
 
765
783
 
766
784
        sizex = w->mlink.offset.x * 3 / 2 - 6;
767
785
        sizey = w->mlink.offset.y * 3 / 4 - 6;
768
 
        Cartesian(w, pos, &dx, &dy);
769
 
        dx += -sizex / 2 + offsetX + 2;
770
 
        dy += w->mlink.tileSize.y / 2 - sizey / 2 - 1 + offsetY;
 
786
        dx = CartesianX(w, pos) - sizex / 2 + offsetX + 2;
 
787
        dy = CartesianY(w, pos) + w->mlink.tileSize.y / 2 - sizey / 2 -
 
788
                1 + offsetY;
771
789
        thick = MIN(sizey, sizex) / 3;
772
790
        thick = MIN(thick, THICKNESS);
773
791
        if (thick > 0) {
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 +
 
856
                        offsetY;
 
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);
845
865
                } else {
846
866
                        DRAWARC(w, dr, gc, 1, gc, dx, dy,
847
867
                                 sizex, sizey, 89 * MULT, -32 * MULT);
876
896
                w->mlink.tileFaces;
877
897
        Pixmap dr = 0;
878
898
 
879
 
        Cartesian(w, pos, &dx, &dy);
880
 
        dx += pressedOffset + offsetX;
881
 
        dy += pressedOffset + offsetY;
882
 
        Cartesian(w, tile, &sx, &sy);
 
899
        dx = CartesianX(w, pos) + pressedOffset + offsetX;
 
900
        dy = CartesianY(w, pos) + pressedOffset + offsetY;
 
901
        sx = CartesianX(w, tile);
 
902
        sy = CartesianY(w, tile);
883
903
        if (blank) {
884
904
                FILLRECTANGLE(w, dr,
885
905
                        (erase) ? w->mlink.inverseGC : w->mlink.tileGC,
935
955
                }
936
956
#endif
937
957
        }
938
 
        Cartesian(w, pos, &dx, &dy);
939
 
        dx += pressedOffset;
940
 
        dy += pressedOffset;
 
958
        dx = CartesianX(w, pos) + pressedOffset;
 
959
        dy = CartesianY(w, pos) + pressedOffset;
941
960
        if (pressedOffset != 0) {
942
961
                drawShadow(w, *dr, w->mlink.tileDarkerGC,
943
962
                        dx - pressedOffset, dy - pressedOffset,
995
1014
                DrawLink(w, *dr, linkGC, pos, pressedOffset, pressedOffset);
996
1015
#if 0
997
1016
        DRAWRECTANGLE(w, *dr, borderGC, dx, dy,
998
 
                w->mlink.tileSize.x + 1, w->mlink.tileSize.y - 1);
 
1017
                w->mlink.tileSize.x - 1, w->mlink.tileSize.y - 1);
999
1018
#endif
1000
1019
}
1001
1020
 
1029
1048
        Pixmap dr = 0;
1030
1049
 
1031
1050
        fillBeginPos = TileNFromSpace(w, numTiles, dir);
1032
 
        Cartesian(w, fillBeginPos, &fillBeginI, &dy);
 
1051
        fillBeginI = CartesianX(w, fillBeginPos);
 
1052
        dy = CartesianY(w, fillBeginPos);
1033
1053
        gapI = w->mlink.tileSize.x * fast / w->mlink.numSlices;
1034
1054
        moveI = w->mlink.tileSize.x + w->mlink.delta.x;
1035
1055
        if (gapI == 0)
1047
1067
              PutMove(dir, posNext, 0);
1048
1068
            }
1049
1069
            /* Calculate deltas */
1050
 
            Cartesian(w, posNext, &dx, &dy);
 
1070
            dx = CartesianX(w, posNext);
 
1071
            dy = CartesianY(w, posNext);
1051
1072
            ix = ((dir == RIGHT) ? inc : -inc);
1052
1073
            iy = 0;
1053
1074
            DrawTile(w, posNext, False, False, FALSE, ix, iy);
1056
1077
            iy += dy;
1057
1078
            if (aTile < numTiles - 1) {
1058
1079
              switch (dir) {
1059
 
                case RIGHT:
1060
 
                  FILLRECTANGLE(w, dr,
1061
 
                    w->mlink.inverseGC,
1062
 
                    ix - gapI, iy, gapI, w->mlink.tileSize.y);
1063
 
                  break;
1064
 
                case LEFT:
1065
 
                  FILLRECTANGLE(w, dr,
1066
 
                    w->mlink.inverseGC,
1067
 
                    ix + w->mlink.tileSize.x, iy,
1068
 
                    gapI, w->mlink.tileSize.y);
1069
 
                  break;
 
1080
              case RIGHT:
 
1081
                FILLRECTANGLE(w, dr,
 
1082
                  w->mlink.inverseGC,
 
1083
                  ix - gapI, iy, gapI, w->mlink.tileSize.y);
 
1084
                break;
 
1085
              case LEFT:
 
1086
                FILLRECTANGLE(w, dr,
 
1087
                  w->mlink.inverseGC,
 
1088
                  ix + w->mlink.tileSize.x, iy,
 
1089
                  gapI, w->mlink.tileSize.y);
 
1090
                break;
1070
1091
              }
1071
1092
            } else {
1072
1093
              switch (dir) {
1073
 
                case RIGHT:
1074
 
                  FILLRECTANGLE(w, dr,
1075
 
                    w->mlink.inverseGC,
1076
 
                    fillBeginI, iy,
1077
 
                    ix - fillBeginI, w->mlink.tileSize.y);
1078
 
                  break;
1079
 
                case LEFT:
1080
 
                  FILLRECTANGLE(w, dr,
1081
 
                    w->mlink.inverseGC,
1082
 
                    ix + w->mlink.tileSize.x, iy,
1083
 
                    fillBeginI - ix, w->mlink.tileSize.y);
1084
 
                 break;
 
1094
              case RIGHT:
 
1095
                FILLRECTANGLE(w, dr,
 
1096
                  w->mlink.inverseGC,
 
1097
                  fillBeginI, iy,
 
1098
                  ix - fillBeginI, w->mlink.tileSize.y);
 
1099
                break;
 
1100
              case LEFT:
 
1101
                FILLRECTANGLE(w, dr,
 
1102
                  w->mlink.inverseGC,
 
1103
                  ix + w->mlink.tileSize.x, iy,
 
1104
                  fillBeginI - ix, w->mlink.tileSize.y);
 
1105
                break;
1085
1106
              }
1086
1107
            }
1087
1108
          }
1089
1110
        }
1090
1111
        pos = w->mlink.spacePosition;
1091
1112
        for (aTile = 0; aTile < numTiles; aTile++) {
1092
 
            posNext = TileNFromSpace(w, aTile + 1, dir);
1093
 
            w->mlink.tileOfPosition[pos] =
1094
 
              w->mlink.tileOfPosition[posNext];
1095
 
            pos = posNext;
 
1113
          posNext = TileNFromSpace(w, aTile + 1, dir);
 
1114
          w->mlink.tileOfPosition[pos] =
 
1115
            w->mlink.tileOfPosition[posNext];
 
1116
          pos = posNext;
1096
1117
        }
1097
1118
        w->mlink.spacePosition = fillBeginPos;
1098
1119
        w->mlink.tileOfPosition[fillBeginPos] = 0;
1139
1160
                        w->mlink.puzzleSize.y);
1140
1161
        SelectObject(memDC, hBit);
1141
1162
        BitBlt(memDC, 0, 0,
1142
 
                size * moveI + 1,
 
1163
                size * moveI,
1143
1164
                w->mlink.puzzleSize.y,
1144
1165
                w->core.hDC,
1145
1166
                start * moveI + w->mlink.puzzleOffset.x + 1,
1148
1169
#else
1149
1170
        (void) XGetWindowAttributes(XtDisplay(w), XtWindow(w), &xgwa);
1150
1171
        if ((bufferBox = XCreatePixmap(XtDisplay(w), XtWindow(w),
1151
 
                        size * moveI + 1,
 
1172
                        size * moveI,
1152
1173
                        w->mlink.puzzleSize.y,
1153
1174
                        xgwa.depth)) == None) {
1154
1175
                DISPLAY_ERROR("Not enough memory, exiting.");
1157
1178
                w->mlink.frameGC,
1158
1179
                start * moveI + w->mlink.puzzleOffset.x + 1,
1159
1180
                w->mlink.puzzleOffset.y,
1160
 
                size * moveI + 1,
 
1181
                size * moveI,
1161
1182
                w->mlink.puzzleSize.y,
1162
1183
                0, 0);
1163
1184
        XSetGraphicsExposures(XtDisplay(w), w->mlink.frameGC, False);
1175
1196
                BitBlt(w->core.hDC,
1176
1197
                        start * moveI + w->mlink.puzzleOffset.x + 1,
1177
1198
                        w->mlink.puzzleOffset.y + 1,
1178
 
                        size * moveI + 1,
 
1199
                        size * moveI,
1179
1200
                        w->mlink.puzzleSize.y - i,
1180
1201
                        memDC,
1181
1202
                        0, i,
1184
1205
                        start * moveI + w->mlink.puzzleOffset.x + 1,
1185
1206
                        w->mlink.puzzleSize.y - i + w->mlink.puzzleOffset.y -
1186
1207
                        w->mlink.delta.y + 1,
1187
 
                        size * moveI + 1,
 
1208
                        size * moveI,
1188
1209
                        i - w->mlink.delta.y,
1189
1210
                        memDC,
1190
1211
                        0, 0,
1193
1214
                XCopyArea(XtDisplay(w), bufferBox, XtWindow(w),
1194
1215
                        w->mlink.frameGC,
1195
1216
                        0, i,
1196
 
                        size * moveI + 1,
 
1217
                        size * moveI,
1197
1218
                        w->mlink.puzzleSize.y - i,
1198
1219
                        start * moveI + w->mlink.puzzleOffset.x + 1,
1199
1220
                        w->mlink.puzzleOffset.y + 1);
1200
1221
                XCopyArea(XtDisplay(w), bufferBox, XtWindow(w),
1201
1222
                        w->mlink.frameGC,
1202
1223
                        0, 0,
1203
 
                        size * moveI + 1,
 
1224
                        size * moveI,
1204
1225
                        i - w->mlink.delta.y,
1205
1226
                        start * moveI + w->mlink.puzzleOffset.x + 1,
1206
1227
                        w->mlink.puzzleSize.y - i + w->mlink.puzzleOffset.y -
1217
1238
}
1218
1239
 
1219
1240
static void
1220
 
ResetTiles(MlinkWidget w)
1221
 
{
1222
 
        int i;
1223
 
 
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.");
1230
 
        }
1231
 
 
1232
 
        if (startPosition)
1233
 
                free(startPosition);
1234
 
        if (!(startPosition = (int *)
1235
 
                        malloc(sizeof (int) * w->mlink.tileFaces))) {
1236
 
                DISPLAY_ERROR("Not enough memory, exiting.");
1237
 
        }
1238
 
 
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;
1243
 
        FlushMoves(w);
1244
 
        w->mlink.currentRef = -w->mlink.tileFaces;
1245
 
        w->mlink.started = False;
1246
 
}
1247
 
 
1248
 
static void
1249
 
EraseFrame(const MlinkWidget w, Pixmap dr)
1250
 
{
1251
 
        FILLRECTANGLE(w, dr, w->mlink.inverseGC,
1252
 
                0, 0, w->core.width, w->core.height);
1253
 
}
1254
 
 
1255
 
static void
1256
1241
DrawFrame(MlinkWidget w, Pixmap dr, Boolean focus)
1257
1242
{
1258
1243
        int sumX, sumY, offsetX, offsetY, k;
1288
1273
}
1289
1274
 
1290
1275
static void
 
1276
EraseFrame(const MlinkWidget w, Pixmap dr)
 
1277
{
 
1278
        FILLRECTANGLE(w, dr, w->mlink.inverseGC,
 
1279
                0, 0, w->core.width, w->core.height);
 
1280
}
 
1281
 
 
1282
static void
1291
1283
MoveNoTiles(MlinkWidget w)
1292
1284
{
1293
1285
        SetMlink(w, MLINK_IGNORE);
1378
1370
 
1379
1371
                FILLRECTANGLE(w, dr, w->mlink.inverseGC,
1380
1372
                        start * moveI + w->mlink.puzzleOffset.x + 1, 0,
1381
 
                        (finish - start + 1) * moveI + 1, w->core.height);
 
1373
                        (finish - start + 1) * moveI, w->core.height);
1382
1374
                DrawFrame(w, dr, w->mlink.focus);
1383
1375
                DrawAllTilesForColumns(w, start, finish);
1384
1376
        }
1390
1382
        }
1391
1383
#endif
1392
1384
}
1393
 
 
 
1385
 
1394
1386
static Boolean
1395
1387
MoveTilesDir(MlinkWidget w, int direction, int tile, Boolean all, int fast)
1396
1388
{
1460
1452
}
1461
1453
 
1462
1454
static void
 
1455
MoveShift(MlinkWidget w, int direction, int fast)
 
1456
{
 
1457
        (void) MoveTilesDir(w, direction, 0, True, fast);
 
1458
        SetMlink(w, MLINK_CONTROL);
 
1459
}
 
1460
 
 
1461
static void
1463
1462
ControlMlink(MlinkWidget w, int direction)
1464
1463
{
1465
1464
        switch (direction) {
1494
1493
        }
1495
1494
}
1496
1495
 
1497
 
static void
1498
 
MoveShift(MlinkWidget w, int direction, int fast)
1499
 
{
1500
 
        (void) MoveTilesDir(w, direction, 0, True, fast);
1501
 
        SetMlink(w, MLINK_CONTROL);
 
1496
Boolean
 
1497
MoveMlink(MlinkWidget w, const int direction, const int tile, const int shift,
 
1498
                const Boolean motion, const int fast)
 
1499
{
 
1500
        if (shift != 0 && (direction == TOP || direction == BOTTOM)) {
 
1501
                MoveShift(w, direction, fast);
 
1502
                if (!motion) {
 
1503
                        PutMove(direction, tile, 1);
 
1504
                }
 
1505
                return True;
 
1506
        } else if (MoveTilesDir(w, direction, tile, False, fast)) {
 
1507
                if (!motion) {
 
1508
                        SetMlink(w, MLINK_MOVED);
 
1509
                        PutMove(direction, tile, 0);
 
1510
                }
 
1511
                return True;
 
1512
        }
 
1513
        return False;
 
1514
}
 
1515
 
 
1516
static void
 
1517
DiffMove(MlinkWidget w, int diff, int j, int shift)
 
1518
{
 
1519
        int k;
 
1520
 
 
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);
 
1526
        else
 
1527
                for (k = 0; k < diff; k++)
 
1528
                        (void) MoveMlink(w, TOP, w->mlink.currentTile,
 
1529
                                shift, True, NORMAL);
 
1530
}
 
1531
 
 
1532
static void
 
1533
MoveRecord(MlinkWidget w, const int direction, const int tile, const int shift)
 
1534
{
 
1535
        if (shift != 0 && (direction == TOP || direction == BOTTOM)) {
 
1536
                PutMove(direction, tile, 1);
 
1537
        } else {
 
1538
                SetMlink(w, MLINK_MOVED);
 
1539
                PutMove(direction, tile, 0);
 
1540
        }
 
1541
}
 
1542
 
 
1543
static void
 
1544
DiffRecord(MlinkWidget w, int diff, int j, int shift)
 
1545
{
 
1546
        int k;
 
1547
 
 
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);
 
1553
        else
 
1554
                for (k = 0; k < diff; k++)
 
1555
                        (void) MoveRecord(w, TOP,
 
1556
                                w->mlink.currentTile, shift);
 
1557
}
 
1558
 
 
1559
void
 
1560
MoveMlinkDelay(MlinkWidget w,
 
1561
                const int direction, const int tile, const Boolean all)
 
1562
{
 
1563
        int n, pos;
 
1564
 
 
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);
 
1570
                }
 
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);
 
1576
                }
 
1577
        } else {
 
1578
                SetMlink(w, MLINK_MOVED);
 
1579
                PutMove(direction, tile, all);
 
1580
        }
 
1581
        (void) MoveTilesDir(w, direction, tile, all, NORMAL);
 
1582
        Sleep((unsigned int) w->mlink.delay);
1502
1583
}
1503
1584
 
1504
1585
static void
1508
1589
                MoveNoTiles(w);
1509
1590
                return;
1510
1591
        }
1511
 
        if (!MoveMlink(w, direction, pos, FALSE, NORMAL)) {
 
1592
        if (!MoveMlink(w, direction, pos, FALSE, False, NORMAL)) {
1512
1593
                SetMlink(w, MLINK_BLOCKED);
1513
1594
                return;
1514
1595
        }
1525
1606
                MoveNoTiles(w);
1526
1607
                return;
1527
1608
        }
1528
 
        (void) MoveMlink(w, direction, tile, FALSE, NORMAL);
 
1609
        (void) MoveMlink(w, direction, tile, FALSE, False, NORMAL);
1529
1610
        if (CheckSolved(w)) {
1530
1611
                SetMlink(w, MLINK_SOLVED);
1531
1612
        }
1540
1621
{
1541
1622
        int r;
1542
1623
 
1543
 
        if (control)
 
1624
        if (control != 0)
1544
1625
                ControlMlink(w, direction);
1545
 
        else if (shift && (direction == TOP || direction == BOTTOM)) {
 
1626
        else if (shift != 0 && (direction == TOP || direction == BOTTOM)) {
1546
1627
                MoveShift(w, direction, NORMAL);
1547
1628
                PutMove(direction, 0, 1);
1548
1629
        } else if (CheckSolved(w) && !w->mlink.practice) {
1563
1644
        }
1564
1645
}
1565
1646
 
1566
 
void
1567
 
MoveMlinkDelay(MlinkWidget w,
1568
 
                const int direction, const int tile, const Boolean all)
1569
 
{
1570
 
        int n, pos;
1571
 
 
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);
1577
 
                }
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);
1583
 
                }
1584
 
        } else {
1585
 
                SetMlink(w, MLINK_MOVED);
1586
 
                PutMove(direction, tile, all);
1587
 
        }
1588
 
        (void) MoveTilesDir(w, direction, tile, all, NORMAL);
1589
 
        Sleep((unsigned int) w->mlink.delay);
1590
 
}
1591
 
 
1592
 
Boolean
1593
 
MoveMlink(MlinkWidget w, const int direction, const int tile, const int shift,
1594
 
                const int fast)
1595
 
{
1596
 
        if (shift && (direction == TOP || direction == BOTTOM)) {
1597
 
                MoveShift(w, direction, fast);
1598
 
                PutMove(direction, tile, 1);
1599
 
                return True;
1600
 
        } else if (MoveTilesDir(w, direction, tile, False, fast)) {
1601
 
                SetMlink(w, MLINK_MOVED);
1602
 
                PutMove(direction, tile, 0);
1603
 
                return True;
1604
 
        }
1605
 
        return False;
1606
 
}
1607
 
 
1608
1647
static int
1609
1648
SelectTiles(MlinkWidget w, int x, int y, int *i, int *j)
1610
1649
{
 
1650
        int temp = w->mlink.faces * w->mlink.offset.y + w->mlink.delta.y - 1;
 
1651
 
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)) /
1615
 
                w->mlink.offset.y;
 
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 -
1657
1697
}
1658
1698
 
1659
1699
static void
 
1700
ResetTiles(MlinkWidget w)
 
1701
{
 
1702
        int i;
 
1703
 
 
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.");
 
1710
        }
 
1711
 
 
1712
        if (startPosition)
 
1713
                free(startPosition);
 
1714
        if (!(startPosition = (int *)
 
1715
                        malloc(sizeof (int) * w->mlink.tileFaces))) {
 
1716
                DISPLAY_ERROR("Not enough memory, exiting.");
 
1717
        }
 
1718
 
 
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;
 
1723
        FlushMoves(w);
 
1724
        w->mlink.currentRef = -w->mlink.tileFaces;
 
1725
        w->mlink.started = False;
 
1726
}
 
1727
 
 
1728
static void
1660
1729
GetTiles(MlinkWidget w)
1661
1730
{
1662
1731
        FILE *fp;
1856
1925
 
1857
1926
                GetMove(&direction, &tile, &shift);
1858
1927
                direction = (direction + COORD / 2) % COORD;
1859
 
                if (shift && (direction == TOP || direction == BOTTOM)) {
 
1928
                if (shift != 0 && (direction == TOP || direction == BOTTOM)) {
1860
1929
                        MoveShift(w, direction, DOUBLE);
1861
1930
                } else {
1862
1931
                        if (direction == LEFT)
1907
1976
                if (count % 2 &&
1908
1977
                    !ExchangeTiles(w, 0, 1) &&
1909
1978
                    !ExchangeTiles(w, w->mlink.tileFaces - 2,
1910
 
                               w->mlink.tileFaces - 1)) {
 
1979
                                w->mlink.tileFaces - 1)) {
1911
1980
                        DISPLAY_WARNING("RandomizeTiles: should not get here");
1912
1981
                }
1913
1982
                DrawAllTiles(w);
1961
2030
#endif
1962
2031
                        if ((randomDirection + COORD / 2) % COORD != lastDirection ||
1963
2032
                            w->mlink.tiles == 1 || w->mlink.faces == 1) {
1964
 
                                if (MoveMlink(w, randomDirection, NRAND(w->mlink.tiles), FALSE, INSTANT))
 
2033
                                if (MoveMlink(w, randomDirection,
 
2034
                                    NRAND(w->mlink.tiles), FALSE, False,
 
2035
                                    INSTANT))
1965
2036
                                        lastDirection = randomDirection;
1966
2037
                                else
1967
2038
                                        big++;
2590
2661
        w->mlink.delta.y = 1;
2591
2662
        w->mlink.offset.x = MAX(((int) w->core.width - 2) /
2592
2663
                w->mlink.tiles, 0);
2593
 
        w->mlink.offset.y = MAX(((int) w->core.height /
2594
 
                w->mlink.faces - 2), 0);
 
2664
        w->mlink.offset.y = MAX((int) w->core.height /
 
2665
                w->mlink.faces - 2, 0);
2595
2666
        w->mlink.faceSize.x = w->mlink.offset.x * w->mlink.tiles +
2596
2667
                w->mlink.delta.x + 2;
2597
2668
        w->mlink.faceSize.y = w->mlink.offset.y + w->mlink.delta.y + 2;
2720
2791
        int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
2721
2792
#endif
2722
2793
 
 
2794
        w->mlink.motion = False;
 
2795
        w->mlink.motionDiff = 0;
 
2796
        w->mlink.shiftDiff = 0;
2723
2797
        pos = SelectTiles(w, x, y, &i, &j);
2724
2798
        if (-w->mlink.tileFaces != pos) {
2725
2799
                w->mlink.currentTile = i;
2726
2800
                w->mlink.currentFace = j;
2727
2801
                w->mlink.currentRef = pos;
2728
 
                if (shift || w->mlink.practice || !CheckSolved(w)) {
 
2802
                if (shift != 0 || w->mlink.practice || !CheckSolved(w)) {
2729
2803
                        pos = w->mlink.currentTile + w->mlink.currentFace * w->mlink.tiles;
2730
2804
                        DrawTile(w, pos, (w->mlink.tileOfPosition[i + j * w->mlink.tiles] <= 0),
2731
2805
                                 False, TRUE, 0, 0);
2738
2812
static
2739
2813
#endif
2740
2814
void
 
2815
MotionMlink(MlinkWidget w
 
2816
#ifdef WINVER
 
2817
, const int x, const int y, const int shift
 
2818
#else
 
2819
, XEvent * event, char **args, int nArgs
 
2820
#endif
 
2821
)
 
2822
{
 
2823
        int i, j, pos, diff;
 
2824
#ifndef WINVER
 
2825
        int x = event->xbutton.x, y = event->xbutton.y;
 
2826
        int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
 
2827
#endif
 
2828
 
 
2829
        if (w->mlink.currentRef == -w->mlink.tileFaces)
 
2830
                return;
 
2831
        if (shift == 0 && !w->mlink.practice && CheckSolved(w)) {
 
2832
                MoveNoTiles(w);
 
2833
                w->mlink.currentRef = -w->mlink.tileFaces;
 
2834
                return;
 
2835
        }
 
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;
 
2840
 
 
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);
 
2848
                }
 
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;
 
2854
        }
 
2855
        if (-w->mlink.tileFaces != pos) {
 
2856
                if (j != w->mlink.currentFace) {
 
2857
                        diff = (w->mlink.currentFace - j + w->mlink.faces) %
 
2858
                                w->mlink.faces;
 
2859
                        DiffMove(w, diff, j, shift);
 
2860
                        if (shift == 0 && CheckSolved(w)) {
 
2861
                                SetMlink(w, MLINK_SOLVED);
 
2862
                        }
 
2863
                        w->mlink.motion = True;
 
2864
                        if (shift == 0)
 
2865
                                w->mlink.motionDiff = (diff +
 
2866
                                        w->mlink.motionDiff) % w->mlink.faces;
 
2867
                        else
 
2868
                                w->mlink.shiftDiff = (diff +
 
2869
                                        w->mlink.shiftDiff) % w->mlink.faces;
 
2870
                }
 
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),
 
2878
                                 False, TRUE, 0, 0);
 
2879
                }
 
2880
        } else
 
2881
                w->mlink.currentRef = -w->mlink.tileFaces;
 
2882
}
 
2883
 
 
2884
#ifndef WINVER
 
2885
static
 
2886
#endif
 
2887
void
2741
2888
ReleaseMlink(MlinkWidget w
2742
2889
#ifdef WINVER
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);
2761
2908
        }
2762
 
        if (!shift && !w->mlink.practice && CheckSolved(w))
 
2909
        if (shift == 0 && !w->mlink.practice && CheckSolved(w)) {
2763
2910
                MoveNoTiles(w);
2764
 
        else {
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))
2772
 
                                                MoveNoTiles(w);
2773
 
                                        else {
2774
 
                                                SelectSlideTiles(w, pos);
2775
 
                                                w->mlink.currentTile = w->mlink.tiles;
2776
 
                                                if (CheckSolved(w)) {
2777
 
                                                        SetMlink(w, MLINK_SOLVED);
2778
 
                                                }
 
2911
                w->mlink.currentRef = -w->mlink.tileFaces;
 
2912
                return;
 
2913
        }
 
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))
 
2921
                                        MoveNoTiles(w);
 
2922
                                else {
 
2923
                                        SelectSlideTiles(w, pos);
 
2924
                                        w->mlink.currentTile = w->mlink.tiles;
 
2925
                                        if (CheckSolved(w)) {
 
2926
                                                SetMlink(w, MLINK_SOLVED);
2779
2927
                                        }
2780
2928
                                }
2781
 
                        } else {
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);
2787
 
                                else
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);
2792
 
                                }
 
2929
                        }
 
2930
                } else {
 
2931
                        diff = (w->mlink.currentFace - j + w->mlink.faces) %
 
2932
                                w->mlink.faces;
 
2933
                        DiffMove(w, diff, j, shift);
 
2934
                        if (shift == 0)
 
2935
                                w->mlink.motionDiff = (diff +
 
2936
                                        w->mlink.motionDiff) %
 
2937
                                        w->mlink.faces;
 
2938
                        else
 
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);
2793
2945
                        }
2794
2946
                }
2795
2947
        }
3045
3197
 
3046
3198
#ifndef WINVER
3047
3199
static void
3048
 
MoveMlinkTop(MlinkWidget w, XEvent * event, char **args, int nArgs)
3049
 
{
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
 
3201
)
 
3202
{
 
3203
        int x = event->xbutton.x;
 
3204
        int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
 
3205
        int control = (int) (event->xkey.state & ControlMask);
 
3206
 
 
3207
        MoveMlinkInput(w, x, TOP, shift, control);
 
3208
}
 
3209
 
 
3210
static void
 
3211
MoveMlinkBottom(MlinkWidget w , XEvent * event, char **args, int nArgs
 
3212
)
 
3213
{
 
3214
        int x = event->xbutton.x;
 
3215
        int shift = (int) (event->xkey.state & (ShiftMask | LockMask));
 
3216
        int control = (int) (event->xkey.state & ControlMask);
 
3217
 
 
3218
        MoveMlinkInput(w, x, BOTTOM, shift, control);
3053
3219
}
3054
3220
 
3055
3221
static void
3067
3233
                (int) (event->xkey.state & (ShiftMask | LockMask)),
3068
3234
                (int) (event->xkey.state & ControlMask));
3069
3235
}
3070
 
 
3071
 
static void
3072
 
MoveMlinkBottom(MlinkWidget w, XEvent * event, char **args, int nArgs)
3073
 
{
3074
 
        MoveMlinkInput(w, event->xbutton.x, BOTTOM,
3075
 
                (int) (event->xkey.state & (ShiftMask | LockMask)),
3076
 
                (int) (event->xkey.state & ControlMask));
3077
 
}
3078
3236
#endif