1
2 /*-
3 # MOTIF-BASED DINOSAUR CUBE
4 #
5 # xmdino.c
6 #
7 ###
8 #
9 # Copyright (c) 1995 - 99 David Albert Bagley, bagleyd@tux.org
10 #
11 # All Rights Reserved
12 #
13 # Permission to use, copy, modify, and distribute this software and
14 # its documentation for any purpose and without fee is hereby granted,
15 # provided that the above copyright notice appear in all copies and
16 # that both that copyright notice and this permission notice appear in
17 # supporting documentation, and that the name of the author not be
18 # used in advertising or publicity pertaining to distribution of the
19 # software without specific, written prior permission.
20 #
21 # This program is distributed in the hope that it will be "playable",
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 #
25 */
26
27 /*-
28 Version 5: 95/10/06 Xt/Motif
29 Version 4: 94/05/30 Xt
30 */
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <errno.h>
35 #ifdef VMS
36 #include <unixlib.h>
37 #define getlogin() cuserid(NULL)
38 #else
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #endif
43 #if HAVE_FCNTL_H
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #endif
48 #include <X11/Intrinsic.h>
49 #include <X11/StringDefs.h>
50 #include <X11/Shell.h>
51 #include <X11/cursorfont.h>
52 #include <Xm/PanedW.h>
53 #include <Xm/RowColumn.h>
54 #include <Xm/Label.h>
55 #include <Xm/LabelG.h>
56 #include <Xm/Scale.h>
57 #include <Xm/ToggleB.h>
58 #include <Xm/ToggleBG.h>
59 #include "Dino.h"
60 #include "Dino2d.h"
61 #include "Dino3d.h"
62 #include "dino.xbm"
63 #include "mouse-l.xbm"
64 #include "mouse-r.xbm"
65
66 #ifndef SCOREFILE
67 #define SCOREFILE "/usr/games/lib/dino.scores"
68 #endif
69
70 /* The following are in DinoP.h also */
71 #define PERIOD2 2
72 #define PERIOD3 3
73 #define BOTH 4
74 #define MAXMODES 3
75 #define MAXFACES 6
76
77 #define MAXRECORD 32767
78 #define FILENAMELEN 1024
79 #define USERNAMELEN 128
80 #define NOACCESS "noaccess"
81 #define NOBODY "nobody"
82
83 typedef struct {
84 int score;
85 char name[USERNAMELEN];
86 } GameRecord;
87
88 static void Initialize(void);
89 static void CallbackDino(Widget w, caddr_t clientData, dinoCallbackStruct * callData);
90
91 static void PrintRecord(int mode, Boolean orient, Boolean practice);
92 static Boolean HandleSolved(int counter, int mode, Boolean orient);
93 static void InitRecords(void);
94 static void ReadRecords(void);
95 static void WriteRecords(void);
96
97 static void ModeToggle(Widget w, int mode, XmToggleButtonCallbackStruct * cbs);
98 static void OrientToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs);
99 static void PracticeToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs);
100 static void motif_print(Widget w, char *text);
101
102 static Arg arg[5];
103 static Widget moves, record, message, dino2d, dino3d, modes[MAXMODES], orientSwitch,
104 practiceSwitch;
105 static GameRecord dinoRecord[MAXMODES][2];
106 static int movesDsp = 0;
107 static char messageDsp[128] = "Welcome";
108 static char usernameDsp[USERNAMELEN] = "";
109 static char buff[256];
110
111 static char *modeString[] =
112 {
113 "Period 2", "Period 3", "Both"
114 };
115
116 static void
Usage(void)117 Usage(void)
118 {
119 (void) fprintf(stderr, "usage: xmdino\n");
120 (void) fprintf(stderr,
121 "\t[-geometry [{width}][x{height}][{+-}{xoff}[{+-}{yoff}]]]\n");
122 (void) fprintf(stderr,
123 "\t[-display [{host}]:[{vs}]] [-[no]mono] [-[no]{reverse|rv}]\n");
124 (void) fprintf(stderr,
125 "\t[-{foreground|fg} {color}] [-{background|bg} {color}]\n");
126 (void) fprintf(stderr,
127 "\t[-{border|bd} {color}] [-face{0|1|2|3|4|5} {color}]\n");
128 (void) fprintf(stderr,
129 "\t[-{mode {int} | both}] [-[no]orient] [-[no]practice]\n");
130 (void) fprintf(stderr,
131 "\t[-username {string}]\n");
132 exit(1);
133 }
134
135 static XrmOptionDescRec options[] =
136 {
137 {"-mono", "*dino.mono", XrmoptionNoArg, "TRUE"},
138 {"-nomono", "*dino.mono", XrmoptionNoArg, "FALSE"},
139 {"-rv", "*dino.reverse", XrmoptionNoArg, "TRUE"},
140 {"-reverse", "*dino.reverse", XrmoptionNoArg, "TRUE"},
141 {"-norv", "*dino.reverse", XrmoptionNoArg, "FALSE"},
142 {"-noreverse", "*dino.reverse", XrmoptionNoArg, "FALSE"},
143 {"-fg", "*dino.Foreground", XrmoptionSepArg, NULL},
144 {"-foreground", "*dino.Foreground", XrmoptionSepArg, NULL},
145 {"-bg", "*Background", XrmoptionSepArg, NULL},
146 {"-background", "*Background", XrmoptionSepArg, NULL},
147 {"-bd", "*dino.pieceBorder", XrmoptionSepArg, NULL},
148 {"-border", "*dino.pieceBorder", XrmoptionSepArg, NULL},
149 {"-face0", "*dino.faceColor0", XrmoptionSepArg, NULL},
150 {"-face1", "*dino.faceColor1", XrmoptionSepArg, NULL},
151 {"-face2", "*dino.faceColor2", XrmoptionSepArg, NULL},
152 {"-face3", "*dino.faceColor3", XrmoptionSepArg, NULL},
153 {"-face4", "*dino.faceColor4", XrmoptionSepArg, NULL},
154 {"-face5", "*dino.faceColor5", XrmoptionSepArg, NULL},
155 {"-mode", "*dino.mode", XrmoptionSepArg, NULL},
156 {"-both", "*dino.mode", XrmoptionNoArg, "4"},
157 {"-orient", "*dino.orient", XrmoptionNoArg, "TRUE"},
158 {"-noorient", "*dino.orient", XrmoptionNoArg, "FALSE"},
159 {"-practice", "*dino.practice", XrmoptionNoArg, "TRUE"},
160 {"-nopractice", "*dino.practice", XrmoptionNoArg, "FALSE"},
161 {"-username", "*dino.userName", XrmoptionSepArg, NULL}
162 };
163
164 int
main(int argc,char ** argv)165 main(int argc, char **argv)
166 {
167 Widget toplevel;
168 Widget panel, panel2, rowcol, rowcol2, rowcol3, rowcol4;
169 Pixmap mouseLeftCursor, mouseRightCursor;
170 Pixel fg, bg;
171 int i;
172
173 toplevel = XtInitialize(argv[0], "Dino",
174 options, XtNumber(options), &argc, argv);
175 if (argc != 1)
176 Usage();
177
178 XtSetArg(arg[0],
179 XtNiconPixmap, XCreateBitmapFromData(XtDisplay(toplevel),
180 RootWindowOfScreen(XtScreen(toplevel)),
181 (char *) dino_bits, dino_width, dino_height));
182 XtSetArg(arg[1], XmNkeyboardFocusPolicy, XmPOINTER); /* not XmEXPLICIT */
183 XtSetValues(toplevel, arg, 2);
184 panel = XtCreateManagedWidget("panel",
185 xmPanedWindowWidgetClass, toplevel, NULL, 0);
186 panel2 = XtVaCreateManagedWidget("panel2", xmPanedWindowWidgetClass, panel,
187 XmNseparatorOn, False,
188 XmNsashWidth, 1,
189 XmNsashHeight, 1, NULL);
190
191 rowcol = XtVaCreateManagedWidget("Rowcol", xmRowColumnWidgetClass, panel2,
192 XmNnumColumns, 2,
193 XmNorientation, XmHORIZONTAL,
194 XmNpacking, XmPACK_COLUMN, NULL);
195 XtVaGetValues(rowcol,
196 XmNforeground, &fg,
197 XmNbackground, &bg, NULL);
198 mouseLeftCursor = XCreatePixmapFromBitmapData(XtDisplay(rowcol),
199 RootWindowOfScreen(XtScreen(rowcol)), (char *) mouse_left_bits,
200 mouse_left_width, mouse_left_height, fg, bg,
201 DefaultDepthOfScreen(XtScreen(rowcol)));
202 mouseRightCursor = XCreatePixmapFromBitmapData(XtDisplay(rowcol),
203 RootWindowOfScreen(XtScreen(rowcol)), (char *) mouse_right_bits,
204 mouse_right_width, mouse_right_height, fg, bg,
205 DefaultDepthOfScreen(XtScreen(rowcol)));
206 XtVaCreateManagedWidget("mouseLeftText",
207 xmLabelGadgetClass, rowcol,
208 XtVaTypedArg, XmNlabelString, XmRString, "Move", 5, NULL);
209 XtVaCreateManagedWidget("mouseLeft",
210 xmLabelGadgetClass, rowcol,
211 XmNlabelType, XmPIXMAP, XmNlabelPixmap, mouseLeftCursor, NULL);
212 XtVaCreateManagedWidget("mouseRightText",
213 xmLabelGadgetClass, rowcol,
214 XtVaTypedArg, XmNlabelString, XmRString, "Randomize", 10, NULL);
215 XtVaCreateManagedWidget("mouseRight",
216 xmLabelGadgetClass, rowcol,
217 XmNlabelType, XmPIXMAP, XmNlabelPixmap, mouseRightCursor, NULL);
218 XtVaCreateManagedWidget("movesText",
219 xmLabelGadgetClass, rowcol,
220 XtVaTypedArg, XmNlabelString, XmRString, "Moves", 6, NULL);
221 moves = XtVaCreateManagedWidget("0",
222 xmLabelWidgetClass, rowcol, NULL);
223 XtVaCreateManagedWidget("recordText",
224 xmLabelGadgetClass, rowcol,
225 XtVaTypedArg, XmNlabelString, XmRString, "Record", 7, NULL);
226 record = XtVaCreateManagedWidget("0",
227 xmLabelWidgetClass, rowcol, NULL);
228
229 rowcol2 = XtVaCreateManagedWidget("Rowcol2",
230 xmRowColumnWidgetClass, panel2,
231 XmNnumColumns, 1,
232 XmNorientation, XmHORIZONTAL,
233 XmNpacking, XmPACK_COLUMN,
234 XmNradioBehavior, True, NULL);
235 for (i = 0; i < XtNumber(modeString); i++) {
236 modes[i] = XtVaCreateManagedWidget(modeString[i],
237 xmToggleButtonGadgetClass, rowcol2,
238 XmNradioBehavior, True, NULL);
239 XtAddCallback(modes[i],
240 XmNvalueChangedCallback, (XtCallbackProc) ModeToggle, (XtPointer) i);
241 }
242
243 rowcol3 = XtVaCreateManagedWidget("Rowcol3",
244 xmRowColumnWidgetClass, panel2,
245 XmNnumColumns, 1,
246 XmNorientation, XmHORIZONTAL,
247 XmNpacking, XmPACK_COLUMN, NULL);
248 orientSwitch = XtVaCreateManagedWidget("Orient",
249 xmToggleButtonWidgetClass, rowcol3, NULL);
250 XtAddCallback(orientSwitch,
251 XmNvalueChangedCallback, (XtCallbackProc) OrientToggle, (XtPointer) NULL);
252 practiceSwitch = XtVaCreateManagedWidget("Practice",
253 xmToggleButtonWidgetClass, rowcol3, NULL);
254 XtAddCallback(practiceSwitch,
255 XmNvalueChangedCallback, (XtCallbackProc) PracticeToggle, (XtPointer) NULL);
256
257 rowcol4 = XtVaCreateManagedWidget("Rowcol4",
258 xmRowColumnWidgetClass, panel2,
259 XmNnumColumns, 1,
260 XmNorientation, XmHORIZONTAL,
261 XmNpacking, XmPACK_COLUMN, NULL);
262 message = XtVaCreateManagedWidget("Play Dino! (use mouse and keypad)",
263 xmLabelWidgetClass, rowcol4, NULL);
264
265 dino2d = XtCreateManagedWidget("dino",
266 dino2dWidgetClass, panel, NULL, 0);
267 XtVaSetValues(dino2d,
268 XtNheight, 200, NULL);
269 XtAddCallback(dino2d,
270 XtNselectCallback, (XtCallbackProc) CallbackDino, (XtPointer) NULL);
271 dino3d = XtCreateManagedWidget("dino",
272 dino3dWidgetClass, panel, NULL, 0);
273 XtVaSetValues(dino3d,
274 XtNheight, 200, NULL);
275 XtAddCallback(dino3d,
276 XtNselectCallback, (XtCallbackProc) CallbackDino, (XtPointer) NULL);
277 Initialize();
278 XtRealizeWidget(toplevel);
279 XGrabButton(XtDisplay(dino2d), (unsigned int) AnyButton, AnyModifier,
280 XtWindow(dino2d), TRUE,
281 (unsigned int) (ButtonPressMask | ButtonMotionMask | ButtonReleaseMask),
282 GrabModeAsync, GrabModeAsync, XtWindow(dino2d),
283 XCreateFontCursor(XtDisplay(dino2d), XC_crosshair));
284 XGrabButton(XtDisplay(dino3d), (unsigned int) AnyButton, AnyModifier,
285 XtWindow(dino3d), TRUE,
286 (unsigned int) (ButtonPressMask | ButtonMotionMask | ButtonReleaseMask),
287 GrabModeAsync, GrabModeAsync, XtWindow(dino3d),
288 XCreateFontCursor(XtDisplay(dino3d), XC_crosshair));
289 XtMainLoop();
290
291 #ifdef VMS
292 return 1;
293 #else
294 return 0;
295 #endif
296 }
297
298 /* There's probably a better way to assure that they are the same but I don't
299 know it off hand. */
300 static void
MakeEquivalent(String * username,int * mode,Boolean * orient,Boolean * practice)301 MakeEquivalent(String * username, int *mode, Boolean * orient, Boolean * practice)
302 {
303 Boolean mono, reverse;
304 Pixel foreground, background, pieceBorder;
305 String faceColor[MAXFACES];
306
307 XtVaGetValues(dino2d,
308 XtNuserName, username,
309 XtNmode, mode,
310 XtNorient, orient,
311 XtNpractice, practice,
312 XtNmono, &mono,
313 XtNreverse, &reverse,
314 XtNforeground, &foreground,
315 XtNbackground, &background,
316 XtNpieceBorder, &pieceBorder,
317 XtNfaceColor0, &(faceColor[0]),
318 XtNfaceColor1, &(faceColor[1]),
319 XtNfaceColor2, &(faceColor[2]),
320 XtNfaceColor3, &(faceColor[3]),
321 XtNfaceColor4, &(faceColor[4]),
322 XtNfaceColor5, &(faceColor[5]), NULL);
323 XtVaSetValues(dino2d,
324 XtNdirection, DINO_IGNORE,
325 XtNstart, False, NULL);
326 XtVaSetValues(dino3d,
327 XtNuserName, *username,
328 XtNmode, *mode,
329 XtNorient, *orient,
330 XtNpractice, *practice,
331 XtNmono, mono,
332 XtNreverse, reverse,
333 XtNdirection, DINO_IGNORE,
334 XtNstart, False,
335 XtNforeground, foreground,
336 XtNbackground, background,
337 XtNpieceBorder, pieceBorder,
338 XtNfaceColor0, faceColor[0],
339 XtNfaceColor1, faceColor[1],
340 XtNfaceColor2, faceColor[2],
341 XtNfaceColor3, faceColor[3],
342 XtNfaceColor4, faceColor[4],
343 XtNfaceColor5, faceColor[5], NULL);
344 }
345
346 static void
Initialize(void)347 Initialize(void)
348 {
349 int mode;
350 Boolean orient, practice;
351 String username;
352
353 MakeEquivalent(&username, &mode, &orient, &practice);
354 XmToggleButtonSetState(modes[mode - PERIOD2], True, False);
355 XmToggleButtonSetState(orientSwitch, orient, True);
356 XmToggleButtonSetState(practiceSwitch, practice, True);
357 InitRecords();
358 ReadRecords();
359 (void) strcpy(usernameDsp, username);
360 if (!strcmp(usernameDsp, "") || !strcmp(usernameDsp, NOACCESS) ||
361 !strcmp(usernameDsp, NOBODY)) {
362 /* The NOACCESS is not necasary, but it stops people from being cute. */
363 (void) sprintf(usernameDsp, "%s", getlogin());
364 if (!strcmp(usernameDsp, "") || !strcmp(usernameDsp, NOACCESS))
365 (void) sprintf(usernameDsp, "%s", NOBODY); /* It really IS nobody */
366 }
367 PrintRecord(mode, orient, practice);
368 }
369
370 static void
CallbackDino(Widget w,caddr_t clientData,dinoCallbackStruct * callData)371 CallbackDino(Widget w, caddr_t clientData, dinoCallbackStruct * callData)
372 {
373 int mode;
374 Boolean orient, practice, start;
375 Widget otherw;
376
377 if (w == dino2d)
378 otherw = dino3d;
379 else /* (w == dino3d) */
380 otherw = dino2d;
381 XtVaGetValues(w,
382 XtNorient, &orient,
383 XtNmode, &mode,
384 XtNpractice, &practice,
385 XtNstart, &start, NULL);
386 (void) strcpy(messageDsp, "");
387 switch (callData->reason) {
388 case DINO_RESTORE:
389 XtSetArg(arg[0], XtNdirection, DINO_RESTORE);
390 XtSetValues(otherw, arg, 1);
391 XtSetValues(w, arg, 1);
392 movesDsp = 0;
393 break;
394 case DINO_RESET:
395 movesDsp = 0;
396 break;
397 case DINO_ILLEGAL:
398 if (practice || start)
399 (void) strcpy(messageDsp, "Illegal move");
400 else
401 (void) strcpy(messageDsp, "Randomize to start");
402 break;
403 case DINO_MOVED:
404 movesDsp++;
405 XtSetArg(arg[0], XtNstart, True);
406 XtSetArg(arg[1], XtNface, callData->face);
407 XtSetArg(arg[2], XtNpos, callData->position);
408 XtSetArg(arg[3], XtNdirection, callData->direction);
409 XtSetArg(arg[4], XtNstyle, callData->style);
410 XtSetValues(otherw, arg, 5);
411 XtSetValues(w, arg, 1);
412 break;
413 case DINO_CONTROL:
414 XtSetArg(arg[0], XtNface, callData->face);
415 XtSetArg(arg[1], XtNpos, callData->position);
416 XtSetArg(arg[2], XtNdirection, callData->direction);
417 XtSetArg(arg[3], XtNstyle, callData->style);
418 XtSetValues(otherw, arg, 4);
419 return;
420 case DINO_SOLVED:
421 if (practice)
422 movesDsp = 0;
423 else {
424 if (HandleSolved(movesDsp, mode, orient))
425 (void) sprintf(messageDsp, "Congratulations %s!!", usernameDsp);
426 else
427 (void) strcpy(messageDsp, "Solved!");
428 }
429 XtSetArg(arg[0], XtNstart, False);
430 XtSetValues(w, arg, 1);
431 XtSetValues(otherw, arg, 1);
432 break;
433 case DINO_PRACTICE:
434 movesDsp = 0;
435 practice = !practice;
436 if (!practice)
437 (void) strcpy(messageDsp, "Randomize to start");
438 PrintRecord(mode, orient, practice);
439 XtSetArg(arg[0], XtNpractice, practice);
440 XtSetArg(arg[1], XtNstart, False);
441 XtSetValues(w, arg, 2);
442 XtSetValues(otherw, arg, 2);
443 XmToggleButtonSetState(practiceSwitch, practice, True);
444 break;
445 case DINO_RANDOMIZE:
446 movesDsp = 0;
447 XtSetArg(arg[0], XtNpractice, False);
448 XtSetArg(arg[1], XtNstart, False);
449 XtSetValues(w, arg, 2);
450 XtSetValues(otherw, arg, 2);
451 break;
452 case DINO_ORIENT:
453 movesDsp = 0;
454 orient = !orient;
455 PrintRecord(mode, orient, practice);
456 XtSetArg(arg[0], XtNorient, orient);
457 XtSetValues(w, arg, 1);
458 XtSetValues(otherw, arg, 1);
459 XmToggleButtonSetState(orientSwitch, orient, True);
460 break;
461 case DINO_PERIOD2:
462 case DINO_PERIOD3:
463 case DINO_BOTH:
464 movesDsp = 0;
465 mode = callData->reason - DINO_PERIOD2 + PERIOD2;
466 PrintRecord(mode, orient, practice);
467 XtSetArg(arg[0], XtNmode, mode);
468 XtSetValues(w, arg, 1);
469 XtSetValues(otherw, arg, 1);
470 XmToggleButtonSetState(modes[mode - PERIOD2], True, True);
471 break;
472 case DINO_COMPUTED:
473 XtSetArg(arg[0], XtNstart, False);
474 XtSetValues(w, arg, 1);
475 XtSetValues(otherw, arg, 1);
476 break;
477 case DINO_UNDO:
478 movesDsp--;
479 XtSetArg(arg[0], XtNstart, True);
480 XtSetArg(arg[1], XtNface, callData->face);
481 XtSetArg(arg[2], XtNpos, callData->position);
482 XtSetArg(arg[3], XtNdirection, callData->direction);
483 XtSetArg(arg[4], XtNstyle, callData->style);
484 XtSetValues(otherw, arg, 5);
485 XtSetValues(w, arg, 1);
486 break;
487 }
488 motif_print(message, messageDsp);
489 (void) sprintf(buff, "%d", movesDsp);
490 motif_print(moves, buff);
491 }
492
493 static void
ModeToggle(Widget w,int mode,XmToggleButtonCallbackStruct * cbs)494 ModeToggle(Widget w, int mode, XmToggleButtonCallbackStruct * cbs)
495 {
496 Boolean orient, practice;
497
498 if (cbs->set) {
499 XtVaGetValues(dino2d,
500 XtNorient, &orient,
501 XtNpractice, &practice, NULL);
502 XtVaSetValues(dino2d,
503 XtNmode, mode + PERIOD2, NULL);
504 XtVaSetValues(dino3d,
505 XtNmode, mode + PERIOD2, NULL);
506 movesDsp = 0;
507 (void) sprintf(buff, "%d", movesDsp);
508 motif_print(moves, buff);
509 PrintRecord(mode + PERIOD2, orient, practice);
510 }
511 }
512
513 static void
OrientToggle(Widget w,XtPointer clientData,XmToggleButtonCallbackStruct * cbs)514 OrientToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
515 {
516 int mode;
517 Boolean orient = cbs->set, practice;
518
519 XtVaGetValues(dino2d,
520 XtNmode, &mode,
521 XtNpractice, &practice, NULL);
522 XtVaSetValues(dino2d,
523 XtNorient, orient, NULL);
524 XtVaSetValues(dino3d,
525 XtNorient, orient, NULL);
526 movesDsp = 0;
527 (void) sprintf(buff, "%d", movesDsp);
528 motif_print(moves, buff);
529 PrintRecord(mode, orient, practice);
530 }
531
532 static void
PracticeToggle(Widget w,XtPointer clientData,XmToggleButtonCallbackStruct * cbs)533 PracticeToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
534 {
535 int mode;
536 Boolean orient, practice = cbs->set;
537
538 XtVaSetValues(dino2d,
539 XtNpractice, practice,
540 XtNstart, False, NULL);
541 XtVaSetValues(dino3d,
542 XtNpractice, practice,
543 XtNstart, False, NULL);
544 XtVaGetValues(dino2d,
545 XtNmode, &mode,
546 XtNpractice, &orient, NULL);
547 movesDsp = 0;
548 (void) sprintf(buff, "%d", movesDsp);
549 motif_print(moves, buff);
550 if (!practice)
551 (void) strcpy(messageDsp, "Randomize to start");
552 PrintRecord(mode, orient, practice);
553 }
554
555 static void
PrintRecord(int mode,Boolean orient,Boolean practice)556 PrintRecord(int mode, Boolean orient, Boolean practice)
557 {
558 int i = mode - PERIOD2;
559 int j = (orient) ? 1 : 0;
560
561 if (practice)
562 motif_print(record, "practice");
563 else if (dinoRecord[i][j].score >= MAXRECORD) {
564 (void) sprintf(buff, "NEVER %s", NOACCESS);
565 motif_print(record, buff);
566 } else {
567 (void) sprintf(buff, "%d %s",
568 dinoRecord[i][j].score, dinoRecord[i][j].name);
569 motif_print(record, buff);
570 }
571 }
572
573 static Boolean
HandleSolved(int counter,int mode,Boolean orient)574 HandleSolved(int counter, int mode, Boolean orient)
575 {
576 int i = mode - PERIOD2;
577 int j = (orient) ? 1 : 0;
578
579 if (counter < dinoRecord[i][j].score) {
580 dinoRecord[i][j].score = counter;
581 (void) strcpy(dinoRecord[i][j].name, usernameDsp);
582 if (orient && (counter < dinoRecord[!i][j].score)) {
583 dinoRecord[!i][j].score = counter;
584 (void) strcpy(dinoRecord[!i][j].name, usernameDsp);
585 }
586 WriteRecords();
587 PrintRecord(mode, orient, False);
588 return True;
589 }
590 return False;
591 }
592
593 static void
InitRecords(void)594 InitRecords(void)
595 {
596 int mode, orient;
597
598 for (mode = 0; mode < MAXMODES; mode++)
599 for (orient = 0; orient < 2; orient++) {
600 dinoRecord[mode][orient].score = MAXRECORD;
601 (void) strcpy(dinoRecord[mode][orient].name, NOACCESS);
602 }
603 }
604
605 static void
ReadRecords(void)606 ReadRecords(void)
607 {
608 FILE *fp;
609 int n, mode, orient;
610 char username[USERNAMELEN];
611
612 if ((fp = fopen(SCOREFILE, "r")) == NULL) {
613 (void) sprintf(buff, "Can not open %s, taking defaults.", SCOREFILE);
614 motif_print(message, buff);
615 } else {
616 for (mode = 0; mode < MAXMODES; mode++)
617 for (orient = 0; orient < 2; orient++) {
618 (void) fscanf(fp, "%d %s\n", &n, username);
619 if (n <= dinoRecord[mode][orient].score) {
620 dinoRecord[mode][orient].score = n;
621 (void) strcpy(dinoRecord[mode][orient].name, username);
622 }
623 }
624 (void) fclose(fp);
625 }
626 }
627
628 static void
WriteRecords(void)629 WriteRecords(void)
630 {
631 FILE *fp;
632 int mode, orient;
633
634 if ((fp = fopen(SCOREFILE, "w")) == NULL) {
635 (void) sprintf(buff, "Can not write to %s.", SCOREFILE);
636 motif_print(message, buff);
637 } else {
638 #if HAVE_FCNTL_H
639 int lfd;
640 char lockfile[FILENAMELEN];
641
642 (void) strcpy(lockfile, SCOREFILE);
643 (void) strcat(lockfile, ".lock");
644 while (((lfd = open(lockfile, O_CREAT | O_EXCL, 0644)) < 0) &&
645 errno == EEXIST)
646 (void) sleep(1);
647 if (lfd < 0) {
648 #if 1
649 (void) fprintf(stderr, "Lock file exists... guessing its an old one.\n");
650 #else
651 (void) fprintf(stderr, "Lock file exists... score not recorded - sorry.\n"
652 );
653 return;
654 #endif
655 }
656 #endif
657 for (mode = 0; mode < MAXMODES; mode++) {
658 for (orient = 0; orient < 2; orient++)
659 (void) fprintf(fp, "%d %s\n",
660 dinoRecord[mode][orient].score, dinoRecord[mode][orient].name);
661 (void) fprintf(fp, "\n");
662 }
663 #if HAVE_FCNTL_H
664 (void) close(lfd);
665 (void) unlink(lockfile);
666 #endif
667 (void) fclose(fp);
668 }
669 }
670
671 static void
motif_print(Widget w,char * text)672 motif_print(Widget w, char *text)
673 {
674 Arg wargs[1];
675 XmString xmstr;
676
677 if (!XtIsSubclass(w, xmLabelWidgetClass))
678 XtError("motif_print() requires a Label Widget");
679 xmstr = XmStringCreateLtoR(text, XmSTRING_DEFAULT_CHARSET);
680 XtSetArg(wargs[0], XmNlabelString, xmstr);
681 XtSetValues(w, wargs, 1);
682 }
683