commit ce626e50b6838a725f494777bf24ae0369fa5368 Author: Amber Date: Tue Jul 15 10:42:53 2025 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2066820 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bbs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3e5d900 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +CC=gcc +CFLAGS=-lncursesw +EXECUTABLE=bbs + +all: make + +make: + $(CC) $(CFLAGS) bbs.c -o $(EXECUTABLE) + +run: + ./$(EXECUTABLE) diff --git a/bbs.c b/bbs.c new file mode 100644 index 0000000..659a634 --- /dev/null +++ b/bbs.c @@ -0,0 +1,132 @@ +#include +#include + +int terminal_width; +int terminal_height; + +char errorMessage[60]; + +enum Status { + WAITING, + NEED_REFRESH +}; + +enum ActiveScreen { + HOME, + ERROR +}; + +struct Screen { + char name[20]; + WINDOW *win; + void (*draw_screen)(struct Screen *); +}; + +void draw_home(struct Screen *screen) { + char* banner = "" + " _ _ _ \n" + " | | | | | | \n" + " __ _ _ __ ___ | |__ ___ _ __ ___ _ __ | | __ _ ___ ___ _ __ ___| |_ \n" + " / _` | '_ ` _ \\| '_ \\ / _ \\ '__/ __| '_ \\| |/ _` |/ __/ _ \\ | '_ \\ / _ \\ __|\n" + " | (_| | | | | | | |_) | __/ | \\__ \\ |_) | | (_| | (_| __/_| | | | __/ |_ \n" + " \\__,_|_| |_| |_|_.__/ \\___|_| |___/ .__/|_|\\__,_|\\___\\___(_)_| |_|\\___|\\__|\n" + " | | \n" + " |_| \n"; + + mvwprintw(screen->win, 1, 2, "Thank you for visiting:"); + mvwprintw(screen->win, 2, 1, "%s", banner); +} + +void draw_error(struct Screen *screen) { + mvwprintw(screen->win, 1, 2, "%s", errorMessage); +} + +void draw_screen (struct Screen *screen) { + screen->draw_screen(screen); + box(screen->win, 0, 0); + + mvwprintw(screen->win, 0, 1, " %s ", screen->name); +}; + +int main() { + + initscr(); /* start ncurses */ + noecho(); /* hide keyboard input */ + curs_set(0); /* disable cursor */ + timeout(10); /* set timeout for getch() to 10ms */ + + int start_y = 0; + int start_x = 0; + int old_terminal_width = 0; + int old_terminal_height = 0; + + struct Screen screens[5]; + + enum Status status = NEED_REFRESH; /* refresh screens[active_screen].window on first loop */ + char input = ' '; + + strcpy(errorMessage, ""); + + getmaxyx(stdscr, terminal_height, terminal_width); + + int screen_before_error = HOME; + + enum ActiveScreen active_screen = HOME; + struct Screen home = { + "home", + newwin(terminal_height, terminal_width, start_y, start_x), + draw_home + }; + screens[HOME] = home; + struct Screen error = { + "error", + newwin(terminal_height, terminal_width, start_y, start_x), + draw_error + }; + screens[ERROR] = error; + + /* main event loop */ + while (input != 'q') { + if ((input = getch())) { /* if any input was read */ + status = NEED_REFRESH; + }; + getmaxyx(stdscr, terminal_height, terminal_width); + + /* resize active screen's window */ + if (old_terminal_width != terminal_width || old_terminal_height != terminal_height) { + wclear(screens[active_screen].win); + wresize(screens[active_screen].win, terminal_height, terminal_width); + mvwin(screens[active_screen].win, 0, 0); + wrefresh(screens[active_screen].win); + old_terminal_width = terminal_width; + old_terminal_height = terminal_height; + + if (terminal_width < 80 || terminal_height < 24) { + if (active_screen != ERROR) { + strcpy(errorMessage, "This program expects at least 80 rows by 24 columns."); + screen_before_error = active_screen; + }; + active_screen = ERROR; + } else if (active_screen != screen_before_error) { + active_screen = screen_before_error; + }; + status = NEED_REFRESH; + }; + + /* refresh active screen's window */ + if (status == NEED_REFRESH) { + draw_screen(&screens[active_screen]); + wrefresh(screens[active_screen].win); + status = WAITING; + } + + }; + + delwin(screens[active_screen].win); + nocbreak(); /* cbreak is the not needing to press enter on input, gets set in initscr, not undoing it causes + printing errors after exit as this is a setting of the terminal itself */ + endwin(); /* ends curses mode */ + curs_set(1); + echo(); + return 0; +}