diff --git a/advent.tlv b/advent.tlv index 2acb5dd..f3b9fa9 100644 --- a/advent.tlv +++ b/advent.tlv @@ -137,6 +137,7 @@ function init_colors() curses.init_pair(13, 7, 5) curses.init_pair(14, 7, 6) curses.init_pair(15, -1, 15) + curses.init_pair(255, 15, 1) -- reserved for Teliva error messages end]==], }, { diff --git a/chesstv.tlv b/chesstv.tlv index 9776653..e64b3e2 100644 --- a/chesstv.tlv +++ b/chesstv.tlv @@ -219,6 +219,7 @@ function init_colors() curses.init_pair(6, dark_piece, light_last_moved_square) curses.init_pair(7, light_piece, dark_last_moved_square) curses.init_pair(8, dark_piece, dark_last_moved_square) + curses.init_pair(255, 15, 1) -- reserved for Teliva error messages end]==], }, { diff --git a/counter.tlv b/counter.tlv index 31fed56..0c16d75 100644 --- a/counter.tlv +++ b/counter.tlv @@ -51,6 +51,7 @@ function main() for i=1,7 do curses.init_pair(i, 0, i) end + curses.init_pair(255, 15, 1) -- reserved for Teliva error messages while true do render(window) diff --git a/hanoi.tlv b/hanoi.tlv index 06537f6..f529831 100644 --- a/hanoi.tlv +++ b/hanoi.tlv @@ -88,6 +88,7 @@ function main() for i=1,7 do curses.init_pair(i, 0, i) end + curses.init_pair(255, 15, 1) -- reserved for Teliva error messages while true do render(window) diff --git a/life.tlv b/life.tlv index 08307e8..4c948c7 100644 --- a/life.tlv +++ b/life.tlv @@ -266,6 +266,7 @@ function main() for i=1,7 do curses.init_pair(i, i, -1) end + curses.init_pair(255, 15, 1) -- reserved for Teliva error messages -- initialize grid based on commandline args if (#arg == 0) then diff --git a/src/kilo.c b/src/kilo.c index 7349537..df7359a 100644 --- a/src/kilo.c +++ b/src/kilo.c @@ -95,15 +95,11 @@ struct editorConfig { erow *row; /* Rows */ int dirty; /* File modified but not saved. */ char *filename; /* Currently open filename */ - char statusmsg[80]; - time_t statusmsg_time; struct editorSyntax *syntax; /* Current syntax highlight, or NULL. */ }; static struct editorConfig E; -static void editorSetStatusMessage(const char *fmt, ...); - /* =========================== Syntax highlights DB ========================= * * In order to add a new syntax, define two arrays with a list of file name @@ -642,13 +638,16 @@ static int editorSaveToDisk(void) { close(fd); free(buf); E.dirty = 0; - memset(E.statusmsg, '\0', 80); return 0; writeerr: free(buf); if (fd != -1) close(fd); - editorSetStatusMessage("Can't save! I/O error: %s",strerror(errno)); + /* TODO: better error handling. */ + /* I haven't gotten to this yet since we have version control. */ + endwin(); + printf("Can't save! I/O error: %s",strerror(errno)); + exit(1); return 1; } @@ -720,6 +719,7 @@ static void editorGoMenu(void) { attrset(A_NORMAL); } +extern int render_previous_error(); static void editorRefreshScreen(void (*menu_func)(void)) { int y; erow *r; @@ -771,12 +771,9 @@ static void editorRefreshScreen(void (*menu_func)(void)) { } } - (*menu_func)(); + render_previous_error(); - attrset(A_REVERSE); - addstr(" "); - addstr(E.statusmsg); - attrset(A_NORMAL); + (*menu_func)(); /* Put cursor at its current position. Note that the horizontal position * at which the cursor is displayed may be different compared to 'E.cx' @@ -795,16 +792,6 @@ static void editorRefreshScreen(void (*menu_func)(void)) { curs_set(1); } -/* Set an editor status message for the second line of the status, at the - * end of the screen. */ -static void editorSetStatusMessage(const char *fmt, ...) { - va_list ap; - va_start(ap,fmt); - vsnprintf(E.statusmsg,sizeof(E.statusmsg),fmt,ap); - va_end(ap); - E.statusmsg_time = time(NULL); -} - /* =============================== Find mode ================================ */ #define KILO_QUERY_LEN 256 @@ -843,7 +830,6 @@ static void editorFind() { E.coloff = saved_coloff; E.rowoff = saved_rowoff; } FIND_RESTORE_HL; - editorSetStatusMessage(""); return; } else if (c == CTRL_U) { qlen = 0; @@ -1040,7 +1026,6 @@ static void editorGo(lua_State* L) { if (c == KEY_BACKSPACE || c == DELETE || c == CTRL_H) { if (qlen != 0) query[--qlen] = '\0'; } else if (c == CTRL_X || c == ENTER) { - editorSetStatusMessage(""); if (c == ENTER) { save_to_current_definition_and_editor_buffer(L, query); clearEditor(); @@ -1182,12 +1167,11 @@ static void initEditor(void) { } /* return true if user chose to back into the big picture view */ -int edit(lua_State* L, char* filename, const char* message) { +int edit(lua_State* L, char* filename) { Quit = 0; Back_to_big_picture = 0; initEditor(); editorOpen(filename); - editorSetStatusMessage(message); while(!Quit) { editorRefreshScreen(editorMenu); editorProcessKeypress(L); @@ -1196,7 +1180,7 @@ int edit(lua_State* L, char* filename, const char* message) { } /* return true if user chose to back into the big picture view */ -int edit_from(lua_State* L, char* filename, const char* message, int rowoff, int coloff, int cy, int cx) { +int edit_from(lua_State* L, char* filename, int rowoff, int coloff, int cy, int cx) { Quit = 0; Back_to_big_picture = 0; initEditor(); @@ -1205,7 +1189,6 @@ int edit_from(lua_State* L, char* filename, const char* message, int rowoff, int E.cy = cy; E.cx = cx; editorOpen(filename); - editorSetStatusMessage(message); while(!Quit) { editorRefreshScreen(editorMenu); editorProcessKeypress(L); @@ -1216,7 +1199,6 @@ int edit_from(lua_State* L, char* filename, const char* message, int rowoff, int int resumeEdit(lua_State* L) { Quit = 0; Back_to_big_picture = 0; - editorSetStatusMessage(Previous_error); while(!Quit) { editorRefreshScreen(editorMenu); editorProcessKeypress(L); diff --git a/src/lua.c b/src/lua.c index e73ac49..f00b4ae 100644 --- a/src/lua.c +++ b/src/lua.c @@ -81,21 +81,56 @@ static int report (lua_State *L, int status) { } -char *strdup(const char *s); -extern void developer_mode (lua_State *L, const char *status_message); +/* return final y containing text */ +static int render_wrapped_text (int y, int xmin, int xmax, const char *text) { + int x = xmin; + move(y, x); + for (int j = 0; j < strlen(text); ++j) { + char c = text[j]; + if (c != '\n') { + addch(text[j]); + ++x; + if (x >= xmax) { + ++y; + x = xmin; + move(y, x); + } + } + else { + /* newline */ + ++y; + x = xmin; + move(y, x); + } + } + return y; +} + + +const char *Previous_error = NULL; +void render_previous_error (void) { + if (!Previous_error) return; + attrset(COLOR_PAIR(255)); + render_wrapped_text(LINES-10, COLS/2, COLS, Previous_error); + attrset(A_NORMAL); +} + + +extern char *strdup(const char *s); +extern void developer_mode (lua_State *L); static int report_in_developer_mode (lua_State *L, int status) { if (status && !lua_isnil(L, -1)) { - const char *msg = strdup(lua_tostring(L, -1)); /* memory leak */ - if (msg == NULL) msg = "(error object is not a string)"; + Previous_error = strdup(lua_tostring(L, -1)); /* memory leak */ + if (Previous_error == NULL) Previous_error = "(error object is not a string)"; lua_pop(L, 1); for (int x = 0; x < COLS; ++x) { mvaddch(LINES-2, x, ' '); mvaddch(LINES-1, x, ' '); } - mvaddstr(LINES-2, 0, msg); + render_previous_error(); mvaddstr(LINES-1, 0, "press any key to continue"); getch(); - developer_mode(L, msg); + developer_mode(L); } return status; } @@ -413,11 +448,10 @@ int load_editor_buffer_to_current_definition_in_image(lua_State *L) { /* return true if user chose to back into the big picture view */ /* But only if there are no errors. Otherwise things can get confusing. */ -const char *Previous_error = NULL; -extern int edit (lua_State *L, char *filename, const char *message); +extern int edit (lua_State *L, char *filename); extern int resumeEdit (lua_State *L); int edit_current_definition (lua_State *L) { - int back_to_big_picture = edit(L, "teliva_editor_buffer", /*status message*/ ""); + int back_to_big_picture = edit(L, "teliva_editor_buffer"); // error handling while (1) { int status; @@ -482,7 +516,7 @@ static int render_wrapped_lua_text (int y, int xmin, int xmax, const char *text) else { /* newline */ ++y; - x = 0; + x = xmin; move(y, x); attroff(FG(6)); } @@ -625,7 +659,7 @@ void recent_changes_view (lua_State *L) { save_note_to_editor_buffer(L, cursor); /* big picture hotkey unnecessarily available here */ /* TODO: go hotkey is misleading. edits will not be persisted until you return to recent changes */ - edit(L, "teliva_editor_buffer", /*status message*/ ""); + edit(L, "teliva_editor_buffer"); load_note_from_editor_buffer(L, cursor); save_image(L); break; @@ -697,7 +731,7 @@ void draw_definition_name (const char *definition_name) { } /* return true if submitted */ -void big_picture_view (lua_State *L, const char *status_message) { +void big_picture_view (lua_State *L) { restart: clear(); luaL_newmetatable(L, "__teliva_call_graph_depth"); @@ -804,7 +838,7 @@ restart: } lua_settop(L, 0); - mvprintw(LINES-3, 0, status_message); + render_previous_error(); char query[CURRENT_DEFINITION_LEN+1] = {0}; int qlen = 0; @@ -858,8 +892,8 @@ int editor_view_in_progress (lua_State *L) { return result; } -extern int edit_from(lua_State *L, char *filename, const char *message, int rowoff, int coloff, int cy, int cx); -int restore_editor_view (lua_State *L, const char *status_message) { +extern int edit_from(lua_State *L, char *filename, int rowoff, int coloff, int cy, int cx); +int restore_editor_view (lua_State *L) { lua_getglobal(L, "__teliva_editor_state"); int editor_state_index = lua_gettop(L); lua_getfield(L, editor_state_index, "definition"); @@ -874,7 +908,7 @@ int restore_editor_view (lua_State *L, const char *status_message) { lua_getfield(L, editor_state_index, "cx"); int cx = lua_tointeger(L, -1); lua_settop(L, editor_state_index); - int back_to_big_picture = edit_from(L, "teliva_editor_buffer", status_message, rowoff, coloff, cy, cx); + int back_to_big_picture = edit_from(L, "teliva_editor_buffer", rowoff, coloff, cy, cx); // error handling while (1) { int status; @@ -892,18 +926,19 @@ int restore_editor_view (lua_State *L, const char *status_message) { char **Argv = NULL; extern void cleanup_curses (void); -void developer_mode (lua_State *L, const char *status_message) { +void developer_mode (lua_State *L) { /* clobber the app's ncurses colors; we'll restart the app when we rerun it. */ for (int i = 0; i < 8; ++i) init_pair(i, i, 15); for (int i = 0; i < 8; ++i) init_pair(i+8, 0, i); + init_pair(255, /*white fg*/ 15, /*red bg*/ 1); /* for teliva error messages */ nodelay(stdscr, 0); /* make getch() block */ int switch_to_big_picture_view = 1; if (editor_view_in_progress(L)) - switch_to_big_picture_view = restore_editor_view(L, status_message); + switch_to_big_picture_view = restore_editor_view(L); if (switch_to_big_picture_view) - big_picture_view(L, status_message); + big_picture_view(L); cleanup_curses(); execv(Argv[0], Argv); /* never returns */