]> git.draconx.ca Git - rrace.git/commitdiff
Initial commit
authorNick Bowler <nbowler@draconx.ca>
Thu, 3 Mar 2022 04:37:18 +0000 (23:37 -0500)
committerNick Bowler <nbowler@draconx.ca>
Thu, 3 Mar 2022 04:39:12 +0000 (23:39 -0500)
12 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
common [new submodule]
configure.ac [new file with mode: 0644]
m4/.gitignore [new file with mode: 0644]
src/.gitignore [new file with mode: 0644]
src/motif.c [new file with mode: 0644]
src/motif.h [new file with mode: 0644]
src/motif_ui.c [new file with mode: 0644]
src/motifgui.dat [new file with mode: 0644]
src/options.opt [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..fa34998
--- /dev/null
@@ -0,0 +1,18 @@
+*.a
+*.o
+.deps
+.dirstamp
+/Makefile
+/Makefile.in
+/aclocal.m4
+/autom4te.cache
+/compile
+/config.*
+/configure
+/depcomp
+/install-sh
+/libtool
+/ltmain.sh
+/missing
+/rrace-motif
+/stamp-h1
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..a0019b3
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "common"]
+       path = common
+       url = https://git.draconx.ca/dxcommon.git
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..96e7340
--- /dev/null
@@ -0,0 +1,51 @@
+# Copyright © 2022 Nick Bowler
+#
+# License WTFPL2: Do What The Fuck You Want To Public License, version 2.
+# This is free software: you are free to do what the fuck you want to.
+# There is NO WARRANTY, to the extent permitted by law.
+
+ACLOCAL_AMFLAGS = -I m4 -I common/m4
+
+EXTRA_DIST =
+EXTRA_LIBRARIES =
+MAINTAINERCLEANFILES =
+DISTCLEANFILES =
+CLEANFILES = $(EXTRA_LIBRARIES)
+
+AM_CPPFLAGS = -I$(DX_BASEDIR)/src
+AM_CFLAGS = $(MOTIF_CFLAGS)
+
+bin_PROGRAMS = rrace-motif
+
+rrace_motif_SOURCES = #src/motif.c common/src/help.c
+rrace_motif_LDADD = $(libmotifmain_a_OBJECTS) $(libmotifui_a_OBJECTS) \
+                    $(libglohelp_a_OBJECTS) $(MOTIF_LIBS)
+
+EXTRA_LIBRARIES += libmotifmain.a
+libmotifmain_a_SOURCES = src/motif.c
+$(libmotifmain_a_OBJECTS): src/options.h
+
+EXTRA_LIBRARIES += libmotifui.a
+libmotifui_a_SOURCES = src/motif_ui.c
+$(libmotifui_a_OBJECTS): src/motifgui.h
+
+EXTRA_LIBRARIES += libglohelp.a
+libglohelp_a_SOURCES = common/src/help.c
+libglohelp_a_CFLAGS = -DHELP_GETOPT_LONG_ONLY
+libglohelp_a_SHORTNAME = glo
+
+OPTFILES = src/options.opt
+.opt.h:
+       $(AM_V_GEN) $(AWK) -f $(DX_BASEDIR)/scripts/gen-options.awk $< >$@.tmp
+       $(AM_V_at) mv -f $@.tmp $@
+$(OPTFILES:.opt=.h): $(DX_BASEDIR)/scripts/gen-options.awk
+DISTCLEANFILES += $(OPTFILES:.opt=.h)
+EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-options.awk $(OPTFILES)
+
+GUIFILES = src/motifgui.dat
+.dat.h:
+       $(AM_V_GEN) $(AWK) -f $(DX_BASEDIR)/scripts/gen-tree.awk $< >$@.tmp
+       $(AM_V_at) mv -f $@.tmp $@
+$(GUIFILES:.dat=.h): $(DX_BASEDIR)/scripts/gen-tree.awk
+DISTCLEANFILES += $(GUIFILES:.dat=.h)
+EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-tree.awk $(GUIFILES)
diff --git a/common b/common
new file mode 160000 (submodule)
index 0000000..a7cabb5
--- /dev/null
+++ b/common
@@ -0,0 +1 @@
+Subproject commit a7cabb5d0f067e78afd029d8ec41d14660d8f9e2
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..fb7dd41
--- /dev/null
@@ -0,0 +1,39 @@
+dnl Copyright © 2022 Nick Bowler
+dnl
+dnl License WTFPL2: Do What The Fuck You Want To Public License, version 2.
+dnl This is free software: you are free to do what the fuck you want to.
+dnl There is NO WARRANTY, to the extent permitted by law.
+
+AC_INIT([rrace], [0], [nbowler@draconx.ca])
+AC_CONFIG_HEADERS([config.h])
+
+AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign subdir-objects])
+AM_SILENT_RULES([yes])
+DX_AUTOMAKE_COMPAT
+
+AC_PROG_CC_C99
+LT_INIT
+
+AC_PATH_XTRA
+AS_IF([test x"$no_x" != x"yes"],
+[AC_CACHE_CHECK([for Motif], [dx_cv_have_motif],
+[save_CFLAGS=$CFLAGS save_LIBS=$LIBS
+dx_cv_motif_cflags="$X_CFLAGS"
+dx_cv_motif_libs="$X_LIBS $X_PRE_LIBS -lXm -lXt -lX11 $X_EXTRA_LIBS"
+CFLAGS="$dx_cv_motif_cflags $CFLAGS"
+LIBS="$dx_cv_motif_libs $LIBS"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <Xm/XmAll.h>],
+  [XmCreateMainWindow(0, 0, 0, 0); XtAppSetExitFlag(0)])],
+  [dx_cv_have_motif=yes], [dx_cv_have_motif=no])
+CFLAGS=$save_CFLAGS LIBS=$save_LIBS])])
+
+AS_IF([test x"$with_x" = x"yes" && test "$dx_cv_have_motif" != x"yes"],
+  [AC_MSG_FAILURE([--with-x requested but Motif was not found])])
+
+AC_SUBST([MOTIF_CFLAGS], [@&t@])
+AC_SUBST([MOTIF_LIBS], [@&t@])
+AS_IF([test x"$dx_cv_have_motif" = x"yes"],
+  [MOTIF_CFLAGS=$dx_cv_motif_cflags MOTIF_LIBS=$dx_cv_motif_libs])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644 (file)
index 0000000..94e6f26
--- /dev/null
@@ -0,0 +1,5 @@
+/libtool.m4
+/ltoptions.m4
+/ltsugar.m4
+/ltversion.m4
+/lt~obsolete.m4
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644 (file)
index 0000000..7537698
--- /dev/null
@@ -0,0 +1,2 @@
+/motifgui.h
+/options.h
diff --git a/src/motif.c b/src/motif.c
new file mode 100644 (file)
index 0000000..cce9f3f
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * X11 GUI for slide puzzle game
+ * Copyright © 2022 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <Xm/XmAll.h>
+
+#include "help.h"
+#include "motif.h"
+#include "options.h"
+
+#define PROGNAME "rrace"
+static const char *progname = PROGNAME;
+static const struct option lopts[] = { LOPTS_INITIALIZER, {0} };
+
+static char * const default_resources[] = {
+       PROGNAME "*game.height: 371", // 365 + 2*shadowThickness
+       PROGNAME "*game.width: 498",
+
+       PROGNAME "*game.XmFrame.shadowThickness: 3",
+       PROGNAME "*game.XmFrame.shadowType: shadow_in",
+       PROGNAME "*goalArea.leftOffset: 1",
+
+       NULL
+};
+
+static void print_version(void)
+{
+       printf("%s %s\n", PROGNAME, PACKAGE_VERSION);
+       printf("Copyright (C) 2022 Nick Bowler\n");
+       puts("License GPLv3+: GNU GPL version 3 or any later version");
+       puts("This is free software: you are free to change and redistribute it.");
+       puts("There is NO WARRANTY, to the extent permitted by law.");
+}
+
+static void print_usage(FILE *f)
+{
+       fprintf(f, "Usage: %s [options]\n", progname);
+       if (f != stdout)
+               fprintf(f, "Try %s --help for more information.\n", progname);
+}
+
+static void print_help(void)
+{
+       const struct option *opt;
+
+       print_usage(stdout);
+
+       putchar('\n');
+       puts("Options:");
+       for (opt = lopts; opt->name; opt++) {
+               struct lopt_help help;
+               int w;
+
+               if (!lopt_get_help(opt, &help))
+                       continue;
+               help_print_option(opt, help.arg, help.desc, 20);
+       }
+       putchar('\n');
+
+       printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+}
+
+static Widget early_setup(XtAppContext *app, int argc, char **argv)
+{
+       Widget shell;
+       int opt;
+
+       /* Check for --help/--version early (before X connection) */
+       opterr = 0;
+       while ((opt = getopt_long_only(argc, argv, "", lopts, NULL)) != -1) {
+               switch (opt) {
+               case LOPT_VERSION:
+                       print_version();
+                       exit(EXIT_SUCCESS);
+               case LOPT_HELP:
+                       print_help();
+                       exit(EXIT_SUCCESS);
+               }
+       }
+
+       shell = XtOpenApplication(app, PROGNAME, NULL, 0,
+                                 &argc, argv, (String *)default_resources,
+                                 sessionShellWidgetClass, NULL, 0);
+
+       opterr = optind = 1;
+       while ((opt = getopt_long_only(argc, argv, "", lopts, NULL)) != -1) {
+               switch (opt) {
+               default:
+                       print_usage(stderr);
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       if (argv[optind]) {
+               fprintf(stderr, "%s: excess command-line arguments.\n",
+                               progname);
+               print_usage(stderr);
+               exit(EXIT_FAILURE);
+       }
+
+       return shell;
+}
+
+static XtAppContext app_initialize(int argc, char **argv)
+{
+       XtAppContext app;
+       Widget shell;
+
+       if (argc > 0)
+               progname = argv[0];
+
+       shell = early_setup(&app, argc, argv);
+       ui_initialize(shell);
+       XtRealizeWidget(shell);
+
+       return app;
+}
+
+int main(int argc, char **argv)
+{
+       XtAppMainLoop(app_initialize(argc, argv));
+       return 0;
+}
diff --git a/src/motif.h b/src/motif.h
new file mode 100644 (file)
index 0000000..f337618
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * X11 GUI for slide puzzle game
+ * Copyright © 2022 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef RRACE_MOTIF_H_
+#define RRACE_MOTIF_H_
+
+#include <X11/Intrinsic.h>
+
+void ui_initialize(Widget shell);
+
+#endif
diff --git a/src/motif_ui.c b/src/motif_ui.c
new file mode 100644 (file)
index 0000000..0708b40
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * X11 GUI for slide puzzle game
+ * Copyright © 2022 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <Xm/XmAll.h>
+
+#include "motif.h"
+#include "motifgui.h"
+
+#define SPLIT_NUMERATOR    75
+#define SPLIT_DENOMINATOR 100
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static void game_configure(Widget w);
+
+static const struct ui_widget {
+       uint_least16_t name;
+       uint_least16_t subtree;
+       WidgetClass *class;
+       void (*configure)(Widget w);
+} mainwin[] = { MAINWIN_INITIALIZER };
+
+static void
+ResizeGameArea(Widget form, XEvent *e, String *args, Cardinal *num_args)
+{
+       Widget game = XtNameToWidget(form, &tree_strtab[gameArea]);
+       Widget goal = XtNameToWidget(form, &tree_strtab[goalArea]);
+       Dimension w, h, gamesz, gameborder, goalsz, goalborder;
+       int x, y, gap;
+
+       XtVaGetValues(form, XmNwidth, &w, XmNheight, &h, (char *)NULL);
+       XtVaGetValues(game, XmNshadowThickness, &gameborder, (char *)NULL);
+       XtVaGetValues(goal, XmNshadowThickness, &goalborder,
+                           XmNleftOffset, &gap,
+                           (char *)NULL);
+
+       gamesz = MIN(h, w * SPLIT_NUMERATOR / SPLIT_DENOMINATOR);
+       gamesz = 5*( (gamesz - 2*gameborder)/5 ) + 2*gameborder;
+
+       goalsz = MIN(gamesz*3/5, w - gamesz - gap);
+       goalsz = 3*( (goalsz - 2*goalborder)/3 ) + 2*goalborder;
+
+       x = (w - gamesz - goalsz - gap) / 2;
+       if (x < 2) x = 0;
+
+       y = (h - gamesz) / 2;
+       if (y < 3) y = 0;
+
+       XtVaSetValues(game, XmNleftOffset, x, XmNtopOffset, y, (char *)NULL);
+       XtVaSetValues(game, XmNwidth, gamesz, XmNheight, gamesz, (char *)NULL);
+       XtVaSetValues(goal, XmNwidth, goalsz, XmNheight, goalsz, (char *)NULL);
+}
+
+static void game_configure(Widget form)
+{
+       Widget gamearea = XtNameToWidget(form, &tree_strtab[gameArea]);
+       Widget goalarea = XtNameToWidget(form, &tree_strtab[goalArea]);
+       XtActionsRec resize_rec;
+
+       assert(gamearea && goalarea);
+       XtVaSetValues(form, XmNfractionBase, SPLIT_DENOMINATOR, (char *)NULL);
+
+       XtVaSetValues(gamearea, //XmNrightAttachment, XmATTACH_POSITION,
+                               //XmNrightPosition, SPLIT_NUMERATOR,
+                               XmNleftAttachment, XmATTACH_FORM,
+                               XmNtopAttachment, XmATTACH_FORM,
+                               (char *)NULL);
+
+       XtVaSetValues(goalarea, XmNleftAttachment, XmATTACH_WIDGET,
+                               XmNleftWidget, gamearea,
+                               XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+                               XmNtopWidget, gamearea,
+                               (char *)NULL);
+
+       resize_rec.string = "ResizeGameArea";
+       resize_rec.proc = ResizeGameArea;
+       XtAppAddActions(XtWidgetToApplicationContext(form), &resize_rec, 1);
+       XtOverrideTranslations(form, XtParseTranslationTable(
+               "<Configure>: ResizeGameArea()\n"
+               "<Map>: ResizeGameArea()\n"
+       ));
+}
+
+static void
+construct_widgets(const struct ui_widget *root, Widget parent, unsigned i)
+{
+       const struct ui_widget *item;
+
+       for (item = &root[i]; item->name; item++) {
+               Widget w;
+
+               w = XtCreateWidget(&tree_strtab[item->name], *item->class,
+                                  parent, NULL, 0);
+               if (item->subtree) {
+                       construct_widgets(root, w, item->subtree);
+               }
+
+               if (item->configure) {
+                       item->configure(w);
+               }
+
+               XtManageChild(w);
+       }
+}
+
+static void game_resize(Widget w, void *data, void *cb_data)
+{
+       Dimension width, height;
+
+       XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, (char *)NULL);
+
+       printf("game %ux%u\n", width, height);
+}
+
+static void goal_resize(Widget w, void *data, void *cb_data)
+{
+       Dimension width, height;
+
+       XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, (char *)NULL);
+
+       printf("goal %ux%u\n", width, height);
+}
+
+void ui_initialize(Widget shell)
+{
+       Widget game, goal;
+
+       construct_widgets(mainwin, shell, 0);
+
+       game = XtNameToWidget(shell, "*gameCanvas");
+       goal = XtNameToWidget(shell, "*goalCanvas");
+
+       XtAddCallback(game, XmNresizeCallback, game_resize, NULL);
+       XtAddCallback(goal, XmNresizeCallback, goal_resize, NULL);
+}
diff --git a/src/motifgui.dat b/src/motifgui.dat
new file mode 100644 (file)
index 0000000..a8d69cb
--- /dev/null
@@ -0,0 +1,7 @@
+MAINWIN
+ main, main_OFFSET, &xmMainWindowWidgetClass
+  game, game_OFFSET, &xmFormWidgetClass, game_configure
+   gameArea, gameArea_OFFSET, &xmFrameWidgetClass
+    gameCanvas, 0, &xmDrawingAreaWidgetClass
+   goalArea, goalArea_OFFSET, &xmFrameWidgetClass
+    goalCanvas, 0, &xmDrawingAreaWidgetClass
diff --git a/src/options.opt b/src/options.opt
new file mode 100644 (file)
index 0000000..9fd8240
--- /dev/null
@@ -0,0 +1,17 @@
+--display=DISPLAY
+X server DISPLAY name to use.
+
+--geometry=[W][xH][+X[+Y]]
+Set initial window size (W by H) and/or position (X, Y).
+
+--title=NAME
+Set window title to NAME.
+
+--xrm=STRING
+Set the X resource described by STRING, overriding defaults.
+
+--version
+Print a version message and then exit.
+
+--help
+Print this message and then exit.