From c62897ca07641522603344920057a6d529932bdd Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Fri, 28 Jun 2024 07:10:21 +0200 Subject: [PATCH 1/1] initial commit --- constant.c | 5 ++ constant.h | 8 ++ debug.c | 5 ++ debug.h | 21 +++++ display.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++++ display.h | 21 +++++ function.c | 176 ++++++++++++++++++++++++++++++++++++ function.h | 36 ++++++++ getcomments.pl | 85 ++++++++++++++++++ makefile | 177 +++++++++++++++++++++++++++++++++++++ solitaire.c | 210 +++++++++++++++++++++++++++++++++++++++++++ type.h | 12 +++ 12 files changed, 992 insertions(+) create mode 100644 constant.c create mode 100644 constant.h create mode 100644 debug.c create mode 100644 debug.h create mode 100644 display.c create mode 100644 display.h create mode 100644 function.c create mode 100644 function.h create mode 100644 getcomments.pl create mode 100644 makefile create mode 100644 solitaire.c create mode 100644 type.h diff --git a/constant.c b/constant.c new file mode 100644 index 0000000..1bfd22b --- /dev/null +++ b/constant.c @@ -0,0 +1,5 @@ +#include "type.h" + +#include "constant.h" + +/* vim: set ts=4 sw=4 et: */ diff --git a/constant.h b/constant.h new file mode 100644 index 0000000..e270e12 --- /dev/null +++ b/constant.h @@ -0,0 +1,8 @@ +#ifndef __CONSTANT_H__ +#define __CONSTANT_H__ + +#include "type.h" + +#endif /* __CONSTANT_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..b9eba44 --- /dev/null +++ b/debug.c @@ -0,0 +1,5 @@ +#include "debug.h" + +int verbose = 0; + +/* vim: set ts=4 sw=4 et: */ diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..32dc0ca --- /dev/null +++ b/debug.h @@ -0,0 +1,21 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +/* constants */ + +#define DEBUG 3 +#define INFO 2 +#define WARNING 1 +#define ERROR 0 + +/* macros */ + +#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0) + +/* gobal variables */ + +extern int verbose; + +#endif /* __DEBUG_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.c b/display.c new file mode 100644 index 0000000..e8601cc --- /dev/null +++ b/display.c @@ -0,0 +1,236 @@ +#include +#include +#include +#include + +#include "debug.h" +#include "function.h" +#include "type.h" + +#include "display.h" + +#define LIBWIDTH 11 + +typedef enum { + white = 1, + red, + green, + blue, + cyan, + magenta, + yellow, + black, + wred, + wgreen, + wblue, + wcyan, + wmagenta, + wyellow, +} color_t; + +void set_color (color_t color) +{ + static int init = 1; + + if (init) { + init_pair (white, COLOR_WHITE, COLOR_BLACK); + init_pair (red, COLOR_BLACK, COLOR_RED); + init_pair (green, COLOR_BLACK, COLOR_GREEN); + init_pair (blue, COLOR_BLACK, COLOR_BLUE); + init_pair (magenta, COLOR_BLACK, COLOR_MAGENTA); + init_pair (yellow, COLOR_BLACK, COLOR_YELLOW); + init_pair (cyan, COLOR_BLACK, COLOR_CYAN); + init_pair (black, COLOR_BLACK, COLOR_WHITE); + init_pair (wred, COLOR_WHITE, COLOR_RED); + init_pair (wgreen, COLOR_WHITE, COLOR_GREEN); + init_pair (wblue, COLOR_WHITE, COLOR_BLUE); + init_pair (wcyan, COLOR_WHITE, COLOR_CYAN); + init_pair (wmagenta, COLOR_WHITE, COLOR_MAGENTA); + init_pair (wyellow, COLOR_WHITE, COLOR_YELLOW); + init = 0; + } + + attrset (COLOR_PAIR(color)); +} + +int _helpwindow (char *msg, int xoffset, int yoffset, int length) +{ + int i = 0; + int j = 0; + while ((msg) && (*msg != '\0')) { + if ((*msg == '\n') || (i == length)) { + i = 0; + j++; + } + if (*msg != '\n') { + mvaddch (yoffset + j, xoffset + i, *msg); + i++; + } + msg++; + } + return j; +} + +void _displaytitle (char *title, int xoffset, int yoffset) +{ + int i; + for (i = 0; title[i] != '\0'; i++) { + mvaddch (yoffset, xoffset + i, title[i]); + mvaddch (yoffset + 1, xoffset + i, ACS_HLINE); + } +} + +void _dobound (int xsize, int ysize, int xoffset, int yoffset) +{ + int i, j; + + for (i = 0; i < xsize; i++) { + mvaddch (yoffset - 1, xoffset + i, ACS_HLINE); + mvaddch (yoffset + ysize, xoffset + i, ACS_HLINE); + } + for (j = 0; j < ysize; j++) { + mvaddch (yoffset + j, xoffset - 1, ACS_VLINE); + mvaddch (yoffset + j, xoffset + xsize, ACS_VLINE); + } + mvaddch (yoffset - 1, xoffset - 1, ACS_ULCORNER); + mvaddch (yoffset + ysize, xoffset - 1, ACS_LLCORNER); + mvaddch (yoffset - 1, xoffset + xsize, ACS_URCORNER); + mvaddch (yoffset + ysize, xoffset + xsize, ACS_LRCORNER); +} + +int helpwindow (char *msg, int xoffset, int yoffset) +{ + _displaytitle ("Help message", xoffset, yoffset); + int length = strmaxlen (msg, '\n'); + int j = 2; + j += _helpwindow (msg, xoffset, yoffset + j, length); + + return j; +} + +void librarywindow (char *msg, int xoffset, int yoffset) +{ + _dobound (LIBWIDTH, 2, xoffset, yoffset); + mvaddstr (yoffset, xoffset + (LIBWIDTH - 7) / 2, "Library"); + set_color (black); + + int i; + for (i = 0; i < LIBWIDTH; i++) { + mvaddch (yoffset + 1, xoffset + i, ' '); + } + + char str[LIBWIDTH + 1] = {0}; + strncpy (str, msg, LIBWIDTH); + mvaddstr (yoffset + 1, xoffset + (LIBWIDTH - (int)strlen (str)) / 2, str); + set_color (white); +} + +void boardwindow (board_t *board, int xoffset, int yoffset, int bound) +{ + int i, j; + + if (bound) { + _dobound (board->xsize, board->ysize, xoffset, yoffset); + } + + for (i = 0; i < board->xsize; i++) { + for (j = 0; j < board->ysize; j++) { + char cell = *getcell (board, i, j); + switch (cell) { + case '1': + set_color (yellow); + break; + case 'N': + set_color (green); + break; + case 'O': + set_color (red); + break; + case 'X': + set_color (black); + break; + case ' ': + set_color (white); + break; + default: + VERBOSE (WARNING, printf ("unknown code '%c'\n", cell)); + } + mvaddch (yoffset + j, xoffset + i, ' '); + set_color (white); + } + } +} + +char *savewindow (int length, int xoffset, int yoffset) +{ + char *name = (char *) calloc (1, length + 1); + CHECKALLOC (name); + memset (name, ' ', length); + + set_color (black); + _dobound (length, 1, xoffset, yoffset); + set_color (white); + + int i = 0, j; + int stop = 0; + while (!stop) { + for (j = 0; j < length; j++) { + set_color ((j == i) ? yellow : black); + mvaddch (yoffset, xoffset + j, name[j]); + set_color (white); + } + int ch = getch (); + switch (ch) { + case '\n': + case '\r': + stop = 1; + break; + case KEY_BACKSPACE: + case KEY_DELETE: + case 127: + case '\b': + name[i] = ' '; + i--; + break; + case KEY_LEFT: + i--; + break; + case KEY_RIGHT: + i++; + break; + case KEY_ESC: + free (name); + name = NULL; + stop = 1; + break; + default: + if ((ch >= 32) && ( ch < 128)) { + name[i] = ch; + i++; + } + } + + if (i < 0) { + i = 0; + } + if (i >= length) { + i = length - 1; + } + } + + if (name) { + for (j = length - 1; j >= 0; j--) { + if (name[i] == ' ') { + name[i] = '\0'; + } + } + if (*name == '\0') { + free (name); + name = NULL; + } + } + + return name; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/display.h b/display.h new file mode 100644 index 0000000..3f4ce7d --- /dev/null +++ b/display.h @@ -0,0 +1,21 @@ +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include "type.h" + +#define KEY_ESC 0x1b +#define KEY_DELETE 0x014a + +int helpwindow (char *msg, int xoffset, int yoffset); + +void librarywindow (char *msg, int xoffset, int yoffset); + +void boardwindow (board_t *board, int xboard, int yboard, int bound); + +void elementwindow (board_t *board, int xoffset, int yoffset, board_t *element, int x, int y); + +char *savewindow (int length, int xoffset, int yoffset); + +#endif /* __DISPLAY_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.c b/function.c new file mode 100644 index 0000000..f8e5daa --- /dev/null +++ b/function.c @@ -0,0 +1,176 @@ +#include +#include +#include + +#include "debug.h" +#include "type.h" + +#include "function.h" + +int strmaxlen (char *str, char ch) +{ + int len = 0; + char *end = NULL; + while ((end = strchr (str, ch)) != NULL) { + int l = (int)(end - str); + if (l > len) { + len = l; + } + str = end + 1; + } + return len; +} + +board_t *initboard (int xsize, int ysize) +{ + board_t *board = (board_t *) malloc (sizeof (board_t)); + CHECKALLOC (board); + board->tab = (char *) calloc (1, xsize * ysize + 1); + CHECKALLOC (board->tab); + memset (board->tab, ' ', xsize * ysize); + board->xsize = xsize; + board->ysize = ysize; + return board; +} + +void freeboard (board_t *board) +{ + if (board) { + free (board->tab); + } + free (board); +} + +int _makecomments (char *buffer, board_t *board) +{ + int i, j, l = 0; + for (j = 0; j < board->ysize; j++) { + l += sprintf (buffer + l, "rem: \""); + for (i = 0; i < board->xsize; i++) { + l += sprintf (buffer + l, "%c", *getcell (board, i, j)); + } + l += sprintf (buffer + l, "\"\n"); + } + return l; +} + +char *saveboard (board_t *board) +{ + int size = 2 * (8 + 3) + 8 + board->xsize * board->ysize + 1; + VERBOSE (INFO, size += board->ysize * (8 + board->xsize)); + + char *buffer = (char *) calloc (size, 1); + CHECKALLOC (buffer); + + int l = sprintf (buffer, "xsize: %d\n", board->xsize); + l += sprintf (buffer + l, "ysize: %d\n", board->ysize); + l += sprintf (buffer + l, "tab: \"%s\"\n", board->tab); + + VERBOSE (INFO, _makecomments (buffer + l, board)); + + return buffer; +} + +int writedata (char *filename, char *data) +{ + int ret = 0; + + FILE *fd = fopen (filename, "w"); + if (fd) { + size_t n = fwrite (data, strlen (data), 1, fd); + fclose (fd); + ret = (n == strlen (data)); + } else { + VERBOSE (WARNING, printf ("can't write file (%s)\n", filename)); + } + + return ret; +} + +char *readdata (char *filename) +{ + char *buffer = NULL; + FILE *fd = fopen (filename, "r"); + if (fd) { + fseek (fd, 0, SEEK_END); + int size = ftell (fd); + buffer = (char *) calloc (size + 1, 1); + CHECKALLOC (buffer); + + fseek (fd, 0, SEEK_SET); + int nb = fread (buffer, 1, size, fd); + if (nb != size) { + VERBOSE (WARNING, printf ("can't fully read file (%s)\n", filename)); + } + fclose (fd); + } + + return buffer; +} + +char *atos (char *str) +{ + char *ret = NULL; + + if (*str == '"') { + char *ptr = ++str; + while ((*ptr != '"') && (*ptr != '\0')) { + ptr++; + } + if (*ptr == '"') { + *ptr = '\0'; + ret = str; + } + } + + return ret; +} + +board_t *loadboard (char *str) +{ + int xsize = 0; + int ysize = 0; + char *tab = NULL; + + char *saveptr1, *saveptr2; + + char *line = strtok_r (str, "\n", &saveptr1); + while (line) { + + char *keyword = strtok_r (line, ":", &saveptr2); + + char *value = line + strlen (keyword) + 1; + while (*value == ' ') { + value++; + } + + if (strcmp (keyword, "xsize") == 0) { + xsize = atoi (value); + } else if (strcmp (keyword, "ysize") == 0) { + ysize = atoi (value); + } else if (strcmp (keyword, "tab") == 0) { + tab = atos (value); + } else if (strcmp (keyword, "rem") == 0) { + /* nothing to do with remark */ + } else { + VERBOSE (WARNING, printf ("unknown keyword: %s\n", keyword)); + } + + line = strtok_r (NULL, "\n", &saveptr1); + } + + board_t *board = NULL; + if ((tab) && (strlen (tab) == (size_t)(xsize * ysize))) { + board = initboard (xsize, ysize); + memcpy (board->tab, tab, xsize * ysize); + } + + return board; +} + +char *getcell (board_t *board, int x, int y) +{ + return board->tab + x + board->xsize * y; +} + +/* vim: set ts=4 sw=4 et: */ diff --git a/function.h b/function.h new file mode 100644 index 0000000..55ba397 --- /dev/null +++ b/function.h @@ -0,0 +1,36 @@ +#ifndef __FUNCTION_H__ +#define __FUNCTION_H__ + +#include "type.h" + +#define CHECKALLOC(ptr) \ + do { \ + if ((ptr) == NULL) { \ + VERBOSE (ERROR, fprintf (stderr, "can't get enough memory for '%s'\n", #ptr)); \ + exit (1); \ + } \ + } while (0) + +#define max(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) + +#define min(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) + +int strmaxlen (char *str, char ch); + +board_t *initboard (int xsize, int ysize); + +void freeboard (board_t *board); + +char *saveboard (board_t *board); + +int writedata (char *filename, char *data); + +char *readdata (char *filename); + +board_t *loadboard (char *str); + +char *getcell (board_t *board, int x, int y); + +#endif /* __FUNCTION_H__ */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/getcomments.pl b/getcomments.pl new file mode 100644 index 0000000..47edf67 --- /dev/null +++ b/getcomments.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl + +use strict; + +# default value +my $format = "%"; +my $pattern = ""; + +# help message +sub usage() { + + print <) { + my $cmt; + + # process c++ comments + ($cmt, $_) = m{//\s*(.*?)\s*$()} if (m{//} && !m{/\*.*//}); + + # process standard c comments + ($cmt, $_) = m{^.*?/\*\s*(.*?)\s*\*/(.*)}s if (m{/\*.*\*/}s); + + push(@comments, $cmt) if ($cmt); + + # empty buffer if no comment is present + undef($_) if (!m{/[/*]}); + } + + # close file + close (IN); + + # display comment blocks + foreach my $block (@comments) { + if (($block) = ($block =~ /$pattern(.*)/s)) { + ($_ = $format) =~ s/%/$block/gs; + print "$_\n"; + } + } +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..15b259d --- /dev/null +++ b/makefile @@ -0,0 +1,177 @@ +# Default flags + +CC = gcc + +#INCLUDES = -I../debug -D__MEMORY_ALLOCATION__ +INCLUDES = +OFLAGS = -O4 -Os +#OFLAGS = -O4 -ffast-math -finline-functions +#OFLAGS = -O4 -finline-functions +#OFLAGS += -mtune=pentium3 -mmmx -msse -msse2 -m3dnow +#OFLAGS += -minline-all-stringops -fsingle-precision-constant +#OFLAGS += -malign-double +CFLAGS += -W -Wall -Wextra -g +#CFLAGS += -std=c99 -D_XOPEN_SOURCE=500 +CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS) +LDFLAGS += -g $(OPTIONS) + +LDOPT = linker +ifeq ($(OS),Windows_NT) +#LDLIBS += -lws2_32 +LDOPT = winlnk +endif +ifeq ($(OS),Dos) +LDOPT = doslnk +endif + +# Targets + +ALLEXE = +ALLEXE += solitaire + +SHELL = bash + +#MAKE = mingw32-make +MAKEFLAGS += -s +include $(wildcard .makefile) + +# Functions + +TITLE = echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t" +PASS = echo -e "\033[1;32m$(strip $(1))\033[0;0m" +WARN = echo -e "\033[1;33m$(strip $(1))\033[0;0m" +FAIL = echo -e "\033[1;31m$(strip $(1))\033[0;0m" + +MKDIR = mkdir -p $(1) && chmod a+rx,go-w $(1) + +INSTALL = test -d `dirname $(2)` || $(call MKDIR, `dirname $(2)`) && cp -pa $(1) $(2) && chmod a+rX,go-w $(2) + +VALID = $(call TITLE, $(1)) && $(2) && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; } + +GETCOMMENTS = awk '/\/\*\s*$(1):/,/\*\// { sub(/.*\/\*\s*$(1):/, ""); sub (/\s*\*\/.*/, ""); print } /\/\/\s*$(1):/ {sub (/.*\/\/\s*$(1):/, ""); print }' $(2) +#GETCOMMENTS = perl -- getcomments.pl -p='$(1):\s' -f='%' $(2) + +## Generic rules + +all: depends + $(MAKE) $(ALLEXE:%=%.exe) + +count: + wc $(wildcard *.c *.h) $(MAKEFILE_LIST) + +clean: + $(call TITLE, "Cleaning") + touch clean + rm -f clean $(wildcard *.d *.ld *.log *.o *.test *~ .exec_* gmon.out) + $(call PASS, SUCCESS) + +depends: $(patsubst %.c, %.d, $(wildcard *.c)) $(patsubst %, %.ld, $(ALLEXE)) + +gcovs: + $(MAKE) $(addprefix gcov_,$(ALLEXE)) + +gprofs: + $(MAKE) $(addprefix gprof_,$(ALLEXE)) + +purge: clean + $(call TITLE, "Purging") + touch purge + rm -f purge $(ALLEXE:%=%.exe) + $(call PASS, SUCCESS) + +valgrinds: all + $(MAKE) $(addprefix valgrind_,$(ALLEXE)) + +wipe: purge + $(call TITLE, "Wiping") + touch wipe + rm -f wipe $(wildcard *.gcda *.gcno *.gcov *.glog) + $(call PASS, SUCCESS) + +tests: all + $(MAKE) $(addprefix test_,$(ALLEXE)) + +## Main rules + +include $(wildcard *.d) +include $(wildcard *.ld) + +gcov_%: + $(MAKE) purge + OPTIONS="-coverage -O0" $(MAKE) + $(MAKE) test_$(@:gcov_%=%) + gcov `sed -e 's/\.exe:/.c/;s/\.o/.c/g' $(@:gcov_%=%.ld)` + touch gcov + rm -f gcov $(wildcard *.gcda *.gcno) + $(MAKE) purge + grep '#####' *.c.gcov || true + +gprof_%: + $(MAKE) purge + $(MAKE) depends + OPTIONS="-pg" $(MAKE) ${@:gprof_%=%}.exe + $(MAKE) ${@:gprof_%=%}.test + IFS=$$'\n'; id=1; \ + for test in `cat ${@:gprof_%=%}.test | sed 's,${@:gprof_%=%}.exe,./${@:gprof_%=%}.exe,g'`; do \ + log=${@:gprof_%=%}.prof-$$id.glog; \ + $(call TITLE, test: $$test); \ + echo $$test > $$log; \ + eval $$test >> $$log; \ + [ $$? -eq 0 ] \ + && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || echo -e "\033[1;31mFAILED\033[0;0m"; \ + [ -f gmon.out ] && { gprof ${@:gprof_%=%}.exe gmon.out >> $$log; rm gmon.out; }; \ + let id++; \ + done; + $(MAKE) purge + +%.test: %.c + $(call TITLE, "Building $@") + $(call GETCOMMENTS,test, $<) > $@ + $(call PASS, SUCCESS) + +test_%: %.test %.exe + IFS=$$'\n'; RC=0; \ + for test in `cat $< | sed 's,${<:.test=.exe},$(VALGRIND) ./${<:.test=.exe},g'`; do \ + echo "=== $$test ==="; \ + eval $$test; \ + [ $$? -eq 0 ] && echo -e "\033[1;32mSUCCESS\033[0;0m" \ + || { echo -e "\033[1;31mFAILED\033[0;0m"; RC=1; }; \ + done; \ + test "$$RC" -ne 1 + +valgrind_%: %.exe + VALGRIND="valgrind -v --leak-check=full --log-fd=3"; \ + export VALGRIND; \ + $(MAKE) $(@:valgrind_%=test_%) 3>$@.log + +%.d: %.c + $(call TITLE, "Building $@") + $(CC) $(INCLUDES) -MM $< -o $@~ + echo ${<:.c=.o}: $(shell $(call GETCOMMENTS,depends, $<)) >> $@~ + mv $@~ $@ + $(call PASS, SUCCESS) + +%.ld: %.c + $(call TITLE, "Building $@") + echo ${<:.c=.exe}: $(shell $(call GETCOMMENTS,$(LDOPT), $<) | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') > $@ + $(call PASS, SUCCESS) + +%.o: %.c + $(call TITLE, "Building $@") + $(CC) $(CFLAGS) $(INCLUDES) $(shell $(call GETCOMMENTS,cflags, $<)) -c $< -o $@ + $(call PASS, SUCCESS) + + +%.exe: %.o %.d + $(call TITLE, "Building $@") + $(CC) $(LDFLAGS) $< $(shell $(call GETCOMMENTS,$(LDOPT), ${<:.o=.c})) $(LDLIBS) -o $@ + $(call PASS, SUCCESS) + +## Phony + +.PHONY: all clean count depends gcovs purge tests + +## Precious + +.PRECIOUS: %.d %.o diff --git a/solitaire.c b/solitaire.c new file mode 100644 index 0000000..95ec4bc --- /dev/null +++ b/solitaire.c @@ -0,0 +1,210 @@ +/* depend: */ +/* cflags: */ +/* linker: constant.o debug.o display.o function.o -lcurses */ +/* doslnk: constant.o debug.o display.o function.o -lpdc~1 */ +/* winlnk: constant.o debug.o display.o function.o -lpdcurses */ + +#include +#include +#include +#include +#include + +#include "constant.h" +#include "debug.h" +#include "display.h" +#include "function.h" +#include "type.h" + +/* static variables */ +char *progname = NULL; +char *version = "0.1"; + +char *boardname = NULL; +char *filename = NULL; + +int xoffset = 1; +int yoffset = 1; +int savelen = 12; + +char *help = + " Get pet\n" + " Move up cursor\n" + " Move left cursor\n" + " Move down cursor\n" + " Move right cursor\n" + " Quit\n" + " Save file\n" + ; + +int usage (int ret) +{ + FILE *fd = ret ? stderr : stdout; + fprintf (fd, "usage: %s [-b board] [-f file] [-h] [-v level]\n", progname); + fprintf (fd, " -b: board name (%s)\n", boardname); + fprintf (fd, " -h: help message\n"); + fprintf (fd, " -f: file name (%s)\n", (filename) ? filename : "none"); + fprintf (fd, " -v: verbose level (%d)\n", verbose); + fprintf (fd, "%s version %s\n", progname, version); + + return ret; +} + +/* main function */ +int main (int argc, char *argv[]) +{ + + /* get basename */ + char *pt = progname = argv[0]; + while (*pt) { + if ((*pt == '/') || (*pt == '\\')) { + progname = pt + 1; + } + pt++; + } + + /* process argument */ + while (argc-- > 1) { + char *arg = *(++argv); + if (arg[0] != '-') { + VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, arg)); + return usage (1); + } + char c = arg[1]; + switch (c) { + case 'b': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: no board specified\n", progname)); + return usage (1); + } + boardname = arg; + break; + case 'f': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: no file specified\n", progname)); + return usage (1); + } + filename = arg; + break; + case 'v': + arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; + if (arg == NULL) { + VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname)); + return usage (1); + } + verbose = atoi (arg); + break; + case 'h': + default: + return usage (c != 'h'); + } + } + + /* load playground */ + board_t *board = NULL; + if (filename) { + } else if (filename) { + } + if (board == NULL) { + return 1; + } + + /* init curses window */ + initscr (); + noecho (); + cbreak (); + nonl (); + keypad (stdscr, TRUE); + curs_set (0); + start_color (); + + /* window positions */ + int xboard = xoffset + 1; + int yboard = xoffset + 1; + int xhelp = xboard + xoffset + 1 + board->xsize; + int xcursor = 0; + int ycursor = 0; + int yhelp = yboard; + int xsave = max (xboard + (board->xsize - savelen) / 2, 1); + int ysave = yboard + (board->ysize - 1) / 2; + char *savename = NULL; + + /* init windows */ + helpwindow (help, xhelp, yhelp); + + /* event loop */ + int stop = 0; + while (!stop) { + char *ptr = NULL; + + boardwindow (board, xboard, yboard, 1); + + int ch = getch (); + switch (ch) { + case ' ': + case '\n': + case '\r': + case 'c': + break; + case KEY_UP: + case 'i': + ycursor = (ycursor + board->ysize - 1) % board->ysize; + break; + case KEY_LEFT: + case 'j': + xcursor = (xcursor + board->xsize - 1) % board->xsize; + break; + case KEY_DOWN: + case 'k': + ycursor = (ycursor + 1) % board->ysize; + break; + case KEY_RIGHT: + case 'l': + xcursor = (xcursor + 1) % board->xsize; + break; + case KEY_ESC: + case 'q': + stop = 1; + break; + case 's': + savename = savewindow (savelen, xsave, ysave); + if (savename != NULL) { + ptr = saveboard (board); + if (writedata (savename, ptr)) { + VERBOSE (WARNING, printf ("issue writing Board\n")); + } + free (ptr); + free (savename); + } + break; + case KEY_BACKSPACE: + case KEY_DELETE: + case 127: + case '\b': + case 'x': + break; + //case ERR: + //default: + } + } + + endwin (); + + freeboard (board); + + return 0; +} + +/* test: solitaire.exe -b 2>&1 | grep 'no board' */ +/* test: solitaire.exe -b bogus 2>&1 | grep 'unkonwn board' */ +/* test: solitaire.exe -f 2>&1 | grep 'no file' */ +/* test: solitaire.exe -f nofile.sol 2>&1 | grep "can't read file" */ +/* test: solitaire.exe -f bogus.sol 2>&1 | grep 'incorrect file' */ +/* test: solitaire.exe -h | grep usage */ +/* test: solitaire.exe -v 2>&1 | grep missing */ +/* test: solitaire.exe _ 2>&1 | grep invalid */ +/* test: echo -n q | solitaire.exe */ + +/* vim: set ts=4 sw=4 et: */ diff --git a/type.h b/type.h new file mode 100644 index 0000000..b32dd56 --- /dev/null +++ b/type.h @@ -0,0 +1,12 @@ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +typedef struct { + int xsize; + int ysize; + char *tab; +} board_t; + +#endif /* __TYPE_H__ */ + +/* vim: set ts=4 sw=4 et: */ -- 2.30.2