golImplementation of Conway's Game of Life writen in C |
git clone git://git.dimitrijedobrota.com/gol.git |
Log | Files | Refs | README | |
commit | 875e9d53a57e3a6e89fa6e6239220986e25281d3 |
parent | 1fbb80b7635b1b38d38cb42a37b4007f61ef6629 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Mon, 30 May 2022 17:15:47 +0200 |
Visual selection of the cells and status bar - In visual mode you can select the pattern to be saved - Save/Load menu for patter as well as the whole game - Ability to save in a new file with name selection - Optional NO_UNICODE mode, use make NO_UNICODE - Status bar that displays basic game information - Status bar does not appear until the game is started - Ability to change time between screen updates in game - General performance and cleanup improvement
Diffstat:M | Makefile | | | +++-- |
M | include/display.h | | | +++++++++++------ |
M | include/file.h | | | ++++- |
M | include/utils.h | | | -- |
M | include/window.h | | | +++++++-- |
M | src/display.c | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- |
M | src/file.c | | | ++++++++++++-- |
M | src/main.c | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
M | src/window.c | | | ++++++++++++++++++++++++++++++++++++++++--------------- |
9 files changed, 414 insertions(+), 158 deletions(-)
diff --git a/Makefile b/Makefile
@@ -17,7 +17,8 @@ OBJS=$(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SRCS))
all: $(BIN)
debug: CFLAGS +=-ggdb -Wall
debug: ${BIN}
NO_UNICODE: CFLAGS += -D NO_UNICODE
NO_UNICODE debug: ${BIN}
$(BIN): $(OBJS)
$(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
@@ -33,4 +34,4 @@ clean:
rm -f $(BIN) $(OBJS)
endif
.PHONY: all clean debug
.PHONY: all clean debug NO_UNICODE
diff --git a/include/display.h b/include/display.h
@@ -1,15 +1,15 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include "window.h"
#include "logic.h"
#include "window.h"
extern window_T MAIN_w;
typedef int (*input_f)(int);
struct menu_T {
void (*callback)(window_T, char *, int);
void (*callback)(char *, int);
char *name;
};
@@ -20,16 +20,21 @@ struct imenu_T {
char *buffer;
};
extern int screen_offset_x, screen_offset_y;
extern int cursor_offset_x, cursor_offset_y;
int input(WINDOW *win, char *buffer, int size, input_f crit);
int display_start(void);
int display_stop(void);
void display_menu(window_T win, struct menu_T *items, int size);
void display_menu(window_T wind, char *name, struct menu_T *items, int size);
int display_imenu(window_T wind, struct imenu_T *items, int size);
void display_game(window_T wind, cell **mat, int w, int h, int screen_offset_y,
int screen_offset_x, int *cursor_offset_y,
int *cursor_offset_x);
void display_game(window_T wind, cell **mat, int h, int w, int ph, int pw);
void display_select(window_T wind, cell **mat, int w, int h);
void display_status(window_T wind, unsigned long int generation, int gen_step,
int height, int wight, int play, int dt, int cursor_y,
int cursor_x);
void handle_winch(int sig);
diff --git a/include/file.h b/include/file.h
@@ -8,6 +8,9 @@ void load_files(void);
void free_files(void);
int file_select(char *ext, char ***buffer);
void load_file(window_T win, char *pass, int index);
void file_load_pattern(char *name, int index);
void file_save_pattern(char *name, int index);
void file_load(char *name, int index);
void file_save(char *name, int index);
#endif
diff --git a/include/utils.h b/include/utils.h
@@ -15,13 +15,11 @@
{ \
resize_term(0, 0); \
handle_winch(10); \
goto redraw; \
}
#else
#define HANDLE_RESIZE \
{ \
handle_winch(10); \
goto redraw; \
}
#endif
#endif
diff --git a/include/window.h b/include/window.h
@@ -9,10 +9,13 @@ typedef struct T *T;
T window_new(void);
void window_free(T self);
T window_init(T self);
T window_split(T self, int hor, int a, int b);
T window_center(T self, int tmp, int h, int w);
T window_split(T self, int hor, int a, int b, char *name1, char *name2);
void window_unsplit(T self);
T window_center(T self, int tmp, int h, int w, char *name);
void window_update_children(T self);
WINDOW *WINDOW_new(T self);
T window_sibiling(T self);
int window_height(T self);
int window_wight(T self);
@@ -20,6 +23,8 @@ WINDOW *window_win(T self);
void window_settings(WINDOW *win);
void window_clear(T self);
void window_set_title(T self, char *title);
void wcenter_horizontal(T window, int y, int n);
int wcenter_vertical(T window, int n);
void cursor_offset(WINDOW *win, int oy, int ox);
diff --git a/src/display.c b/src/display.c
@@ -11,10 +11,11 @@
#define center_vertical(n) wcenter_vertical(MAIN_W, n);
#define center_horizontal(y, n) wcenter_horizontal(MAIN_W, y, n);
#define CHAR_CIRCLE L'\u26AB'
#define CHAR_SQUARE L'\u2B1B'
#define CHAR_SQUARED L'\u2B1C'
#define CHAR_CIRCLE_DOT L'\u2299'
#define CHAR_BLANK " "
#define CHAR_CIRCLE "\u26AB"
#define CHAR_SQUARE "\u2B1B"
#define CHAR_SQUARED "\u2B1C"
#define CHAR_CIRCLE_DOT "\u2299"
window_T MAIN_w = NULL;
@@ -77,7 +78,7 @@ int display_imenu(window_T wind, struct imenu_T *items, int size) {
window_clear(wind);
redraw:;
win = window_win(wind);
y_offset = wcenter_vertical(wind, size);
y_offset = wcenter_vertical(wind, size * 2 - 1);
for (int i = 0; i < size; i++) {
wcenter_horizontal(wind, y_offset + 2 * i, 20);
@@ -119,7 +120,7 @@ redraw:;
curs_set(0);
}
void display_menu(window_T wind, struct menu_T *items, int size) {
void display_menu(window_T wind, char *name, struct menu_T *items, int size) {
WINDOW *win;
int current = 0;
@@ -128,10 +129,12 @@ void display_menu(window_T wind, struct menu_T *items, int size) {
if ((len = strlen(items[i].name)) > maxi)
maxi = len;
window_set_title(wind, name);
window_clear(wind);
redraw:;
win = window_win(wind);
int CLINES = LINES, CCOLS = COLS;
int y_offset = wcenter_vertical(wind, size * 2);
int y_offset = wcenter_vertical(wind, size * 2 - 1);
while (TRUE) {
CLAMP(current, 0, size - 1);
@@ -144,17 +147,15 @@ redraw:;
while (TRUE) {
int c = getch();
if (c == 'k' || c == KEY_UP) {
if (c == 'k' || c == 'w' || c == KEY_UP) {
current--;
break;
} else if (c == 'j' || c == KEY_DOWN) {
} else if (c == 'j' || c == 's' || c == KEY_DOWN) {
current++;
break;
} else if (c == '\n') {
wattrset(win, COLOR_PAIR(0));
window_clear(wind);
items[current].callback(wind, items[current].name, current);
/* window_clear(wind); */
items[current].callback(items[current].name, current);
return;
} else if (c == 27)
return;
@@ -166,51 +167,134 @@ redraw:;
}
}
#define y_at(y) (y + screen_offset_y + h) % h + 1
#define x_at(x) (x + screen_offset_x + w) % w + 1
#define y_at(y) (y + screen_offset_y + h) % h + 1
#define x_at(x) (x + screen_offset_x + w) % w + 1
#define at(y, x) mat[y_at(y)][x_at(x)]
#define at_offset(off) mat[y_at(off##_y)][x_at(off##_x)]
#ifndef NO_UNICODE
#define print_cell(win, k, l, blank) \
if (at(k, l)) \
waddstr(win, CHAR_CIRCLE); \
else \
waddstr(win, blank);
#else
#define print_cell(win, i, j, blank) waddstr(win, blank);
#endif
void display_game(window_T wind, cell **mat, int w, int h, int screen_offset_y,
int screen_offset_x, int *cursor_offset_y,
int *cursor_offset_x) {
WINDOW *win = window_win(wind);
wattrset(win, COLOR_PAIR(0));
#define print_cells(win, start_i, end_i, start_j, end_j, color_offset, blank) \
for (int i = start_i; i < end_i; i++) { \
wmove(win, i + 1, 1 + start_j * 2); \
for (int j = start_j; j < end_j; j++) { \
wattrset(win, COLOR_PAIR((mat[y_at(i)][x_at(j)]) + color_offset)); \
print_cell(win, i, j, blank); \
} \
}
int ph = window_height(wind), pw = window_wight(wind) / 2;
int screen_offset_x, screen_offset_y;
int cursor_offset_x, cursor_offset_y;
void display_game(window_T wind, cell **mat, int h, int w, int ph, int pw) {
WINDOW *win = window_win(wind);
#ifdef _WIN32
window_clear(wind);
#endif
for (int i = 0; i < ph; i++) {
wmove(win, i + 1, 1);
for (int j = 0; j < pw; j++) {
wattrset(win, COLOR_PAIR((mat[y_at(i)][x_at(j)]) + 2));
if (mat[y_at(i)][x_at(j)])
waddstr(win, "\u26AB");
else
waddstr(win, " ");
print_cells(win, 0, ph, 0, pw, 2, CHAR_BLANK);
wmove(win, cursor_offset_y + 1, cursor_offset_x * 2 + 1);
wattrset(win, COLOR_PAIR(at_offset(cursor_offset) + 5));
print_cell(win, cursor_offset_y, cursor_offset_x, "<>");
wrefresh(win);
}
void display_select(window_T wind, cell **mat, int w, int h) {
int current_offset_y = cursor_offset_y;
int current_offset_x = cursor_offset_x;
redraw:;
int CLINES = LINES, CCOLS = COLS;
WINDOW *new = WINDOW_new(wind);
WINDOW *win = window_win(wind);
overlay(win, new);
wrefresh(new);
int ph = window_height(wind), pw = window_wight(wind) / 2;
nodelay(stdscr, 0);
while (TRUE) {
int start_i = MIN(cursor_offset_y, current_offset_y);
int end_i = MAX(cursor_offset_y, current_offset_y);
int start_j = MIN(cursor_offset_x, current_offset_x);
int end_j = MAX(cursor_offset_x, current_offset_x);
print_cells(new, start_i, end_i + 1, start_j, end_j + 1, 8, CHAR_BLANK);
wrefresh(new);
if (is_term_resized(CLINES, CCOLS)) {
flushinp();
delwin(new);
HANDLE_RESIZE;
ph = window_height(wind), pw = window_wight(wind) / 2;
display_game(wind, mat, w, h, ph, pw);
goto redraw;
}
}
CLAMP(*cursor_offset_y, 0, ph - 1);
CLAMP(*cursor_offset_x, 0, pw - 1);
int c = getch();
switch (c) {
// offset selection
case 'w':
case 'W':
current_offset_y--;
break;
case 's':
case 'S':
current_offset_y++;
break;
case 'a':
case 'A':
current_offset_x--;
break;
case 'd':
case 'D':
current_offset_x++;
break;
case '\n':
save_pattern();
wmove(win, *cursor_offset_y + 1, *cursor_offset_x * 2 + 1);
wattrset(win, COLOR_PAIR(
(mat[y_at(*cursor_offset_y)][x_at(*cursor_offset_x)]) + 5));
// quit
case 27:
case 'q':
case 'Q':
nodelay(stdscr, 1);
delwin(new);
return;
defalut:
continue;
}
if (mat[y_at(*cursor_offset_y)][x_at(*cursor_offset_x)])
waddstr(win, "\u26AB");
else
waddstr(win, " ");
CLAMP(current_offset_y, 0, ph - 1);
CLAMP(current_offset_x, 0, pw - 1);
wrefresh(win);
wclear(new);
overlay(win, new);
}
}
#define LMAX 8
#define LEFT 0
#define CENTER 1
#define RIGHT 2
void display_status(window_T wind, unsigned long int gen, int gen_step,
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, "Size: %dx%d | ", 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);
}
void curses_start(void) {
initscr();
@@ -226,6 +310,7 @@ void curses_start(void) {
init_pair(0, COLOR_WHITE, -1);
init_pair(1, COLOR_RED, -1);
#ifndef NO_UNICODE
init_pair(2, COLOR_WHITE, -1);
init_pair(3, COLOR_WHITE, -1);
init_pair(4, COLOR_RED, -1);
@@ -233,6 +318,23 @@ void curses_start(void) {
init_pair(5, COLOR_WHITE, COLOR_CYAN);
init_pair(6, COLOR_WHITE, COLOR_CYAN);
init_pair(7, COLOR_RED, COLOR_CYAN);
init_pair(8, COLOR_WHITE, COLOR_YELLOW);
init_pair(9, COLOR_WHITE, COLOR_YELLOW);
init_pair(10, COLOR_RED, COLOR_YELLOW);
#else
init_pair(2, COLOR_WHITE, -1);
init_pair(3, COLOR_WHITE, COLOR_WHITE);
init_pair(4, COLOR_RED, COLOR_RED);
init_pair(5, COLOR_YELLOW, -1);
init_pair(6, COLOR_YELLOW, COLOR_WHITE);
init_pair(7, COLOR_YELLOW, COLOR_RED);
init_pair(8, COLOR_WHITE, COLOR_YELLOW);
init_pair(9, COLOR_WHITE, COLOR_WHITE);
init_pair(10, COLOR_RED, COLOR_RED);
#endif
}
void curses_stop(void) {
diff --git a/src/file.c b/src/file.c
@@ -130,6 +130,16 @@ int file_select(char *ext, char ***buffer) {
return size;
}
void load_files(void) { loaded_files = file_fromDirectory(); }
void load_files(void) {
if (loaded_files)
file_free(loaded_files);
loaded_files = file_fromDirectory();
}
void free_files(void) { file_free(loaded_files); }
void load_file(window_T win, char *pass, int index) { (void)3; }
// Comming soon...
void file_load_pattern(char *name, int index) { return; }
void file_save_pattern(char *name, int index) { return; }
void file_load(char *name, int index) { return; }
void file_save(char *name, int index) { return; }
diff --git a/src/main.c b/src/main.c
@@ -15,9 +15,9 @@
#include "window.h"
#ifdef _WIN32
#define TIME_CONST 100
#define TIME_MOD 1
#else
#define TIME_CONST 100000
#define TIME_MOD 1000
#endif
extern window_T MAIN_w;
@@ -26,49 +26,136 @@ extern char *evolution_names[];
extern int evolution_cells[];
extern int evolution_size;
window_T status_w, screen_w, game_w;
window_T menu_w;
int top_space = 5;
void game(window_T wind, int w, int h, int ncells) {
int screen_offset_y = 0, screen_offset_x = 0;
int cursor_offset_y = 0, cursor_offset_x = 0;
int in = 3;
int gen_step = 1;
int play = 0;
int gen = 1;
void load_pattern(void);
void save_pattern(void);
window_clear(wind);
game_w = window_center(wind, 0, h, w * 2);
#define y_at(y) (y + screen_offset_y + h) % h + 1
#define x_at(x) (x + screen_offset_x + w) % w + 1
extern int screen_offset_x, screen_offset_y;
extern int cursor_offset_x, cursor_offset_y;
void game(int h, int w, char *name, int ncells) {
unsigned long int gen = 0;
int gen_step = 1, play = 0, time_const = 100, time_step = 1;
window_T status_w, screen_w, game_w;
window_set_title(menu_w, NULL);
window_clear(menu_w);
status_w = window_split(menu_w, 1, 3, 0, "Status", name);
screen_w = window_sibiling(status_w);
game_w = window_center(screen_w, 0, h, w * 2, "Game");
clock_t start_t, end_t = 0, total_t;
redraw:;
int CLINES = LINES, CCOLS = COLS;
int ph = window_height(game_w), pw = window_wight(game_w) / 2;
window_clear(game_w);
while (TRUE) {
start_t = clock();
display_game(game_w, mat, w, h, screen_offset_y, screen_offset_x,
&cursor_offset_y, &cursor_offset_x);
display_status(status_w, gen, gen_step, h, w, play, time_const,
y_at(cursor_offset_y), x_at(cursor_offset_x));
display_game(game_w, mat, h, w, ph, pw);
if (play) {
do_evolution(gen_step);
gen++;
gen += gen_step;
}
while ((total_t = (long int)(end_t - start_t)) < TIME_CONST) {
while ((total_t = (long int)(end_t - start_t)) < time_const * TIME_MOD) {
refresh();
int c = getch();
switch (c) {
// toggle pause
case 'p':
case 'P':
play = !play;
break;
// lead pattern
case 'l':
case 'L':
load_pattern();
window_set_title(screen_w, name);
goto redraw;
break;
// quit
case 27:
case 'q':
case 'Q':
window_unsplit(menu_w);
return;
// change num of evolutions before display
case '+':
gen_step++;
break;
case '-':
gen_step--;
break;
// change refreshrate
case ']':
time_const += time_step;
break;
case '[':
time_const -= time_step;
break;
}
if (!play) {
// move cursor around
switch (c) {
case 'w':
case 'W':
cursor_offset_y--;
break;
case 's':
case 'S':
cursor_offset_y++;
break;
case 'a':
case 'A':
cursor_offset_x--;
break;
case 'd':
case 'D':
cursor_offset_x++;
break;
// toggle cell
case ' ':
mat[y_at(cursor_offset_y)][x_at(cursor_offset_x)] += 1;
mat[y_at(cursor_offset_y)][x_at(cursor_offset_x)] %= ncells;
break;
// visual selection
case 'v':
case 'V':
display_select(game_w, mat, h, h);
// clear up the screen afterwards
window_set_title(menu_w, NULL);
window_clear(menu_w);
window_clear(screen_w);
window_clear(status_w);
window_clear(game_w);
break;
}
}
// move screen around
switch (c) {
case KEY_A1:
case KEY_C1:
case KEY_END:
@@ -101,73 +188,47 @@ redraw:;
screen_offset_y++;
}
if (!play) {
switch (c) {
case 'w':
case 'W':
cursor_offset_y--;
break;
case 's':
case 'S':
cursor_offset_y++;
break;
case 'a':
case 'A':
cursor_offset_x--;
break;
case 'd':
case 'D':
cursor_offset_x++;
break;
case ' ':
mat[(cursor_offset_y + screen_offset_y + h) % h + 1]
[(cursor_offset_x + screen_offset_x + w) % w + 1] =
(mat[(cursor_offset_y + screen_offset_y + h) % h + 1]
[(cursor_offset_x + screen_offset_x + w) % w + 1] +
1) %
ncells;
break;
}
}
screen_offset_x = (screen_offset_x + w) % w;
screen_offset_y = (screen_offset_y + h) % h;
CLAMP(cursor_offset_y, 0, ph - 1);
CLAMP(cursor_offset_x, 0, pw - 1);
CLAMP(gen_step, 1, 10);
CLAMP(time_const, 1, 1000);
/* usleep(100000); */
if (is_term_resized(CLINES, CCOLS)) {
flushinp();
HANDLE_RESIZE;
goto redraw;
}
end_t = clock(); // clock stopped
end_t = clock();
}
flushinp();
}
}
struct imenu_T imenu_items[] = {
{"Unesi broj redova", 4, isdigit, NULL},
{"Unesi broj kolona", 4, isdigit, NULL},
};
int imenu_items_s = sizeof(imenu_items) / sizeof(struct imenu_T);
void settings(char *pass, int index) {
struct imenu_T imenu_items[] = {
{ "Number of rows", 4, isdigit, NULL},
{"Number of columns", 4, isdigit, NULL},
};
int imenu_items_s = sizeof(imenu_items) / sizeof(struct imenu_T);
void settings(window_T wind, char *pass, int index) {
while (TRUE) {
if (display_imenu(wind, imenu_items, imenu_items_s)) {
int row = atoi(imenu_items[0].buffer);
int column = atoi(imenu_items[1].buffer);
window_set_title(menu_w, "Game settings");
while (display_imenu(menu_w, imenu_items, imenu_items_s)) {
int row = atoi(imenu_items[0].buffer);
int column = atoi(imenu_items[1].buffer);
if (!row || !column)
continue;
if (!row || !column)
continue;
logic_init(column, row);
evolution_init(index);
logic_init(column, row);
evolution_init(index);
game(wind, row, column, evolution_cells[index]);
break;
} else {
break;
}
game(row, column, pass, evolution_cells[index]);
logic_free();
break;
}
for (int i = 0; i < imenu_items_s; i++) {
@@ -176,39 +237,83 @@ void settings(window_T wind, char *pass, int index) {
}
}
void mode_select(window_T wind, char *pass, int index) {
void mode_select(char *pass, int index) {
struct menu_T *mode_items = malloc(evolution_size * sizeof(struct menu_T));
for (int i = 0; i < evolution_size; i++) {
mode_items[i].name = evolution_names[i];
mode_items[i].callback = settings;
}
display_menu(wind, mode_items, evolution_size);
display_menu(menu_w, "Game Mode", mode_items, evolution_size);
free(mode_items);
}
void load(window_T wind, char *pass, int index) {
void new_file(char *pass, int index) {
struct imenu_T new_file_items[] = {
{"Pick a name", 10, isalnum, NULL},
};
int new_file_items_s = sizeof(new_file_items) / sizeof(struct imenu_T);
window_set_title(menu_w, "New File");
while (display_imenu(menu_w, new_file_items, new_file_items_s)) {
file_save_pattern(new_file_items[0].buffer, index);
break;
}
for (int i = 0; i < new_file_items_s; i++) {
free(new_file_items[i].buffer);
new_file_items[i].buffer = NULL;
}
}
struct menu_T *file_menu_list(char *ext, void (*callback)(char *, int),
int offset, int *size) {
char **buffer;
int n;
load_files();
n = file_select("all", &buffer);
n = file_select("part", &buffer);
struct menu_T *file_items = malloc(n * sizeof(struct menu_T));
struct menu_T *file_items = malloc((n + offset) * sizeof(struct menu_T));
for (int i = 0; i < n; i++) {
file_items[i].name = buffer[i];
file_items[i].callback = load_file;
file_items[i + offset].name = buffer[i];
file_items[i + offset].callback = callback;
}
free(buffer);
display_menu(wind, file_items, n);
mode_select(wind, "nothing", 0);
*size = n + offset;
return file_items;
}
void save_pattern(void) {
int n;
struct menu_T *file_items = file_menu_list("part", file_save_pattern, 1, &n);
file_items[0].name = "NEW";
file_items[0].callback = new_file;
display_menu(menu_w, "Save Pattern", file_items, n);
free(file_items);
free_files();
}
void exitp(window_T wind, char *pass, int index) {
void load_pattern(void) {
int n;
struct menu_T *file_items = file_menu_list("part", file_load_pattern, 0, &n);
display_menu(menu_w, "Load Pattern", file_items, n);
free(file_items);
}
void load(char *pass, int index) {
int n;
struct menu_T *file_items = file_menu_list("part", file_load, 0, &n);
display_menu(menu_w, "Load Game", file_items, n);
free(file_items);
mode_select("nothing", 0);
}
void exitp(char *pass, int index) {
display_stop();
exit(0);
}
@@ -226,24 +331,26 @@ int state = 0;
int main(void) {
setlocale(LC_ALL, "");
if (!display_start()) {
printf("Couldn't start the display!\n");
}
if (!file_setup()) {
printf("File setup error\n");
abort();
}
status_w = window_split(MAIN_w, 1, 3, 0);
screen_w = window_sibiling(status_w);
if (!display_start()) {
printf("Couldn't start the display!\n");
abort();
}
menu_w = MAIN_w;
while (TRUE) {
display_menu(screen_w, menu_items, menu_items_s);
window_clear(screen_w);
display_menu(menu_w, "Main menu", menu_items, menu_items_s);
}
window_free(MAIN_w);
if (!display_stop()) {
printf("Couldn't stop the display!\n");
abort();
}
return 0;
diff --git a/src/window.c b/src/window.c
@@ -21,17 +21,24 @@ struct T {
int param[4];
int mod[3];
char *title;
};
void WINDOW_init(WINDOW *win) {
void WINDOW_init(WINDOW *win, char *title) {
window_settings(win);
wattrset(win, COLOR_PAIR(0));
box(win, ACS_VLINE, ACS_HLINE);
if (title) {
mvwprintw(win, 0, 1, "%s", title);
}
wrefresh(win);
}
void WINDOW_new(T self) {
self->win = newwin(H(self), W(self), Y(self), X(self));
WINDOW_init(self->win);
WINDOW *WINDOW_new(T self) {
WINDOW *win = newwin(H(self), W(self), Y(self), X(self));
WINDOW_init(win, self->title);
return win;
}
T window_new(void) {
@@ -40,6 +47,7 @@ T window_new(void) {
self->c1 = NULL;
self->c2 = NULL;
self->sibiling = NULL;
self->title = NULL;
H(self) = 0;
W(self) = 0;
Y(self) = 0;
@@ -52,11 +60,11 @@ int window_height(T self) { return H(self) - 2; }
int window_wight(T self) { return W(self) - 2; }
WINDOW *window_win(T self) { return self->win; }
T window_init(T self) {
void window_set_title(T self, char *title) { self->title = title; }
T window_init(T self) {
self->win = stdscr;
box(self->win, ACS_VLINE, ACS_HLINE);
wrefresh(self->win);
WINDOW_init(stdscr, self->title);
H(self) = LINES;
W(self) = COLS;
return self;
@@ -71,6 +79,13 @@ void window_free(T self) {
free(self);
}
void window_unsplit(T self) {
window_free(self->c1);
window_free(self->c2);
self->c1 = NULL;
self->c2 = NULL;
}
void window_calc_children(T self) {
T c1, c2, f, nf;
c1 = self->c1;
@@ -129,7 +144,12 @@ void window_calc_children(T self) {
}
}
T window_split(T self, int hor, int a, int b) {
T window_split(T self, int hor, int a, int b, char *name1, char *name2) {
if (self->c1)
window_free(self->c1);
if (self->c2)
window_free(self->c2);
self->c1 = window_new();
self->c2 = window_new();
@@ -142,13 +162,16 @@ T window_split(T self, int hor, int a, int b) {
window_calc_children(self);
WINDOW_new(self->c1);
WINDOW_new(self->c2);
self->c1->title = name1;
self->c2->title = name2;
self->c1->win = WINDOW_new(self->c1);
self->c2->win = WINDOW_new(self->c2);
return self->c1;
}
T window_center(T self, int tmp, int h, int w) {
T window_center(T self, int tmp, int h, int w, char *name) {
self->c1 = window_new();
self->c2 = NULL;
@@ -157,7 +180,9 @@ T window_center(T self, int tmp, int h, int w) {
self->mod[2] = w;
window_calc_children(self);
WINDOW_new(self->c1);
self->c1->title = name;
self->c1->win = WINDOW_new(self->c1);
return self->c1;
}
@@ -169,19 +194,19 @@ void window_update_children(T self) {
window_calc_children(self);
delwin(self->c1->win);
WINDOW_new(self->c1);
self->c1->win = WINDOW_new(self->c1);
window_update_children(self->c1);
if (self->c2 != NULL) {
delwin(self->c2->win);
WINDOW_new(self->c2);
self->c2->win = WINDOW_new(self->c2);
window_update_children(self->c2);
}
}
void window_clear(T self) {
wclear(self->win);
WINDOW_init(self->win);
WINDOW_init(self->win, self->title);
}
void window_settings(WINDOW *win) { keypad(win, TRUE); }