6
#include <X11/Xmu/Editres.h>
10
XtAppContext app_context;
15
Dimension max_win_wid;
16
Dimension max_win_hei;
20
static XtWorkProcId workproc_id = 0;
21
static XtIntervalId timeout_id = 0;
22
static int icon_state;
23
static struct timeval idletime;
25
static XtActionsRec actions[] = {
27
{ "PickupPiece", PickupPieceAC },
28
{ "CancelPiece", CancelPieceAC }
30
static XrmOptionDescRec options[] = {
31
{ "-fn", "*fontList", XrmoptionSepArg, NULL },
32
{ "-score", "*scoreOnly", XrmoptionNoArg, (XPointer)"True" },
33
{ "-ctime", "*connectLineTime", XrmoptionSepArg, NULL },
34
{ "-cwidth", "*connectLineWidth", XrmoptionSepArg, NULL },
35
{ "-demo", "*autoDemo", XrmoptionNoArg, (XPointer)"True" },
36
{ "-mag", "*magnifyFactor", XrmoptionSepArg, NULL },
37
{ "-regular","*gameSize", XrmoptionNoArg, (XPointer)"0" },
38
{ "-large", "*gameSize", XrmoptionNoArg, (XPointer)"1" },
39
{ "-huge", "*gameSize", XrmoptionNoArg, (XPointer)"2" },
40
{ "-trial", "*trialMode", XrmoptionNoArg, (XPointer)"True" },
41
{ "-gravity","*gravityMode", XrmoptionNoArg, (XPointer)"True" },
42
{ "-KCONV", "*kanjiConvert", XrmoptionNoArg, (XPointer)"True" }
45
static XtResource gres[] = {
46
{ "aboutString", "AboutString", XtRString, sizeof (char *),
47
0, XtRString, (XtPointer)"XShisen " XSHISEN_VERSION " by Masaoki Kobayashi" },
48
{ "tedumari", "Tedumari", XtRString, sizeof (char *),
49
offsetof(GlobRes, tedumari), XtRString, (XtPointer)"You can get no more pieces." },
50
{ "width", "Width", XtRInt, sizeof (int),
51
offsetof(GlobRes, Width), XtRString, (XtPointer)"640" },
52
{ "height", "Height", XtRInt, sizeof (int),
53
offsetof(GlobRes, Height), XtRString, (XtPointer)"400" },
54
{ "timeFormat", "TimeFormat", XtRString, sizeof (char *),
55
offsetof(GlobRes, timeFormat), XtRString, (XtPointer)"Your time is %2.2d:%2.2d." },
56
{ "displayFormat1", "DisplayFormat1", XtRString, sizeof (char *),
57
offsetof(GlobRes, displayFormat1), XtRString, (XtPointer)"Rest: " },
58
{ "displayFormat2", "DisplayFormat2", XtRString, sizeof (char *),
59
offsetof(GlobRes, displayFormat2), XtRString, (XtPointer)"Time: " },
60
{ "scoreFile", "ScoreFile", XtRString, sizeof (char *),
61
offsetof(GlobRes, scoreFile), XtRString, (XtPointer)"%s/xshisen.scores" },
62
{ "personalScore", "PersonalScore", XtRString, sizeof (char *),
63
offsetof(GlobRes, personalScoreFile), XtRString, (XtPointer)".xshisen.scores" },
64
{ "scoreOnly", "ScoreOnly", XtRBoolean, sizeof (Boolean),
65
offsetof(GlobRes, scoreOnly), XtRString, (XtPointer)"False" },
66
{ "connectLineColor", "ConnectLineColor", XtRPixel, sizeof (Pixel),
67
offsetof(GlobRes, connLineColor), XtRString, (XtPointer)"blue" },
68
{ "connectLineTime", "ConnectLineTime", XtRInt, sizeof (int),
69
offsetof(GlobRes, connLineTime), XtRString, (XtPointer)"1000" },
70
{ "connectLineWidth", "ConnectLineWidth", XtRInt, sizeof (int),
71
offsetof(GlobRes, connLineWidth), XtRString, (XtPointer)"6" },
72
{ "autoDemo", "AutoDemo", XtRBoolean, sizeof (Boolean),
73
offsetof(GlobRes, autoDemo), XtRString, (XtPointer)"False" },
74
{ "libraryDirectory", "LibraryDirectory", XtRString, sizeof (char *),
75
offsetof(GlobRes, libDir), XtRString, (XtPointer)LIB_DIR },
76
{ "scoreDirectory", "ScoreDirectory", XtRString, sizeof (char *),
77
offsetof(GlobRes, scoreDir), XtRString, (XtPointer)DAT_DIR },
78
{ "magnifyFactor", "MagnifyFactor", XtRFloat, sizeof (float),
79
offsetof(GlobRes, magFactor), XtRString, (XtPointer)"1.0" },
80
{ "fitPixmap", "FitPixmap", XtRBoolean, sizeof (Boolean),
81
offsetof(GlobRes, fitPixmap), XtRString, (XtPointer)"True" },
82
{ "colorCloseness", "ColorCloseness", XtRInt, sizeof (int),
83
offsetof(GlobRes, colorCloseness), XtRString, (XtPointer)"40000" },
84
{ "gameSize", "GameSize", XtRInt, sizeof (int),
85
offsetof(GlobRes, gameSize), XtRString, (XtPointer)"0" },
86
{ "trialMode", "TrialMode", XtRBoolean, sizeof (Boolean),
87
offsetof(GlobRes, trialMode), XtRString, (XtPointer)"False" },
88
{ "gravityMode", "GravityMode", XtRBoolean, sizeof (Boolean),
89
offsetof(GlobRes, gravityMode), XtRString, (XtPointer)"False" },
90
{ "idleTime", "IdleTime", XtRInt, sizeof (int),
91
offsetof(GlobRes, idleTime), XtRString, (XtPointer)"100000" },
92
{ "kanjiCode", "KanjiCode", XtRString, sizeof (char *),
93
offsetof(GlobRes, kanjiCode), XtRString, (XtPointer)KANJICODE },
94
{ "kanjiConvert", "KanjiConvert", XtRBoolean, sizeof (Boolean),
95
offsetof(GlobRes, kanjiConv), XtRString, (XtPointer)"False" },
96
{ "imageSet", "ImageSet", XtRInt, sizeof (int),
97
offsetof(GlobRes, imageSet), XtRString, (XtPointer)"1" }
107
gettimeofday(&tv, &tz);
115
This line will cause error because all the random number
116
generating functions are not available!
121
refreshtimer(XtPointer p)
125
tm->DisplayTimer(bd->GetRest());
127
tm->DisplayCurrentTime();
129
// This is a way not to consume too much CPU time
130
// just for such a silly game...
132
usleep(idletime.tv_usec);
134
select(0, NULL, NULL, NULL, &idletime);
144
changeiconwindow(void)
147
fprintf(stderr, "Change icon window!\n");
149
XSetWindowBackgroundPixmap(XtDisplay(toplevel), iconW, (Pixmap)Mp[rand()%36]);
150
XClearArea(XtDisplay(toplevel), iconW, 0, 0, 0, 0, False);
151
timeout_id = XtAppAddTimeOut(app_context, 5000,
152
(XtTimerCallbackProc)changeiconwindow, NULL);
162
black = XBlackPixelOfScreen(XtScreen(toplevel));
163
iconW = XCreateSimpleWindow(XtDisplay(toplevel),
164
XRootWindowOfScreen(XtScreen(toplevel)),
165
0, 0, w, h, 1, black, black);
166
XtVaSetValues(toplevel,
167
XtNbackground, black,
168
XtNiconWindow, iconW,
178
if ((lib_directory = getenv("XSHISENLIB")) == NULL)
179
lib_directory = globRes.libDir;
180
sprintf(subDir, "s%d", globRes.imageSet);
181
InitGlobalMahjong(toplevel, lib_directory, subDir);
185
statewatcher(Widget w, caddr_t unused, XEvent *event)
187
if (event->type == MapNotify) {
190
fprintf(stderr, "Deiconified.\n");
192
workproc_id = XtAppAddWorkProc(app_context, (XtWorkProc)refreshtimer, NULL);
195
XtRemoveTimeOut(timeout_id);
197
else if (event->type == UnmapNotify) {
200
fprintf(stderr, "Iconified.\n");
208
kanjiconvert(const char *operation)
210
char buffer[100], *p;
211
char *(*codeconv)(const char*);
213
strcpy(buffer, operation);
214
if (strchr(buffer, '-') == NULL) {
215
strcat(buffer, "-" KANJICODE);
217
if (strncasecmp(buffer, "jis-euc", 7) == 0)
218
codeconv = jis_to_euc;
219
else if (strncasecmp(buffer, "jis-sjis", 8) == 0)
220
codeconv = jis_to_sjis;
221
else if (strncasecmp(buffer, "euc-jis", 7) == 0)
222
codeconv = euc_to_jis;
223
else if (strncasecmp(buffer, "euc-sjis", 8) == 0)
224
codeconv = euc_to_sjis;
225
else if (strncasecmp(buffer, "sjis-jis", 8) == 0)
226
codeconv = sjis_to_jis;
227
else if (strncasecmp(buffer, "sjis-euc", 8) == 0)
228
codeconv = sjis_to_euc;
230
// fprintf(stderr, "Don't know kanji conversion \"%s\"\n", buffer);
234
while(fgets(buffer, 100, stdin) != NULL) {
235
// If the string "XSHISEN_VERSION" is found, it should be replaced
236
// with the XSHISEN_VERSION value.
237
if ((p = strstr(buffer, "XSHISEN_VERSION")) != NULL) {
238
int len1 = strlen(XSHISEN_VERSION);
239
char *p2 = p + strlen("XSHISEN_VERSION");
240
strncpy(p, XSHISEN_VERSION, len1);
242
memmove(p, p2, 100 - (p2 - buffer));
244
if (codeconv == NULL) {
245
fputs(buffer, stdout);
247
fputs(codeconv(buffer), stdout);
253
usage(const char *myname)
255
printf("%s " XSHISEN_VERSION " by Masaoki Kobayashi\n\n", CLASS_NAME);
256
printf("Usage: %s [options]\n", myname);
257
printf(" -fn font Sets fonts for menubar and time counter.\n");
258
printf(" -score Popup high-score dialog and exit.\n");
259
printf(" -ctime N Set the time that connection line remains (msec).\n");
260
printf(" -cwidth N Set the connection line width (pixel).\n");
261
printf(" -demo Auto demo mode for understanding rules.\n");
262
printf(" -mag F Magnify window F times from original.\n");
263
printf(" -regular Play regular game (default).\n");
264
printf(" -large Play 2x game.\n");
265
printf(" -huge Play 4x game.\n");
266
printf(" -trial Play as \"Click Trial\".\n");
267
printf(" -gravity Play with gravity.\n");
268
printf("\nAll other regular toolkit options are accepted.\n");
273
main(int argc, char **argv)
279
int initial_game_state;
280
int num_piece_x, num_piece_y;
281
Widget topform, base;
282
XrmDatabase rdb1, rdb2;
284
setlocale(LC_ALL, "");
285
XtSetLanguageProc(NULL, NULL, NULL);
288
toplevel = XtVaAppInitialize(&app_context, CLASS_NAME,
289
options, XtNumber(options),
292
XtNminWidth, MIN_WIN_WID,
293
XtNminHeight, MIN_WIN_HEI,
294
XtNallowShellResize, True,
296
disp = XtDisplay(toplevel);
298
// Override resources with $HOME/.xshisenrc file which is
299
// created by Body::WriteRcFile()
300
rdb1 = XrmGetDatabase(disp);
301
home = getenv("HOME");
302
rcfile = new char [strlen(home) + 12];
303
sprintf(rcfile, "%s/.xshisenrc", home);
304
rdb2 = XrmGetFileDatabase(rcfile);
305
XrmMergeDatabases(rdb2, &rdb1);
306
XrmSetDatabase(disp, rdb1);
307
XtVaGetApplicationResources(toplevel, (XtPointer)&globRes,
308
gres, XtNumber(gres), NULL);
310
if (globRes.kanjiConv) {
311
kanjiconvert(argv[1]);
317
XtAddEventHandler(toplevel, StructureNotifyMask, False,
318
(XtEventHandler)statewatcher,
321
XtAddEventHandler(toplevel, (EventMask)0, True,
322
(XtEventHandler)_XEditResCheckMessages,
325
XtAppAddActions(app_context, actions, XtNumber(actions));
327
globRes.Width = (int)(globRes.Width * globRes.magFactor);
328
globRes.Height = (int)(globRes.Height * globRes.magFactor);
330
initial_game_state = globRes.gameSize;
331
if (globRes.trialMode)
332
initial_game_state += NUM_GAME;
333
else if (globRes.gravityMode)
334
initial_game_state += 2*NUM_GAME;
336
idletime.tv_usec = globRes.idleTime;
337
max_win_wid = DisplayWidth (disp, XDefaultScreen(disp));
338
max_win_hei = DisplayHeight(disp, XDefaultScreen(disp));
339
XtVaSetValues(toplevel,
340
XtNmaxWidth, max_win_wid,
341
XtNmaxHeight, max_win_hei,
344
if ((dat_directory = getenv("XSHISENDAT")) == NULL)
345
dat_directory = globRes.scoreDir;
347
sc = new Score(toplevel);
348
scorefile = new char[strlen(dat_directory)+strlen(globRes.scoreFile)+1];
349
sprintf(scorefile, globRes.scoreFile, dat_directory);
350
sc->SetScoreFile(scorefile, globRes.kanjiCode, globRes.personalScoreFile);
353
if (globRes.scoreOnly) {
354
sc->DisplayScore(initial_game_state);
356
XtAddCallback(*sc, XmNokCallback, (XtCallbackProc)ExitCB, NULL);
358
XtAddCallback(XtNameToWidget(*sc, "*ok_button"),
359
XtNcallback, (XtCallbackProc)ExitCB, NULL);
363
GetGameSize(initial_game_state, num_piece_x, num_piece_y);
365
topform = XtVaCreateManagedWidget("form", xmFormWidgetClass, toplevel,
367
mb = new MenuBar(topform, initial_game_state % NUM_GAME,
368
initial_game_state / NUM_GAME, globRes.imageSet - 1);
371
topform = XtVaCreateManagedWidget("form", formWidgetClass, toplevel,
372
XtNdefaultDistance, 0,
374
mb = new MenuBar(topform, initial_game_state % NUM_GAME,
375
initial_game_state / NUM_GAME, globRes.imageSet - 1);
376
base = XtVaCreateManagedWidget("sform", formWidgetClass, topform,
377
XtNfromVert, (Widget)*mb,
378
XtNleft, XawChainLeft,
379
XtNright, XawChainRight,
381
XtNbottom, XawChainBottom,
384
XtNdefaultDistance, 0,
387
tm = new TimerW(base, *mb,
388
globRes.displayFormat1, "000",
389
globRes.displayFormat2, "00:00:00");
390
bd = new Body(initial_game_state, num_piece_x, num_piece_y, base, *tm);
391
workproc_id = XtAppAddWorkProc(app_context, (XtWorkProc)refreshtimer, NULL);
392
XtRealizeWidget(toplevel);
393
// InitGlobalMahjong must be called after realized because it
394
// requires the real Window.
398
GetBoardSizeFromGameSize(num_piece_x, num_piece_y,
399
globRes.Width, globRes.Height);
400
bd->SetGeometry(globRes.Width, globRes.Height);
404
XtAppMainLoop(app_context);