diff --git a/README.md b/README.md index ef1be2e..f4fd4ff 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ system requirements to do ----- * terminal resizing -* proper region invalidation/redraw * good console emulation (to be implemented with libvterm) * saving/loading connection settings * nicer connection dialog diff --git a/ssheven-console.c b/ssheven-console.c index f507f7e..23f67b9 100644 --- a/ssheven-console.c +++ b/ssheven-console.c @@ -10,6 +10,26 @@ void draw_char(int x, int y, Rect* r, char c) { + MoveTo(r->left + x * con.cell_width + 2, r->top + ((y+1) * con.cell_height) - 2); + DrawChar(c); +} + +} + +void draw_screen(Rect* r) +{ + // get the intersection of our console region and the update region + Rect bounds = (con.win->portRect); + SectRect(r, &bounds, r); + + short minRow = (0 > (r->top - bounds.top) / con.cell_height) ? 0 : (r->top - bounds.top) / con.cell_height; + short maxRow = (24 < (r->bottom - bounds.top + con.cell_height - 1) / con.cell_height) ? 24 : (r->bottom - bounds.top + con.cell_height - 1) / con.cell_height; + + short minCol = (0 > (r->left - bounds.left) / con.cell_width) ? 0 : (r->left - bounds.left) / con.cell_width; + short maxCol = (80 < (r->right - bounds.left + con.cell_width - 1) / con.cell_width) ? 80 : (r->right - bounds.left + con.cell_width - 1) / con.cell_width; + + EraseRect(r); + // don't clobber font settings short save_font = qd.thePort->txFont; short save_font_size = qd.thePort->txSize; @@ -19,25 +39,17 @@ void draw_char(int x, int y, Rect* r, char c) TextSize(9); TextFace(normal); - int cell_height = 12; - int cell_width = CharWidth('M'); - - MoveTo(r->left + x * cell_width + 2, r->top + ((y+1) * cell_height) - 2); - DrawChar(c); + for(int i = minRow; i < maxRow; i++) + { + for (int j = minCol; j < maxCol; j++) + draw_char(j, i, r, con.data[j][i]); + } TextFont(save_font); TextSize(save_font_size); TextFace(save_font_face); } -void draw_screen(Rect* r) -{ - EraseRect(r); - for (int x = 0; x < 80; x++) - for (int y = 0; y < 24; y++) - draw_char(x, y, r, con.data[x][y]); -} - void ruler(Rect* r) { char itoc[] = {'0','1','2','3','4','5','6','7','8','9'}; @@ -58,6 +70,8 @@ void bump_up_line() } for (int x = 0; x < 80; x++) con.data[x][23] = ' '; + + InvalRect(&(con.win->portRect)); } int is_printable(char c) @@ -72,6 +86,8 @@ void print_char(char c) { // erase current location con.data[con.cursor_x][con.cursor_y] = ' '; + Rect inval = cell_rect(con.cursor_x, con.cursor_y, (con.win->portRect)); + InvalRect(&inval); // wrap back to the previous line if possible and necessary if (con.cursor_x == 0 && con.cursor_y != 0) @@ -100,6 +116,8 @@ void print_char(char c) if (is_printable(c)) { con.data[con.cursor_x][con.cursor_y] = c; + Rect inval = cell_rect(con.cursor_x, con.cursor_y, (con.win->portRect)); + InvalRect(&inval); con.cursor_x++; } @@ -138,13 +156,6 @@ void print_int(int d) print_string(buffer+i+1); } -void print_string_i(const char* c) -{ - print_string(c); - // TODO invalidate only the correct region - InvalRect(&(con.win->portRect)); -} - void print_string(const char* c) { while (*c != '\0') @@ -185,8 +196,6 @@ void printf_i(const char* str, ...) str++; } - InvalRect(&(con.win->portRect)); - va_end(args); } @@ -211,8 +220,8 @@ void console_setup(void) TextSize(9); TextFace(normal); - int cell_height = 12; - int cell_width = CharWidth('M'); + con.cell_height = 12; + con.cell_width = CharWidth('M'); TextFont(save_font); TextSize(save_font_size); @@ -222,8 +231,8 @@ void console_setup(void) InsetRect(&initial_window_bounds, 20, 20); initial_window_bounds.top += 40; - initial_window_bounds.bottom = initial_window_bounds.top + cell_height * 24 + 2; - initial_window_bounds.right = initial_window_bounds.left + cell_width * 80 + 4; + initial_window_bounds.bottom = initial_window_bounds.top + con.cell_height * 24 + 2; + initial_window_bounds.right = initial_window_bounds.left + con.cell_width * 80 + 4; // limits on window size changes: // top = min vertical @@ -248,6 +257,12 @@ void console_setup(void) con.cursor_x = 0; con.cursor_y = 0; - } +Rect cell_rect(int x, int y, Rect bounds) +{ + Rect r = { (short) (bounds.top + y * con.cell_height), (short) (bounds.left + x * con.cell_width + 2), + (short) (bounds.top + (y+1) * con.cell_height), (short) (bounds.left + (x+1) * con.cell_width + 2) }; + + return r; +} diff --git a/ssheven-console.h b/ssheven-console.h index 7246d6d..cfc8dcb 100644 --- a/ssheven-console.h +++ b/ssheven-console.h @@ -28,3 +28,5 @@ void printf_i(const char* c, ...); void set_window_title(WindowPtr w, const char* c_name); void ruler(Rect* r); + +Rect cell_rect(int x, int y, Rect bounds); diff --git a/ssheven.c b/ssheven.c index ad60377..aee715b 100644 --- a/ssheven.c +++ b/ssheven.c @@ -16,7 +16,7 @@ #define SSH_CHECK(X) rc = (X); if (rc != LIBSSH2_ERROR_NONE) { printf_i("" #X " failed: %s\n", libssh2_error_string(rc)); return 0;}; // sinful globals -struct ssheven_console con = { NULL, {0}, 0, 0 }; +struct ssheven_console con = { NULL, {0}, 0, 0, 0 , 0 }; struct ssheven_ssh_connection ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NULL, NULL }; enum { WAIT, READ, EXIT } read_thread_command = WAIT; @@ -69,9 +69,6 @@ void ssh_read(void) { printf_i("channel read error: %s\n", libssh2_error_string(rc)); } - - // TODO invalidate only the correct region - InvalRect(&(con.win->portRect)); } int end_connection(void) @@ -244,10 +241,6 @@ void event_loop(void) while (!WaitNextEvent(everyEvent, &event, sleep_time, NULL)) { // timed out without any GUI events - - // process any network events - //check_network_events(); - // let any other threads run before we wait for events again YieldToAnyThread(); } @@ -257,7 +250,6 @@ void event_loop(void) int r = 0; switch(event.what) { - // TODO: don't redraw the whole screen, just do needed region case updateEvt: eventWin = (WindowPtr)event.message; BeginUpdate(eventWin); diff --git a/ssheven.h b/ssheven.h index 87aca50..4aae0cd 100644 --- a/ssheven.h +++ b/ssheven.h @@ -36,6 +36,9 @@ struct ssheven_console int cursor_x; int cursor_y; + + int cell_height; + int cell_width; }; extern struct ssheven_console con;