diff --git a/.gitignore b/.gitignore index ae351b3..f15af53 100644 --- a/.gitignore +++ b/.gitignore @@ -76,8 +76,7 @@ menus/file.mnu menus/logoff.mnu menus/mail.mnu menus/main.mnu -.vscode/settings.json core -.vscode/launch.json docs/site utils/reset_pass/reset_pass +.vscode diff --git a/STRINGS.CHANGES b/STRINGS.CHANGES index e51abda..fff2b32 100644 --- a/STRINGS.CHANGES +++ b/STRINGS.CHANGES @@ -110,3 +110,27 @@ NEWSTRING: " \e[1;32mLocation : \e[1;37m%s\r\n" LINE 268 NEW OLDSTRING: (NONE) NEWSTRING: "\e[1;30m-------------------------------------------------------------------------------\e[0m\r\n" + +LINE 269 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[%d;1H\e[1;30;40m[\e[1;34m%3d\e[1;30;40m] \e[1;37m%-18.18s \e[1;33m%-16.16s \e[1;32m%-37.37s\e[K" + +LINE 270 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[%d;1H\e[1;30;40m[\e[1;34;44m%3d\e[1;30;40m] \e[1;37m%-18.18s \e[1;33m%-16.16s \e[1;32m%-37.37s\e[K" + +LINE 271 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[1;37;44mBBS Listing\e[K" + +LINE 272 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[24;1H\e[1;37;44mUp / Down to Select, A to Add, D to Delete, Q to Quit\e[K" + +LINE 273 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[8;28H\e[1;31;40mNo BBSes in the list!" + +LINE 274 NEW +OLDSTRING: (NONE) +NEWSTRING: "\e[10;22H\e[1;37mPress \e[1;33mA \e[1;37m to Add yours or \e[1;33mQ \e[1;37mto Quit\e[0m" diff --git a/dist/magicka.strings b/dist/magicka.strings index 8656f08..5b7b778 100644 --- a/dist/magicka.strings +++ b/dist/magicka.strings @@ -266,3 +266,9 @@ File exists!\r\n \e[1;32mSysop Name : \e[1;37m%s\r\n \e[1;32mLocation : \e[1;37m%s\r\n \e[1;30m-------------------------------------------------------------------------------\e[0m\r\n +\e[%d;1H\e[1;30;40m[\e[1;34m%3d\e[1;30;40m] \e[1;37m%-18.18s \e[1;33m%-16.16s \e[1;32m%-37.37s\e[K +\e[%d;1H\e[1;30;40m[\e[1;34;44m%3d\e[1;30;40m] \e[1;37m%-18.18s \e[1;33m%-16.16s \e[1;32m%-37.37s\e[K +\e[1;37;44mBBS Listing\e[K +\e[24;1H\e[1;37;44mUp / Down to Select, A to Add, D to Delete, Q to Quit\e[K +\e[8;28H\e[1;31;40mNo BBSes in the list! +\e[10;22H\e[1;37mPress \e[1;33mA \e[1;37m to Add yours or \e[1;33mQ \e[1;37mto Quit\e[0m diff --git a/src/bbs.h b/src/bbs.h index 179092c..457462f 100644 --- a/src/bbs.h +++ b/src/bbs.h @@ -308,7 +308,7 @@ extern int new_messages(struct user_record *user, int conference, int area); extern void rundoor(struct user_record *user, char *cmd, int stdio, char *codepage); extern void runexternal(struct user_record *user, char *cmd, int stdio, char **argv, char *cwd, int raw, char *codepage); -extern void bbs_list(struct user_record *user); +extern void bbs_list(); extern void chat_system(struct user_record *user); diff --git a/src/bbs_list.c b/src/bbs_list.c index 8aab3cc..ac5f260 100644 --- a/src/bbs_list.c +++ b/src/bbs_list.c @@ -6,9 +6,16 @@ #include "bbs.h" extern struct bbs_config conf; -extern int mynode; +extern struct user_record *gUser; +struct bbs_list_entry_t { + int id; + char *bbsname; + char *sysopname; + char *telnet; + int owner; +}; -void add_bbs(struct user_record *user) { +int add_bbs(struct bbs_list_entry_t *new_entry) { char *create_sql = "CREATE TABLE IF NOT EXISTS bbslist (" "id INTEGER PRIMARY KEY," "bbsname TEXT," @@ -21,12 +28,15 @@ void add_bbs(struct user_record *user) { char bbsname[19]; char sysop[17]; char telnet[39]; - char buffer[256]; + char buffer[PATH_MAX]; char c; char *err_msg = 0; sqlite3 *db; sqlite3_stmt *res; int rc; + int id; + + s_printf("\e[2J\e[1;1H"); s_printf(get_string(28)); s_readstring(bbsname, 18); @@ -47,15 +57,13 @@ void add_bbs(struct user_record *user) { c = s_getc(); if (tolower(c) == 'y') { - sprintf(buffer, "%s/bbslist.sq3", conf.bbs_path); + snprintf(buffer, PATH_MAX, "%s/bbslist.sq3", conf.bbs_path); rc = sqlite3_open(buffer, &db); if (rc != SQLITE_OK) { dolog("Cannot open database: %s", sqlite3_errmsg(db)); - sqlite3_close(db); - - exit(1); + return 0; } sqlite3_busy_timeout(db, 5000); rc = sqlite3_exec(db, create_sql, 0, 0, &err_msg); @@ -66,7 +74,7 @@ void add_bbs(struct user_record *user) { sqlite3_free(err_msg); sqlite3_close(db); - return; + return 0; } rc = sqlite3_prepare_v2(db, insert_sql, -1, &res, 0); @@ -75,11 +83,11 @@ void add_bbs(struct user_record *user) { sqlite3_bind_text(res, 1, bbsname, -1, 0); sqlite3_bind_text(res, 2, sysop, -1, 0); sqlite3_bind_text(res, 3, telnet, -1, 0); - sqlite3_bind_int(res, 4, user->id); - - + sqlite3_bind_int(res, 4, gUser->id); } else { dolog("Failed to execute statement: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + return 0; } @@ -88,47 +96,57 @@ void add_bbs(struct user_record *user) { if (rc != SQLITE_DONE) { dolog("execution failed: %s", sqlite3_errmsg(db)); + sqlite3_finalize(res); sqlite3_close(db); - exit(1); + return 0; } + id = sqlite3_last_insert_rowid(db); + sqlite3_finalize(res); sqlite3_close(db); s_printf(get_string(38)); + + if (new_entry != NULL) { + new_entry->id = id; + new_entry->bbsname = strdup(bbsname); + new_entry->sysopname = strdup(sysop); + new_entry->telnet = strdup(telnet); + new_entry->owner = gUser->id; + } + return 1; } else { s_printf(get_string(39)); + return 0; } } -void delete_bbs(struct user_record *user) { - char buffer[256]; +int delete_bbs(int id) { + char buffer[PATH_MAX]; sqlite3 *db; - sqlite3_stmt *res; - int rc; - char *sql = "SELECT bbsname FROM bbslist WHERE id=? and owner=?"; - char *dsql = "DELETE FROM bbslist WHERE id=?"; - int i; - char c; + sqlite3_stmt *res; + int rc; + char *sql = "SELECT bbsname FROM bbslist WHERE id=? and owner=?"; + char *dsql = "DELETE FROM bbslist WHERE id=?"; + char c; + + s_printf("\e[2J\e[1;1H"); - s_printf(get_string(40)); - s_readstring(buffer, 5); - i = atoi(buffer); + snprintf(buffer, PATH_MAX, "%s/bbslist.sq3", conf.bbs_path); - sprintf(buffer, "%s/bbslist.sq3", conf.bbs_path); - - rc = sqlite3_open(buffer, &db); + rc = sqlite3_open(buffer, &db); if (rc != SQLITE_OK) { - return; + return 0; } - sqlite3_busy_timeout(db, 5000); - rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); + sqlite3_busy_timeout(db, 5000); + rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); if (rc == SQLITE_OK) { - sqlite3_bind_int(res, 1, i); - sqlite3_bind_int(res, 2, user->id); + sqlite3_bind_int(res, 1, id); + sqlite3_bind_int(res, 2, gUser->id); } else { sqlite3_close(db); s_printf(get_string(41)); - return; + return 0; } if (sqlite3_step(res) == SQLITE_ROW) { s_printf(get_string(42), sqlite3_column_text(res, 0)); @@ -137,100 +155,238 @@ void delete_bbs(struct user_record *user) { if (tolower(c) == 'y') { rc = sqlite3_prepare_v2(db, dsql, -1, &res, 0); if (rc == SQLITE_OK) { - sqlite3_bind_int(res, 1, i); + sqlite3_bind_int(res, 1, id); } else { sqlite3_close(db); s_printf(get_string(41)); - return; + return 0; } sqlite3_step(res); s_printf(get_string(43)); sqlite3_finalize(res); + sqlite3_close(db); + return 1; } else { s_printf(get_string(39)); + sqlite3_close(db); + return 0; } } else { sqlite3_finalize(res); s_printf(get_string(44)); + sqlite3_close(db); + return 0; } - sqlite3_close(db); } -void list_bbses() { - char buffer[256]; - sqlite3 *db; - sqlite3_stmt *res; - int rc; - char *sql = "SELECT id,bbsname,sysop,telnet FROM bbslist"; - int i; - - sprintf(buffer, "%s/bbslist.sq3", conf.bbs_path); - - rc = sqlite3_open(buffer, &db); - - if (rc != SQLITE_OK) { - dolog("Cannot open database: %s", sqlite3_errmsg(db)); - sqlite3_close(db); - exit(1); - } - sqlite3_busy_timeout(db, 5000); - rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); - if (rc != SQLITE_OK) { - sqlite3_close(db); - s_printf(get_string(41)); - return; - } - i = 0; - s_printf(get_string(45)); - - while (sqlite3_step(res) == SQLITE_ROW) { - s_printf(get_string(46), sqlite3_column_int(res, 0), sqlite3_column_text(res, 1), sqlite3_column_text(res, 2), sqlite3_column_text(res, 3)); - i++; - if (i == 20) { - s_printf(get_string(6)); - s_getc(); - i = 0; - } - } - - s_printf(get_string(47)); - sqlite3_finalize(res); - sqlite3_close(db); - - s_printf(get_string(6)); - s_getc(); -} - -void bbs_list(struct user_record *user) { - int doquit = 0; +void bbs_list() { + int i; + int redraw = 1; + int start = 0; + int selected = 0; char c; + char buffer[PATH_MAX]; + sqlite3 *db; + sqlite3_stmt *res; + int rc; + char *sql = "SELECT id,bbsname,sysop,telnet FROM bbslist"; + struct bbs_list_entry_t **entries; + int entrycount; + struct bbs_list_entry_t *newentry; - while(!doquit) { - s_printf(get_string(48)); + while(1) { + entrycount = 0; + snprintf(buffer, PATH_MAX, "%s/bbslist.sq3", conf.bbs_path); - c = s_getc(); + rc = sqlite3_open(buffer, &db); - switch(tolower(c)) { - case 27: - { - c = s_getc(); - if (c == 91) { - c = s_getc(); - } - } - break; - case 'l': - list_bbses(); - break; - case 'a': - add_bbs(user); - break; - case 'd': - delete_bbs(user); - break; - case 'q': - doquit = 1; - break; - } - } -} + if (rc != SQLITE_OK) { + dolog("Cannot open database: %s", sqlite3_errmsg(db)); + return; + } + + sqlite3_busy_timeout(db, 5000); + rc = sqlite3_prepare_v2(db, sql, -1, &res, 0); + if (rc != SQLITE_OK) { + sqlite3_close(db); + + } else { + while (sqlite3_step(res) == SQLITE_ROW) { + if (entrycount == 0) { + entries = (struct bbs_list_entry_t **)malloc(sizeof(struct bbs_list_entry_t *)); + } else { + entries = (struct bbs_list_entry_t **)realloc(entries, sizeof(struct bbs_list_entry_t *) * (entrycount + 1)); + } + entries[entrycount] = (struct bbs_list_entry_t *)malloc(sizeof(struct bbs_list_entry_t)); + + entries[entrycount]->id = sqlite3_column_int(res, 0); + entries[entrycount]->bbsname = strdup(sqlite3_column_text(res, 1)); + entries[entrycount]->sysopname = strdup(sqlite3_column_text(res, 2)); + entries[entrycount]->telnet = strdup(sqlite3_column_text(res, 3)); + entrycount++; + } + sqlite3_finalize(res); + sqlite3_close(db); + } + + if (entrycount > 0) { + while (1) { + if (redraw) { + s_printf("\e[2J\e[1;1H"); + s_printf(get_string(270)); + s_printf(get_string(271)); + for (i=start;ibbsname, entries[i]->sysopname, entries[i]->telnet); + } else { + s_printf(get_string(268), i - start + 2, i, entries[i]->bbsname, entries[i]->sysopname, entries[i]->telnet); + } + } + s_printf("\e[%d;5H", selected - start + 2); + redraw = 0; + } + c = s_getchar(); + if (tolower(c) == 'q') { + for (i=0;ibbsname); + free(entries[i]->sysopname); + free(entries[i]->telnet); + free(entries[i]); + } + free(entries); + return; + } else if (tolower(c) == 'a') { + newentry = (struct bbs_list_entry_t *)malloc(sizeof(struct bbs_list_entry_t)); + if (add_bbs(newentry)) { + entries = (struct bbs_list_entry_t **)realloc(entries, sizeof(struct bbs_list_entry_t *) * (entrycount + 1)); + entries[entrycount] = newentry; + entrycount++; + redraw = 1; + } else { + free(newentry); + } + } else if (tolower(c) == 'd') { + if (delete_bbs(entries[selected]->id)) { + free(entries[selected]->bbsname); + free(entries[selected]->sysopname); + free(entries[selected]->telnet); + free(entries[selected]); + + for (i=selected;i= entrycount) { + selected = entrycount - 1; + } + } + redraw = 1; + } else if (c == 27) { + c = s_getchar(); + if (c == 91) { + c = s_getchar(); + if (c == 66) { + // down + if (selected + 1 >= start + 22) { + start += 22; + if (start >= entrycount) { + start = entrycount - 22; + } + redraw = 1; + } + selected++; + if (selected >= entrycount) { + selected = entrycount - 1; + } else { + if (!redraw) { + s_printf(get_string(268), selected - start + 1, selected - 1, entries[selected - 1]->bbsname, entries[selected - 1]->sysopname, entries[selected - 1]->telnet); + s_printf(get_string(269), selected - start + 2, selected, entries[selected]->bbsname, entries[selected]->sysopname, entries[selected]->telnet); + s_printf("\e[%d;4H", selected - start + 2); + } + } + } else if (c == 65) { + // up + if (selected - 1 < start) { + start -= 22; + if (start < 0) { + start = 0; + } + redraw = 1; + } + selected--; + if (selected < 0) { + selected = 0; + } else { + if (!redraw) { + s_printf(get_string(269), selected - start + 2, selected, entries[selected]->bbsname, entries[selected]->sysopname, entries[selected]->telnet); + s_printf(get_string(268), selected - start + 3, selected + 1, entries[selected + 1]->bbsname, entries[selected + 1]->sysopname, entries[selected + 1]->telnet); + s_printf("\e[%d;4H", selected - start + 2); + } + } + } else if (c == 75) { + // END KEY + selected = entrycount - 1; + start = entrycount - 22; + if (start < 0) { + start = 0; + } + redraw = 1; + } else if (c == 72) { + // HOME KEY + selected = 0; + start = 0; + redraw = 1; + } else if (c == 86 || c == '5') { + if (c == '5') { + s_getchar(); + } + // PAGE UP + selected = selected - 22; + if (selected < 0) { + selected = 0; + } + start = selected; + redraw = 1; + } else if (c == 85 || c == '6') { + if (c == '6') { + s_getchar(); + } + // PAGE DOWN + selected = selected + 22; + if (selected >= entrycount) { + selected = entrycount -1; + } + start = selected; + redraw = 1; + } + } + } + } + } else { + // no entries + s_printf("\e[2J\e[1;1H"); + s_printf(get_string(270)); + s_printf(get_string(271)); + s_printf(get_string(272)); + s_printf(get_string(273)); + + while(1) { + c = s_getchar(); + + if (tolower(c) == 'a') { + add_bbs(NULL); + break; + } else if (tolower(c) == 'q') { + return; + } + } + } + } +} \ No newline at end of file