home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume21 / xmine / part01 < prev    next >
Encoding:
Text File  |  1994-01-05  |  52.1 KB  |  1,889 lines

  1. Newsgroups: comp.sources.x
  2. From: pf@z-code.z-code.com ("Paul Falstad")
  3. Subject: v21i084:  xmine - X11-based version of the popular PC game Minesweeper, Part01/01
  4. Message-ID: <1994Jan4.185238.14877@sparky.sterling.com>
  5. X-Md4-Signature: 565ce27ab9c3f7fe563d023a5069695d
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Tue, 4 Jan 1994 18:52:38 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: pf@z-code.z-code.com ("Paul Falstad")
  12. Posting-number: Volume 21, Issue 84
  13. Archive-name: xmine/part01
  14. Environment: X11, OSF/Motif
  15.  
  16. xmine is an X11-based version of the popular PC game Minesweeper. The
  17. object is to place flags on mines on the game board without exposing
  18. them.
  19.  
  20. xmine is freely redistributable.  It's mostly Xlib-based, but it
  21. requires Motif libraries for the menus.
  22.  
  23. Author: Paul Falstad (pf@z-code.com)
  24.  
  25. ---- Cut Here and feed the following to sh ----
  26. #! /bin/sh
  27. # This is a shell archive.  Remove anything before this line, then feed it
  28. # into a shell via "sh file" or similar.  To overwrite existing files,
  29. # type "sh file -c".
  30. # Contents:  README Imakefile Makefile Xmine cool.xbm dead.xbm
  31. #   fallback.h fillface.xbm happy.xbm ohno.xbm patchlevel.h press.xbm
  32. #   xmine.1 xmine.c
  33. # Wrapped by chris@sparky on Tue Jan  4 12:37:03 1994
  34. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  35. echo If this archive is complete, you will see the following message:
  36. echo '          "shar: End of archive 1 (of 1)."'
  37. if test -f 'README' -a "${1}" != "-c" ; then 
  38.   echo shar: Will not clobber existing file \"'README'\"
  39. else
  40.   echo shar: Extracting \"'README'\" \(289 characters\)
  41.   sed "s/^X//" >'README' <<'END_OF_FILE'
  42. Xxmine is an X11-based version of the popular PC game Minesweeper. The
  43. Xobject is to place flags on mines on the game board without exposing
  44. Xthem.
  45. X
  46. Xxmine is freely redistributable.  It's mostly Xlib-based, but it
  47. Xrequires Motif libraries for the menus.
  48. X
  49. XAuthor: Paul Falstad (pf@z-code.com)
  50. END_OF_FILE
  51.   if test 289 -ne `wc -c <'README'`; then
  52.     echo shar: \"'README'\" unpacked with wrong size!
  53.   fi
  54.   # end of 'README'
  55. fi
  56. if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  57.   echo shar: Will not clobber existing file \"'Imakefile'\"
  58. else
  59.   echo shar: Extracting \"'Imakefile'\" \(79 characters\)
  60.   sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
  61. XSYS_LIBRARIES = -lXm -lXt -lX11
  62. X
  63. XAllTarget(xmine)
  64. X
  65. XSimpleProgramTarget(xmine)
  66. X
  67. END_OF_FILE
  68.   if test 79 -ne `wc -c <'Imakefile'`; then
  69.     echo shar: \"'Imakefile'\" unpacked with wrong size!
  70.   fi
  71.   # end of 'Imakefile'
  72. fi
  73. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  74.   echo shar: Will not clobber existing file \"'Makefile'\"
  75. else
  76.   echo shar: Extracting \"'Makefile'\" \(211 characters\)
  77.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  78. XCC = cc
  79. XCFLAGS = -O -D_NO_PROTO
  80. X
  81. XLIBS = -lXm -lXt -lX11
  82. X
  83. Xxmine: xmine.c fallback.h
  84. X    $(CC) $(CFLAGS) -o xmine xmine.c $(LIBS)
  85. X
  86. Xfallback.h: Xmine
  87. X    sed -e 's/^/"/' -e 's/\\/\\\\/g' -e 's/$$/",/' Xmine > fallback.h
  88. END_OF_FILE
  89.   if test 211 -ne `wc -c <'Makefile'`; then
  90.     echo shar: \"'Makefile'\" unpacked with wrong size!
  91.   fi
  92.   # end of 'Makefile'
  93. fi
  94. if test -f 'Xmine' -a "${1}" != "-c" ; then 
  95.   echo shar: Will not clobber existing file \"'Xmine'\"
  96. else
  97.   echo shar: Extracting \"'Xmine'\" \(1353 characters\)
  98.   sed "s/^X//" >'Xmine' <<'END_OF_FILE'
  99. XXmine*foreground: White
  100. XXmine*background: Grey50
  101. XXmine*menubar*fontList: -*-times-bold-i-normal--14-100-*-*-*-*-*-*
  102. XXmine*fontList: -*-times-bold-r-normal--14-100-*-*-*-*-*-*
  103. X*game.labelString: Game
  104. X*game.mnemonic: G
  105. X*New.mnemonic: N
  106. X*New.accelerator: <Key>F2
  107. X*New.acceleratorText: F2
  108. X*Beginner.mnemonic: B
  109. X*Intermediate.mnemonic: I
  110. X*Expert.mnemonic: E
  111. X*Custom.labelString: Custom ...
  112. X*Custom.mnemonic: C
  113. X*Marks.labelString: Marks [?]
  114. X*Marks.mnemonic: M
  115. X*Best.labelString: Best Times
  116. X*Best.mnemonic: T
  117. X*Exit.mnemonic: x
  118. X*About.labelString: About xmine ...
  119. X*About.mnemonic: A
  120. X*Custom.title: Custom Field
  121. X*Custom*height_label.labelString: Height:
  122. X*Custom*width_label.labelString: Width:
  123. X*Custom*mines_label.labelString: Mines:
  124. X*Custom*height_text.columns: 4
  125. X*Custom*width_text.columns: 4
  126. X*Custom*mines_text.columns: 4
  127. X*Custom*ok.labelString: Ok
  128. X*Best.title: Best Scores
  129. X*Best*label.labelString: Fastest Mine Sweepers
  130. X*Best*begin_label.labelString: Beginner:
  131. X*Best*inter_label.labelString: Intermediate:
  132. X*Best*expert_label.labelString: Expert:
  133. X*Best*ok.labelString: Ok
  134. X*Best*clear.labelString: Reset Scores
  135. X*About.title: About xmine
  136. X*About*ok.labelString: Ok
  137. X*HighScorer.title: New Best Score
  138. X*HighScorer*label.labelString: You have the fastest time for this
  139. Xlevel.\nPlease enter your name.
  140. X*HighScorer*name.value: Anonymous
  141. X*HighScorer*ok.labelString: Ok
  142. END_OF_FILE
  143.   if test 1353 -ne `wc -c <'Xmine'`; then
  144.     echo shar: \"'Xmine'\" unpacked with wrong size!
  145.   fi
  146.   # end of 'Xmine'
  147. fi
  148. if test -f 'cool.xbm' -a "${1}" != "-c" ; then 
  149.   echo shar: Will not clobber existing file \"'cool.xbm'\"
  150. else
  151.   echo shar: Extracting \"'cool.xbm'\" \(275 characters\)
  152.   sed "s/^X//" >'cool.xbm' <<'END_OF_FILE'
  153. X#define cool_width 16
  154. X#define cool_height 16
  155. Xstatic char cool_bits[] = {
  156. X   0xc0, 0x07, 0x30, 0x18, 0x08, 0x20, 0x04, 0x40, 0x04, 0x40, 0xfa, 0xbf,
  157. X   0xf6, 0xde, 0x62, 0x8c, 0x02, 0x80, 0x12, 0x90, 0x24, 0x48, 0xc4, 0x47,
  158. X   0x08, 0x20, 0x30, 0x18, 0xc0, 0x07, 0x00, 0x00};
  159. END_OF_FILE
  160.   if test 275 -ne `wc -c <'cool.xbm'`; then
  161.     echo shar: \"'cool.xbm'\" unpacked with wrong size!
  162.   fi
  163.   # end of 'cool.xbm'
  164. fi
  165. if test -f 'dead.xbm' -a "${1}" != "-c" ; then 
  166.   echo shar: Will not clobber existing file \"'dead.xbm'\"
  167. else
  168.   echo shar: Extracting \"'dead.xbm'\" \(275 characters\)
  169.   sed "s/^X//" >'dead.xbm' <<'END_OF_FILE'
  170. X#define dead_width 16
  171. X#define dead_height 16
  172. Xstatic char dead_bits[] = {
  173. X   0xc0, 0x07, 0x30, 0x18, 0x08, 0x20, 0x04, 0x40, 0x54, 0x54, 0x22, 0x88,
  174. X   0x52, 0x94, 0x02, 0x80, 0x02, 0x80, 0xc2, 0x87, 0x24, 0x48, 0x04, 0x40,
  175. X   0x08, 0x20, 0x30, 0x18, 0xc0, 0x07, 0x00, 0x00};
  176. END_OF_FILE
  177.   if test 275 -ne `wc -c <'dead.xbm'`; then
  178.     echo shar: \"'dead.xbm'\" unpacked with wrong size!
  179.   fi
  180.   # end of 'dead.xbm'
  181. fi
  182. if test -f 'fallback.h' -a "${1}" != "-c" ; then 
  183.   echo shar: Will not clobber existing file \"'fallback.h'\"
  184. else
  185.   echo shar: Extracting \"'fallback.h'\" \(1480 characters\)
  186.   sed "s/^X//" >'fallback.h' <<'END_OF_FILE'
  187. X"Xmine*foreground: White",
  188. X"Xmine*background: Grey50",
  189. X"Xmine*menubar*fontList: -*-times-bold-i-normal--14-100-*-*-*-*-*-*",
  190. X"Xmine*fontList: -*-times-bold-r-normal--14-100-*-*-*-*-*-*",
  191. X"*game.labelString: Game",
  192. X"*game.mnemonic: G",
  193. X"*New.mnemonic: N",
  194. X"*New.accelerator: <Key>F2",
  195. X"*New.acceleratorText: F2",
  196. X"*Beginner.mnemonic: B",
  197. X"*Intermediate.mnemonic: I",
  198. X"*Expert.mnemonic: E",
  199. X"*Custom.labelString: Custom ...",
  200. X"*Custom.mnemonic: C",
  201. X"*Marks.labelString: Marks [?]",
  202. X"*Marks.mnemonic: M",
  203. X"*Best.labelString: Best Times",
  204. X"*Best.mnemonic: T",
  205. X"*Exit.mnemonic: x",
  206. X"*About.labelString: About xmine ...",
  207. X"*About.mnemonic: A",
  208. X"*Custom.title: Custom Field",
  209. X"*Custom*height_label.labelString: Height:",
  210. X"*Custom*width_label.labelString: Width:",
  211. X"*Custom*mines_label.labelString: Mines:",
  212. X"*Custom*height_text.columns: 4",
  213. X"*Custom*width_text.columns: 4",
  214. X"*Custom*mines_text.columns: 4",
  215. X"*Custom*ok.labelString: Ok",
  216. X"*Best.title: Best Scores",
  217. X"*Best*label.labelString: Fastest Mine Sweepers",
  218. X"*Best*begin_label.labelString: Beginner:",
  219. X"*Best*inter_label.labelString: Intermediate:",
  220. X"*Best*expert_label.labelString: Expert:",
  221. X"*Best*ok.labelString: Ok",
  222. X"*Best*clear.labelString: Reset Scores",
  223. X"*About.title: About xmine",
  224. X"*About*ok.labelString: Ok",
  225. X"*HighScorer.title: New Best Score",
  226. X"*HighScorer*label.labelString: You have the fastest time for this
  227. Xlevel.\\nPlease enter your name.",
  228. X"*HighScorer*name.value: Anonymous",
  229. X"*HighScorer*ok.labelString: Ok",
  230. END_OF_FILE
  231.   if test 1480 -ne `wc -c <'fallback.h'`; then
  232.     echo shar: \"'fallback.h'\" unpacked with wrong size!
  233.   fi
  234.   # end of 'fallback.h'
  235. fi
  236. if test -f 'fillface.xbm' -a "${1}" != "-c" ; then 
  237.   echo shar: Will not clobber existing file \"'fillface.xbm'\"
  238. else
  239.   echo shar: Extracting \"'fillface.xbm'\" \(287 characters\)
  240.   sed "s/^X//" >'fillface.xbm' <<'END_OF_FILE'
  241. X#define fillface_width 16
  242. X#define fillface_height 16
  243. Xstatic char fillface_bits[] = {
  244. X   0xc0, 0x07, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, 0xff,
  245. X   0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0xfc, 0x7f,
  246. X   0xf8, 0x3f, 0xf0, 0x1f, 0xc0, 0x07, 0x00, 0x00};
  247. END_OF_FILE
  248.   if test 287 -ne `wc -c <'fillface.xbm'`; then
  249.     echo shar: \"'fillface.xbm'\" unpacked with wrong size!
  250.   fi
  251.   # end of 'fillface.xbm'
  252. fi
  253. if test -f 'happy.xbm' -a "${1}" != "-c" ; then 
  254.   echo shar: Will not clobber existing file \"'happy.xbm'\"
  255. else
  256.   echo shar: Extracting \"'happy.xbm'\" \(278 characters\)
  257.   sed "s/^X//" >'happy.xbm' <<'END_OF_FILE'
  258. X#define happy_width 16
  259. X#define happy_height 16
  260. Xstatic char happy_bits[] = {
  261. X   0xc0, 0x07, 0x30, 0x18, 0x08, 0x20, 0x04, 0x40, 0x64, 0x4c, 0x62, 0x8c,
  262. X   0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x12, 0x90, 0x24, 0x48, 0xc4, 0x47,
  263. X   0x08, 0x20, 0x30, 0x18, 0xc0, 0x07, 0x00, 0x00};
  264. END_OF_FILE
  265.   if test 278 -ne `wc -c <'happy.xbm'`; then
  266.     echo shar: \"'happy.xbm'\" unpacked with wrong size!
  267.   fi
  268.   # end of 'happy.xbm'
  269. fi
  270. if test -f 'ohno.xbm' -a "${1}" != "-c" ; then 
  271.   echo shar: Will not clobber existing file \"'ohno.xbm'\"
  272. else
  273.   echo shar: Extracting \"'ohno.xbm'\" \(275 characters\)
  274.   sed "s/^X//" >'ohno.xbm' <<'END_OF_FILE'
  275. X#define ohno_width 16
  276. X#define ohno_height 16
  277. Xstatic char ohno_bits[] = {
  278. X   0xc0, 0x07, 0x30, 0x18, 0x08, 0x20, 0x64, 0x4c, 0x64, 0x4c, 0x62, 0x8c,
  279. X   0x02, 0x80, 0x02, 0x80, 0x82, 0x83, 0x42, 0x84, 0x44, 0x44, 0x84, 0x43,
  280. X   0x08, 0x20, 0x30, 0x18, 0xc0, 0x07, 0x00, 0x00};
  281. END_OF_FILE
  282.   if test 275 -ne `wc -c <'ohno.xbm'`; then
  283.     echo shar: \"'ohno.xbm'\" unpacked with wrong size!
  284.   fi
  285.   # end of 'ohno.xbm'
  286. fi
  287. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  288.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  289. else
  290.   echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
  291.   sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  292. X#define PATCHLEVEL 1
  293. END_OF_FILE
  294.   if test 21 -ne `wc -c <'patchlevel.h'`; then
  295.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  296.   fi
  297.   # end of 'patchlevel.h'
  298. fi
  299. if test -f 'press.xbm' -a "${1}" != "-c" ; then 
  300.   echo shar: Will not clobber existing file \"'press.xbm'\"
  301. else
  302.   echo shar: Extracting \"'press.xbm'\" \(278 characters\)
  303.   sed "s/^X//" >'press.xbm' <<'END_OF_FILE'
  304. X#define press_width 16
  305. X#define press_height 16
  306. Xstatic char press_bits[] = {
  307. X   0xc0, 0x07, 0x30, 0x18, 0x08, 0x20, 0x04, 0x40, 0x04, 0x46, 0xc2, 0x86,
  308. X   0xc2, 0x80, 0x02, 0x80, 0x12, 0x80, 0x22, 0x90, 0x24, 0x4c, 0xc4, 0x43,
  309. X   0x08, 0x20, 0x30, 0x18, 0xc0, 0x07, 0x00, 0x00};
  310. END_OF_FILE
  311.   if test 278 -ne `wc -c <'press.xbm'`; then
  312.     echo shar: \"'press.xbm'\" unpacked with wrong size!
  313.   fi
  314.   # end of 'press.xbm'
  315. fi
  316. if test -f 'xmine.1' -a "${1}" != "-c" ; then 
  317.   echo shar: Will not clobber existing file \"'xmine.1'\"
  318. else
  319.   echo shar: Extracting \"'xmine.1'\" \(2123 characters\)
  320.   sed "s/^X//" >'xmine.1' <<'END_OF_FILE'
  321. X.TH XMINE 1
  322. X.SH NAME
  323. Xxmine \- identify mines in a mine field without getting blown up
  324. X.SH SYNOPSIS
  325. X.RB xmine
  326. X.SH DESCRIPTION
  327. X.I xmine
  328. Xis an X11-based version of the popular PC game Minesweeper. The
  329. Xobject is to place flags on mines on the game board without exposing
  330. Xthem.  If you expose a mine, it "explodes" and the game ends.  Exposed
  331. Xmines appear as black capital "M" characters.
  332. X.PP
  333. XTo begin, click the first mouse button anywhere on the field.
  334. XA series of numbers will be revealed.  The number
  335. Xin each square corresponds to the number of mines that border
  336. Xthat square, including diagonals.  Squares that do not border
  337. Xmines are empty.
  338. X.PP
  339. XOnce you have determined the location of a mine, flag it by
  340. Xclicking with the third mouse button.  Flags appear as
  341. Xcapital "X" characters which are red on color displays.
  342. XOnce you have marked
  343. Xall the mines surrounding a number, click the middle mouse
  344. Xbutton to reveal the contents of the un-mined squares surrounding
  345. Xit.  If you flag a mine incorrectly and force an unflagged mine
  346. Xto be revealed, the game ends.
  347. X.PP
  348. XThe number at the top left of the game board displays the number
  349. Xof mines left for you to identify.  At the top right is a timer
  350. Xthat indicates the number of seconds for which the game has
  351. Xbeen running.  High scores are achieved by having the fastest
  352. Xtime for a skill level.
  353. X.PP
  354. XThere are four levels of game play: beginner, intermediate,
  355. Xexpert, and custom, set using the Game menu.  For each level, the number of
  356. Xmines and the size of the board increase:
  357. X.TP 5
  358. X.B beginner
  359. Xhas 10 mines in an 8x8 board.
  360. X.TP 5
  361. X.B intermediate
  362. Xhas 40 mines in a 16x16 board.
  363. X.TP 5
  364. X.B expert
  365. Xhas 99 mines in a 16x39 board.
  366. X.TP 5
  367. X.B custom
  368. Xallows you to specify your own board dimensions and number of mines.
  369. X.PP
  370. XIf you choose Marks [?] from the Game menu, you may place question
  371. Xmarks on squares by clicking twice with the third mouse button.
  372. XAlthough they may be helpful for deducing the location of mines,
  373. Xthey are not treated as flagged mines when you click with the middle
  374. Xmouse button on a numbered square.
  375. X.SH AUTHOR
  376. XPaul Falstad
  377. X.br
  378. XManual entry written by Linda Branagan.
  379. END_OF_FILE
  380.   if test 2123 -ne `wc -c <'xmine.1'`; then
  381.     echo shar: \"'xmine.1'\" unpacked with wrong size!
  382.   fi
  383.   # end of 'xmine.1'
  384. fi
  385. if test -f 'xmine.c' -a "${1}" != "-c" ; then 
  386.   echo shar: Will not clobber existing file \"'xmine.c'\"
  387. else
  388.   echo shar: Extracting \"'xmine.c'\" \(37268 characters\)
  389.   sed "s/^X//" >'xmine.c' <<'END_OF_FILE'
  390. X/* xmine - Copyright (c) 1993 by Paul Falstad
  391. X * freely redistributable
  392. X */
  393. X
  394. X#include <stdio.h>
  395. X#include <Xm/MainW.h>
  396. X#include <Xm/DrawingA.h>
  397. X#include <Xm/PushBG.h>
  398. X#include <Xm/PushB.h>
  399. X#include <Xm/RowColumn.h>
  400. X#include <Xm/ScrolledW.h>
  401. X#include <Xm/Form.h>
  402. X#include <Xm/CascadeBG.h>
  403. X#include <Xm/Separator.h>
  404. X#include <Xm/ToggleB.h>
  405. X#include <Xm/DialogS.h>
  406. X#include <Xm/TextF.h>
  407. X#include <Xm/LabelG.h>
  408. X#include <Xm/PanedW.h>
  409. X
  410. X#include "patchlevel.h"
  411. X
  412. X#define GSPACEX 16
  413. X#define GSPACEY 16
  414. X
  415. X#define SCORE_FILE "~/.xmine_scores"
  416. X#define TOPMARGIN 60
  417. X#define BOTMARGIN 12
  418. X#define SIDEMARGIN 12
  419. X#define STATUS_Y_OFFSET 12
  420. X#define TOTAL_WIDTH (SIDEMARGIN*2+gsizex*GSPACEX)
  421. X#define TOTAL_HEIGHT (TOPMARGIN+BOTMARGIN+gsizey*GSPACEY)
  422. X#define STATUS_HEIGHT (TOPMARGIN-STATUS_Y_OFFSET*2)
  423. X#define DIGIT_X_OFFSET (SIDEMARGIN+4)
  424. X#define DIGIT_Y_OFFSET (STATUS_Y_OFFSET+4)
  425. X#define DIGIT_HEIGHT (TOPMARGIN-DIGIT_Y_OFFSET*2)
  426. X#define DIGIT_WIDTH 16
  427. X#define DIGIT_COUNT 3
  428. X#define DIGIT_MARGIN 2
  429. X#define DIGIT_HWEDGE_WIDTH (DIGIT_WIDTH-(DIGIT_MARGIN+1)*2)
  430. X#define DIGIT_VWEDGE_HEIGHT ((DIGIT_HEIGHT-7)/2)
  431. X
  432. X#define COVERED 0
  433. X#define MARKED 1
  434. X#define UNCOVERED 2
  435. X#define QUESTIONED 3
  436. X#define MINE -1
  437. X#define MAX_GSIZEX 100
  438. X#define MAX_GSIZEY 100
  439. Xint grid[MAX_GSIZEX][MAX_GSIZEY]; /* fix this */
  440. Xint gridview[MAX_GSIZEX][MAX_GSIZEY]; /* fix this */
  441. X#define INITIAL_SIZE_X 8
  442. X#define INITIAL_SIZE_Y 8
  443. Xint gsizex = INITIAL_SIZE_X, gsizey = INITIAL_SIZE_Y;
  444. Xint layed_out = 0, game_on = 1, face_armed = 0;
  445. Xint questions_allowed = 0, game_level = 0;
  446. XXFontStruct *font_info;
  447. XWidget drawarea;
  448. XDisplay *disp;
  449. XWindow win;
  450. X
  451. X#define COL_BLUE 0
  452. X#define COL_LIMEGREEN 1
  453. X#define COL_RED 2
  454. X#define COL_NAVY 3
  455. X#define COL_BROWN 4
  456. X#define COL_AQUA 5
  457. X#define COL_BLACK 6
  458. X#define COL_GRAY 7
  459. X#define COL_WHITE 8
  460. X#define COL_LITEGRAY 9
  461. X#define COL_DARKGRAY 10
  462. X#define COL_YELLOW 11
  463. X#define COL_DARKRED 12
  464. X#define COL_COUNT 13
  465. Xchar *colnames[COL_COUNT] = {
  466. X    "Blue", "LimeGreen", "Red", "Navy",
  467. X    "Brown", "MediumAquamarine", "Black", "Gray",
  468. X    "White", "Grey75", "Grey50", "Yellow", "darkred"
  469. X};
  470. XXColor cols[COL_COUNT];
  471. X
  472. Xint numcols[] = {
  473. X    COL_BLUE, COL_LIMEGREEN, COL_RED, COL_NAVY,
  474. X    COL_BROWN, COL_AQUA, COL_BLACK, COL_GRAY
  475. X};
  476. X
  477. X#include "cool.xbm"
  478. X#include "fillface.xbm"
  479. X#include "dead.xbm"
  480. X#include "happy.xbm"
  481. X#include "ohno.xbm"
  482. X#include "press.xbm"
  483. X
  484. X#define FACE_HAPPY 0
  485. X#define FACE_OHNO 1
  486. X#define FACE_COOL 2
  487. X#define FACE_DEAD 3
  488. X#define FACE_PRESS 4
  489. X#define FACE_COUNT 5
  490. XPixmap faces[FACE_COUNT];
  491. Xstatic char *face_bits[FACE_COUNT] = {
  492. X    happy_bits, ohno_bits, cool_bits, dead_bits, press_bits
  493. X};
  494. Xint cur_face = FACE_HAPPY;
  495. Xint mine_count, covered_count, marked_count;
  496. Xint armed_x, armed_y, armed, timer;
  497. XXtIntervalId timer_id;
  498. X
  499. X#define FACE_BUTTON_WIDTH (fillface_width+5)
  500. X#define FACE_BUTTON_HEIGHT (fillface_height+5)
  501. X#define FACE_X_POS ((TOTAL_WIDTH-FACE_BUTTON_WIDTH)/2+1)
  502. X#define FACE_Y_POS ((TOPMARGIN-FACE_BUTTON_HEIGHT)/2)
  503. X
  504. XGC gc;
  505. X
  506. X#ifdef __STDC__
  507. X#define P(X) X
  508. X#else
  509. X#define P(X) ()
  510. X#endif /* __STDC__ */
  511. X
  512. Xtypedef void (*void_proc)();
  513. X
  514. Xextern void search_action P ((Widget, XButtonEvent *, String *, int *));
  515. Xextern void clear_action P ((Widget, XButtonEvent *, String *, int *));
  516. Xextern void mark_action P ((Widget, XButtonEvent *, String *, int *));
  517. Xextern void redraw_cb P ((Widget, XtPointer, XmDrawingAreaCallbackStruct *));
  518. Xextern void redrawsquare P ((int, int));
  519. Xextern void drawsquare P ((int, int));
  520. Xextern int hasmine P ((int, int));
  521. Xextern void uncover P ((int, int));
  522. Xextern void clear_around P ((int, int));
  523. Xextern int is_state P ((int, int, int));
  524. Xextern void shadow_rev_rect P ((int, int, int, int, int));
  525. Xextern void shadow_rect P ((int, int, int, int, int));
  526. Xextern XmString genxmstr P ((char *));
  527. Xextern void layout_board P ((int, int));
  528. Xextern void boom P ((void));
  529. Xextern void restart P ((void));
  530. Xextern void draw_face P ((void));
  531. Xextern void set_face P ((int));
  532. Xextern void winner P ((void));
  533. Xextern void draw_blank_square P ((int, int, int));
  534. Xextern void draw_button P ((int, int));
  535. Xextern void arm_clear P ((int, int, int));
  536. Xextern void track_face P ((int, int, int));
  537. Xextern void arm_face P ((int));
  538. Xextern void draw_digit P ((int, int, int));
  539. Xextern void draw_digits P ((int, int));
  540. Xextern void timer_callback P ((void));
  541. Xextern void set_level P ((Widget, int));
  542. Xextern void tog_question P ((void));
  543. Xextern void set_custom P ((void));
  544. Xextern void dialog_ok P ((void));
  545. Xextern void get_text_int P ((Widget, int *));
  546. Xextern void best_times P ((void));
  547. Xextern void about P ((void));
  548. Xextern struct scores *get_scores P ((void));
  549. Xextern void write_scores P ((struct scores *));
  550. Xextern void get_score_file_name P ((char *));
  551. Xextern void new_best P ((int));
  552. Xextern void clear_scores P ((void));
  553. Xextern int cant_write_score_file P ((void));
  554. Xextern void fix_size P ((void));
  555. Xextern void relax_size P ((void));
  556. Xextern void resize_handler P ((Widget, XtPointer, XEvent *, Boolean *));
  557. X
  558. XPixmap fillface;
  559. XXtAppContext app;
  560. XWidget toplevel, menubar;
  561. XWidget level_buttons[4];
  562. X
  563. Xstruct scores {
  564. X    char names[3][80];
  565. X    int times[3];
  566. X};
  567. X
  568. Xchar *fallbacks[] = {
  569. X#include "fallback.h"
  570. X    NULL
  571. X};
  572. X
  573. Xmain(argc, argv)
  574. Xunsigned int argc;
  575. Xchar *argv[];
  576. X{
  577. X    Widget main_w, drawing_a, menu, btn;
  578. X    XGCValues gcv;
  579. X    void draw(), redraw_cb(), set_color(), exit();
  580. X    XColor unused;
  581. X    int i;
  582. X
  583. X    XtActionsRec actions[3];
  584. X    String translations =
  585. X        "<Btn1Down>:   search(down)\n\
  586. X         <Btn1Up>:     search(up)\n\
  587. X         <Btn1Motion>: search(move)\n\
  588. X     <Btn2Down>:   clear(down)\n\
  589. X     <Btn2Motion>: clear(move)\n\
  590. X     <Btn2Up>:     clear(up)\n\
  591. X     <Btn3Down>:   mark(down)\n";
  592. X
  593. X    toplevel = XtVaAppInitialize(&app, "Xmine", NULL, 0,
  594. X        &argc, argv, fallbacks, NULL);
  595. X
  596. X    main_w = XtVaCreateManagedWidget("main_w",
  597. X        xmFormWidgetClass, toplevel,
  598. X    NULL);
  599. X
  600. X    menubar = XmCreateMenuBar(main_w, "menubar", NULL, 0);
  601. X    XtVaSetValues(menubar,
  602. X    XmNtopAttachment, XmATTACH_FORM,
  603. X    XmNleftAttachment, XmATTACH_FORM,
  604. X    XmNrightAttachment,    XmATTACH_FORM,
  605. X    NULL);
  606. X    menu = XmCreatePulldownMenu(menubar, "game_menu", NULL, 0);
  607. X    XtVaCreateManagedWidget("game",
  608. X    xmCascadeButtonGadgetClass, menubar,
  609. X    XmNsubMenuId,            menu,
  610. X    XmNbackground,     cols[COL_LITEGRAY].pixel,
  611. X    NULL);
  612. X    btn = XtVaCreateManagedWidget("New",
  613. X    xmPushButtonGadgetClass,   menu,
  614. X    NULL);
  615. X    XtAddCallback(btn, XmNactivateCallback, (void_proc) restart, 0);
  616. X    XtVaCreateManagedWidget("_sep1", xmSeparatorWidgetClass, menu, NULL);
  617. X    level_buttons[0] = btn = XtVaCreateManagedWidget("Beginner",
  618. X    xmToggleButtonWidgetClass,   menu,
  619. X    NULL);
  620. X    XtAddCallback(btn, XmNvalueChangedCallback, (void_proc) set_level,
  621. X(XtPointer) 1);
  622. X    level_buttons[1] = btn = XtVaCreateManagedWidget("Intermediate",
  623. X    xmToggleButtonWidgetClass,   menu,
  624. X    NULL);
  625. X    XtAddCallback(btn, XmNvalueChangedCallback, (void_proc) set_level,
  626. X(XtPointer) 2);
  627. X    level_buttons[2] = btn = XtVaCreateManagedWidget("Expert",
  628. X    xmToggleButtonWidgetClass,   menu,
  629. X    NULL);
  630. X    XtAddCallback(btn, XmNvalueChangedCallback, (void_proc) set_level,
  631. X(XtPointer) 3);
  632. X    level_buttons[3] = btn = XtVaCreateManagedWidget("Custom",
  633. X    xmToggleButtonWidgetClass,   menu,
  634. X    NULL);
  635. X    XtAddCallback(btn, XmNvalueChangedCallback, (void_proc) set_custom, NULL);
  636. X    XtVaCreateManagedWidget("_sep2", xmSeparatorWidgetClass, menu, NULL);
  637. X    btn = XtVaCreateManagedWidget("Marks",
  638. X    xmToggleButtonWidgetClass,   menu,
  639. X    NULL);
  640. X    XtAddCallback(btn, XmNvalueChangedCallback,
  641. X    (XtPointer) tog_question, NULL);
  642. X    XtVaCreateManagedWidget("_sep3", xmSeparatorWidgetClass, menu, NULL);
  643. X    btn = XtVaCreateManagedWidget("Best",
  644. X    xmPushButtonWidgetClass,   menu,
  645. X    NULL);
  646. X    XtAddCallback(btn, XmNactivateCallback, (void_proc) best_times, NULL);
  647. X    btn = XtVaCreateManagedWidget("About",
  648. X    xmPushButtonWidgetClass,   menu,
  649. X    NULL);
  650. X    XtAddCallback(btn, XmNactivateCallback, (void_proc) about, NULL);
  651. X    btn = XtVaCreateManagedWidget("Exit",
  652. X    xmPushButtonWidgetClass,   menu,
  653. X    NULL);
  654. X    XtAddCallback(btn, XmNactivateCallback, (void_proc) exit, NULL);
  655. X    XtManageChild(menubar);
  656. X
  657. X    for (i = 0; i != COL_COUNT; i++)
  658. X    XAllocNamedColor(XtDisplay(main_w),
  659. X        DefaultColormapOfScreen(XtScreen(main_w)),
  660. X        colnames[i], &cols[i], &unused);
  661. X    {
  662. X    cols[COL_DARKRED].red = 60*256;
  663. X    cols[COL_DARKRED].green = cols[COL_DARKRED].blue = 0;
  664. X    XAllocColor(XtDisplay(main_w),
  665. X        DefaultColormapOfScreen(XtScreen(main_w)),
  666. X        &cols[COL_DARKRED]);
  667. X    }
  668. X
  669. X    gcv.foreground = cols[COL_WHITE].pixel;
  670. X    gc = XCreateGC(XtDisplay(main_w),
  671. X        RootWindowOfScreen(XtScreen(main_w)), GCForeground, &gcv);
  672. X
  673. X    actions[0].string = "clear";
  674. X    actions[0].proc = (void_proc) clear_action;
  675. X    actions[1].string = "search";
  676. X    actions[1].proc = (void_proc) search_action;
  677. X    actions[2].string = "mark";
  678. X    actions[2].proc = (void_proc) mark_action;
  679. X    XtAppAddActions(app, actions, 3);
  680. X
  681. X    drawing_a = XtVaCreateManagedWidget("drawing_a",
  682. X        xmDrawingAreaWidgetClass, main_w,
  683. X        XmNtranslations, XtParseTranslationTable(translations),
  684. X        XmNwidth,        GSPACEX*gsizex+SIDEMARGIN*2,
  685. X        XmNheight,       GSPACEY*gsizey+TOPMARGIN+BOTMARGIN,
  686. X        XmNresizePolicy, XmNONE,  /* remain this a fixed size */
  687. X    XmNbackground,     cols[COL_LITEGRAY].pixel,
  688. X    XmNtopAttachment,XmATTACH_WIDGET,
  689. X    XmNtopWidget,     menubar,
  690. X        NULL);
  691. X    XtAddCallback(drawing_a, XmNexposeCallback, (void_proc) redraw_cb, NULL);
  692. X    font_info = XLoadQueryFont(XtDisplay(main_w),
  693. X    "-*-courier-bold-r-normal-*-*-120-*");
  694. X    XSetFont(XtDisplay(main_w), gc, font_info->fid);
  695. X
  696. X    set_level((Widget) 0, 1);
  697. X    XtAddEventHandler(toplevel,
  698. X    StructureNotifyMask, False, resize_handler, 0);
  699. X    XtRealizeWidget(toplevel);
  700. X    fillface = XCreateBitmapFromData(XtDisplay(main_w),
  701. X    XtWindow(main_w), fillface_bits,
  702. X    fillface_width, fillface_height);
  703. X    for (i = 0; i != FACE_COUNT; i++)
  704. X    faces[i] = XCreateBitmapFromData(XtDisplay(main_w),
  705. X        XtWindow(main_w), face_bits[i],
  706. X        fillface_width, fillface_height);
  707. X    drawarea = drawing_a;
  708. X    win = XtWindow(drawing_a);
  709. X    disp = XtDisplay(drawing_a);
  710. X    XtAppMainLoop(app);
  711. X    return 0;
  712. X}
  713. X
  714. Xvoid
  715. Xsearch_action(widget, event, args, num_args)
  716. XWidget widget;
  717. XXButtonEvent *event;
  718. XString *args;
  719. Xint *num_args;
  720. X{
  721. X    int xg, yg;
  722. X
  723. X    track_face(event->x, event->y, *args[0]);
  724. X    if (!game_on) return;
  725. X    xg = (event->x-SIDEMARGIN)/GSPACEX;
  726. X    yg = (event->y-TOPMARGIN)/GSPACEY;
  727. X    if (!strcmp(args[0], "down")) {
  728. X    armed = False;
  729. X    if (!(xg >= 0 && xg < gsizex && yg >= 0 && yg < gsizey))
  730. X        return;
  731. X    if (gridview[xg][yg] != COVERED) return;
  732. X    armed_x = xg; armed_y = yg;
  733. X    armed = True;
  734. X    set_face(FACE_OHNO);
  735. X    draw_blank_square(xg, yg, True);
  736. X    return;
  737. X    }
  738. X    if (!strcmp(args[0], "move")) {
  739. X    if (xg == armed_x && yg == armed_y) {
  740. X        if (!armed) {
  741. X        set_face(FACE_OHNO);
  742. X        draw_blank_square(armed_x, armed_y, True);
  743. X        armed = True;
  744. X        }
  745. X    } else {
  746. X        if (armed) {
  747. X        set_face(FACE_HAPPY);
  748. X        draw_button(armed_x, armed_y);
  749. X        armed = False;
  750. X        }
  751. X    }
  752. X    return;
  753. X    }
  754. X    if (!armed) return;
  755. X    if (!layed_out) layout_board(armed_x, armed_y);
  756. X    uncover(armed_x, armed_y);
  757. X    if (game_on) set_face(FACE_HAPPY);
  758. X}
  759. X
  760. Xvoid
  761. Xtrack_face(x, y, op)
  762. Xint x, y, op;
  763. X{
  764. X    int onface = False;
  765. X
  766. X    if (x >= FACE_X_POS && x <= FACE_X_POS+FACE_BUTTON_WIDTH &&
  767. X    y >= FACE_Y_POS && y <= FACE_Y_POS+FACE_BUTTON_HEIGHT)
  768. X    onface = True;
  769. X    if (op == 'u') {
  770. X    if (!face_armed) return;
  771. X    arm_face(False);
  772. X    restart();
  773. X    return;
  774. X    }
  775. X    if (op == 'd') {
  776. X    if (!onface) return;
  777. X    arm_face(True);
  778. X    armed = False;
  779. X    return;
  780. X    }
  781. X    if (onface != face_armed)
  782. X    arm_face(onface);
  783. X}
  784. X
  785. Xvoid
  786. Xarm_face(armit)
  787. Xint armit;
  788. X{
  789. X    face_armed = armit;
  790. X    XClearArea(disp, win,
  791. X    FACE_X_POS, FACE_Y_POS, FACE_BUTTON_WIDTH, FACE_BUTTON_HEIGHT,
  792. X    False);
  793. X    if (face_armed)
  794. X    shadow_rev_rect(FACE_X_POS+2, FACE_Y_POS+2,
  795. X        FACE_BUTTON_WIDTH-4, FACE_BUTTON_HEIGHT-4, 2);
  796. X    else
  797. X    shadow_rect(FACE_X_POS, FACE_Y_POS,
  798. X        FACE_BUTTON_WIDTH, FACE_BUTTON_HEIGHT, 2);
  799. X    draw_face();
  800. X}
  801. X
  802. Xvoid
  803. Xmark_action(widget, event, args, num_args)
  804. XWidget widget;
  805. XXButtonEvent *event;
  806. XString *args;
  807. Xint *num_args;
  808. X{
  809. X    if (!game_on) return;
  810. X    if (!layed_out) return;
  811. X    if (!strcmp(args[0], "down")) {
  812. X    int xg, yg;
  813. X
  814. X    xg = (event->x-SIDEMARGIN)/GSPACEX;
  815. X    yg = (event->y-TOPMARGIN)/GSPACEY;
  816. X    if (xg >= 0 && xg < gsizex &&
  817. X        yg >= 0 && yg < gsizey) {
  818. X        if (gridview[xg][yg] == UNCOVERED) return;
  819. X        if (gridview[xg][yg] == MARKED) {
  820. X        gridview[xg][yg] = (questions_allowed) ? QUESTIONED : COVERED;
  821. X        marked_count--;
  822. X        } else if (gridview[xg][yg] == QUESTIONED)
  823. X        gridview[xg][yg] = COVERED;
  824. X        else {
  825. X        gridview[xg][yg] = MARKED;
  826. X        marked_count++;
  827. X        }
  828. X        redrawsquare(xg, yg);
  829. X        draw_digits(mine_count-marked_count, 0);
  830. X        draw_digits(timer, 1);
  831. X    }
  832. X    }
  833. X}
  834. X
  835. Xvoid
  836. Xclear_action(widget, event, args, num_args)
  837. XWidget widget;
  838. XXButtonEvent *event;
  839. XString *args;
  840. Xint *num_args;
  841. X{
  842. X    int xg, yg;
  843. X
  844. X    if (!game_on) return;
  845. X    if (!layed_out) return;
  846. X    xg = (event->x-SIDEMARGIN)/GSPACEX;
  847. X    yg = (event->y-TOPMARGIN)/GSPACEY;
  848. X    if (!(xg >= 0 && xg < gsizex && yg >= 0 && yg < gsizey))
  849. X    return;
  850. X    if (!strcmp(args[0], "down")) {
  851. X    arm_clear(xg, yg, True);
  852. X    armed_x = xg; armed_y = yg;
  853. X    return;
  854. X    }
  855. X    if (!strcmp(args[0], "move")) {
  856. X    int arm_it = (xg == armed_x && yg == armed_y);
  857. X    if (arm_it != armed) arm_clear(armed_x, armed_y, arm_it);
  858. X    return;
  859. X    }
  860. X    if (!armed) return;
  861. X    arm_clear(armed_x, armed_y, False);
  862. X    clear_around(xg, yg);
  863. X    if (game_on)
  864. X    set_face(FACE_HAPPY);
  865. X}
  866. X
  867. Xvoid
  868. Xarm_clear(x, y, armit)
  869. Xint x, y, armit;
  870. X{
  871. X    int dx, dy;
  872. X
  873. X    armed = armit;
  874. X    set_face(armit ? FACE_OHNO : FACE_HAPPY);
  875. X    for (dx = -1; dx <= 1; dx++)
  876. X    for (dy = -1; dy <= 1; dy++)
  877. X        if (is_state(x+dx, y+dy, COVERED))
  878. X        if (armit)
  879. X            draw_blank_square(x+dx, y+dy, True);
  880. X        else
  881. X            draw_button(x+dx, y+dy);
  882. X}
  883. X
  884. Xvoid
  885. Xdraw_face()
  886. X{
  887. X    int x, y;
  888. X
  889. X    x = (TOTAL_WIDTH-fillface_width)/2+face_armed;
  890. X    y = (TOPMARGIN-fillface_height)/2+face_armed;
  891. X    XSetClipMask(disp, gc, fillface);
  892. X    XSetClipOrigin(disp, gc, x, y);
  893. X    XSetBackground(disp, gc, cols[COL_YELLOW].pixel);
  894. X    XSetForeground(disp, gc, cols[COL_BLACK].pixel);
  895. X    XCopyPlane(disp,
  896. X    (Drawable) faces[(face_armed) ? FACE_PRESS : cur_face],
  897. X    win, gc, 0, 0,
  898. X    fillface_width, fillface_height, x, y, 1L);
  899. X    XSetClipMask(disp, gc, None);
  900. X}
  901. X
  902. Xvoid
  903. Xset_face(f)
  904. Xint f;
  905. X{
  906. X    if (cur_face == f) return;
  907. X    cur_face = f;
  908. X    draw_face();
  909. X}
  910. X
  911. Xvoid
  912. Xredraw_cb(drawing_a, client_data, cbs)
  913. XWidget    drawing_a;
  914. XXtPointer client_data;
  915. XXmDrawingAreaCallbackStruct *cbs;
  916. X{
  917. X    int x, y, w, h, xf, yf, xt, yt;
  918. X
  919. X    x = cbs->event->xexpose.x-SIDEMARGIN;
  920. X    y = cbs->event->xexpose.y-TOPMARGIN;
  921. X    w = cbs->event->xexpose.width;
  922. X    h = cbs->event->xexpose.height;
  923. X    xf = x/GSPACEX;
  924. X    yf = y/GSPACEY;
  925. X    xt = (x+w+GSPACEX-1)/GSPACEX;
  926. X    yt = (y+h+GSPACEX-1)/GSPACEX;
  927. X    for (x = xf; x <= xt; x++)
  928. X    for (y = yf; y <= yt; y++)
  929. X        drawsquare(x, y);
  930. X    if (xf < 0 || yf < 0 || xt >= gsizex || yt >= gsizey) {
  931. X    shadow_rect(0, 0, TOTAL_WIDTH, TOTAL_HEIGHT, 3);
  932. X    shadow_rev_rect(SIDEMARGIN, TOPMARGIN,
  933. X        TOTAL_WIDTH-SIDEMARGIN*2,
  934. X        TOTAL_HEIGHT-(TOPMARGIN+BOTMARGIN), 3);
  935. X    shadow_rev_rect(SIDEMARGIN, STATUS_Y_OFFSET,
  936. X        TOTAL_WIDTH-SIDEMARGIN*2,
  937. X        STATUS_HEIGHT, 3);
  938. X    shadow_rect(FACE_X_POS, FACE_Y_POS,
  939. X        FACE_BUTTON_WIDTH, FACE_BUTTON_HEIGHT, 2);
  940. X    draw_face();
  941. X    draw_digits(mine_count-marked_count, 0);
  942. X    draw_digits(timer, 1);
  943. X    }
  944. X}
  945. X
  946. Xvoid
  947. Xredrawsquare(x, y)
  948. Xint x, y;
  949. X{
  950. X    XClearArea(disp, win, x*GSPACEX+SIDEMARGIN,
  951. X    y*GSPACEY+TOPMARGIN, GSPACEX, GSPACEY, True);
  952. X}
  953. X
  954. Xvoid
  955. Xredraw_all()
  956. X{
  957. X    XClearArea(disp, win, SIDEMARGIN,
  958. X    TOPMARGIN, GSPACEX*gsizex, GSPACEY*gsizey, True);
  959. X}
  960. X
  961. Xvoid
  962. Xredraw_entire()
  963. X{
  964. X    if (disp)
  965. X    XClearArea(disp, win, 0, 0, TOTAL_WIDTH, TOTAL_HEIGHT, True);
  966. X}
  967. X
  968. Xvoid
  969. Xshadow_rect(xp, yp, w, h, thick)
  970. Xint xp, yp, w, h, thick;
  971. X{
  972. X    int off = 0;
  973. X
  974. X    w--, h--;
  975. X    while (thick--) {
  976. X    XSetForeground(disp, gc, cols[COL_WHITE].pixel);
  977. X    XDrawLine(disp, win, gc,
  978. X        xp, yp+off, xp+w-off, yp+off);
  979. X    XDrawLine(disp, win, gc,
  980. X        xp+off, yp, xp+off, yp+h-off);
  981. X    XSetForeground(disp, gc, cols[COL_DARKGRAY].pixel);
  982. X    XDrawLine(disp, win, gc,
  983. X        xp+off, yp+h-off, xp+w, yp+h-off);
  984. X    XDrawLine(disp, win, gc,
  985. X        xp+w-off, yp+off, xp+w-off, yp+h);
  986. X    off++;
  987. X    }
  988. X}
  989. X
  990. Xvoid
  991. Xshadow_rev_rect(xp, yp, w, h, thick)
  992. Xint xp, yp, w, h, thick;
  993. X{
  994. X    int off = 0;
  995. X
  996. X    w--, h--;
  997. X    xp -= thick; yp -= thick;
  998. X    w += thick*2; h += thick*2;
  999. X    while (thick--) {
  1000. X    XSetForeground(disp, gc, cols[COL_DARKGRAY].pixel);
  1001. X    XDrawLine(disp, win, gc,
  1002. X        xp, yp+off, xp+w-off, yp+off);
  1003. X    XDrawLine(disp, win, gc,
  1004. X        xp+off, yp, xp+off, yp+h-off);
  1005. X    XSetForeground(disp, gc, cols[COL_WHITE].pixel);
  1006. X    XDrawLine(disp, win, gc,
  1007. X        xp+off, yp+h-off, xp+w, yp+h-off);
  1008. X    XDrawLine(disp, win, gc,
  1009. X        xp+w-off, yp+off, xp+w-off, yp+h);
  1010. X    off++;
  1011. X    }
  1012. X}
  1013. X
  1014. Xvoid
  1015. Xdraw_button(xp, yp)
  1016. Xint xp, yp;
  1017. X{
  1018. X    xp = xp*GSPACEX+SIDEMARGIN;
  1019. X    yp = yp*GSPACEY+TOPMARGIN;
  1020. X    shadow_rect(xp, yp, GSPACEX, GSPACEY, 2);
  1021. X}
  1022. X
  1023. Xvoid
  1024. Xdraw_blank_square(xp, yp, clr)
  1025. Xint xp, yp, clr;
  1026. X{
  1027. X    xp = xp*GSPACEX+SIDEMARGIN;
  1028. X    yp = yp*GSPACEY+TOPMARGIN;
  1029. X    if (clr)
  1030. X    XClearArea(disp, win,
  1031. X        xp, yp, GSPACEX, GSPACEY, False);
  1032. X    XSetForeground(disp, gc, cols[COL_DARKGRAY].pixel);
  1033. X    XDrawLine(disp, win, gc,
  1034. X    xp, yp, xp+GSPACEX-1, yp);
  1035. X    XDrawLine(disp, win, gc,
  1036. X    xp, yp, xp, yp+GSPACEY-1);
  1037. X}
  1038. X
  1039. Xvoid
  1040. Xdrawsquare(x, y)
  1041. Xint x, y;
  1042. X{
  1043. X    int xp, yp;
  1044. X    char buf[2];
  1045. X    int wid;
  1046. X    int color, yoffset = 0;
  1047. X
  1048. X    if (x < 0 || y < 0 || x >= gsizex || y >= gsizey) return;
  1049. X    buf[1] = 0;
  1050. X    xp = x*GSPACEX+SIDEMARGIN;
  1051. X    yp = y*GSPACEY+TOPMARGIN;
  1052. X    if (gridview[x][y] == UNCOVERED) {
  1053. X    draw_blank_square(x, y, False);
  1054. X    if (!grid[x][y]) return;
  1055. X    if (grid[x][y] == MINE) {
  1056. X        buf[0] = 'M';
  1057. X        color = COL_BLACK;
  1058. X    } else {
  1059. X        color = numcols[grid[x][y]-1];
  1060. X        buf[0] = grid[x][y]+'0';
  1061. X        yoffset = 2;
  1062. X    }
  1063. X    } else if (gridview[x][y] == MARKED) {
  1064. X    draw_button(x, y);
  1065. X    buf[0] = 'X';
  1066. X    color = COL_RED;
  1067. X    } else if (gridview[x][y] == QUESTIONED) {
  1068. X    draw_button(x, y);
  1069. X    buf[0] = '?';
  1070. X    color = COL_RED;
  1071. X    } else {
  1072. X    draw_button(x, y);
  1073. X    return;
  1074. X    }
  1075. X
  1076. X    wid = XTextWidth(font_info, buf, 1);
  1077. X    XSetForeground(disp, gc, cols[color].pixel);
  1078. X    XDrawString(disp, win, gc,
  1079. X    xp+(GSPACEX-wid)/2,
  1080. X    yp+(GSPACEY+font_info->ascent-font_info->descent)/2+yoffset,
  1081. X    buf, 1);
  1082. X}
  1083. X
  1084. Xvoid
  1085. Xlayout_board(fx, fy)
  1086. Xint fx, fy;
  1087. X{
  1088. X    int i, x, y, xd, yd, tries;
  1089. X
  1090. X    srand((unsigned int) time(0));
  1091. X    for (i = 0; i != mine_count; i++) {
  1092. X    tries = 1000;
  1093. X    do {
  1094. X        x = (rand()>>1) % gsizex;
  1095. X        y = (rand()>>1) % gsizey;
  1096. X        tries--;
  1097. X    } while (tries && (grid[x][y] ||
  1098. X             !(x < fx-1 || x > fx+1 || y < fy-1 || y > fy+1)));
  1099. X    grid[x][y] = MINE;
  1100. X    if (!tries) {
  1101. X        mine_count = i;
  1102. X        break;
  1103. X    }
  1104. X    }
  1105. X    for (x = 0; x != gsizex; x++)
  1106. X    for (y = 0; y != gsizey; y++) {
  1107. X        if (grid[x][y] == MINE) continue;
  1108. X        i = 0;
  1109. X        for (xd = -1; xd <= 1; xd++)
  1110. X        for (yd = -1; yd <= 1; yd++)
  1111. X            if (hasmine(x+xd, y+yd)) i++;
  1112. X        grid[x][y] = i;
  1113. X    }
  1114. X    layed_out = 1;
  1115. X    if (timer_id)
  1116. X    XtRemoveTimeOut(timer_id);
  1117. X    timer_id = XtAppAddTimeOut(app, 1000L, (void_proc) timer_callback, NULL);
  1118. X    covered_count = gsizex*gsizey;
  1119. X    fix_size();
  1120. X}
  1121. X
  1122. Xvoid
  1123. Xtimer_callback()
  1124. X{
  1125. X    if (!(layed_out && game_on)) {
  1126. X    timer_id = 0;
  1127. X    return;
  1128. X    }
  1129. X    if (timer >= 999) return;
  1130. X    draw_digits(++timer, 1);
  1131. X    timer_id = XtAppAddTimeOut(app, 1000L, (void_proc) timer_callback, NULL);
  1132. X}
  1133. X
  1134. Xint
  1135. Xhasmine(x, y)
  1136. Xint x, y;
  1137. X{
  1138. X    if (x < 0 || y < 0 || x >= gsizex || y >= gsizey) return False;
  1139. X    return grid[x][y] == MINE;
  1140. X}
  1141. X
  1142. Xint
  1143. Xis_state(x, y, state)
  1144. Xint x, y, state;
  1145. X{
  1146. X    if (x < 0 || y < 0 || x >= gsizex || y >= gsizey) return False;
  1147. X    return gridview[x][y] == state;
  1148. X}
  1149. X
  1150. Xint
  1151. Xiscovered(x, y)
  1152. Xint x, y;
  1153. X{
  1154. X    if (x < 0 || y < 0 || x >= gsizex || y >= gsizey) return False;
  1155. X    return gridview[x][y] == COVERED;
  1156. X}
  1157. X
  1158. Xvoid
  1159. Xuncover(x, y)
  1160. Xint x, y;
  1161. X{
  1162. X    int dx, dy;
  1163. X
  1164. X    if (x < 0 || y < 0 || x >= gsizex || y >= gsizey) return;
  1165. X    if (gridview[x][y] != COVERED) return;
  1166. X    gridview[x][y] = UNCOVERED;
  1167. X    covered_count--;
  1168. X    if (grid[x][y] == MINE)
  1169. X    boom();
  1170. X    else if (covered_count == mine_count)
  1171. X    winner();
  1172. X    redrawsquare(x, y);
  1173. X    if (grid[x][y] == 0)
  1174. X    for (dx = -1; dx <= 1; dx++)
  1175. X        for (dy = -1; dy <= 1; dy++)
  1176. X        uncover(x+dx, y+dy);
  1177. X}
  1178. X
  1179. Xvoid
  1180. Xboom()
  1181. X{
  1182. X    int x, y;
  1183. X
  1184. X    for (x = 0; x != gsizex; x++)
  1185. X    for (y = 0; y != gsizey; y++) {
  1186. X        if (grid[x][y] != MINE || gridview[x][y] == MARKED) continue;
  1187. X        gridview[x][y] = UNCOVERED;
  1188. X        redrawsquare(x, y);
  1189. X    }
  1190. X    game_on = 0;
  1191. X    relax_size();
  1192. X    set_face(FACE_DEAD);
  1193. X}
  1194. X
  1195. Xvoid
  1196. Xwinner()
  1197. X{
  1198. X    int x, y;
  1199. X
  1200. X    game_on = 0;
  1201. X    relax_size();
  1202. X    for (x = 0; x != gsizex; x++)
  1203. X    for (y = 0; y != gsizey; y++)
  1204. X        if (gridview[x][y] == COVERED) {
  1205. X        gridview[x][y] = MARKED;
  1206. X        redrawsquare(x, y);
  1207. X        }
  1208. X    draw_digits(0, 0);
  1209. X    set_face(FACE_COOL);
  1210. X    XtAppAddTimeOut(app, 500L, (void_proc) new_best, (XtPointer) game_level);
  1211. X}
  1212. X
  1213. Xvoid
  1214. Xrestart()
  1215. X{
  1216. X    int x, y;
  1217. X
  1218. X    for (x = 0; x != gsizex; x++)
  1219. X    for (y = 0; y != gsizey; y++) {
  1220. X        gridview[x][y] = COVERED;
  1221. X        grid[x][y] = 0;
  1222. X    }
  1223. X    game_on = 1;
  1224. X    layed_out = 0;
  1225. X    relax_size();
  1226. X    if (drawarea) {
  1227. X    redraw_all();
  1228. X    set_face(FACE_HAPPY);
  1229. X    }
  1230. X    timer = marked_count = 0;
  1231. X}
  1232. X
  1233. Xvoid
  1234. Xclear_around(x, y)
  1235. Xint x, y;
  1236. X{
  1237. X    int dx, dy, ct = 0;
  1238. X
  1239. X    if (gridview[x][y] != UNCOVERED) return;
  1240. X    for (dx = -1; dx <= 1; dx++)
  1241. X    for (dy = -1; dy <= 1; dy++)
  1242. X        if (is_state(x+dx, y+dy, MARKED)) ct++;
  1243. X    if (grid[x][y] != ct) return;
  1244. X    for (dx = -1; dx <= 1; dx++)
  1245. X    for (dy = -1; dy <= 1; dy++)
  1246. X        if (is_state(x+dx, y+dy, COVERED)) uncover(x+dx, y+dy);
  1247. X}
  1248. X
  1249. XXmString
  1250. Xgenxmstr(str)
  1251. Xchar *str;
  1252. X{
  1253. X    static XmString oldstr;
  1254. X
  1255. X    if (oldstr) XmStringFree(oldstr);
  1256. X    return oldstr = XmStringLtoRCreate(str, XmSTRING_DEFAULT_CHARSET);
  1257. X}
  1258. X
  1259. Xvoid
  1260. Xdraw_hwedge(x, y, dir)
  1261. Xint x, y, dir;
  1262. X{
  1263. X    int i;
  1264. X
  1265. X    for (i = 0; i <= 2; i++, y += dir)
  1266. X    XDrawLine(disp, win, gc, x+i, y, x+DIGIT_HWEDGE_WIDTH-(i+1), y);
  1267. X}
  1268. X
  1269. Xvoid
  1270. Xdraw_midwedge(x, y)
  1271. Xint x, y;
  1272. X{
  1273. X
  1274. X    XDrawLine(disp, win, gc, x, y, x+DIGIT_HWEDGE_WIDTH-1, y);
  1275. X    XDrawLine(disp, win, gc, x+1, y+1, x+DIGIT_HWEDGE_WIDTH-2, y+1);
  1276. X    XDrawLine(disp, win, gc, x+1, y-1, x+DIGIT_HWEDGE_WIDTH-2, y-1);
  1277. X}
  1278. X
  1279. Xvoid
  1280. Xdraw_vwedge(x, y, dir)
  1281. Xint x, y, dir;
  1282. X{
  1283. X    int i;
  1284. X
  1285. X    for (i = 0; i <= 2; i++, x += dir)
  1286. X    XDrawLine(disp, win, gc, x, y+i, x, y+DIGIT_VWEDGE_HEIGHT-(i+1));
  1287. X}
  1288. X
  1289. Xvoid
  1290. Xdraw_digit(val, num, which)
  1291. Xint val, num, which;
  1292. X{
  1293. X    int x, y;
  1294. X    static int segs[11] = {
  1295. X    127-2, 32+64, 127-(8+64),
  1296. X    127-(8+16), 8+32+2+64, 127-(32+16),
  1297. X    127-32, 1+32+64, 127,
  1298. X    127-16, 2
  1299. X    };
  1300. X    int seg = segs[val];
  1301. X
  1302. X    x = !which ? DIGIT_X_OFFSET :
  1303. X              TOTAL_WIDTH-(DIGIT_X_OFFSET+DIGIT_COUNT*DIGIT_WIDTH);
  1304. X    x += num*DIGIT_WIDTH+DIGIT_MARGIN;
  1305. X    y = DIGIT_Y_OFFSET+DIGIT_MARGIN+1;
  1306. X    XSetForeground(disp, gc, cols[(seg & 1) ? COL_RED : COL_DARKRED].pixel);
  1307. X    draw_hwedge(x+1, y, 1);
  1308. X    XSetForeground(disp, gc, cols[(seg & 2) ? COL_RED : COL_DARKRED].pixel);
  1309. X    draw_midwedge(x+1, y+1+DIGIT_VWEDGE_HEIGHT);
  1310. X    XSetForeground(disp, gc, cols[(seg & 4) ? COL_RED : COL_DARKRED].pixel);
  1311. X    draw_hwedge(x+1, y+(1+DIGIT_VWEDGE_HEIGHT)*2, -1);
  1312. X    XSetForeground(disp, gc, cols[(seg & 8) ? COL_RED : COL_DARKRED].pixel);
  1313. X    draw_vwedge(x, y+1, 1);
  1314. X    XSetForeground(disp, gc, cols[(seg & 16) ? COL_RED : COL_DARKRED].pixel);
  1315. X    draw_vwedge(x, y+2+DIGIT_VWEDGE_HEIGHT, 1);
  1316. X    XSetForeground(disp, gc, cols[(seg & 32) ? COL_RED : COL_DARKRED].pixel);
  1317. X    draw_vwedge(x+1+DIGIT_HWEDGE_WIDTH, y+1, -1);
  1318. X    XSetForeground(disp, gc, cols[(seg & 64) ? COL_RED : COL_DARKRED].pixel);
  1319. X    draw_vwedge(x+1+DIGIT_HWEDGE_WIDTH, y+2+DIGIT_VWEDGE_HEIGHT, -1);
  1320. X}
  1321. X
  1322. Xvoid
  1323. Xdraw_digits(val, which)
  1324. Xint val, which;
  1325. X{
  1326. X    XSetForeground(disp, gc, cols[COL_BLACK].pixel);
  1327. X    XFillRectangle(disp, win, gc,
  1328. X    !which ? DIGIT_X_OFFSET :
  1329. X               TOTAL_WIDTH-(DIGIT_X_OFFSET+DIGIT_COUNT*DIGIT_WIDTH),
  1330. X    DIGIT_Y_OFFSET,
  1331. X    DIGIT_WIDTH * DIGIT_COUNT, DIGIT_HEIGHT);
  1332. X    XSetForeground(disp, gc, cols[COL_RED].pixel);
  1333. X    if (val < 0) {
  1334. X    draw_digit(10, 0, which);
  1335. X    val = -val;
  1336. X    } else
  1337. X    draw_digit((val/100)%10, 0, which);
  1338. X    draw_digit((val/10)%10, 1, which);
  1339. X    draw_digit(val%10, 2, which);
  1340. X}
  1341. X
  1342. Xvoid
  1343. Xset_level(w, level)
  1344. XWidget w;
  1345. Xint level;
  1346. X{
  1347. X    int i;
  1348. X
  1349. X    if (level == 1) {
  1350. X    mine_count = 10;
  1351. X    gsizex = gsizey = 8;
  1352. X    } else if (level == 2) {
  1353. X    mine_count = 40;
  1354. X    gsizex = gsizey = 16;
  1355. X    } else if (level == 3) {
  1356. X    mine_count = 99;
  1357. X    gsizex = 30;
  1358. X    gsizey = 16;
  1359. X    }
  1360. X    game_level = level-1;
  1361. X    if (!drawarea) return;
  1362. X    for (i = 0; i != XtNumber(level_buttons); i++)
  1363. X    if (i != level-1)
  1364. X        XmToggleButtonSetState(level_buttons[i], False, False);
  1365. X    XtVaSetValues(toplevel, XmNallowShellResize, True, NULL);
  1366. X    XtVaSetValues(drawarea,
  1367. X        XmNwidth,        GSPACEX*gsizex+SIDEMARGIN*2,
  1368. X        XmNheight,       GSPACEY*gsizey+TOPMARGIN+BOTMARGIN,
  1369. X    NULL);
  1370. X    XtVaSetValues(toplevel, XmNallowShellResize, False, NULL);
  1371. X    redraw_entire();
  1372. X    restart();
  1373. X}
  1374. X
  1375. Xvoid
  1376. Xtog_question()
  1377. X{
  1378. X    questions_allowed ^= 1;
  1379. X}
  1380. X
  1381. Xint dialog_up;
  1382. X
  1383. Xvoid
  1384. Xset_custom()
  1385. X{
  1386. X    Widget custom, pane, w, rc, rc2, mine_w, height_w, width_w;
  1387. X    char buf[20];
  1388. X
  1389. X    custom = XtVaCreatePopupShell("Custom",
  1390. X    topLevelShellWidgetClass, toplevel,
  1391. X    XmNdeleteResponse, XmDESTROY,
  1392. X    XmNdialogStyle,    XmDIALOG_FULL_APPLICATION_MODAL,
  1393. X    NULL);
  1394. X    pane = XtVaCreateWidget(NULL, xmPanedWindowWidgetClass, custom,
  1395. X    XmNsashHeight, 1,
  1396. X    XmNsashWidth,  1,
  1397. X    NULL);
  1398. X    rc2 = XtVaCreateManagedWidget(NULL,
  1399. X    xmRowColumnWidgetClass, pane,
  1400. X    NULL);
  1401. X    rc = XtVaCreateManagedWidget(NULL,
  1402. X    xmRowColumnWidgetClass, rc2,
  1403. X    XmNorientation, XmHORIZONTAL,
  1404. X    NULL);
  1405. X    XtVaCreateManagedWidget("height_label",
  1406. X    xmLabelGadgetClass, rc,
  1407. X    NULL);
  1408. X    sprintf(buf, "%d", gsizey);
  1409. X    height_w = XtVaCreateManagedWidget("height_text",
  1410. X    xmTextFieldWidgetClass, rc,
  1411. X    XmNvalue,        buf,
  1412. X    NULL);
  1413. X    rc = XtVaCreateManagedWidget(NULL,
  1414. X    xmRowColumnWidgetClass, rc2,
  1415. X    XmNorientation, XmHORIZONTAL,
  1416. X    NULL);
  1417. X    XtVaCreateManagedWidget("width_label",
  1418. X    xmLabelGadgetClass, rc,
  1419. X    NULL);
  1420. X    sprintf(buf, "%d", gsizex);
  1421. X    width_w = XtVaCreateManagedWidget("width_text",
  1422. X    xmTextFieldWidgetClass, rc,
  1423. X    XmNvalue,        buf,
  1424. X    NULL);
  1425. X    rc = XtVaCreateManagedWidget(NULL,
  1426. X    xmRowColumnWidgetClass, rc2,
  1427. X    XmNorientation, XmHORIZONTAL,
  1428. X    NULL);
  1429. X    XtVaCreateManagedWidget("mines_label",
  1430. X    xmLabelGadgetClass, rc,
  1431. X    NULL);
  1432. X    sprintf(buf, "%d", mine_count);
  1433. X    mine_w = XtVaCreateManagedWidget("mines_text",
  1434. X    xmTextFieldWidgetClass, rc,
  1435. X    XmNvalue,        buf,
  1436. X    NULL);
  1437. X    rc2 = XtVaCreateManagedWidget(NULL,
  1438. X    xmFormWidgetClass, pane,
  1439. X    NULL);
  1440. X    w = XtVaCreateManagedWidget("ok",
  1441. X    xmPushButtonWidgetClass, rc2,
  1442. X    XmNleftAttachment, XmATTACH_POSITION,
  1443. X    XmNrightAttachment,XmATTACH_POSITION,
  1444. X    XmNleftPosition,   30,
  1445. X    XmNrightPosition,  70,
  1446. X    NULL);
  1447. X    XtAddCallback(w, XmNactivateCallback, (void_proc) dialog_ok, NULL);
  1448. X    XtManageChild(pane);
  1449. X    XtPopup(custom, XtGrabExclusive);
  1450. X    dialog_up = True;
  1451. X    while (dialog_up) {
  1452. X    XtAppProcessEvent(app, XtIMAll);
  1453. X    XSync(disp, 0);
  1454. X    }
  1455. X    XtPopdown(custom);
  1456. X    get_text_int(width_w, &gsizex);
  1457. X    if (gsizex > 100) gsizex = 100;
  1458. X    if (gsizex < 8) gsizex = 8;
  1459. X    get_text_int(height_w, &gsizey);
  1460. X    if (gsizey > 100) gsizey = 100;
  1461. X    if (gsizey < 8) gsizey = 8;
  1462. X    get_text_int(mine_w, &mine_count);
  1463. X    if (mine_count < 1) mine_count = 1;
  1464. X    set_level((Widget) 0, 4);
  1465. X}
  1466. X
  1467. Xvoid
  1468. Xdialog_ok()
  1469. X{
  1470. X    dialog_up = False;
  1471. X}
  1472. X
  1473. Xvoid
  1474. Xget_text_int(w, val)
  1475. XWidget w;
  1476. Xint *val;
  1477. X{
  1478. X    char *str;
  1479. X
  1480. X    str = XmTextFieldGetString(w);
  1481. X    if (!str) return;
  1482. X    if (atoi(str)) *val = atoi(str);
  1483. X    XtFree(str);
  1484. X}
  1485. X
  1486. Xvoid
  1487. Xbest_times()
  1488. X{
  1489. X    Widget custom, pane, w, rc2, ok_w;
  1490. X    Widget matrix[9];
  1491. X    char buf[20];
  1492. X    struct scores *sc;
  1493. X
  1494. X    sc = get_scores();
  1495. X    custom = XtVaCreatePopupShell("Best",
  1496. X    topLevelShellWidgetClass, toplevel,
  1497. X    XmNdeleteResponse, XmDESTROY,
  1498. X    XmNdialogStyle,    XmDIALOG_FULL_APPLICATION_MODAL,
  1499. X    NULL);
  1500. X    pane = XtVaCreateWidget(NULL, xmPanedWindowWidgetClass, custom,
  1501. X    XmNsashHeight, 1,
  1502. X    XmNsashWidth,  1,
  1503. X    NULL);
  1504. X    XtVaCreateManagedWidget("label",
  1505. X    xmLabelGadgetClass, pane,
  1506. X    NULL);
  1507. X    rc2 = XtVaCreateManagedWidget(NULL,
  1508. X    xmFormWidgetClass, pane,
  1509. X    NULL);
  1510. X    matrix[0] = XtVaCreateManagedWidget("begin_label",
  1511. X    xmLabelGadgetClass, rc2,
  1512. X    XmNtopAttachment, XmATTACH_FORM,
  1513. X    XmNleftAttachment, XmATTACH_FORM,
  1514. X    NULL);
  1515. X    sprintf(buf, "%d", sc->times[0]);
  1516. X    matrix[1] = XtVaCreateManagedWidget("begin_time",
  1517. X    xmLabelGadgetClass, rc2,
  1518. X    XmNtopAttachment,   XmATTACH_FORM,
  1519. X    XmNleftAttachment,  XmATTACH_OPPOSITE_WIDGET,
  1520. X    XmNlabelString,        genxmstr(buf),
  1521. X    XmNalignment,       XmALIGNMENT_BEGINNING,
  1522. X    NULL);
  1523. X    matrix[2] = XtVaCreateManagedWidget("begin_name",
  1524. X    xmLabelGadgetClass, rc2,
  1525. X    XmNtopAttachment,   XmATTACH_FORM,
  1526. X    XmNleftAttachment,  XmATTACH_WIDGET,
  1527. X    XmNleftWidget,        matrix[1],
  1528. X    XmNrightAttachment, XmATTACH_FORM,
  1529. X    XmNlabelString,        genxmstr(sc->names[0]),
  1530. X    XmNleftOffset,        20,
  1531. X    XmNalignment,       XmALIGNMENT_BEGINNING,
  1532. X    NULL);
  1533. X    matrix[3] = XtVaCreateManagedWidget("inter_label",
  1534. X    xmLabelGadgetClass, rc2,
  1535. X    XmNtopAttachment,   XmATTACH_WIDGET,
  1536. X    XmNtopWidget,        matrix[0],
  1537. X    XmNleftAttachment,  XmATTACH_FORM,
  1538. X    NULL);
  1539. X    sprintf(buf, "%d", sc->times[1]);
  1540. X    matrix[4] = XtVaCreateManagedWidget("inter_time",
  1541. X    xmLabelGadgetClass, rc2,
  1542. X    XmNtopAttachment,   XmATTACH_WIDGET,
  1543. X    XmNtopWidget,        matrix[0],
  1544. X    XmNleftAttachment,  XmATTACH_WIDGET,
  1545. X    XmNleftWidget,        matrix[3],
  1546. X    XmNleftOffset,        20,
  1547. X    XmNlabelString,        genxmstr(buf),
  1548. X    XmNalignment,       XmALIGNMENT_BEGINNING,
  1549. X    NULL);
  1550. X    XtVaSetValues(matrix[1], XmNleftWidget, matrix[4], NULL);
  1551. X    matrix[5] = XtVaCreateManagedWidget("inter_name",
  1552. X    xmLabelGadgetClass, rc2,
  1553. X    XmNtopAttachment,   XmATTACH_WIDGET,
  1554. X    XmNtopWidget,        matrix[2],
  1555. X    XmNleftAttachment,  XmATTACH_OPPOSITE_WIDGET,
  1556. X    XmNleftWidget,        matrix[2],
  1557. X    XmNrightAttachment, XmATTACH_FORM,
  1558. X    XmNlabelString,        genxmstr(sc->names[1]),
  1559. X    XmNalignment,       XmALIGNMENT_BEGINNING,
  1560. X    NULL);
  1561. X    matrix[6] = XtVaCreateManagedWidget("expert_label",
  1562. X    xmLabelGadgetClass, rc2,
  1563. X    XmNtopAttachment,   XmATTACH_WIDGET,
  1564. X    XmNtopWidget,        matrix[3],
  1565. X    XmNleftAttachment,  XmATTACH_FORM,
  1566. X    XmNbottomAttachment,XmATTACH_FORM,
  1567. X    NULL);
  1568. X    sprintf(buf, "%d", sc->times[2]);
  1569. X    matrix[7] = XtVaCreateManagedWidget("expert_time",
  1570. X    xmLabelGadgetClass, rc2,
  1571. X    XmNtopAttachment,   XmATTACH_WIDGET,
  1572. X    XmNtopWidget,        matrix[4],
  1573. X    XmNleftAttachment,  XmATTACH_OPPOSITE_WIDGET,
  1574. X    XmNleftWidget,        matrix[4],
  1575. X    XmNbottomAttachment,XmATTACH_FORM,
  1576. X    XmNlabelString,        genxmstr(buf),
  1577. X    XmNalignment,       XmALIGNMENT_BEGINNING,
  1578. X    NULL);
  1579. X    matrix[8] = XtVaCreateManagedWidget("expert_name",
  1580. X    xmLabelGadgetClass, rc2,
  1581. X    XmNtopAttachment,   XmATTACH_WIDGET,
  1582. X    XmNtopWidget,        matrix[5],
  1583. X    XmNleftAttachment,  XmATTACH_OPPOSITE_WIDGET,
  1584. X    XmNleftWidget,        matrix[5],
  1585. X    XmNrightAttachment, XmATTACH_FORM,
  1586. X    XmNbottomAttachment,XmATTACH_FORM,
  1587. X    XmNlabelString,        genxmstr(sc->names[2]),
  1588. X    XmNalignment,       XmALIGNMENT_BEGINNING,
  1589. X    NULL);
  1590. X    rc2 = XtVaCreateManagedWidget(NULL,
  1591. X    xmFormWidgetClass, pane,
  1592. X    NULL);
  1593. X    ok_w = XtVaCreateManagedWidget("ok",
  1594. X    xmPushButtonWidgetClass, rc2,
  1595. X    XmNleftAttachment, XmATTACH_POSITION,
  1596. X    XmNrightAttachment,XmATTACH_POSITION,
  1597. X    XmNleftPosition,   0,
  1598. X    XmNrightPosition,  50,
  1599. X    NULL);
  1600. X    XtAddCallback(ok_w, XmNactivateCallback, (void_proc) dialog_ok, NULL);
  1601. X    w = XtVaCreateManagedWidget("clear",
  1602. X    xmPushButtonWidgetClass, rc2,
  1603. X    XmNleftAttachment, XmATTACH_POSITION,
  1604. X    XmNrightAttachment,XmATTACH_POSITION,
  1605. X    XmNleftPosition,   50,
  1606. X    XmNrightPosition,  100,
  1607. X    NULL);
  1608. X    XtAddCallback(w, XmNactivateCallback, (void_proc) clear_scores, NULL);
  1609. X    if (cant_write_score_file()) XtSetSensitive(w, False);
  1610. X    XtManageChild(pane);
  1611. X    XtPopup(custom, XtGrabExclusive);
  1612. X    XmProcessTraversal(ok_w, XmTRAVERSE_CURRENT);
  1613. X    dialog_up = True;
  1614. X    while (dialog_up) {
  1615. X    XtAppProcessEvent(app, XtIMAll);
  1616. X    XSync(disp, 0);
  1617. X    }
  1618. X    XtPopdown(custom);
  1619. X
  1620. X}
  1621. X
  1622. Xvoid
  1623. Xabout()
  1624. X{
  1625. X    Widget custom, pane, w, rc2;
  1626. X    char buf[100];
  1627. X
  1628. X    custom = XtVaCreatePopupShell("About",
  1629. X    topLevelShellWidgetClass, toplevel,
  1630. X    XmNdeleteResponse, XmDESTROY,
  1631. X    XmNdialogStyle,    XmDIALOG_FULL_APPLICATION_MODAL,
  1632. X    NULL);
  1633. X    pane = XtVaCreateWidget(NULL, xmPanedWindowWidgetClass, custom,
  1634. X    XmNsashHeight, 1,
  1635. X    XmNsashWidth,  1,
  1636. X    NULL);
  1637. X    sprintf(buf, "xmine 1.0.%d by Paul Falstad", PATCHLEVEL);
  1638. X    XtVaCreateManagedWidget("label",
  1639. X    xmLabelGadgetClass, pane,
  1640. X    XmNlabelString,     genxmstr(buf),
  1641. X    NULL);
  1642. X    rc2 = XtVaCreateManagedWidget(NULL,
  1643. X    xmFormWidgetClass, pane,
  1644. X    NULL);
  1645. X    w = XtVaCreateManagedWidget("ok",
  1646. X    xmPushButtonWidgetClass, rc2,
  1647. X    XmNleftAttachment, XmATTACH_POSITION,
  1648. X    XmNrightAttachment,XmATTACH_POSITION,
  1649. X    XmNleftPosition,   30,
  1650. X    XmNrightPosition,  70,
  1651. X    NULL);
  1652. X    XtAddCallback(w, XmNactivateCallback, (void_proc) dialog_ok, NULL);
  1653. X    XtManageChild(pane);
  1654. X    XtPopup(custom, XtGrabExclusive);
  1655. X    XmProcessTraversal(w, XmTRAVERSE_CURRENT);
  1656. X    dialog_up = True;
  1657. X    while (dialog_up) {
  1658. X    XtAppProcessEvent(app, XtIMAll);
  1659. X    XSync(disp, 0);
  1660. X    }
  1661. X    XtPopdown(custom);
  1662. X}
  1663. X
  1664. Xvoid
  1665. Xget_score_file_name(buf)
  1666. Xchar *buf;
  1667. X{
  1668. X    if (*SCORE_FILE == '~' && getenv("HOME"))
  1669. X    sprintf(buf, "%s%s", getenv("HOME"), SCORE_FILE+1);
  1670. X    else
  1671. X    strcpy(buf, SCORE_FILE);
  1672. X}
  1673. X
  1674. Xstruct scores *
  1675. Xget_scores()
  1676. X{
  1677. X    static struct scores sc;
  1678. X    char buf[1000];
  1679. X    int i, score;
  1680. X    FILE *in;
  1681. X
  1682. X    for (i = 0; i != 3; i++) {
  1683. X    strcpy(sc.names[i], "Anonymous");
  1684. X    sc.times[i] = 999;
  1685. X    }
  1686. X    get_score_file_name(buf);
  1687. X    if (in = fopen(buf, "r")) {
  1688. X    while (fscanf(in, "%d %d \"%[^\"]\"", &i, &score, buf) == 3) {
  1689. X        if (i < 0 || i > 2) break;
  1690. X        strcpy(sc.names[i], buf);
  1691. X        sc.times[i] = score;
  1692. X    }
  1693. X    fclose(in);
  1694. X    }
  1695. X    return ≻
  1696. X}
  1697. X
  1698. Xvoid
  1699. Xwrite_scores(sc)
  1700. Xstruct scores *sc;
  1701. X{
  1702. X    int i;
  1703. X    char buf[1000];
  1704. X    FILE *out;
  1705. X
  1706. X    get_score_file_name(buf);
  1707. X    if (!(out = fopen(buf, "w")))
  1708. X    return;
  1709. X    for (i = 0; i != 3; i++)
  1710. X    if (sc->times[i] != 999)
  1711. X        fprintf(out, "%d %d \"%s\"\n", i, sc->times[i], sc->names[i]);
  1712. X    fclose(out);
  1713. X}
  1714. X
  1715. Xvoid
  1716. Xnew_best(level)
  1717. Xint level;
  1718. X{
  1719. X    Widget custom, pane, rc2, name_w, w;
  1720. X    char *str;
  1721. X    struct scores *sc;
  1722. X
  1723. X    if (level < 0 || level >= 3) return;
  1724. X    sc = get_scores();
  1725. X    if (timer >= sc->times[level]) return;
  1726. X    custom = XtVaCreatePopupShell("HighScorer",
  1727. X    topLevelShellWidgetClass, toplevel,
  1728. X    XmNdeleteResponse, XmDESTROY,
  1729. X    XmNdialogStyle,    XmDIALOG_FULL_APPLICATION_MODAL,
  1730. X    NULL);
  1731. X    pane = XtVaCreateWidget(NULL, xmPanedWindowWidgetClass, custom,
  1732. X    XmNsashHeight, 1,
  1733. X    XmNsashWidth,  1,
  1734. X    NULL);
  1735. X    XtVaCreateManagedWidget("label",
  1736. X    xmLabelGadgetClass, pane,
  1737. X    NULL);
  1738. X    name_w = XtVaCreateManagedWidget("name",
  1739. X    xmTextFieldWidgetClass, pane, NULL);
  1740. X    XtAddCallback(name_w, XmNactivateCallback, (void_proc) dialog_ok, NULL);
  1741. X    rc2 = XtVaCreateManagedWidget(NULL,
  1742. X    xmFormWidgetClass, pane,
  1743. X    NULL);
  1744. X    w = XtVaCreateManagedWidget("ok",
  1745. X    xmPushButtonWidgetClass, rc2,
  1746. X    XmNleftAttachment, XmATTACH_POSITION,
  1747. X    XmNrightAttachment,XmATTACH_POSITION,
  1748. X    XmNleftPosition,   30,
  1749. X    XmNrightPosition,  70,
  1750. X    NULL);
  1751. X    XtAddCallback(w, XmNactivateCallback, (void_proc) dialog_ok, NULL);
  1752. X    XtManageChild(pane);
  1753. X    XtPopup(custom, XtGrabExclusive);
  1754. X    XmTextFieldSetSelection(name_w, 0, XmTextFieldGetLastPosition(name_w),
  1755. XCurrentTime);
  1756. X    XmProcessTraversal(name_w, XmTRAVERSE_CURRENT);
  1757. X    dialog_up = True;
  1758. X    while (dialog_up) {
  1759. X    XtAppProcessEvent(app, XtIMAll);
  1760. X    XSync(disp, 0);
  1761. X    }
  1762. X    XtPopdown(custom);
  1763. X    str = XmTextFieldGetString(name_w);
  1764. X    if (str && *str) {
  1765. X    strcpy(sc->names[level], str);
  1766. X    sc->times[level] = timer;
  1767. X    write_scores(sc);
  1768. X    }
  1769. X    if (str) XtFree(str);
  1770. X    best_times();
  1771. X}
  1772. X
  1773. Xvoid
  1774. Xclear_scores()
  1775. X{
  1776. X    char buf[1000];
  1777. X    FILE *out;
  1778. X
  1779. X    dialog_up = False;
  1780. X    get_score_file_name(buf);
  1781. X    if (out = fopen(buf, "w")) fclose(out);
  1782. X}
  1783. X
  1784. Xint
  1785. Xcant_write_score_file()
  1786. X{
  1787. X    return geteuid() != getuid();
  1788. X}
  1789. X
  1790. Xvoid
  1791. Xfix_size()
  1792. X{
  1793. X    XSizeHints hints;
  1794. X    Dimension wid, hgt;
  1795. X
  1796. X    XtVaGetValues(toplevel,
  1797. X    XmNwidth, &wid,
  1798. X    XmNheight, &hgt,
  1799. X    NULL);
  1800. X    hints.flags = PMaxSize|PMinSize;
  1801. X    hints.max_width = hints.min_width = wid;
  1802. X    hints.max_height = hints.min_height = hgt;
  1803. X    XSetWMNormalHints(disp, XtWindow(toplevel), &hints);
  1804. X}
  1805. X
  1806. Xvoid
  1807. Xrelax_size()
  1808. X{
  1809. X    XSizeHints hints;
  1810. X    Dimension wid, hgt, menu_hgt;
  1811. X
  1812. X    XtVaGetValues(toplevel,
  1813. X    XmNwidth, &wid,
  1814. X    XmNheight, &hgt,
  1815. X    NULL);
  1816. X    hints.flags = PMaxSize|PMinSize|PResizeInc;
  1817. X    XtVaGetValues(menubar,
  1818. X    XmNheight, &menu_hgt,
  1819. X    NULL);
  1820. X    hints.min_width = SIDEMARGIN*2+GSPACEX*INITIAL_SIZE_X;
  1821. X    hints.min_height = TOPMARGIN+BOTMARGIN+menu_hgt+GSPACEY*INITIAL_SIZE_Y;
  1822. X    hints.max_width = hints.max_height = 10000;
  1823. X    hints.width_inc = GSPACEX;
  1824. X    hints.height_inc = GSPACEY;
  1825. X    XSetWMNormalHints(disp, XtWindow(toplevel), &hints);
  1826. X}
  1827. X
  1828. Xvoid
  1829. Xresize_handler(w, data, event, contflag)
  1830. XWidget w;
  1831. XXtPointer data;
  1832. XXEvent *event;
  1833. XBoolean *contflag;
  1834. X{
  1835. X    int new_gsizex, new_gsizey;
  1836. X    static int started = 0;
  1837. X    Dimension menu_hgt;
  1838. X
  1839. X    if (!started) {
  1840. X    relax_size();
  1841. X    started = 1;
  1842. X    }
  1843. X    if (event->type != ConfigureNotify) return;
  1844. X    if (layed_out && game_on) return;
  1845. X    XtVaGetValues(menubar,
  1846. X    XmNheight, &menu_hgt,
  1847. X    NULL);
  1848. X    new_gsizex = (event->xconfigure.width-SIDEMARGIN*2)/GSPACEX;
  1849. X    new_gsizey = (event->xconfigure.height-
  1850. X              (menu_hgt+TOPMARGIN+BOTMARGIN))/GSPACEY;
  1851. X    if (new_gsizex > MAX_GSIZEX)
  1852. X    new_gsizex = MAX_GSIZEX;
  1853. X    if (new_gsizey > MAX_GSIZEY)
  1854. X    new_gsizey = MAX_GSIZEY;
  1855. X    if (new_gsizex != gsizex || new_gsizey != gsizey) {
  1856. X    gsizex = new_gsizex;
  1857. X    gsizey = new_gsizey;
  1858. X    set_level(w, 4);
  1859. X    }
  1860. X}
  1861. END_OF_FILE
  1862.   if test 37268 -ne `wc -c <'xmine.c'`; then
  1863.     echo shar: \"'xmine.c'\" unpacked with wrong size!
  1864.   fi
  1865.   # end of 'xmine.c'
  1866. fi
  1867. echo shar: End of archive 1 \(of 1\).
  1868. cp /dev/null ark1isdone
  1869. MISSING=""
  1870. for I in 1 ; do
  1871.     if test ! -f ark${I}isdone ; then
  1872.     MISSING="${MISSING} ${I}"
  1873.     fi
  1874. done
  1875. if test "${MISSING}" = "" ; then
  1876.     echo You have the archive.
  1877.     rm -f ark[1-9]isdone
  1878. else
  1879.     echo You still must unpack the following archives:
  1880.     echo "        " ${MISSING}
  1881. fi
  1882. exit 0
  1883. exit 0 # Just in case...
  1884. -- 
  1885.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1886. \X/  Amiga: The only way to fly!  |    sources-x@sterling.com
  1887.        "It's intuitively obvious to the most casual observer..."
  1888.  GCS d++(--) -p+ c++ !l u++ e+ m+(-) s++/++ n h--- f+ g+++ w+ t++ r+ y+
  1889.