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

« back to all changes in this revision

Viewing changes to xpanex/Panex.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) 1996 - 2004    David Albert Bagley, bagleyd@tux.org
 
8
#  Copyright (c) 1996 - 2005    David Albert Bagley, bagleyd@tux.org
9
9
#
10
10
#                   All Rights Reserved
11
11
#
25
25
 
26
26
/* Methods file for Panex */
27
27
 
 
28
#if defined(USE_RPLAY) || defined(USE_NAS) || defined(USE_VMSPLAY) || defined(USE_ESOUND) || defined(WINVER) || defined(DEF_PLAY)
 
29
#define USE_SOUND
 
30
extern void playSound(char * filename);
 
31
#endif
28
32
#include "PanexP.h"
29
33
 
30
34
#ifdef WINVER
63
67
static void ExposePanex(Widget renew, XEvent * event, Region region);
64
68
static void HidePanex(PanexWidget w, XEvent * event, char **args, int nArgs);
65
69
static void SelectPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
66
 
static void ReleasePanex(PanexWidget w, XEvent * event, char **args, int nArgs);
 
70
static void MotionPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
 
71
static void ReleasePanex(PanexWidget w, XEvent * event, char **args,
 
72
        int nArgs);
67
73
static void GetPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
68
74
static void WritePanex(PanexWidget w, XEvent * event, char **args, int nArgs);
69
75
static void ClearPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
70
 
static void ClearPanexMaybe(PanexWidget w, XEvent * event, char **args, int nArgs);
 
76
static void ClearPanexMaybe(PanexWidget w, XEvent * event, char **args,
 
77
        int nArgs);
71
78
static void ClearPanex2(PanexWidget w, XEvent * event, char **args, int nArgs);
72
79
static void UndoPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
73
80
static void SolvePanex(PanexWidget w, XEvent * event, char **args, int nArgs);
74
 
static void IncrementPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
75
 
static void DecrementPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
 
81
static void SpeedPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
 
82
static void SlowPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
 
83
static void SoundPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
 
84
static void IncrementPanex(PanexWidget w, XEvent * event, char **args,
 
85
        int nArgs);
 
86
static void DecrementPanex(PanexWidget w, XEvent * event, char **args,
 
87
        int nArgs);
76
88
static void ModePanex(PanexWidget w, XEvent * event, char **args, int nArgs);
77
89
static void EnterPanex(PanexWidget w, XEvent * event, char **args, int nArgs);
78
90
static void LeavePanex(PanexWidget w, XEvent * event, char **args, int nArgs);
86
98
 Ctrl<KeyPress>[: Hide()\n\
87
99
 <KeyPress>0x1B: Hide()\n\
88
100
 <Btn1Down>: Select()\n\
 
101
 <Btn1Motion>: Motion()\n\
89
102
 <Btn1Up>: Release()\n\
90
103
 <KeyPress>r: Clear()\n\
91
104
 <KeyPress>c: Clear()\n\
95
108
 <KeyPress>w: Write()\n\
96
109
 <KeyPress>u: Undo()\n\
97
110
 <KeyPress>s: Solve()\n\
 
111
 <KeyPress>0x2E: Speed()\n\
 
112
 <KeyPress>0x3E: Speed()\n\
 
113
 <KeyPress>0x3C: Slow()\n\
 
114
 <KeyPress>0x2C: Slow()\n\
 
115
 <KeyPress>@: Sound()\n\
98
116
 <KeyPress>i: Increment()\n\
99
117
 <KeyPress>d: Decrement()\n\
100
118
 <KeyPress>m: Mode()\n\
106
124
        {(char *) "Quit", (XtActionProc) QuitPanex},
107
125
        {(char *) "Hide", (XtActionProc) HidePanex},
108
126
        {(char *) "Select", (XtActionProc) SelectPanex},
 
127
        {(char *) "Motion", (XtActionProc) MotionPanex},
109
128
        {(char *) "Release", (XtActionProc) ReleasePanex},
110
129
        {(char *) "Clear", (XtActionProc) ClearPanex},
111
130
        {(char *) "ClearMaybe", (XtActionProc) ClearPanexMaybe},
114
133
        {(char *) "Write", (XtActionProc) WritePanex},
115
134
        {(char *) "Undo", (XtActionProc) UndoPanex},
116
135
        {(char *) "Solve", (XtActionProc) SolvePanex},
 
136
        {(char *) "Speed", (XtActionProc) SpeedPanex},
 
137
        {(char *) "Slow", (XtActionProc) SlowPanex},
 
138
        {(char *) "Sound", (XtActionProc) SoundPanex},
117
139
        {(char *) "Increment", (XtActionProc) IncrementPanex},
118
140
        {(char *) "Decrement", (XtActionProc) DecrementPanex},
119
141
        {(char *) "Mode", (XtActionProc) ModePanex},
167
189
         XtRString, (caddr_t) "FALSE"},
168
190
        {XtNdelay, XtCDelay, XtRInt, sizeof (int),
169
191
         XtOffset(PanexWidget, panex.delay),
170
 
         XtRString, (caddr_t) "300"}, /* DEFAULTDELAY */
 
192
         XtRString, (caddr_t) "10"}, /* DEFAULTDELAY */
 
193
        {XtNsound, XtCSound, XtRBoolean, sizeof (Boolean),
 
194
         XtOffset(PanexWidget, panex.sound),
 
195
         XtRString, (caddr_t) "FALSE"},
 
196
        {XtNmoveSound, XtCMoveSound, XtRString, sizeof (String),
 
197
         XtOffset(PanexWidget, panex.moveSound),
 
198
         XtRString, (caddr_t) MOVESOUND},
171
199
        {XtNfont, XtCFont, XtRString, sizeof (String),
172
200
         XtOffset(PanexWidget, panex.font),
173
201
         XtRString, (caddr_t) "9x15bold"},
228
256
WidgetClass panexWidgetClass = (WidgetClass) & panexClassRec;
229
257
 
230
258
#ifndef HAVE_USLEEP
231
 
#if !defined( VMS ) || defined( XVMSUTILS ) ||  ( __VMS_VER >= 70000000 )
 
259
#if !defined( VMS ) || defined( XVMSUTILS ) || ( __VMS_VER >= 70000000 )
232
260
#ifdef USE_XVMSUTILS
233
261
#include <X11/unix_time.h>
234
262
#endif
272
300
#endif
273
301
#else
274
302
#ifdef VMS
275
 
        long        timadr[2];
 
303
        long timadr[2];
276
304
 
277
305
        if (usec != 0) {
278
306
                timadr[0] = -usec * 10;
286
314
 
287
315
#if 0
288
316
        /* (!defined(AIXV3) && !defined(__hpux)) */
289
 
        extern int  select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
317
        extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
290
318
 
291
319
#endif
292
320
 
352
380
#define LOGFILE "panex.log"
353
381
#endif
354
382
 
355
 
static int  startPositions[MAXMODES][MAXSTACKS] =
 
383
static int startPositions[MAXMODES][MAXSTACKS] =
356
384
{
357
385
        {0, -1, -1},
358
386
        {0, -1, 1}
359
387
};
360
 
static int  finishPositions[MAXMODES][MAXSTACKS] =
 
388
static int finishPositions[MAXMODES][MAXSTACKS] =
361
389
{
362
390
        {-1, -1, 0},
363
391
        {1, -1, 0}
372
400
        {2, 0}
373
401
};
374
402
 
 
403
#define MULTDELAY 48
 
404
 
375
405
#if (!defined(WINVER) || (WINVER <= 0x030a)) /* if X or WINDOWS 3.1 or less */
376
406
static void
377
407
Sleep(unsigned int cMilliseconds)
386
416
}
387
417
#endif
388
418
 
 
419
static void
 
420
initTimer(PanexWidget w)
 
421
{
 
422
#ifdef WINVER
 
423
        w->panex.oldTime = GetTickCount();
 
424
#else
 
425
        XFlush(XtDisplay(w));
 
426
        (void) X_GETTIMEOFDAY(&(w->panex.oldTime));
 
427
#endif
 
428
}
 
429
 
 
430
static void
 
431
useTimer(PanexWidget w, int delay)
 
432
{
 
433
        int sleepTime;
 
434
#ifdef WINVER
 
435
        long tv = GetTickCount();
 
436
 
 
437
        sleepTime = delay - (tv - w->panex.oldTime);
 
438
        w->panex.oldTime = tv;
 
439
        if (sleepTime > 0) {
 
440
                Sleep((unsigned int) sleepTime);
 
441
        }
 
442
#else
 
443
        struct timeval tv;
 
444
 
 
445
        XFlush(XtDisplay(w));
 
446
        (void) X_GETTIMEOFDAY(&tv);
 
447
        sleepTime = delay * 1000 - ((tv.tv_sec - w->panex.oldTime.tv_sec) *
 
448
                1000000 + tv.tv_usec - w->panex.oldTime.tv_usec);
 
449
        w->panex.oldTime.tv_sec = tv.tv_sec;
 
450
        w->panex.oldTime.tv_usec = tv.tv_usec;
 
451
        if (sleepTime > 0) {
 
452
                (void) usleep((unsigned int) sleepTime);
 
453
        }
 
454
#endif
 
455
}
 
456
 
389
457
void
390
458
intCat(char ** string, const char * var1, const int var2)
391
459
{
392
460
        if (!(*string = (char *) malloc(strlen(var1) + 21))) {
393
 
                DISPLAY_ERROR("Not enough memory, exiting.");
 
461
                DISPLAY_ERROR("Not enough memory, exiting.");
394
462
        }
395
463
        (void) sprintf(*string, "%s%d", var1, var2);
396
464
}
399
467
stringCat(char ** string, const char * var1, const char * var2)
400
468
{
401
469
        if (!(*string = (char *) malloc(strlen(var1) + strlen(var2) + 1))) {
402
 
                DISPLAY_ERROR("Not enough memory, exiting.");
 
470
                DISPLAY_ERROR("Not enough memory, exiting.");
403
471
        }
404
472
        (void) sprintf(*string, "%s%s", var1, var2);
405
473
}
439
507
        }
440
508
}
441
509
 
 
510
static int
 
511
CartesianX(PanexWidget w, int stack)
 
512
{
 
513
        return stack * w->panex.pos.x + w->panex.delta.x + w->panex.puzzleOffset.x;
 
514
}
 
515
 
 
516
static int
 
517
CartesianY(PanexWidget w, int loc)
 
518
{
 
519
        return loc * w->panex.pos.y + w->panex.delta.y + w->panex.puzzleOffset.y;
 
520
}
 
521
 
442
522
#if 0
443
523
/* Only applies to Panex */
444
 
static int  middlePositions[MAXSTACKS] =
 
524
static int middlePositions[MAXSTACKS] =
445
525
{-1, 0, 1};
446
526
 
447
527
Boolean
448
528
CheckMiddle(PanexWidget w)
449
529
{
450
 
        int         stack, loc;
451
 
        PanexLoc    i;
 
530
        int stack, loc;
 
531
        PanexLoc i;
452
532
 
453
533
        for (stack = 0; stack < MAXSTACKS; stack++)
454
534
                if ((i.stack = middlePositions[stack]) >= 0)
455
535
                        for (loc = 1; loc <= w->panex.tiles; loc++) {
456
536
                                i.loc = loc - 1;
457
537
                                if (w->panex.tileOfPosition[stack][loc].stack != i.stack ||
458
 
                                    w->panex.tileOfPosition[stack][loc].loc != i.loc)
 
538
                                                w->panex.tileOfPosition[stack][loc].loc != i.loc)
459
539
                                        return False;
460
540
                        }
461
541
        return True;
465
545
Boolean
466
546
CheckSolved(PanexWidget w)
467
547
{
468
 
        int         stack, loc;
469
 
        PanexLoc    i;
 
548
        int stack, loc;
 
549
        PanexLoc i;
470
550
 
471
551
        for (stack = 0; stack < MAXSTACKS; stack++)
472
552
                if ((i.stack = finishPositions[w->panex.mode][stack]) >= 0)
473
553
                        for (loc = 1; loc <= w->panex.tiles; loc++) {
474
554
                                i.loc = loc - 1;
475
555
                                if (w->panex.tileOfPosition[stack][loc].stack != i.stack ||
476
 
                                    w->panex.tileOfPosition[stack][loc].loc != i.loc)
 
556
                                                w->panex.tileOfPosition[stack][loc].loc != i.loc)
477
557
                                        return False;
478
558
                        }
479
559
        return True;
483
563
void
484
564
PrintStacks(PanexWidget w)
485
565
{
486
 
        int         stack, position;
 
566
        int stack, position;
487
567
 
488
568
        (void) printf("top: where are the tiles in the stack\n");
489
569
        for (position = 0; position <= w->panex.tiles; position++)
490
570
                for (stack = 0; stack < MAXSTACKS; stack++) {
491
571
                        printf("%d,%d", w->panex.tileOfPosition[stack][position].stack,
492
 
                               w->panex.tileOfPosition[stack][position].loc);
 
572
                                w->panex.tileOfPosition[stack][position].loc);
493
573
                        if (stack + 1 == MAXSTACKS)
494
574
                                (void) printf("\n");
495
575
                        else
500
580
void
501
581
PrintTiles(PanexWidget w)
502
582
{
503
 
        int         stack, position;
 
583
        int stack, position;
504
584
 
505
585
        (void) printf("pot: which stack are the tiles in\n");
506
586
        for (position = 0; position < w->panex.tiles; position++)
507
587
                for (stack = 0; stack <= w->panex.mode; stack++) {
508
588
                        printf("%d,%d", w->panex.positionOfTile[stack][position].stack,
509
 
                               w->panex.positionOfTile[stack][position].loc);
 
589
                                w->panex.positionOfTile[stack][position].loc);
510
590
                        if (stack == w->panex.mode)
511
591
                                (void) printf("\n");
512
592
                        else
517
597
 
518
598
#ifdef WINVER
519
599
static void
520
 
POLYGON(PanexWidget w, GC color, GC lineColor, const POINT * poly, int n,
521
 
                Boolean origin)
 
600
POLYGON(PanexWidget w, Pixmap dr, GC color, GC lineColor,
 
601
                const POINT * poly, int n, Boolean origin)
522
602
{
523
603
        /* CoordModePrevious -> CoordModeOrigin */
524
 
        POINT      *temp = NULL;
525
 
        int         pt;
 
604
        POINT *temp = NULL;
 
605
        int pt;
526
606
 
527
607
        if (!origin) {
528
608
                if (!(temp = (POINT *) malloc(sizeof (POINT) * n))) {
534
614
                        temp[pt].y = temp[pt - 1].y + poly[pt].y;
535
615
                }
536
616
        }
 
617
        if (dr)
 
618
                w->panex.hOldBitmap =
 
619
                        (HBITMAP) SelectObject(w->panex.memDC, dr);
537
620
        w->panex.hPen = CreatePen(PS_SOLID, 1, lineColor);
538
 
        w->panex.hOldPen = (HPEN) SelectObject(w->core.hDC, w->panex.hPen);
 
621
        w->panex.hOldPen = (HPEN) SelectObject(DC(w, dr), w->panex.hPen);
539
622
        w->panex.hBrush = CreateSolidBrush(color);
540
 
        w->panex.hOldBrush = (HBRUSH) SelectObject(w->core.hDC,
 
623
        w->panex.hOldBrush = (HBRUSH) SelectObject(DC(w, dr),
541
624
                w->panex.hBrush);
542
 
        (void) Polygon(w->core.hDC, (origin) ? poly : temp, n);
543
 
        (void) SelectObject(w->core.hDC, w->panex.hOldBrush);
 
625
        (void) Polygon(DC(w, dr), (origin) ? poly : temp, n);
 
626
        (void) SelectObject(DC(w, dr), w->panex.hOldBrush);
544
627
        (void) DeleteObject(w->panex.hBrush);
545
 
        (void) SelectObject(w->core.hDC, w->panex.hOldPen);
 
628
        (void) SelectObject(DC(w, dr), w->panex.hOldPen);
546
629
        (void) DeleteObject(w->panex.hPen);
 
630
        if (dr)
 
631
                (void) SelectObject(w->panex.memDC, w->panex.hOldBitmap);
 
632
 
547
633
        if (!origin) {
548
634
                free(temp);
549
635
        }
551
637
#endif
552
638
 
553
639
static void
554
 
fill3DRect(PanexWidget w, GC gc, GC darkerGC, GC brighterGC,
 
640
fill3DRect(PanexWidget w, Pixmap dr, GC gc, GC darkerGC, GC brighterGC,
555
641
                int x, int y, int width, int height, Boolean raised)
556
642
{
557
643
        GC currentGC = (raised) ? gc : darkerGC;
558
644
 
559
645
        if (width > 2 && height > 2)
560
 
                FILLRECTANGLE(w, currentGC,
 
646
                FILLRECTANGLE(w, dr, currentGC,
561
647
                        x + 1, y + 1, width - 2, height - 2);
562
648
        currentGC = (raised) ? brighterGC : darkerGC;
563
 
        FILLRECTANGLE(w, currentGC,
 
649
        FILLRECTANGLE(w, dr, currentGC,
564
650
                x, y, 1, height);
565
651
        if (width > 1)
566
 
                FILLRECTANGLE(w, currentGC,
 
652
                FILLRECTANGLE(w, dr, currentGC,
567
653
                        x + 1, y, width - 1, 1);
568
 
        FILLRECTANGLE(w, currentGC,
 
654
        FILLRECTANGLE(w, dr, currentGC,
569
655
                x + 1, y, 1, height);
570
656
        if (width > 2)
571
 
                FILLRECTANGLE(w, currentGC,
 
657
                FILLRECTANGLE(w, dr, currentGC,
572
658
                        x + 2, y + 1, width - 2, 1);
573
659
        currentGC = (raised) ? darkerGC : gc;
574
660
        if (width > 1 && height > 1)
575
 
                FILLRECTANGLE(w, currentGC,
 
661
                FILLRECTANGLE(w, dr, currentGC,
576
662
                        x + 1, y + height - 1, width - 1, 1);
577
663
        if (width > 1 && height > 1)
578
 
                FILLRECTANGLE(w, currentGC,
 
664
                FILLRECTANGLE(w, dr, currentGC,
579
665
                        x + width - 1, y, 1, height - 1);
580
666
        if (width > 3 && height > 2)
581
 
                FILLRECTANGLE(w, currentGC,
 
667
                FILLRECTANGLE(w, dr, currentGC,
582
668
                        x + 2, y + height - 2, width - 3, 1);
583
669
        if (width > 2 && height > 3)
584
 
                FILLRECTANGLE(w, currentGC,
 
670
                FILLRECTANGLE(w, dr, currentGC,
585
671
                        x + width - 2, y + 1, 1, height - 3);
586
672
}
587
673
 
588
674
static void
589
 
drawShadow(PanexWidget w, GC gc, int startX, int startY,
 
675
drawShadow(PanexWidget w, Pixmap dr, GC gc, int startX, int startY,
590
676
                int sizeX, int sizeY)
591
677
{
592
 
        FILLRECTANGLE(w, gc,
593
 
                       startX, startY, sizeX, 1);
594
 
        FILLRECTANGLE(w, gc,
595
 
                       startX, startY, 1, sizeY);
 
678
        FILLRECTANGLE(w, dr, gc, startX, startY, sizeX, 1);
 
679
        FILLRECTANGLE(w, dr, gc, startX, startY, 1, sizeY);
596
680
}
597
681
 
598
682
static void
599
 
DrawPyramid(PanexWidget w, int color, int i, int j, int size,
 
683
DrawPyramid(PanexWidget w, Pixmap dr, int color, int i, int j, int size,
600
684
                int offsetPosition)
601
685
{
602
 
        Point      trapazoidList[5];
603
 
        int         k;
604
 
        GC          pyramidGC;
 
686
        Point trapazoidList[5];
 
687
        int k;
 
688
        GC pyramidGC;
605
689
 
606
690
        for (k = 0; k <= 4; k++) {
607
691
                if (ABS(trapazoidUnit[k].x) == 3)
614
698
                else
615
699
                        trapazoidList[k].x = w->panex.tileSize.x /
616
700
                                (2 * (w->panex.tiles + 1));
617
 
                trapazoidList[k].y = (w->panex.tileSize.y - 4) *
 
701
                trapazoidList[k].y = (w->panex.tileSize.y - 5) *
618
702
                        trapazoidUnit[k].y;
619
703
        }
620
704
        k = w->panex.delta.x + i * w->panex.pos.x + w->panex.puzzleOffset.x +
624
708
                w->panex.puzzleOffset.y + offsetPosition + 2;
625
709
        if (w->panex.mono) {
626
710
                pyramidGC = (offsetPosition) ? w->panex.tileGC :
627
 
                        w->panex.borderGC;
 
711
                        w->panex.borderGC;
628
712
        } else {
629
713
#ifndef WINVER
630
714
                if ((w->panex.pyramidColor[color] == w->panex.borderColor)
638
722
                        pyramidGC = w->panex.pyramidGC[color];
639
723
 
640
724
        }
641
 
        POLYGON(w, pyramidGC, pyramidGC, trapazoidList, 4, False);
 
725
        POLYGON(w, dr, pyramidGC, pyramidGC, trapazoidList, 4, False);
642
726
        if (w->panex.mono) {
643
727
 
644
 
                char        buf[2];
 
728
                char buf[2];
645
729
 
646
730
                buf[0] =
647
731
#ifdef WINVER
649
733
#else
650
734
                        w->panex.pyramidName[color][0];
651
735
#endif
652
 
                DRAWTEXT(w, (offsetPosition) ? w->panex.borderGC :
653
 
                            w->panex.tileGC,
654
 
                            k - w->panex.letterOffset.x, trapazoidList[0].y +
655
 
                  w->panex.tileSize.y / 2 + w->panex.letterOffset.y, buf, 1);
656
 
        }
657
 
}
658
 
 
659
 
static void
660
 
DrawTile(PanexWidget w, int i, int j, Boolean erase, int offsetPosition)
661
 
{
662
 
        int         dx, dy;
663
 
        GC          tileGC, borderGC;
664
 
 
 
736
                DRAWTEXT(w, dr, (offsetPosition) ? w->panex.borderGC :
 
737
                        w->panex.tileGC,
 
738
                        k - w->panex.letterOffset.x, trapazoidList[0].y +
 
739
                        w->panex.tileSize.y / 2 + w->panex.letterOffset.y, buf, 1);
 
740
        }
 
741
}
 
742
 
 
743
static void
 
744
FillRectClip(PanexWidget w, Pixmap dr, GC gc, int dx, int dy, int sx, int sy,
 
745
                int wdx, int wdy, int wsx, int wsy)
 
746
{
 
747
        int ndx = wdx, nsx = wsx, ndy = wdy, nsy = wsy;
 
748
 
 
749
        /* w is the clipping window */
 
750
        if (dx + sx < wdx || dx > wdx + wsx ||
 
751
                        dy + sy < wdy || dy > wdy + wsy ||
 
752
                        sx <= 0 || sy <= 0 || wsx <= 0 || wsy <= 0) {
 
753
                return;
 
754
        }
 
755
        if (dx > wdx) {
 
756
                ndx = dx;
 
757
                nsx = wsx - dx + wdx;
 
758
        }
 
759
        if (dy > wdy) {
 
760
                ndy = dy;
 
761
                nsy = wsy - dy + wdy;
 
762
        }
 
763
        if (ndx + nsx > dx + sx) {
 
764
                nsx = sx + dx - ndx;
 
765
        }
 
766
        if (ndy + nsy > dy + sy) {
 
767
                nsy = sy + dy - ndy;
 
768
        }
 
769
        FILLRECTANGLE(w, dr, gc, ndx, ndy, nsx, nsy);
 
770
}
 
771
 
 
772
static void
 
773
DrawSlot(PanexWidget w, int stack, int x, int y, int width, int height)
 
774
{
 
775
        Pixmap dr = 0;
 
776
        GC gc = w->panex.inverseGC;
 
777
        int sizex = w->panex.tileSize.x / 3;
 
778
        int sizey = w->panex.tileSize.y / 3;
 
779
 
 
780
        FILLRECTANGLE(w, dr, gc, x, y, width, height);
 
781
        FillRectClip(w, dr, w->panex.borderGC,
 
782
                sizex + w->panex.delta.x +
 
783
                w->panex.puzzleOffset.x,
 
784
                w->panex.delta.y / 2 + w->panex.puzzleOffset.y + sizey,
 
785
                sizex + (MAXSTACKS - 1) * w->panex.pos.x,
 
786
                sizey,
 
787
                x, y, width, height);
 
788
        FillRectClip(w, dr, w->panex.borderGC,
 
789
                sizex + w->panex.delta.x +
 
790
                w->panex.puzzleOffset.x + stack * w->panex.pos.x,
 
791
                w->panex.delta.y / 2 + w->panex.puzzleOffset.y + sizey,
 
792
                sizex,
 
793
                (w->panex.tiles + 1) * w->panex.pos.y + w->panex.delta.y -
 
794
                1 - 2 * sizey,
 
795
                x, y, width, height);
 
796
        FillRectClip(w, dr, w->panex.borderGC,
 
797
                sizex + w->panex.delta.x +
 
798
                w->panex.puzzleOffset.x + w->panex.pos.x,
 
799
                w->panex.delta.y / 2 + w->panex.puzzleOffset.y + sizey,
 
800
                sizex,
 
801
                (w->panex.tiles + 1) * w->panex.pos.y + w->panex.delta.y -
 
802
                1 - 2 * sizey,
 
803
                x, y, width, height);
 
804
}
 
805
 
 
806
static void
 
807
DrawTile(PanexWidget w, int i, int j, Boolean erase, int pressedOffset,
 
808
                int offsetX, int offsetY)
 
809
{
 
810
        int dx, dy, sx, sy;
 
811
        int tileI = w->panex.tileOfPosition[i][j].stack;
 
812
        int tileJ = w->panex.tileOfPosition[i][j].loc;
 
813
        Pixmap dr = 0;
 
814
 
 
815
        dx = CartesianX(w, i) + pressedOffset + offsetX;
 
816
        dy = CartesianY(w, j) + pressedOffset + offsetY;
 
817
        sx = CartesianX(w, tileI);
 
818
        sy = CartesianY(w, tileJ);
665
819
        if (erase) {
666
 
                tileGC = w->panex.inverseGC;
667
 
                borderGC = w->panex.borderGC;
668
 
        } else {
669
 
                tileGC = w->panex.tileGC;
670
 
                borderGC = w->panex.borderGC;
671
 
        }
672
 
        dx = i * w->panex.pos.x + w->panex.delta.x + w->panex.puzzleOffset.x;
673
 
        dy = j * w->panex.pos.y + w->panex.delta.y + w->panex.puzzleOffset.y;
674
 
        if (erase)  {
675
820
                /* Draw Slots */
676
 
                FILLRECTANGLE(w, tileGC,
677
 
                        dx + offsetPosition, dy + offsetPosition,
 
821
                FILLRECTANGLE(w, dr, w->panex.inverseGC,
 
822
                        dx, dy,
678
823
                        w->panex.tileSize.x, w->panex.tileSize.y);
679
824
                if (j == 0) {
680
825
                        if (i == 0) {
681
 
                                FILLRECTANGLE(w, borderGC,
682
 
                                        dx + w->panex.tileSize.x / 3 + offsetPosition,
683
 
                                        dy + w->panex.tileSize.y / 3 - 1,
 
826
                                FILLRECTANGLE(w, dr, w->panex.borderGC,
 
827
                                        dx + w->panex.tileSize.x / 3,
 
828
                                        dy + w->panex.tileSize.y / 3 - 1 -
 
829
                                        pressedOffset,
684
830
                                        2 * w->panex.tileSize.x / 3 + 2,
685
831
                                        w->panex.tileSize.y / 3);
686
832
                        } else if (i == MAXSTACKS - 1) {
687
 
                                FILLRECTANGLE(w, borderGC,
688
 
                                        dx + offsetPosition,
689
 
                                        dy + w->panex.tileSize.y / 3 - 1,
 
833
                                FILLRECTANGLE(w, dr, w->panex.borderGC,
 
834
                                        dx,
 
835
                                        dy + w->panex.tileSize.y / 3 - 1 -
 
836
                                        pressedOffset,
690
837
                                        2 * w->panex.tileSize.x / 3 - 1,
691
838
                                        w->panex.tileSize.y / 3 +
692
 
                                        offsetPosition);
 
839
                                        pressedOffset);
693
840
                        } else {
694
 
                                FILLRECTANGLE(w, borderGC,
695
 
                                        dx + offsetPosition,
696
 
                                        dy + w->panex.tileSize.y / 3 - 1,
 
841
                                FILLRECTANGLE(w, dr, w->panex.borderGC,
 
842
                                        dx,
 
843
                                        dy + w->panex.tileSize.y / 3 - 1 -
 
844
                                        pressedOffset,
697
845
                                        w->panex.tileSize.x + 1,
698
846
                                        w->panex.tileSize.y / 3);
699
847
                        }
700
 
                        FILLRECTANGLE(w, borderGC,
701
 
                                dx + w->panex.tileSize.x / 3,
702
 
                                dy + w->panex.tileSize.y / 3 - 1,
 
848
                        FILLRECTANGLE(w, dr, w->panex.borderGC,
 
849
                                dx + w->panex.tileSize.x / 3 - pressedOffset,
 
850
                                dy + w->panex.tileSize.y / 3 - 1 - pressedOffset,
703
851
                                w->panex.tileSize.x / 3,
704
852
                                w->panex.tileSize.y - w->panex.tileSize.y / 3 +
705
 
                                2 + offsetPosition - 1);
 
853
                                1 + pressedOffset);
706
854
                } else if (j == w->panex.tiles) {
707
 
                        FILLRECTANGLE(w, borderGC,
708
 
                                dx + w->panex.tileSize.x / 3, dy,
 
855
                        FILLRECTANGLE(w, dr, w->panex.borderGC,
 
856
                                dx + w->panex.tileSize.x / 3 - pressedOffset,
 
857
                                dy - pressedOffset,
709
858
                                w->panex.tileSize.x / 3,
710
859
                                2 * w->panex.tileSize.y / 3 + 2);
711
860
                } else {
712
 
                        FILLRECTANGLE(w, borderGC,
713
 
                                dx + w->panex.tileSize.x / 3, dy,
 
861
                        FILLRECTANGLE(w, dr, w->panex.borderGC,
 
862
                                dx + w->panex.tileSize.x / 3 - pressedOffset,
 
863
                                dy - pressedOffset,
714
864
                                w->panex.tileSize.x / 3,
715
 
                                w->panex.tileSize.y + offsetPosition);
716
 
                }
717
 
        } else {
718
 
                if (offsetPosition != 0) {
719
 
                        drawShadow(w, w->panex.tileDarkerGC,
720
 
                                dx, dy,
721
 
                                w->panex.tileSize.x, w->panex.tileSize.y);
722
 
                }
723
 
                dx += offsetPosition;
724
 
                dy += offsetPosition;
725
 
 
726
 
                fill3DRect(w, tileGC,
727
 
                        w->panex.tileDarkerGC, w->panex.tileBrighterGC,
728
 
                        dx, dy, w->panex.tileSize.x, w->panex.tileSize.y,
729
 
                        offsetPosition == 0);
730
 
                DrawPyramid(w,
731
 
                            w->panex.tileOfPosition[i][j].stack, i, j,
732
 
                            w->panex.tileOfPosition[i][j].loc, offsetPosition);
733
 
        }
 
865
                                w->panex.tileSize.y + pressedOffset);
 
866
                }
 
867
                return;
 
868
        }
 
869
#ifdef WINVER
 
870
        w->panex.hOldBitmap = (HBITMAP) SelectObject(w->panex.memDC,
 
871
                w->panex.bufferTiles[pressedOffset]);
 
872
        BitBlt(w->core.hDC,
 
873
                dx, dy,
 
874
                w->panex.tileSize.x, w->panex.tileSize.y,
 
875
                w->panex.memDC,
 
876
                sx, sy,
 
877
                SRCCOPY);
 
878
        SelectObject(w->panex.memDC, w->panex.hOldBitmap);
 
879
#else
 
880
        XSetGraphicsExposures(XtDisplay(w), w->panex.tileGC, False);
 
881
        XCopyArea(XtDisplay(w),
 
882
                w->panex.bufferTiles[pressedOffset],
 
883
                XtWindow(w),
 
884
                w->panex.tileGC,
 
885
                sx, sy,
 
886
                w->panex.tileSize.x, w->panex.tileSize.y,
 
887
                dx, dy);
 
888
#endif
 
889
}
 
890
 
 
891
 
 
892
static void
 
893
DrawBufferedTile(PanexWidget w, int i, int j, int pressedOffset)
 
894
{
 
895
        Pixmap *dr;
 
896
        int dx, dy;
 
897
        GC tileGC;
 
898
 
 
899
        dr = &(w->panex.bufferTiles[pressedOffset]);
 
900
        tileGC = w->panex.tileGC;
 
901
        dx = CartesianX(w, i) + pressedOffset;
 
902
        dy = CartesianY(w, j) + pressedOffset;
 
903
        if (pressedOffset != 0) {
 
904
                drawShadow(w, *dr, w->panex.tileDarkerGC,
 
905
                        dx - pressedOffset, dy - pressedOffset,
 
906
                        w->panex.tileSize.x, w->panex.tileSize.y);
 
907
        }
 
908
        fill3DRect(w, *dr, tileGC,
 
909
                w->panex.tileDarkerGC, w->panex.tileBrighterGC,
 
910
                dx, dy, w->panex.tileSize.x, w->panex.tileSize.y,
 
911
                pressedOffset == 0);
 
912
        if (pressedOffset != 0) {
 
913
                FILLRECTANGLE(w, *dr, w->panex.tileGC,
 
914
                        dx + w->panex.tileSize.x - 2, dy - 1, 1, 3);
 
915
                FILLRECTANGLE(w, *dr, w->panex.tileGC,
 
916
                        dx - 1, dy + w->panex.tileSize.y - 2, 3, 1);
 
917
        }
 
918
        DrawPyramid(w, *dr,
 
919
                i, i, j, j, pressedOffset);
 
920
}
 
921
 
 
922
static void
 
923
DrawAllBufferedTiles(const PanexWidget w)
 
924
{
 
925
        int i, j, l;
 
926
 
 
927
        for (i = 0; i <= w->panex.mode; i++)
 
928
                for (j = 0; j < w->panex.tiles; j++)
 
929
                        for (l = 0; l < 2; l++)
 
930
                                DrawBufferedTile(w, i, j, l);
734
931
}
735
932
 
736
933
void
737
934
DrawAllTiles(PanexWidget w)
738
935
{
739
 
        int         i, j;
740
 
 
741
 
        for (i = 0; i < MAXSTACKS; i++)
742
 
                for (j = 0; j <= w->panex.tiles; j++)
743
 
                        if (w->panex.tileOfPosition[i][j].stack >= 0)
744
 
                                DrawTile(w, i, j, False, FALSE);
745
 
}
746
 
 
747
 
static void
748
 
DrawSlots(PanexWidget w)
749
 
{
750
 
        int         i, dx, dy, y, sizey;
751
 
 
 
936
        int i, j;
 
937
 
 
938
        for (i = 0; i <= w->panex.mode; i++)
 
939
                for (j = 0; j < w->panex.tiles; j++)
 
940
                        DrawTile(w,
 
941
                                w->panex.positionOfTile[i][j].stack,
 
942
                                w->panex.positionOfTile[i][j].loc,
 
943
                                False, FALSE, 0, 0);
 
944
}
 
945
 
 
946
static void
 
947
AnimateSlide(PanexWidget w, int currentStack, int currentPosition,
 
948
                int nextStack, int nextPosition, int fast)
 
949
{
 
950
        int diffStack = nextStack - currentStack;
 
951
        int diffPosition = nextPosition - currentPosition;
 
952
        int dir = 0, spaces = 0, inc;
 
953
        int gapI = 0, moveI = 0, space;
 
954
        int dx, dy;
 
955
        int ix = 0, iy = 0;
 
956
 
 
957
        if (diffPosition > 0) {
 
958
                dir = BOTTOM;
 
959
                spaces = diffPosition;
 
960
                moveI = w->panex.pos.y; 
 
961
        } else if (diffPosition < 0) {
 
962
                dir = TOP;
 
963
                spaces = -diffPosition;
 
964
                moveI = w->panex.pos.y;
 
965
        } else if (diffStack > 0) {
 
966
                dir = RIGHT;
 
967
                spaces = diffStack;
 
968
                moveI = w->panex.pos.x;
 
969
        } else if (diffStack < 0) {
 
970
                dir = LEFT;
 
971
                spaces = -diffStack;
 
972
                moveI = w->panex.pos.x;
 
973
        }
 
974
                space = spaces * moveI;
 
975
                if ((dir == RIGHT) || (dir == LEFT)) {
 
976
                        gapI = w->panex.pos.x * fast / w->panex.numSlices;
 
977
                } else if ((dir == TOP) || (dir == BOTTOM)) {
 
978
                        gapI = w->panex.pos.y * fast / w->panex.numSlices;
 
979
                }
 
980
                if (gapI == 0)
 
981
                        gapI++;
 
982
                initTimer(w);
 
983
                for (inc = 0; inc < space + gapI; inc += gapI) {
 
984
                        if (inc > space) {
 
985
                                inc = space;
 
986
                        }
 
987
                        /* Calculate deltas */
 
988
                        dx = CartesianX(w, currentStack);
 
989
                        dy = CartesianY(w, currentPosition);
 
990
 
 
991
                        if ((dir == RIGHT) || (dir == LEFT)) {
 
992
                                ix = ((dir == RIGHT) ? inc : -inc);
 
993
                                iy = 0;
 
994
                        } else if ((dir == TOP) || (dir == BOTTOM)) {
 
995
                                ix = 0;
 
996
                                iy = ((dir == BOTTOM) ? inc : -inc);
 
997
                        }
 
998
                        DrawTile(w, currentStack, currentPosition, False,
 
999
                                FALSE, ix, iy);
 
1000
                        /* Erase old slivers */
 
1001
                        ix += dx;
 
1002
                        iy += dy;
 
1003
                        if (inc != 0)
 
1004
                        switch (dir) {
 
1005
                        case TOP:
 
1006
                                DrawSlot(w, currentStack,
 
1007
                                        ix, iy + w->panex.tileSize.y,
 
1008
                                        w->panex.tileSize.x + 1, gapI);
 
1009
                                useTimer(w, w->panex.delay);
 
1010
                                break;
 
1011
                        case RIGHT:
 
1012
                                DrawSlot(w, currentStack,
 
1013
                                        ix - gapI, iy,
 
1014
                                        gapI, w->panex.tileSize.y + 1);
 
1015
                                useTimer(w, 3 * w->panex.delay);
 
1016
                                break;
 
1017
                        case BOTTOM:
 
1018
                                DrawSlot(w, currentStack,
 
1019
                                        ix, iy - gapI,
 
1020
                                        w->panex.tileSize.x + 1, gapI);
 
1021
                                useTimer(w, w->panex.delay);
 
1022
                                break;
 
1023
                        case LEFT:
 
1024
                                DrawSlot(w, currentStack,
 
1025
                                        ix + w->panex.tileSize.x, iy,
 
1026
                                        gapI + 1, w->panex.tileSize.y + 1);
 
1027
                                useTimer(w, 3 * w->panex.delay);
 
1028
                                break;
 
1029
                        }
 
1030
                }
 
1031
}
 
1032
 
 
1033
static void
 
1034
DrawSlots(PanexWidget w, Pixmap dr)
 
1035
{
 
1036
        int i, dx, dy, y, sizex, sizey;
 
1037
 
 
1038
        sizex = w->panex.tileSize.x / 3;
752
1039
        sizey = w->panex.tileSize.y / 3;
753
1040
        if (sizey == 0)
754
1041
                sizey = 1;
755
 
        dx = w->panex.tileSize.x / 3 + w->panex.delta.x +
756
 
                w->panex.puzzleOffset.x;
 
1042
        dx = sizex + w->panex.delta.x + w->panex.puzzleOffset.x;
757
1043
        y = (w->panex.tiles + 1) * w->panex.pos.y + w->panex.delta.y;
758
1044
        dy = w->panex.delta.y / 2 + w->panex.puzzleOffset.y + sizey;
759
 
        FILLRECTANGLE(w, w->panex.borderGC, dx, dy,
760
 
          w->panex.tileSize.x / 3 + (MAXSTACKS - 1) * w->panex.pos.x,
761
 
                       w->panex.tileSize.y / 3);
 
1045
        FILLRECTANGLE(w, dr, w->panex.borderGC, dx, dy,
 
1046
                sizex + (MAXSTACKS - 1) * w->panex.pos.x,
 
1047
                sizey);
762
1048
        for (i = 0; i < MAXSTACKS; i++) {
763
 
                FILLRECTANGLE(w, w->panex.borderGC, dx, dy,
764
 
                w->panex.tileSize.x / 3, y - 1 - 2 * w->panex.tileSize.y / 3);
 
1049
                FILLRECTANGLE(w, dr, w->panex.borderGC, dx, dy,
 
1050
                        sizex, y - 1 - 2 * sizey);
765
1051
                dx += w->panex.pos.x;
766
1052
        }
767
1053
}
768
1054
 
769
1055
static void
770
 
EraseFrame(PanexWidget w, Boolean focus)
 
1056
EraseFrame(PanexWidget w, Pixmap dr, Boolean focus)
771
1057
{
772
 
        DRAWRECTANGLE(w, (focus) ? w->panex.frameGC : w->panex.inverseGC,
 
1058
        DRAWRECTANGLE(w, dr, (focus) ? w->panex.frameGC : w->panex.inverseGC,
773
1059
                0, 0, w->core.width - 1, w->core.height - 1);
774
 
        FILLRECTANGLE(w, w->panex.inverseGC,
 
1060
        FILLRECTANGLE(w, dr, w->panex.inverseGC,
775
1061
                1, 1, w->core.width - 2, w->core.height - 2);
776
1062
}
777
1063
 
778
1064
static void
779
 
DrawFrame(PanexWidget w, Boolean focus)
 
1065
DrawFrame(PanexWidget w, Pixmap dr, Boolean focus)
780
1066
{
781
 
        DRAWRECTANGLE(w, (focus) ? w->panex.frameGC : w->panex.borderGC,
 
1067
        DRAWRECTANGLE(w, dr, (focus) ? w->panex.frameGC : w->panex.borderGC,
782
1068
                0, 0, w->core.width - 1, w->core.height - 1);
783
1069
}
784
1070
 
 
1071
static void
 
1072
MoveNoTiles(PanexWidget w)
 
1073
{
 
1074
        SetPanex(w, PANEX_IGNORE);
 
1075
}
 
1076
 
785
1077
int
786
 
TopOfStack(PanexWidget w, int stack)
 
1078
TopOfStack(PanexWidget w, int stack, int start)
787
1079
{
788
 
        int         i;
 
1080
        int i;
789
1081
 
790
 
        for (i = 0; i <= w->panex.tiles; i++)
 
1082
        for (i = start; i <= w->panex.tiles; i++)
791
1083
                if (w->panex.tileOfPosition[stack][i].stack >= 0)
792
1084
                        return i;
793
1085
        return -1;
796
1088
static int
797
1089
RequestMove(PanexWidget w, int fromStack, int fromPosition, int toStack)
798
1090
{
799
 
        int         i;
 
1091
        int i;
800
1092
 
801
1093
        /* Do not have to check above stack since it is the top one */
802
 
        if (toStack > fromStack)
 
1094
        if (toStack > fromStack) {
803
1095
                for (i = fromStack + 1; i <= toStack; i++) {
804
1096
                        if (w->panex.tileOfPosition[i][0].stack >= 0)
805
1097
                                return (-1);
806
 
        } else                  /* Already ruled out toStack == fromStack */
 
1098
                }
 
1099
                i = TopOfStack(w, toStack, 0);
 
1100
        } else if (toStack < fromStack) {
807
1101
                for (i = fromStack - 1; i >= toStack; i--) {
808
1102
                        if (w->panex.tileOfPosition[i][0].stack >= 0)
809
1103
                                return (-1);
810
1104
                }
811
 
        i = TopOfStack(w, toStack);
 
1105
                i = TopOfStack(w, toStack, 0);
 
1106
        } else {
 
1107
                /* Ruled out toStack == fromStack, except for motion */
 
1108
                i = TopOfStack(w, toStack, 1);
 
1109
        }
812
1110
        i = (i == -1) ? w->panex.tiles : i - 1;
813
1111
        if (w->panex.mode == HANOI) {
814
 
                if (i == w->panex.tiles || w->panex.tileOfPosition[toStack][i + 1].loc >
815
 
                    w->panex.tileOfPosition[fromStack][fromPosition].loc)
 
1112
                if (i == w->panex.tiles ||
 
1113
                                w->panex.tileOfPosition[toStack][i + 1].loc >=
 
1114
                                w->panex.tileOfPosition[fromStack][fromPosition].loc)
816
1115
                        return i;
817
1116
                else
818
1117
                        return -2;
827
1126
static int
828
1127
SelectTile(PanexWidget w, int x)
829
1128
{
830
 
        int         i;
 
1129
        int i;
831
1130
 
832
1131
        x -= w->panex.puzzleOffset.x;
833
1132
        i = (x - w->panex.delta.x / 2) / w->panex.pos.x;
835
1134
                i = 0;
836
1135
        else if (i >= MAXSTACKS)
837
1136
                i = MAXSTACKS - 1;
838
 
        /*
839
 
           y -= w->panex.puzzleOffset.y;
840
 
           j = (y - w->panex.delta.y / 2) / w->panex.pos.y;
841
 
           if (j < 0)
842
 
           j = 0;
843
 
           else if (j > w->panex.tiles)
844
 
           j = w->panex.tiles;
845
 
         */
 
1137
#if 0
 
1138
        y -= w->panex.puzzleOffset.y;
 
1139
        j = (y - w->panex.delta.y / 2) / w->panex.pos.y;
 
1140
        if (j < 0)
 
1141
                j = 0;
 
1142
        else if (j > w->panex.tiles)
 
1143
                j = w->panex.tiles;
 
1144
#endif
846
1145
        return i;
847
1146
}
848
1147
 
849
 
 
850
 
static void
851
 
SlideTile(PanexWidget w, int fromStack, int fromPosition, int toStack, int toPosition)
852
 
{
853
 
        PanexLoc    top;
854
 
        int         currentStack = fromStack, currentPosition = fromPosition;
855
 
        int         nextStack = fromStack, nextPosition = fromPosition;
856
 
 
857
 
        while (currentPosition > 0) {
858
 
                DrawTile(w, currentStack, currentPosition, True, FALSE);
859
 
                top = w->panex.tileOfPosition[currentStack][currentPosition];
860
 
                nextPosition = currentPosition - 1;
861
 
                w->panex.tileOfPosition[nextStack][nextPosition] = top;
862
 
                w->panex.positionOfTile[top.stack][top.loc].stack = nextStack;
863
 
                w->panex.positionOfTile[top.stack][top.loc].loc = nextPosition;
864
 
                w->panex.tileOfPosition[currentStack][currentPosition].stack = -1;
865
 
                currentPosition = nextPosition;
866
 
                DrawTile(w, currentStack, currentPosition, False, FALSE);
867
 
#ifndef WINVER
868
 
                XFlush(XtDisplay(w));
869
 
#endif
870
 
                Sleep((unsigned int) w->panex.delay / (w->panex.tiles + MAXSTACKS - 1));
871
 
        }
872
 
        while (currentStack != toStack) {
873
 
                DrawTile(w, currentStack, currentPosition, True, FALSE);
874
 
                top = w->panex.tileOfPosition[currentStack][currentPosition];
875
 
                nextStack = (currentStack < toStack) ? currentStack + 1 :
876
 
                        currentStack - 1;
877
 
                w->panex.tileOfPosition[nextStack][nextPosition] = top;
878
 
                w->panex.positionOfTile[top.stack][top.loc].stack = nextStack;
879
 
                w->panex.positionOfTile[top.stack][top.loc].loc = nextPosition;
880
 
                w->panex.tileOfPosition[currentStack][currentPosition].stack = -1;
881
 
                currentStack = nextStack;
882
 
                DrawTile(w, currentStack, currentPosition, False, FALSE);
883
 
#ifndef WINVER
884
 
                XFlush(XtDisplay(w));
885
 
#endif
886
 
                Sleep((unsigned int) w->panex.delay / (w->panex.tiles + MAXSTACKS - 1));
887
 
        }
888
 
        while (currentPosition < toPosition) {
889
 
                DrawTile(w, currentStack, currentPosition, True, FALSE);
890
 
                top = w->panex.tileOfPosition[currentStack][currentPosition];
891
 
                nextPosition = currentPosition + 1;
892
 
                w->panex.tileOfPosition[nextStack][nextPosition] = top;
893
 
                w->panex.positionOfTile[top.stack][top.loc].stack = nextStack;
894
 
                w->panex.positionOfTile[top.stack][top.loc].loc = nextPosition;
895
 
                w->panex.tileOfPosition[currentStack][currentPosition].stack = -1;
896
 
                currentPosition = nextPosition;
897
 
                DrawTile(w, currentStack, currentPosition, False, FALSE);
898
 
#ifndef WINVER
899
 
                XFlush(XtDisplay(w));
900
 
#endif
901
 
                Sleep((unsigned int) w->panex.delay / (w->panex.tiles + MAXSTACKS - 1));
 
1148
static void
 
1149
VirtualMove(PanexWidget w, int currentStack, int currentPosition,
 
1150
                int nextStack, int nextPosition)
 
1151
{
 
1152
        PanexLoc top;
 
1153
 
 
1154
        top = w->panex.tileOfPosition[currentStack][currentPosition];
 
1155
        w->panex.tileOfPosition[nextStack][nextPosition] = top;
 
1156
        w->panex.positionOfTile[top.stack][top.loc].stack = nextStack;
 
1157
        w->panex.positionOfTile[top.stack][top.loc].loc = nextPosition;
 
1158
        w->panex.tileOfPosition[currentStack][currentPosition].stack = -1;
 
1159
}
 
1160
 
 
1161
static void
 
1162
DiscreteMoves(PanexWidget w, int currentStack, int currentPosition,
 
1163
                int nextStack, int nextPosition)
 
1164
{
 
1165
        DrawTile(w, currentStack, currentPosition, True, FALSE, 0, 0);
 
1166
        VirtualMove(w, currentStack, currentPosition, nextStack, nextPosition);
 
1167
        DrawTile(w, nextStack, nextPosition, False, FALSE, 0, 0);
 
1168
#ifndef WINVER
 
1169
        XFlush(XtDisplay(w));
 
1170
#endif
 
1171
        Sleep((unsigned int) MULTDELAY * w->panex.delay /
 
1172
                (w->panex.tiles + MAXSTACKS - 1));
 
1173
}
 
1174
 
 
1175
static void
 
1176
SlideTile(PanexWidget w, int fromStack, int fromPosition,
 
1177
                int toStack, int toPosition)
 
1178
{
 
1179
        int currentStack = fromStack, currentPosition = fromPosition;
 
1180
        int nextStack = fromStack, nextPosition = fromPosition;
 
1181
 
 
1182
        if (currentPosition > 0) {
 
1183
                if (w->panex.delay > 0) {
 
1184
                        nextPosition = 0;
 
1185
                        AnimateSlide(w, currentStack, currentPosition,
 
1186
                                nextStack, nextPosition, NORMAL);
 
1187
                        VirtualMove(w, currentStack, currentPosition,
 
1188
                                nextStack, nextPosition);
 
1189
                        currentPosition = nextPosition;
 
1190
                } else {
 
1191
                        while (currentPosition > 0) {
 
1192
                                nextPosition = currentPosition - 1;
 
1193
                                DiscreteMoves(w, currentStack, currentPosition,
 
1194
                                        nextStack, nextPosition);
 
1195
                                currentPosition = nextPosition;
 
1196
                        }
 
1197
                }
 
1198
#ifdef USE_SOUND
 
1199
                if (w->panex.sound) {
 
1200
                        playSound((char *) MOVESOUND);
 
1201
                }
 
1202
#endif
 
1203
        }
 
1204
        if (currentStack != toStack) {
 
1205
                if (w->panex.delay > 0) {
 
1206
                        nextStack = toStack;
 
1207
                        AnimateSlide(w, currentStack, currentPosition,
 
1208
                                nextStack, nextPosition, NORMAL);
 
1209
                        VirtualMove(w, currentStack, currentPosition,
 
1210
                                nextStack, nextPosition);
 
1211
                        currentStack = nextStack;
 
1212
                } else {
 
1213
                        while (currentStack != toStack) {
 
1214
                                nextStack = (currentStack < toStack) ?
 
1215
                                        currentStack + 1 : currentStack - 1;
 
1216
                                nextPosition = currentPosition;
 
1217
                                DiscreteMoves(w, currentStack, currentPosition,
 
1218
                                        nextStack, nextPosition);
 
1219
                                currentStack = nextStack;
 
1220
                        }
 
1221
                }
 
1222
#ifdef USE_SOUND
 
1223
                if (w->panex.sound) {
 
1224
                        playSound((char *) MOVESOUND);
 
1225
                }
 
1226
#endif
 
1227
        }
 
1228
        if (currentPosition < toPosition) {
 
1229
                if (w->panex.delay > 0) {
 
1230
                        nextPosition = toPosition;
 
1231
                        AnimateSlide(w, currentStack, currentPosition,
 
1232
                                nextStack, nextPosition, NORMAL);
 
1233
                        VirtualMove(w, currentStack, currentPosition,
 
1234
                                nextStack, nextPosition);
 
1235
                        currentPosition = nextPosition;
 
1236
                } else {
 
1237
                        while (currentPosition < toPosition) {
 
1238
                                nextPosition = currentPosition + 1;
 
1239
                                DiscreteMoves(w, currentStack, currentPosition,
 
1240
                                        nextStack, nextPosition);
 
1241
                                currentPosition = nextPosition;
 
1242
                        }
 
1243
                }
 
1244
#ifdef USE_SOUND
 
1245
                if (w->panex.sound) {
 
1246
                        playSound((char *) MOVESOUND);
 
1247
                }
 
1248
#endif
902
1249
        }
903
1250
}
904
1251
 
905
1252
static int
906
1253
MoveTile(PanexWidget w, int fromStack, int fromPosition, int toStack)
907
1254
{
908
 
        int         toPosition;
 
1255
        int toPosition;
909
1256
 
910
1257
        if ((toPosition = RequestMove(w, fromStack, fromPosition, toStack)) >= 0)
911
1258
                SlideTile(w, fromStack, fromPosition, toStack, toPosition);
912
1259
        return toPosition;
913
1260
}
914
1261
 
 
1262
static Boolean
 
1263
MoveTileToLimbo(PanexWidget w, int fromStack, int fromPosition, int toStack)
 
1264
{
 
1265
        Boolean aMove;
 
1266
 
 
1267
        aMove = (RequestMove(w, fromStack, fromPosition, toStack) >= 0);
 
1268
        if (aMove)
 
1269
                SlideTile(w, fromStack, fromPosition, toStack, 0);
 
1270
        return aMove;
 
1271
}
 
1272
 
915
1273
static void
916
1274
ResetTiles(PanexWidget w)
917
1275
{
918
 
        int         stack, loc;
919
 
        PanexLoc    i;
 
1276
        int stack, loc;
 
1277
        PanexLoc i;
920
1278
 
921
1279
        w->panex.currentStack = -1;
922
1280
        for (stack = 0; stack < MAXMODES; stack++) {
931
1289
        }
932
1290
        for (stack = 0; stack <= w->panex.mode; stack++) {
933
1291
                if (!(w->panex.positionOfTile[stack] = (PanexLoc *)
934
 
                      malloc(sizeof (PanexLoc) * w->panex.tiles))) {
935
 
                        DISPLAY_ERROR("Not enough memory, exiting.");
 
1292
                                malloc(sizeof (PanexLoc) * w->panex.tiles))) {
 
1293
                        DISPLAY_ERROR("Not enough memory, exiting.");
936
1294
                }
937
1295
                if (!(startLoc[stack] = (PanexLoc *)
938
 
                      malloc(sizeof (PanexLoc) * w->panex.tiles))) {
939
 
                        DISPLAY_ERROR("Not enough memory, exiting.");
 
1296
                                malloc(sizeof (PanexLoc) * w->panex.tiles))) {
 
1297
                        DISPLAY_ERROR("Not enough memory, exiting.");
940
1298
                }
941
1299
        }
942
1300
        for (stack = 0; stack < MAXSTACKS; stack++) {
943
1301
                if (w->panex.tileOfPosition[stack])
944
1302
                        free(w->panex.tileOfPosition[stack]);
945
1303
                if (!(w->panex.tileOfPosition[stack] = (PanexLoc *)
946
 
                      malloc(sizeof (PanexLoc) * (w->panex.tiles + 1)))) {
947
 
                        DISPLAY_ERROR("Not enough memory, exiting.");
 
1304
                                malloc(sizeof (PanexLoc) *
 
1305
                                (w->panex.tiles + 1)))) {
 
1306
                        DISPLAY_ERROR("Not enough memory, exiting.");
948
1307
                }
949
1308
        }
950
1309
        for (stack = 0; stack <= w->panex.mode; stack++) {
968
1327
        }
969
1328
        FlushMoves(w);
970
1329
        w->panex.started = False;
 
1330
        w->panex.cheat = False;
971
1331
}
972
1332
 
973
1333
static void
974
1334
GetTiles(PanexWidget w)
975
1335
{
976
 
        FILE       *fp;
977
 
        int         c, i, tiles, mode, moves;
 
1336
        FILE *fp;
 
1337
        int c, i, tiles, mode, moves;
978
1338
        char *buf1 = NULL, *buf2 = NULL;
979
1339
        char *fname, *lname, *name;
980
1340
 
1081
1441
static void
1082
1442
WriteTiles(PanexWidget w)
1083
1443
{
1084
 
        FILE       *fp;
 
1444
        FILE *fp;
1085
1445
        char *buf1 = NULL, *buf2 = NULL;
1086
1446
        char *fname, *lname, *name;
1087
1447
 
1136
1496
{
1137
1497
        if (w->panex.currentStack >= 0)
1138
1498
                return;
1139
 
        w->panex.cheat = False;
1140
 
        EraseFrame(w, w->panex.focus);
 
1499
        EraseFrame(w, 0, w->panex.focus);
1141
1500
        ResetTiles(w);
1142
 
        DrawSlots(w);
 
1501
        DrawSlots(w, 0);
1143
1502
        DrawAllTiles(w);
1144
1503
        SetPanex(w, PANEX_RESET);
1145
1504
}
1148
1507
UndoTiles(PanexWidget w)
1149
1508
{
1150
1509
        if (MadeMoves() && w->panex.currentStack < 0) {
1151
 
                int         fromStack, fromPosition, toStack;
 
1510
                int fromStack, fromPosition, toStack;
1152
1511
 
1153
1512
                GetMove(&toStack, &fromStack);
1154
 
                if ((fromPosition = TopOfStack(w, fromStack)) < 0 ||
1155
 
                    MoveTile(w, fromStack, fromPosition, toStack) < 0) {
 
1513
                if ((fromPosition = TopOfStack(w, fromStack, 0)) < 0 ||
 
1514
                                MoveTile(w, fromStack, fromPosition, toStack) < 0) {
1156
1515
                        char *buf1, *buf2;
1157
1516
 
1158
 
                        intCat(&buf1, "Move from ", fromStack);
1159
 
                        stringCat(&buf2, buf1, " to ");
1160
 
                        free(buf1);
1161
 
                        intCat(&buf1, buf2, toStack);
1162
 
                        free(buf2);
1163
 
                        stringCat(&buf2, buf1, " can not be made");
1164
 
                        free(buf1);
 
1517
                        intCat(&buf1, "Move from ", fromStack);
 
1518
                        stringCat(&buf2, buf1, " to ");
 
1519
                        free(buf1);
 
1520
                        intCat(&buf1, buf2, toStack);
 
1521
                        free(buf2);
 
1522
                        stringCat(&buf2, buf1, " can not be made");
 
1523
                        free(buf1);
1165
1524
                        DISPLAY_WARNING(buf2);
1166
 
                        free(buf2);
 
1525
                        free(buf2);
1167
1526
                } else {
1168
1527
                        SetPanex(w, PANEX_UNDO);
1169
1528
                }
1174
1533
SolveTiles(PanexWidget w)
1175
1534
{
1176
1535
        /* Cheat and Reset To Start */
1177
 
        EraseFrame(w, w->panex.focus);
 
1536
        EraseFrame(w, 0, w->panex.focus);
1178
1537
        ResetTiles(w);
1179
 
        DrawSlots(w);
 
1538
        DrawSlots(w, 0);
1180
1539
        DrawAllTiles(w);
1181
1540
        SetPanex(w, PANEX_RESET);
1182
1541
        SolveTilesFromStart(w);
1183
1542
}
1184
1543
 
1185
1544
static void
 
1545
SpeedTiles(PanexWidget w)
 
1546
{
 
1547
        w->panex.delay -= 5;
 
1548
        if (w->panex.delay < 0)
 
1549
                w->panex.delay = 0;
 
1550
#ifdef HAVE_MOTIF
 
1551
        SetPanex(w, PANEX_SPEED);
 
1552
#endif
 
1553
}
 
1554
 
 
1555
static void
 
1556
SlowTiles(PanexWidget w)
 
1557
{
 
1558
        w->panex.delay += 5;
 
1559
#ifdef HAVE_MOTIF
 
1560
        SetPanex(w, PANEX_SPEED);
 
1561
#endif
 
1562
}
 
1563
 
 
1564
static void
 
1565
SoundTiles(PanexWidget w)
 
1566
{
 
1567
        w->panex.sound = !w->panex.sound;
 
1568
}
 
1569
 
 
1570
static void
1186
1571
IncrementTiles(PanexWidget w)
1187
1572
{
1188
1573
        SetPanex(w, PANEX_INC);
1202
1587
        SetPanex(w, PANEX_MODE);
1203
1588
}
1204
1589
 
1205
 
static void
1206
 
MoveNoTiles(PanexWidget w)
1207
 
{
1208
 
        SetPanex(w, PANEX_IGNORE);
1209
 
}
1210
 
 
1211
1590
int
1212
1591
MovePanex(PanexWidget w, int fromStack, int fromPosition, int toStack)
1213
1592
{
1214
 
        int         toPosition;
 
1593
        int      toPosition;
1215
1594
 
1216
1595
        if ((toPosition = MoveTile(w, fromStack, fromPosition, toStack)) >= 0) {
1217
1596
                SetPanex(w, PANEX_MOVED);
1246
1625
SetValuesPanex(PanexWidget w)
1247
1626
{
1248
1627
        struct tagColor {
1249
 
                int         red, green, blue;
 
1628
                int red, green, blue;
1250
1629
        } color;
1251
 
        char        szBuf[80], buf[20], charbuf[2];
1252
 
        int         pyramid;
 
1630
        char szBuf[80], buf[20], charbuf[2];
 
1631
        int pyramid;
1253
1632
 
1254
1633
        w->panex.tiles = GetPrivateProfileInt(SECTION, "tiles",
1255
1634
                DEFAULTTILES, INIFILE);
1256
1635
        w->panex.mode = GetPrivateProfileInt(SECTION, "mode",
1257
1636
                DEFAULTMODE, INIFILE);
1258
 
        w->panex.delay = GetPrivateProfileInt(SECTION, "delay",
1259
 
                DEFAULTDELAY, INIFILE);
1260
1637
        w->panex.mono = (BOOL) GetPrivateProfileInt(SECTION, "mono",
1261
1638
                DEFAULTMONO, INIFILE);
1262
1639
        w->panex.reverse = (BOOL) GetPrivateProfileInt(SECTION, "reverse",
1305
1682
                        szBuf, sizeof (szBuf), INIFILE);
1306
1683
                w->panex.pyramidChar[pyramid] = szBuf[0];
1307
1684
        }
 
1685
        w->panex.delay = GetPrivateProfileInt(SECTION, "delay",
 
1686
                DEFAULTDELAY, INIFILE);
 
1687
        w->panex.sound = (BOOL)
 
1688
                GetPrivateProfileInt(SECTION, "sound", 0, INIFILE);
 
1689
        (void) GetPrivateProfileString(SECTION, "moveSound", MOVESOUND,
 
1690
                szBuf, sizeof (szBuf), INIFILE);
 
1691
        (void) strcpy(w->panex.moveSound, szBuf);
 
1692
                w->panex.moveSound[80] = 0;
1308
1693
        (void) GetPrivateProfileString(SECTION, "name", "Guest",
1309
1694
                szBuf, sizeof (szBuf), INIFILE);
1310
1695
        (void) strcpy(w->panex.username, szBuf);
1365
1750
static void
1366
1751
GetColor(PanexWidget w, int pyramid)
1367
1752
{
1368
 
        XGCValues   values;
1369
 
        XtGCMask    valueMask;
1370
 
        XColor      colorCell, rgb;
 
1753
        XGCValues values;
 
1754
        XtGCMask valueMask;
 
1755
        XColor colorCell, rgb;
1371
1756
 
1372
1757
        valueMask = GCForeground | GCBackground;
1373
1758
        if (w->panex.reverse) {
1377
1762
        }
1378
1763
        if (!w->panex.mono) {
1379
1764
                if (XAllocNamedColor(XtDisplay(w),
1380
 
                                  DefaultColormapOfScreen(XtScreen(w)),
1381
 
                          w->panex.pyramidName[pyramid], &colorCell, &rgb)) {
 
1765
                                DefaultColormapOfScreen(XtScreen(w)),
 
1766
                                w->panex.pyramidName[pyramid], &colorCell, &rgb)) {
1382
1767
                        values.foreground = w->panex.pyramidColor[pyramid] =
1383
1768
                                colorCell.pixel;
1384
1769
                        if (w->panex.pyramidGC[pyramid])
1416
1801
static void
1417
1802
SetAllColors(PanexWidget w)
1418
1803
{
1419
 
        XGCValues   values;
1420
 
        XtGCMask    valueMask;
1421
 
        int         pyramid;
 
1804
        XGCValues values;
 
1805
        XtGCMask valueMask;
 
1806
        int pyramid;
1422
1807
 
1423
1808
        valueMask = GCForeground | GCBackground;
1424
1809
        if (w->panex.reverse) {
1505
1890
                        w->panex.fontInfo->fid);
1506
1891
}
1507
1892
 
1508
 
static      Boolean
 
1893
static Boolean
1509
1894
SetValuesPanex(Widget current, Widget request, Widget renew)
1510
1895
{
1511
1896
        PanexWidget c = (PanexWidget) current, w = (PanexWidget) renew;
1512
 
        Boolean     redraw = False;
1513
 
        Boolean     redrawTiles = False, setColors = False;
1514
 
        int         pyramid;
 
1897
        Boolean redraw = False;
 
1898
        Boolean redrawTiles = False, setColors = False;
 
1899
        int pyramid;
1515
1900
 
1516
1901
        CheckTiles(w);
1517
1902
        for (pyramid = 0; pyramid <= w->panex.mode; pyramid++) {
1525
1910
                        w->panex.borderColor != c->panex.borderColor ||
1526
1911
                        w->panex.reverse != c->panex.reverse ||
1527
1912
                        w->panex.mono != c->panex.mono ||
1528
 
                        setColors) {
 
1913
                        setColors) {
1529
1914
                loadFont(w);
1530
1915
                SetAllColors(w);
1531
1916
                redrawTiles = True;
1532
1917
        } else if (w->panex.background != c->panex.background ||
1533
 
            w->panex.foreground != c->panex.foreground ||
1534
 
            w->panex.borderColor != c->panex.borderColor ||
1535
 
            w->panex.tileColor != c->panex.tileColor ||
1536
 
            w->panex.reverse != c->panex.reverse ||
1537
 
            w->panex.mono != c->panex.mono ||
1538
 
            setColors) {
 
1918
                        w->panex.foreground != c->panex.foreground ||
 
1919
                        w->panex.borderColor != c->panex.borderColor ||
 
1920
                        w->panex.tileColor != c->panex.tileColor ||
 
1921
                        w->panex.reverse != c->panex.reverse ||
 
1922
                        w->panex.mono != c->panex.mono ||
 
1923
                        setColors) {
1539
1924
                SetAllColors(w);
1540
1925
                redrawTiles = True;
1541
1926
        }
1542
1927
        if (w->panex.tiles != c->panex.tiles) {
1543
 
                EraseFrame(c, False);
 
1928
                EraseFrame(c, 0, False);
1544
1929
                SizePanex(w);
1545
1930
                redraw = True;
1546
1931
        } else if (w->panex.mode != c->panex.mode) {
1547
1932
                ResetTiles(w);
1548
1933
                redraw = True;
1549
1934
        } else if (w->panex.puzzleOffset.x != c->panex.puzzleOffset.x ||
1550
 
                   w->panex.puzzleOffset.y != c->panex.puzzleOffset.y) {
1551
 
                EraseFrame(c, False);
 
1935
                        w->panex.puzzleOffset.y != c->panex.puzzleOffset.y) {
 
1936
                EraseFrame(c, 0, False);
1552
1937
                ResizePanex(w);
1553
1938
                redraw = True;
1554
1939
        }
 
1940
        if (w->panex.delay != c->panex.delay) {
 
1941
                w->panex.numSlices = ((w->panex.delay < MAXSLICES) ?
 
1942
                        w->panex.delay + 1 : MAXSLICES);
 
1943
        }
1555
1944
        if (w->panex.menu != -1) {
1556
 
                switch (w->panex.menu) {
 
1945
                int menu = w->panex.menu;
 
1946
 
 
1947
                w->panex.menu = -1;
 
1948
                switch (menu) {
1557
1949
                case 0:
1558
 
                        w->panex.menu = -1;
1559
1950
                        GetTiles(w);
1560
1951
                        break;
1561
1952
                case 1:
1562
 
                        w->panex.menu = -1;
1563
1953
                        WriteTiles(w);
1564
1954
                        break;
1565
1955
                case 3:
1566
 
                        w->panex.menu = -1;
1567
1956
                        ClearTiles(w);
1568
1957
                        break;
1569
1958
                case 4:
1570
 
                        w->panex.menu = -1;
1571
1959
                        UndoTiles(w);
1572
1960
                        break;
1573
1961
                case 5:
1574
 
                        w->panex.menu = -1;
1575
1962
                        SolveTiles(w);
1576
1963
                        break;
1577
1964
                case 6:
1578
 
                        w->panex.menu = -1;
1579
1965
                        IncrementTiles(w);
1580
1966
                        break;
1581
1967
                case 7:
1582
 
                        w->panex.menu = -1;
1583
1968
                        DecrementTiles(w);
1584
1969
                        break;
1585
1970
                case 8:
1586
 
                        w->panex.menu = -1;
1587
1971
                        ModeTiles(w);
1588
1972
                        break;
 
1973
                case 9:
 
1974
                        SpeedTiles(w);
 
1975
                        break;
 
1976
                case 10:
 
1977
                        SlowTiles(w);
 
1978
                        break;
 
1979
                case 11:
 
1980
                        SoundTiles(w);
 
1981
                        break;
 
1982
 
1589
1983
                default:
1590
 
                        w->panex.menu = -1;
1591
1984
                        break;
1592
1985
                }
1593
1986
        }
1594
1987
        if (redrawTiles && !redraw && XtIsRealized(renew) &&
1595
 
                       renew->core.visible) {
1596
 
                EraseFrame(w, w->panex.focus);
1597
 
                DrawSlots(w);
 
1988
                        renew->core.visible) {
 
1989
                EraseFrame(w, 0, w->panex.focus);
 
1990
                DrawSlots(w, 0);
1598
1991
                DrawAllTiles(w);
1599
1992
        }
1600
1993
        return (redraw);
1617
2010
DestroyPanex(Widget old)
1618
2011
{
1619
2012
        PanexWidget w = (PanexWidget) old;
1620
 
        int         pyramid;
 
2013
        int pyramid;
1621
2014
 
1622
2015
        for (pyramid = 0; pyramid <= w->panex.mode; pyramid++)
1623
2016
                XtReleaseGC(old, w->panex.pyramidGC[pyramid]);
1624
 
        XtReleaseGC(old, w->panex.frameGC);
1625
2017
        XtReleaseGC(old, w->panex.tileGC);
1626
2018
        XtReleaseGC(old, w->panex.borderGC);
 
2019
        XtReleaseGC(old, w->panex.tileBrighterGC);
 
2020
        XtReleaseGC(old, w->panex.tileDarkerGC);
 
2021
        XtReleaseGC(old, w->panex.frameGC);
1627
2022
        XtReleaseGC(old, w->panex.inverseGC);
1628
2023
        XtRemoveCallbacks(old, XtNselectCallback, w->panex.select);
1629
2024
}
1630
2025
#endif
1631
2026
 
 
2027
static void
 
2028
ResizeTiles(PanexWidget w)
 
2029
{
 
2030
        int sel;
 
2031
#ifdef WINVER
 
2032
        if (w->panex.memDC == NULL) {
 
2033
                w->panex.memDC = CreateCompatibleDC(w->core.hDC);
 
2034
                if (w->panex.memDC == NULL) {
 
2035
                        DISPLAY_ERROR("Not enough memory, exiting.");
 
2036
                }
 
2037
        }
 
2038
        for (sel = 0; sel < 2; sel++) {
 
2039
                if (w->panex.bufferTiles[sel] != NULL) {
 
2040
                        DeleteObject(w->panex.bufferTiles[sel]);
 
2041
                        w->panex.bufferTiles[sel] = NULL;
 
2042
                }
 
2043
                if ((w->panex.bufferTiles[sel] =
 
2044
                                CreateCompatibleBitmap(w->core.hDC,
 
2045
                                w->core.width, w->core.height)) == NULL) {
 
2046
                        DISPLAY_ERROR("Not enough memory, exiting.");
 
2047
                }
 
2048
        }
 
2049
#else
 
2050
        Display *display = XtDisplay(w);
 
2051
        Window window = XtWindow(w);
 
2052
        XWindowAttributes xgwa;
 
2053
 
 
2054
        (void) XGetWindowAttributes(display, window, &xgwa);
 
2055
        if (w->panex.colormap == None) {
 
2056
                w->panex.mono = (xgwa.depth < 2 || w->panex.mono);
 
2057
                w->panex.colormap = xgwa.colormap;
 
2058
        }
 
2059
        for (sel = 0; sel < 2; sel++) {
 
2060
                if (w->panex.bufferTiles[sel] != None) {
 
2061
                        XFreePixmap(display, w->panex.bufferTiles[sel]);
 
2062
                        w->panex.bufferTiles[sel] = None;
 
2063
                }
 
2064
                if ((w->panex.bufferTiles[sel] = XCreatePixmap(display,
 
2065
                                window, w->core.width, w->core.height,
 
2066
                                xgwa.depth)) == None) {
 
2067
                        DISPLAY_ERROR("Not enough memory, exiting.");
 
2068
                }
 
2069
        }
 
2070
        SetAllColors(w);
 
2071
#endif
 
2072
        DrawAllBufferedTiles(w);
 
2073
}
 
2074
 
1632
2075
#ifndef WINVER
1633
2076
static
1634
2077
#endif
1636
2079
ResizePanex(PanexWidget w)
1637
2080
{
1638
2081
#ifdef WINVER
1639
 
        RECT        rect;
 
2082
        RECT rect;
1640
2083
 
1641
2084
        /* Determine size of client area */
1642
2085
        (void) GetClientRect(w->core.hWnd, &rect);
1646
2089
        w->panex.delta.x = 8;
1647
2090
        w->panex.delta.y = 2;
1648
2091
        w->panex.pos.x = MAX(((int) w->core.width - w->panex.delta.x) /
1649
 
                             MAXSTACKS, w->panex.delta.x);
 
2092
                        MAXSTACKS, w->panex.delta.x);
1650
2093
        w->panex.pos.y = MAX(((int) w->core.height - 2 * w->panex.delta.y - 3) /
1651
 
                             (w->panex.tiles + 1), w->panex.delta.y);
 
2094
                        (w->panex.tiles + 1), w->panex.delta.y);
1652
2095
        w->panex.width = w->panex.pos.x * MAXSTACKS + w->panex.delta.x + 2;
1653
2096
        w->panex.height = w->panex.pos.y * (w->panex.tiles + 1) +
1654
2097
                w->panex.delta.y + 3;
1683
2126
#endif
1684
2127
)
1685
2128
{
1686
 
        int         stack;
 
2129
        int stack;
1687
2130
#ifdef WINVER
1688
2131
        SetValuesPanex(w);
 
2132
        brush = CreateSolidBrush(w->panex.inverseGC);
 
2133
        SETBACK(w->core.hWnd, brush);
 
2134
        (void) SRAND(time(NULL));
 
2135
        w->panex.bufferTiles[0] = NULL;
 
2136
        w->panex.bufferTiles[1] = NULL;
1689
2137
#else
1690
2138
        PanexWidget w = (PanexWidget) renew;
1691
2139
 
1692
 
        w->panex.mono = (DefaultDepthOfScreen(XtScreen(w)) < 2 ||
1693
 
                w->panex.mono);
 
2140
        (void) SRAND(getpid());
1694
2141
        for (stack = 0; stack <= w->panex.mode; stack++)
1695
2142
                w->panex.pyramidGC[stack] = NULL;
 
2143
        w->panex.bufferTiles[0] = None;
 
2144
        w->panex.bufferTiles[1] = None;
 
2145
        w->panex.colormap = None;
1696
2146
        w->panex.fontInfo = NULL;
1697
 
        w->panex.frameGC = NULL;
1698
2147
        w->panex.tileGC = NULL;
1699
2148
        w->panex.borderGC = NULL;
 
2149
        w->panex.tileBrighterGC = NULL;
 
2150
        w->panex.tileDarkerGC = NULL;
 
2151
        w->panex.frameGC = NULL;
1700
2152
        w->panex.inverseGC = NULL;
1701
2153
#endif
1702
2154
        w->panex.focus = False;
1707
2159
        }
1708
2160
        CheckTiles(w);
1709
2161
        InitMoves();
1710
 
        w->panex.cheat = False;
 
2162
        w->panex.numSlices = ((w->panex.delay < MAXSLICES) ?
 
2163
                w->panex.delay + 1 : MAXSLICES);
1711
2164
        SizePanex(w);
1712
 
#ifdef WINVER
1713
 
        brush = CreateSolidBrush(w->panex.inverseGC);
1714
 
        SETBACK(w->core.hWnd, brush);
1715
 
        (void) SRAND(time(NULL));
1716
 
#else
1717
 
        (void) SRAND(getpid());
1718
 
        SetAllColors(w);
1719
 
#endif
1720
2165
}
1721
2166
 
1722
2167
void
1734
2179
        if (!w->core.visible)
1735
2180
                return;
1736
2181
#endif
1737
 
        EraseFrame(w, w->panex.focus);
1738
 
        DrawSlots(w);
 
2182
        ResizeTiles(w);
 
2183
        EraseFrame(w, 0, w->panex.focus);
 
2184
        DrawSlots(w, 0);
1739
2185
        DrawAllTiles(w);
1740
2186
}
1741
2187
 
1763
2209
#endif
1764
2210
)
1765
2211
{
1766
 
        int         stack;
 
2212
        int stack;
1767
2213
#ifndef WINVER
1768
 
        int x = event->xbutton.x;
 
2214
        int x = event->xbutton.x;
1769
2215
#endif
1770
2216
 
 
2217
        w->panex.previousStack = -1;
1771
2218
        if (CheckSolved(w)) {
1772
2219
                MoveNoTiles(w);
1773
2220
        } else if (((stack = SelectTile(w, x)) >= 0) &&
1774
 
            ((w->panex.currentPosition = TopOfStack(w, stack)) >= 0)) {
 
2221
                   ((w->panex.currentPosition = TopOfStack(w, stack, 0)) >= 0)) {
1775
2222
                w->panex.currentStack = stack;
1776
 
                DrawTile(w, stack, w->panex.currentPosition, False, TRUE);
 
2223
                if (MoveTileToLimbo(w, w->panex.currentStack,
 
2224
                    w->panex.currentPosition, w->panex.currentStack)) {
 
2225
                        w->panex.currentPosition = 0; 
 
2226
                        w->panex.previousStack = w->panex.currentStack;
 
2227
                }
 
2228
                DrawTile(w, stack, w->panex.currentPosition, False,
 
2229
                        TRUE, 0, 0);
1777
2230
        } else
1778
2231
                w->panex.currentStack = -1;
1779
2232
}
1782
2235
static
1783
2236
#endif
1784
2237
void
 
2238
MotionPanex(PanexWidget w
 
2239
#ifdef WINVER
 
2240
, const int x
 
2241
#else
 
2242
, XEvent * event, char **args, int nArgs
 
2243
#endif
 
2244
)
 
2245
{
 
2246
        int toStack;
 
2247
#ifndef WINVER
 
2248
        int x = event->xbutton.x;
 
2249
#endif
 
2250
 
 
2251
        if (w->panex.currentStack < 0)
 
2252
                return;
 
2253
        
 
2254
        if ((toStack = SelectTile(w, x)) >= 0 &&
 
2255
                        toStack != w->panex.currentStack) {
 
2256
                if (MoveTileToLimbo(w, w->panex.currentStack,
 
2257
                                w->panex.currentPosition, toStack)) {
 
2258
#if 0
 
2259
        DrawTile(w, w->panex.currentStack, w->panex.currentPosition,
 
2260
                True, TRUE, 0, 0);
 
2261
#endif
 
2262
                        if (w->panex.previousStack < 0) {
 
2263
                                w->panex.previousStack = w->panex.currentStack;
 
2264
                        }
 
2265
                        w->panex.currentStack = toStack; 
 
2266
                        w->panex.currentPosition = 0; 
 
2267
                        DrawTile(w, toStack, w->panex.currentPosition, False,
 
2268
                                TRUE, 0, 0);
 
2269
                }
 
2270
        }
 
2271
}
 
2272
 
 
2273
#ifndef WINVER
 
2274
static
 
2275
#endif
 
2276
void
1785
2277
ReleasePanex(PanexWidget w
1786
2278
#ifdef WINVER
1787
2279
, const int x
1790
2282
#endif
1791
2283
)
1792
2284
{
1793
 
        int         toStack, toPosition;
 
2285
        int toStack, toPosition;
1794
2286
#ifndef WINVER
1795
 
        int x = event->xbutton.x;
 
2287
        int x = event->xbutton.x;
1796
2288
#endif
1797
2289
 
1798
2290
        if (w->panex.currentStack < 0)
1799
2291
                return;
1800
2292
        DrawTile(w, w->panex.currentStack, w->panex.currentPosition,
1801
 
                True, TRUE);
 
2293
                True, TRUE, 0, 0);
1802
2294
        DrawTile(w, w->panex.currentStack, w->panex.currentPosition,
1803
 
                False, FALSE);
 
2295
                False, FALSE, 0, 0);
1804
2296
        if ((toStack = SelectTile(w, x)) >= 0 &&
1805
 
            toStack != w->panex.currentStack) {
1806
 
                if ((toPosition = MovePanex(w, w->panex.currentStack,
 
2297
                        ((w->panex.previousStack < 0 &&
 
2298
                        toStack != w->panex.currentStack) ||
 
2299
                        (w->panex.previousStack >= 0))) {
 
2300
                if ((toPosition = MoveTile(w, w->panex.currentStack,
1807
2301
                                w->panex.currentPosition, toStack)) >= 0) {
1808
 
                        if (CheckSolved(w)) {
1809
 
                                SetPanex(w, PANEX_SOLVED);
 
2302
                        if (w->panex.previousStack != toStack) {
 
2303
                                SetPanex(w, PANEX_MOVED);
 
2304
                                if (w->panex.previousStack >= 0) {
 
2305
                                  PutMove(w->panex.previousStack, toStack);
 
2306
                                } else {
 
2307
                                  PutMove(w->panex.currentStack, toStack);
 
2308
                                }
 
2309
                                if (CheckSolved(w)) {
 
2310
                                        SetPanex(w, PANEX_SOLVED);
 
2311
                                }
1810
2312
                        }
1811
2313
                } else if (toPosition == -1) {
1812
 
                        SetPanex(w, PANEX_BLOCKED);
 
2314
                  SetPanex(w, PANEX_BLOCKED);
 
2315
                  if (w->panex.previousStack != -1) {
 
2316
                    if ((toPosition = MoveTile(w, w->panex.currentStack,
 
2317
                        w->panex.currentPosition,
 
2318
                        w->panex.currentStack)) >= 0) {
 
2319
                      if (w->panex.previousStack != toStack &&
 
2320
                          w->panex.previousStack != w->panex.currentStack) {
 
2321
                                SetPanex(w, PANEX_MOVED);
 
2322
                                if (w->panex.previousStack >= 0) {
 
2323
                                  PutMove(w->panex.previousStack, toStack);
 
2324
                                } else {
 
2325
                                  PutMove(w->panex.currentStack, toStack);
 
2326
                                }
 
2327
                                if (CheckSolved(w)) {
 
2328
                                        SetPanex(w, PANEX_SOLVED);
 
2329
                                }
 
2330
                        }
 
2331
                    }
 
2332
                  }
1813
2333
                } else {
1814
 
                        SetPanex(w, PANEX_ILLEGAL);
 
2334
                  SetPanex(w, PANEX_ILLEGAL);
 
2335
                  if (w->panex.previousStack != -1) {
 
2336
                    if ((toPosition = MoveTile(w, w->panex.currentStack,
 
2337
                        w->panex.currentPosition,
 
2338
                        w->panex.currentStack)) >= 0) {
 
2339
                      if (w->panex.previousStack != toStack &&
 
2340
                          w->panex.previousStack != w->panex.currentStack) {
 
2341
                                SetPanex(w, PANEX_MOVED);
 
2342
                                if (w->panex.previousStack >= 0) {
 
2343
                                  PutMove(w->panex.previousStack, toStack);
 
2344
                                } else {
 
2345
                                  PutMove(w->panex.currentStack, toStack);
 
2346
                                }
 
2347
                                if (CheckSolved(w)) {
 
2348
                                        SetPanex(w, PANEX_SOLVED);
 
2349
                                }
 
2350
                        }
 
2351
                    }
 
2352
                  }
1815
2353
                }
1816
2354
        }
 
2355
        w->panex.previousStack = -1;
1817
2356
        w->panex.currentStack = -1;
1818
2357
}
1819
2358
 
1853
2392
, XEvent * event, char **args, int nArgs
1854
2393
)
1855
2394
{
 
2395
        if (!w->panex.started) {
 
2396
                ClearTiles(w);
 
2397
        }
1856
2398
#ifdef HAVE_MOTIF
1857
 
        if (w->panex.started) {
1858
 
                /* Check if one really wants to destroy calculations. */
 
2399
        else {
 
2400
                /* Check if one really wants to destroy current state. */
1859
2401
                SetPanex(w, PANEX_RESET_QUERY);
1860
2402
        }
1861
2403
#endif
1893
2435
}
1894
2436
 
1895
2437
void
 
2438
ModePanex(PanexWidget w
 
2439
#ifndef WINVER
 
2440
, XEvent * event, char **args, int nArgs
 
2441
#endif
 
2442
)
 
2443
{
 
2444
        ModeTiles(w);
 
2445
}
 
2446
 
 
2447
#ifndef WINVER
 
2448
static
 
2449
#endif
 
2450
void
 
2451
SpeedPanex(PanexWidget w
 
2452
#ifndef WINVER
 
2453
, XEvent * event, char **args, int nArgs
 
2454
#endif
 
2455
)
 
2456
{
 
2457
        SpeedTiles(w);
 
2458
}
 
2459
 
 
2460
#ifndef WINVER
 
2461
static
 
2462
#endif
 
2463
void
 
2464
SlowPanex(PanexWidget w
 
2465
#ifndef WINVER
 
2466
, XEvent * event, char **args, int nArgs
 
2467
#endif
 
2468
)
 
2469
{
 
2470
        SlowTiles(w);
 
2471
}
 
2472
 
 
2473
#ifndef WINVER
 
2474
static
 
2475
#endif
 
2476
void
 
2477
SoundPanex(PanexWidget w
 
2478
#ifndef WINVER
 
2479
, XEvent * event, char **args, int nArgs
 
2480
#endif
 
2481
)
 
2482
{
 
2483
        SoundTiles(w);
 
2484
}
 
2485
 
 
2486
void
1896
2487
IncrementPanex(PanexWidget w
1897
2488
#ifndef WINVER
1898
2489
, XEvent * event, char **args, int nArgs
1913
2504
}
1914
2505
 
1915
2506
void
1916
 
ModePanex(PanexWidget w
1917
 
#ifndef WINVER
1918
 
, XEvent * event, char **args, int nArgs
1919
 
#endif
1920
 
)
1921
 
{
1922
 
        ModeTiles(w);
1923
 
}
1924
 
 
1925
 
void
1926
2507
EnterPanex(PanexWidget w
1927
2508
#ifndef WINVER
1928
2509
, XEvent * event, char **args, int nArgs
1930
2511
)
1931
2512
{
1932
2513
        w->panex.focus = True;
1933
 
        DrawFrame(w, w->panex.focus);
 
2514
        DrawFrame(w, 0, w->panex.focus);
1934
2515
}
1935
2516
 
1936
2517
void
1937
2518
LeavePanex(PanexWidget w
1938
2519
#ifndef WINVER
1939
 
, XEvent * event,  char **args, int nArgs
 
2520
, XEvent * event, char **args, int nArgs
1940
2521
#endif
1941
2522
)
1942
2523
{
1943
2524
        w->panex.focus = False;
1944
 
        DrawFrame(w, w->panex.focus);
 
2525
        DrawFrame(w, 0, w->panex.focus);
1945
2526
}