commit b9104dd02549f3e28fd2be0fa526b77e2d505de7
parent d46d4807e8318027f45798e84b770d627db7aa88
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sun, 12 Jun 2022 16:42:46 +0200
Documentation for display.c and pattern.h.
- Exclude uthash.h from the documentation
- Move display_status() to game.c
- Declutter game.c using static global variables representing a game
state
Diffstat:
6 files changed, 126 insertions(+), 56 deletions(-)
diff --git a/Doxyfile b/Doxyfile
@@ -920,7 +920,7 @@ RECURSIVE = NO
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE = include/uthash.h
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
diff --git a/include/display.h b/include/display.h
@@ -23,21 +23,28 @@ extern window_T MAIN_w;
typedef int (*input_f)(int);
+/*
+ * @breaf A item in a menu
+ *
+ * It's intended to be used with display_menu().
+ */
struct menu_T {
- void (*callback)(char *, int);
- char *name;
+ void (*callback)(char *, int); ///< function called when item is selected
+ char *name; ///< name of the menu item
};
+/*
+ * @breaf A item in a interactive menu
+ *
+ * It's intended to be used with display_imenu().
+ */
struct imenu_T {
- char *message;
- int size;
- input_f crit;
- char *buffer;
+ char *message; ///< prompt for the user
+ int size; ///< max number of characters required
+ input_f crit; ///< function that check the validity of a character
+ char *buffer; ///< place where read character are stored
};
-extern int screen_offset_x, screen_offset_y;
-extern int wrap;
-
int input(WINDOW *win, char *buffer, int size, input_f crit);
int display_start(void);
@@ -46,9 +53,6 @@ int display_stop(void);
void display_menu(window_T wind, char *name, struct menu_T *items, int size,
int title);
int display_imenu(window_T wind, struct imenu_T *items, int size);
-void display_status(window_T wind, unsigned long int generation, int gen_step,
- int wrap, int height, int wight, int play, int dt,
- int cursor_y, int cursor_x);
void display_patterns(window_T wind);
void handle_winch(int sig);
diff --git a/include/pattern.h b/include/pattern.h
@@ -3,11 +3,15 @@
#include "stdlib.h"
+/**
+ * @brief Structure representing one cell pattern to be used in a help menu
+ */
typedef struct pattern_T {
- char *cells;
- char *name;
- int height;
- int width;
+ char *cells; ///< string where 1 represents a living cell and 0 a dead one,
+ /// space is used to detonate a new row
+ char *name; ///< name of the pattern
+ int height; ///< pattern height , used for cache, no need to fill manually
+ int width; ///< pattern width , used for cache, no need to fill manually
} * pattern_T;
struct pattern_T title = {
@@ -84,10 +88,13 @@ struct pattern_T methuselahs[] = {
{"00000010 11000000 01000111", "Diehard", 0},
};
+/**
+ * @brief A structure representing a group of pattern_T of a certain category
+ */
typedef struct pattern_group_T {
- char *name;
- pattern_T pattern;
- int size;
+ char *name; ///< name of the group
+ struct pattern_T *pattern; ///< array of pattern_T that comprise a group
+ int size; ///< number of elements in a group
} pattern_group_T;
struct pattern_group_T pattern_groups[] = {
diff --git a/src/display.c b/src/display.c
@@ -1,5 +1,16 @@
+/**
+ * @file display.c
+ * @author Dimitrije Dobrota
+ * @date 12 June 2022
+ * @brief This file handles ncurses library and UI
+ *
+ * This file is the main link with ncurses interface. It is responsible for
+ * starting and stopping ncurses library as well as managing it's resources and
+ * handling terminal resize by rebuilding window_T binary tree. It exports
+ * window_T MAIN_w as the entery point for other windows and disiplay calls. It
+ * handles the display of menus and user input.
+ */
#include <curses.h>
-#include <signal.h>
#include <stdlib.h>
#include <string.h>
@@ -11,18 +22,33 @@
window_T MAIN_w = NULL;
+/**
+ * @brief Offset the cursor for ncurses WINDOW*
+ *
+ * @param oy: real number representing offset along y axis
+ * @param ox: real number representing offset along x axis
+ */
void cursor_offset(WINDOW *win, int oy, int ox) {
int y, x;
getyx(win, y, x);
wmove(win, y + oy, x + ox);
}
-void print_pattern(WINDOW *win, pattern_T pattern, int *y, int x, int indent) {
+/**
+ * @brief Print pattern_T
+ *
+ * @param y: pointer to int representing y cord where the pattern
+ * should be displayed. Will be inc read by the number of lines
+ * printed
+ * @param x: pointer to int representing x cord where the pattern
+ * should be displayed
+ */
+void print_pattern(WINDOW *win, pattern_T pattern, int *y, int x) {
(*y)++;
- wmove(win, (*y)++, x + indent);
+ wmove(win, (*y)++, x);
for (char *c = pattern->cells; *c != '\0'; c++) {
if (*c == ' ') {
- wmove(win, (*y)++, x + indent);
+ wmove(win, (*y)++, x);
continue;
}
int val = *c - '0';
@@ -31,20 +57,13 @@ void print_pattern(WINDOW *win, pattern_T pattern, int *y, int x, int indent) {
}
}
-void display_status(window_T wind, unsigned long int gen, int gen_step,
- int wrap, int height, int wight, int play, int dt,
- int cursor_y, int cursor_x) {
- WINDOW *win = window_win(wind);
-
- wmove(win, 1, 1);
- wprintw(win, " | %5s | ", play ? "play" : "pause");
- wprintw(win, wrap ? "Size: %dx%d | " : "Size: unlimited | ", height, wight);
- wprintw(win, "Generation: %10lu(+%d) | ", gen, gen_step);
- wprintw(win, "dt: %4dms | ", dt);
- wprintw(win, "Cursor: %4dx%-4d | ", cursor_y, cursor_x);
- wrefresh(win);
-}
-
+/**
+ * @brief Get user input of different type up to the specified size
+ *
+ * @param buffer: buffer where the input will be stored
+ * @param size: maximum number of characters in the input
+ * @param crit: function that checks the validity of the character
+ */
int input(WINDOW *win, char *buffer, int size, input_f crit) {
int CLINES = LINES, CCOLS = COLS;
int ch, read = strlen(buffer);
@@ -87,6 +106,10 @@ int input(WINDOW *win, char *buffer, int size, input_f crit) {
return 0;
}
+/**
+ * @brief Given a array of struct imenu_T, display a menu where user will enter all of
+ * the information required from the array
+ */
int display_imenu(window_T wind, struct imenu_T *items, int size) {
WINDOW *win;
int y_offset;
@@ -147,6 +170,9 @@ redraw:;
curs_set(0);
}
+/**
+ * @brief Display the title of the game in the center of the screen if it can fit
+ */
void display_title(window_T wind, int y) {
WINDOW *win = window_win(wind);
title.height = (!title.height) ? pattern_height(&title) : title.height;
@@ -154,10 +180,16 @@ void display_title(window_T wind, int y) {
int max_w = window_wight(wind);
if (title.width * 2 < max_w)
- print_pattern(win, &title, &y, (max_w - title.width * 2) / 2, 0);
+ print_pattern(win, &title, &y, (max_w - title.width * 2) / 2);
wrefresh(win);
}
+/**
+ * @brief Given a array of struct menu_T, display all menu items and allow user
+ * to chose one of them after which appropriate callback function will be called
+ *
+ * @param title: 1 if title should be displayed
+ */
void display_menu(window_T wind, char *name, struct menu_T *items, int size,
int title) {
WINDOW *win;
@@ -224,6 +256,10 @@ redraw:;
}
}
+/**
+ * @brief Initialize ncurses library and set colors based on display mode
+ * selected while compiling
+ */
void curses_start(void) {
initscr();
window_settings(stdscr);
@@ -265,6 +301,11 @@ void curses_start(void) {
#endif
}
+/**
+ * @brief Handle the reboiling of window_T binary tree after terminal resize
+ *
+ * This function MUST be called after a resize has been detected by any function
+ */
void handle_winch(int sig) {
endwin();
refresh();
@@ -274,6 +315,9 @@ void handle_winch(int sig) {
window_update_children(MAIN_w);
}
+/**
+ * @brief Start ncurses display and export MAIN_w
+ */
int display_start(void) {
curses_start();
MAIN_w = window_init(window_new());
@@ -286,12 +330,19 @@ int display_start(void) {
return 1;
}
+/**
+ * @brief Stop ncurses display and cleanup
+ */
int display_stop(void) {
window_free(MAIN_w);
endwin();
return 1;
}
+/**
+ * @brief Display help menu using all the patterns from all the groups in
+ * pattern_groups array
+ */
void display_patterns(window_T wind) {
int y_start = 2, x_start = 2;
int indent = 2;
@@ -335,7 +386,7 @@ redraw:;
wattrset(win, 0);
if (p.height != 0) {
mvwprintw(win, y++, x, "- %s: ", p.name);
- print_pattern(win, &p, &y, x, indent);
+ print_pattern(win, &p, &y, x + indent);
y += 2;
} else {
if (*p.name) {
diff --git a/src/game.c b/src/game.c
@@ -26,10 +26,13 @@ int coordinate_wrap(int val, int offset, int max) {
return (val + offset + max) % max;
}
-int win_height, win_width, height, width;
-int screen_offset_x, screen_offset_y;
-int cursor_offset_x, cursor_offset_y;
-int wrap;
+int height, width;
+
+static int win_height, win_width;
+static int screen_offset_x, screen_offset_y;
+static int cursor_offset_x, cursor_offset_y;
+static int wrap, gen = 0, gen_step = 1;
+static int play = 0, time_const = 100, time_step = 1;
coordinate_f cord;
@@ -117,6 +120,18 @@ void display_cursor(WINDOW *win) {
prev_x = cursor_offset_x;
}
+void display_status(window_T wind) {
+ WINDOW *win = window_win(wind);
+
+ wmove(win, 1, 1);
+ wprintw(win, " %5s | ", play ? "play" : "pause");
+ wprintw(win, wrap ? "Size: %dx%d | " : "Size: unlimited | ", height, width);
+ wprintw(win, "Generation: %10lu(+%d) | ", gen, gen_step);
+ wprintw(win, "dt: %4dms | ", time_const);
+ wprintw(win, "Cursor: %4dx%-4d | ", cursor_offset_y, cursor_offset_x);
+ wrefresh(win);
+}
+
int display_select(window_T wind) {
int CLINES = LINES, CCOLS = COLS;
@@ -232,7 +247,6 @@ void game(int s_h, int s_w, int mode_index) {
char *mode_name = evolution_names[mode_index];
int t_y = 0, t_x = 0, ct_x = 0, ct_y = 0;
- int gen = 0, gen_step = 1, play = 0, time_const = 100, time_step = 1;
wrap = 1;
window_T status_w, screen_w, game_w;
@@ -314,9 +328,7 @@ redraw:;
gen += gen_step;
}
- display_status(status_w, gen, gen_step, wrap, height, width, play,
- time_const, cord(y_at(cursor_offset_y)),
- cord(x_at(cursor_offset_x)));
+ display_status(status_w);
if (screen_change) {
display_game(game_w);
diff --git a/src/window.c b/src/window.c
@@ -35,11 +35,10 @@ typedef struct T *T;
* children when a terminal resize occurs.
*/
struct window_T {
- WINDOW
- *win; ///< ncurses WINDOW* that represents current window_T on the screen
- T c1; ///< left child, NULL if none
- T c2; ///< right child, NULL if none
- T sibling; ///< sibling, NULL if none
+ WINDOW *win; ///< ncurses WINDOW* that represents current window_T
+ T c1; ///< left child, NULL if none
+ T c2; ///< right child, NULL if none
+ T sibling; ///< sibling, NULL if none
int param[4]; ///< windows size and dimension, refer to macros
int mod[3]; ///< Information an recreating children
@@ -133,7 +132,6 @@ T window_init(T self) {
*
* Free the object itself and ncurses WINDOW* with delwin
*/
-
void window_free(T self) {
if (self == NULL)
return;
@@ -146,7 +144,6 @@ void window_free(T self) {
/**
* @brief Delete all children and subchildren of a window
*/
-
void window_unsplit(T self) {
window_free(self->c1);
window_free(self->c2);
@@ -315,7 +312,6 @@ void window_update_children(T self) {
* @brief Clear the current window, reset the setting, keep the border call
* ncurses refresh()
*/
-
void window_clear(T self) {
werase(self->win);
WINDOW_init(self->win, self->title);