diff options
-rw-r--r-- | 080display.cc | 74 | ||||
-rw-r--r-- | 081print.mu | 304 | ||||
-rw-r--r-- | 100trace_browser.cc | 10 | ||||
-rw-r--r-- | edit/001-editor.mu | 2 | ||||
-rw-r--r-- | edit/002-typing.mu | 5 | ||||
-rw-r--r-- | edit/004-programming-environment.mu | 8 | ||||
-rw-r--r-- | edit/005-sandbox.mu | 4 | ||||
-rw-r--r-- | edit/006-sandbox-copy.mu | 2 | ||||
-rw-r--r-- | edit/007-sandbox-delete.mu | 2 | ||||
-rw-r--r-- | edit/008-sandbox-edit.mu | 2 | ||||
-rw-r--r-- | edit/009-sandbox-test.mu | 2 | ||||
-rw-r--r-- | edit/010-sandbox-trace.mu | 2 | ||||
-rw-r--r-- | sandbox/001-editor.mu | 2 | ||||
-rw-r--r-- | sandbox/002-typing.mu | 5 | ||||
-rw-r--r-- | sandbox/004-programming-environment.mu | 8 | ||||
-rw-r--r-- | sandbox/005-sandbox.mu | 4 | ||||
-rw-r--r-- | sandbox/006-sandbox-copy.mu | 2 | ||||
-rw-r--r-- | sandbox/007-sandbox-delete.mu | 2 | ||||
-rw-r--r-- | sandbox/008-sandbox-edit.mu | 2 | ||||
-rw-r--r-- | sandbox/009-sandbox-test.mu | 2 | ||||
-rw-r--r-- | sandbox/010-sandbox-trace.mu | 2 | ||||
-rw-r--r-- | termbox/termbox.c | 187 | ||||
-rw-r--r-- | termbox/termbox.h | 27 | ||||
-rw-r--r-- | termbox/x.cc | 12 |
24 files changed, 277 insertions, 395 deletions
diff --git a/080display.cc b/080display.cc index 26b17926..b639c2a7 100644 --- a/080display.cc +++ b/080display.cc @@ -7,7 +7,6 @@ :(before "End Globals") int Display_row = 0; int Display_column = 0; -bool Autodisplay = true; :(before "End Includes") #define CHECK_SCREEN \ @@ -38,6 +37,7 @@ case OPEN_CONSOLE: { :(before "End Primitive Recipe Implementations") case OPEN_CONSOLE: { tb_init(); + std::setvbuf(stdout, NULL, _IONBF, 0); // disable buffering in cout Display_row = Display_column = 0; int width = tb_width(); int height = tb_height(); @@ -128,29 +128,24 @@ case PRINT_CHARACTER_TO_DISPLAY: { if (bg_color == 0) bg_color = TB_BLACK; } tb_change_cell(Display_column, Display_row, c, color, bg_color); - if (c == '\n' || c == '\r') { - if (Display_row < height-1) { - Display_column = 0; - ++Display_row; - tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); - } - break; + // track row and column, mimicking what happens on screen + if (c == '\n') { + if (Display_row < height-1) ++Display_row; // otherwise we scroll and Display_row remains unchanged } - if (c == '\b') { - if (Display_column > 0) { - tb_change_cell(Display_column-1, Display_row, ' ', color, bg_color); - --Display_column; - tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); - } - break; + else if (c == '\r') { + Display_column = 0; } - if (Display_column < width-1) { + else if (c == '\b') { + if (Display_column > 0) --Display_column; + } + else { ++Display_column; - tb_set_cursor(Display_column, Display_row); + if (Display_column >= width) { + Display_column = 0; + if (Display_row < height-1) ++Display_row; + } } - if (Autodisplay) tb_present(); + tb_set_cursor(Display_column, Display_row); break; } @@ -197,7 +192,6 @@ case MOVE_CURSOR_ON_DISPLAY: { Display_row = ingredients.at(0).at(0); Display_column = ingredients.at(1).at(0); tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); break; } @@ -217,7 +211,6 @@ case MOVE_CURSOR_DOWN_ON_DISPLAY: { if (Display_row < height-1) { ++Display_row; tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); } break; } @@ -236,7 +229,6 @@ case MOVE_CURSOR_UP_ON_DISPLAY: { if (Display_row > 0) { --Display_row; tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); } break; } @@ -257,7 +249,6 @@ case MOVE_CURSOR_RIGHT_ON_DISPLAY: { if (Display_column < width-1) { ++Display_column; tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); } break; } @@ -276,7 +267,6 @@ case MOVE_CURSOR_LEFT_ON_DISPLAY: { if (Display_column > 0) { --Display_column; tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); } break; } @@ -292,7 +282,6 @@ void move_cursor_to_start_of_next_line_on_display() { else Display_row = 0; Display_column = 0; tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); } :(before "End Primitive Recipe Declarations") @@ -327,37 +316,6 @@ case DISPLAY_HEIGHT: { break; } -:(before "End Primitive Recipe Declarations") -HIDE_DISPLAY, -:(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "hide-display", HIDE_DISPLAY); -:(before "End Primitive Recipe Checks") -case HIDE_DISPLAY: { - break; -} -:(before "End Primitive Recipe Implementations") -case HIDE_DISPLAY: { - CHECK_SCREEN; - Autodisplay = false; - break; -} - -:(before "End Primitive Recipe Declarations") -SHOW_DISPLAY, -:(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "show-display", SHOW_DISPLAY); -:(before "End Primitive Recipe Checks") -case SHOW_DISPLAY: { - break; -} -:(before "End Primitive Recipe Implementations") -case SHOW_DISPLAY: { - CHECK_SCREEN; - Autodisplay = true; - tb_present(); - break; -} - //:: Keyboard/mouse management :(before "End Primitive Recipe Declarations") @@ -481,7 +439,6 @@ case CLEAR_LINE_ON_DISPLAY: { tb_change_cell(x, Display_row, ' ', TB_WHITE, TB_BLACK); } tb_set_cursor(Display_column, Display_row); - if (Autodisplay) tb_present(); break; } @@ -507,6 +464,5 @@ case CLEAR_DISPLAY_FROM: { tb_change_cell(column, row, ' ', TB_WHITE, TB_BLACK); } } - if (Autodisplay) tb_present(); break; } diff --git a/081print.mu b/081print.mu index b778948e..2c2e09ae 100644 --- a/081print.mu +++ b/081print.mu @@ -6,7 +6,9 @@ container screen [ num-columns:num cursor-row:num cursor-column:num - data:&:@:screen-cell + data:&:@:screen-cell # capacity num-rows*num-columns + top-idx:num # index inside data that corresponds to top-left of screen + # modified on scroll, wrapping around to the top of data ] container screen-cell [ @@ -18,9 +20,13 @@ def new-fake-screen w:num, h:num -> result:&:screen [ local-scope load-ingredients result <- new screen:type + non-zero-width?:bool <- greater-than w, 0 + assert non-zero-width?, [screen can't have zero width] + non-zero-height?:bool <- greater-than h, 0 + assert non-zero-height?, [screen can't have zero height] bufsize:num <- multiply w, h data:&:@:screen-cell <- new screen-cell:type, bufsize - *result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data + *result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data, 0/top-idx result <- clear-screen result ] @@ -48,6 +54,7 @@ def clear-screen screen:&:screen -> screen:&:screen [ # reset cursor *screen <- put *screen, cursor-row:offset, 0 *screen <- put *screen, cursor-column:offset, 0 + *screen <- put *screen, top-idx:offset, 0 ] def fake-screen-is-empty? screen:&:screen -> result:bool [ @@ -97,71 +104,152 @@ def print screen:&:screen, c:char -> screen:&:screen [ # (handle special cases exactly like in the real screen) width:num <- get *screen, num-columns:offset height:num <- get *screen, num-rows:offset - # if cursor is out of bounds, silently exit + capacity:num <- multiply width, height row:num <- get *screen, cursor-row:offset - row <- round row - legal?:bool <- greater-or-equal row, 0 - return-unless legal? - legal? <- lesser-than row, height - return-unless legal? column:num <- get *screen, cursor-column:offset + buf:&:@:screen-cell <- get *screen, data:offset + # some potentially slow sanity checks for preconditions { + # eliminate fractions from column and row + row <- round row column <- round column - legal? <- greater-or-equal column, 0 - return-unless legal? - legal? <- lesser-than column, width - return-unless legal? + # if cursor is past left margin (error), reset to left margin + { + too-far-left?:bool <- lesser-than column, 0 + break-unless too-far-left? + column <- copy 0 + *screen <- put *screen, cursor-column:offset, column + } + # if cursor is at right margin, wrap + { + at-right?:bool <- equal column, width + break-unless at-right? + column <- copy 0 + *screen <- put *screen, cursor-column:offset, column + row <- add row, 1 + *screen <- put *screen, cursor-row:offset, row + } + # if cursor is past right margin (error), reset to right margin + { + too-far-right?:bool <- greater-than column, width + break-unless too-far-right? + column <- subtract width, 1 + *screen <- put *screen, cursor-row:offset, row + } + # if row is above top margin (error), reset to top margin + { + too-far-up?:bool <- lesser-than row, 0 + break-unless too-far-up? + row <- copy 0 + *screen <- put *screen, cursor-row:offset, row + } + # if row is at bottom margin, scroll + { + at-bottom?:bool <- equal row, height + break-unless at-bottom? + scroll-fake-screen screen + row <- subtract height, 1 + *screen <- put *screen, cursor-row:offset, row + } + # if row is below bottom margin (error), reset to bottom margin + { + too-far-down?:bool <- greater-than row, height + break-unless too-far-down? + row <- subtract height, 1 + *screen <- put *screen, cursor-row:offset, row + } + # } #? $print [print-character (], row, [, ], column, [): ], c, 10/newline # special-case: newline { newline?:bool <- equal c, 10/newline break-unless newline? - { - # unless cursor is already at bottom - bottom:num <- subtract height, 1 - at-bottom?:bool <- greater-or-equal row, bottom - break-if at-bottom? - # move it to the next row - column <- copy 0 - *screen <- put *screen, cursor-column:offset, column - row <- add row, 1 - *screen <- put *screen, cursor-row:offset, row - } + cursor-down-on-fake-screen screen # doesn't modify column + return + } + # special-case: linefeed + { + linefeed?:bool <- equal c, 13/linefeed + break-unless linefeed? + *screen <- put *screen, cursor-column:offset, 0 return } - # save character in fake screen - index:num <- multiply row, width - index <- add index, column - buf:&:@:screen-cell <- get *screen, data:offset - len:num <- length *buf # special-case: backspace + # moves cursor left but does not erase { - backspace?:bool <- equal c, 8 + backspace?:bool <- equal c, 8/backspace break-unless backspace? { - # unless cursor is already at left margin - at-left?:bool <- lesser-or-equal column, 0 - break-if at-left? - # clear previous location + break-unless column column <- subtract column, 1 *screen <- put *screen, cursor-column:offset, column - index <- subtract index, 1 - cursor:screen-cell <- merge 32/space, 7/white - *buf <- put-index *buf, index, cursor } return } + # save character in fake screen + top-idx:num <- get *screen, top-idx:offset + index:num <- data-index row, column, width, height, top-idx cursor:screen-cell <- merge c, color *buf <- put-index *buf, index, cursor - # increment column unless it's already all the way to the right + # move cursor to next character + # (but don't bother making it valid; we'll do that before the next print) + column <- add column, 1 + *screen <- put *screen, cursor-column:offset, column +] + +def cursor-down-on-fake-screen screen:&:screen -> screen:&:screen [ + local-scope + load-ingredients + row:num <- get *screen, cursor-row:offset + height:num <- get *screen, num-rows:offset + bottom:num <- subtract height, 1 + at-bottom?:bool <- greater-or-equal row, bottom { - right:num <- subtract width, 1 - at-right?:bool <- greater-or-equal column, right - break-if at-right? - column <- add column, 1 - *screen <- put *screen, cursor-column:offset, column + break-if at-bottom? + row <- add row, 1 + *screen <- put *screen, cursor-row:offset, row + } + { + break-unless at-bottom? + scroll-fake-screen screen # does not modify row } ] +def scroll-fake-screen screen:&:screen -> screen:&:screen [ + local-scope + load-ingredients + width:num <- get *screen, num-columns:offset + height:num <- get *screen, num-rows:offset + buf:&:@:screen-cell <- get *screen, data:offset + # clear top line and 'rotate' it to the bottom + top-idx:num <- get *screen, top-idx:offset # 0 <= top-idx < len(buf) + next-top-idx:num <- add top-idx, width # 0 <= next-top-idx <= len(buf) + empty-cell:screen-cell <- merge 0, 0 + { + done?:bool <- greater-or-equal top-idx, next-top-idx + break-if done? + put-index *buf, top-idx, empty-cell + top-idx <- add top-idx, 1 + # no modulo; top-idx is always a multiple of width, + # so it can never wrap around inside this loop + loop + } + # top-idx now same as next-top-idx; wrap around if necessary + capacity:num <- multiply width, height + _, top-idx <- divide-with-remainder, top-idx, capacity + *screen <- put *screen, top-idx:offset, top-idx +] + +# translate from screen (row, column) coordinates to an index into data +# while accounting for scrolling (sliding top-idx) +def data-index row:num, column:num, width:num, height:num, top-idx:num -> result:num [ + local-scope + load-ingredients + result <- multiply width, row + result <- add result, column, top-idx + capacity:num <- multiply width, height + _, result <- divide-with-remainder result, capacity +] + scenario print-character-at-top-left [ local-scope fake-screen:&:screen <- new-fake-screen 3/width, 2/height @@ -232,7 +320,7 @@ scenario print-backspace-character [ memory-should-contain [ 10 <- 0 # cursor column 11 <- 6 # width*height - 12 <- 32 # space, not 'a' + 12 <- 97 # still 'a' 13 <- 7 # white # rest of screen is empty 14 <- 0 @@ -255,7 +343,7 @@ scenario print-extra-backspace-character [ memory-should-contain [ 1 <- 0 # cursor column 3 <- 6 # width*height - 4 <- 32 # space, not 'a' + 4 <- 97 # still 'a' 5 <- 7 # white # rest of screen is empty 6 <- 0 @@ -271,22 +359,26 @@ scenario print-character-at-right-margin [ b:char <- copy 98/b fake-screen <- print fake-screen, b run [ - # cursor now at right margin + # cursor now at next row c:char <- copy 99/c fake-screen <- print fake-screen, c - 10:num/raw <- get *fake-screen, cursor-column:offset + 10:num/raw <- get *fake-screen, cursor-row:offset + 11:num/raw <- get *fake-screen, cursor-column:offset cell:&:@:screen-cell <- get *fake-screen, data:offset - 11:@:screen-cell/raw <- copy *cell + 12:@:screen-cell/raw <- copy *cell ] memory-should-contain [ - 10 <- 1 # cursor column - 11 <- 4 # width*height - 12 <- 97 # 'a' - 13 <- 7 # white - 14 <- 99 # 'c' over 'b' - 15 <- 7 # white - # rest of screen is empty - 16 <- 0 + 10 <- 1 # cursor row + 11 <- 1 # cursor column + 12 <- 4 # width*height + 13 <- 97 # 'a' + 14 <- 7 # white + 15 <- 98 # 'b' + 16 <- 7 # white + 17 <- 99 # 'c' + 18 <- 7 # white + 19 <- 0 # ' ' + 20 <- 7 # white ] ] @@ -305,7 +397,7 @@ scenario print-newline-character [ ] memory-should-contain [ 10 <- 1 # cursor row - 11 <- 0 # cursor column + 11 <- 1 # cursor column 12 <- 6 # width*height 13 <- 97 # 'a' 14 <- 7 # white @@ -336,39 +428,81 @@ scenario print-newline-at-bottom-line [ scenario print-character-at-bottom-right [ local-scope fake-screen:&:screen <- new-fake-screen 2/width, 2/height - newline:char <- copy 10/newline - fake-screen <- print fake-screen, newline a:char <- copy 97/a fake-screen <- print fake-screen, a b:char <- copy 98/b fake-screen <- print fake-screen, b c:char <- copy 99/c fake-screen <- print fake-screen, c - fake-screen <- print fake-screen, newline run [ # cursor now at bottom right d:char <- copy 100/d fake-screen <- print fake-screen, d 10:num/raw <- get *fake-screen, cursor-row:offset 11:num/raw <- get *fake-screen, cursor-column:offset + 12:num/raw <- get *fake-screen, top-idx:offset cell:&:@:screen-cell <- get *fake-screen, data:offset 20:@:screen-cell/raw <- copy *cell ] + # cursor column overflows the screen but is not wrapped yet memory-should-contain [ 10 <- 1 # cursor row - 11 <- 1 # cursor column - 20 <- 4 # width*height - 21 <- 0 # unused + 11 <- 2 # cursor column -- outside screen + 12 <- 0 # top-idx -- not yet scrolled + 20 <- 4 # screen size (width*height) + 21 <- 97 # 'a' 22 <- 7 # white - 23 <- 0 # unused + 23 <- 98 # 'b' 24 <- 7 # white - 25 <- 97 # 'a' + 25 <- 99 # 'c' 26 <- 7 # white - 27 <- 100 # 'd' over 'b' and 'c' and newline + 27 <- 100 # 'd' 28 <- 7 # white - # rest of screen is empty - 29 <- 0 ] + run [ + e:char <- copy 101/e + print fake-screen, e + 10:num/raw <- get *fake-screen, cursor-row:offset + 11:num/raw <- get *fake-screen, cursor-column:offset + 12:num/raw <- get *fake-screen, top-idx:offset + cell:&:@:screen-cell <- get *fake-screen, data:offset + 20:@:screen-cell/raw <- copy *cell + ] + memory-should-contain [ + # text scrolls by 1, we lose the top line + 10 <- 1 # cursor row + 11 <- 1 # cursor column -- wrapped + 12 <- 2 # top-idx -- scrolled + 20 <- 4 # screen size (width*height) + # screen now checked in rotated order + 25 <- 99 # 'c' + 26 <- 7 # white + 27 <- 100 # 'd' + 28 <- 7 # white + # screen wraps; bottom line is cleared of old contents + 21 <- 101 # 'e' + 22 <- 7 # white + 23 <- 0 # unused + 24 <- 0 # no color + ] +] + +# even though our screen supports scrolling, some apps may want to avoid +# scrolling +# these helpers help check for scrolling at development time +def save-top-idx screen:&:screen -> result:num [ + local-scope + load-ingredients + return-unless screen, 0 # check is only for fake screens + result <- get *screen, top-idx:offset +] +def assert-no-scroll screen:&:screen, old-top-idx:num [ + local-scope + load-ingredients + return-unless screen + new-top-idx:num <- get *screen, top-idx:offset + no-scroll?:bool <- equal old-top-idx, new-top-idx + assert no-scroll?, [render should never use screen's scrolling capabilities] ] def clear-line screen:&:screen -> screen:&:screen [ @@ -398,10 +532,14 @@ def clear-line screen:&:screen -> screen:&:screen [ *screen <- put *screen, cursor-column:offset, original-column ] +# only for non-scrolling apps def clear-line-until screen:&:screen, right:num/inclusive -> screen:&:screen [ local-scope load-ingredients - _, column:num <- cursor-position screen + row:num, column:num <- cursor-position screen + height:num <- screen-height screen + past-bottom?:bool <- greater-or-equal row, height + return-if past-bottom? space:char <- copy 32/space bg-color:num, bg-color-found?:bool <- next-ingredient { @@ -597,22 +735,6 @@ def screen-height screen:&:screen -> height:num [ height <- display-height ] -def hide-screen screen:&:screen -> screen:&:screen [ - local-scope - load-ingredients - return-if screen # fake screen; do nothing - # real screen - hide-display -] - -def show-screen screen:&:screen -> screen:&:screen [ - local-scope - load-ingredients - return-if screen # fake screen; do nothing - # real screen - show-display -] - def print screen:&:screen, s:text -> screen:&:screen [ local-scope load-ingredients @@ -640,24 +762,32 @@ def print screen:&:screen, s:text -> screen:&:screen [ } ] -scenario print-text-stops-at-right-margin [ +scenario print-text-wraps-past-right-margin [ local-scope fake-screen:&:screen <- new-fake-screen 3/width, 2/height run [ fake-screen <- print fake-screen, [abcd] + 5:num/raw <- get *fake-screen, cursor-row:offset + 6:num/raw <- get *fake-screen, cursor-column:offset + 7:num/raw <- get *fake-screen, top-idx:offset cell:&:@:screen-cell <- get *fake-screen, data:offset 10:@:screen-cell/raw <- copy *cell ] memory-should-contain [ + 5 <- 1 # cursor-row + 6 <- 1 # cursor-column + 7 <- 0 # top-idx 10 <- 6 # width*height 11 <- 97 # 'a' 12 <- 7 # white 13 <- 98 # 'b' 14 <- 7 # white - 15 <- 100 # 'd' overwrites 'c' + 15 <- 99 # 'c' 16 <- 7 # white + 17 <- 100 # 'd' + 18 <- 7 # white # rest of screen is empty - 17 <- 0 + 19 <- 0 ] ] diff --git a/100trace_browser.cc b/100trace_browser.cc index 42a4d848..ffa66b41 100644 --- a/100trace_browser.cc +++ b/100trace_browser.cc @@ -276,7 +276,6 @@ bool start_search_editor(search_direction dir) { tb_change_cell(col, bottom_screen_line, '/', TB_WHITE, TB_BLACK); ++col; tb_set_cursor(col, bottom_screen_line); - tb_present(); string pattern; while (true) { int key = read_key(); @@ -294,25 +293,21 @@ bool start_search_editor(search_direction dir) { if (col > /*slash*/1) { --col; tb_set_cursor(col, bottom_screen_line); - tb_present(); } } else if (key == TB_KEY_ARROW_RIGHT) { if (col-/*slash*/1 < SIZE(pattern)) { ++col; tb_set_cursor(col, bottom_screen_line); - tb_present(); } } else if (key == TB_KEY_HOME || key == TB_KEY_CTRL_A) { col = /*skip slash*/1; tb_set_cursor(col, bottom_screen_line); - tb_present(); } else if (key == TB_KEY_END || key == TB_KEY_CTRL_E) { col = SIZE(pattern)+/*skip slash*/1; tb_set_cursor(col, bottom_screen_line); - tb_present(); } else if (key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2) { if (col > /*slash*/1) { @@ -330,7 +325,6 @@ bool start_search_editor(search_direction dir) { tb_change_cell(SIZE(pattern)+/*skip slash*/1, bottom_screen_line, ' ', TB_WHITE, TB_BLACK); } tb_set_cursor(col, bottom_screen_line); - tb_present(); } } else if (key == TB_KEY_CTRL_K) { @@ -339,7 +333,6 @@ bool start_search_editor(search_direction dir) { for (int x = col; x < old_pattern_size+/*slash*/1; ++x) tb_change_cell(x, bottom_screen_line, ' ', TB_WHITE, TB_BLACK); tb_set_cursor(col, bottom_screen_line); - tb_present(); } else if (key == TB_KEY_CTRL_U) { int old_pattern_size = SIZE(pattern); @@ -349,7 +342,6 @@ bool start_search_editor(search_direction dir) { for (int x = SIZE(pattern)+/*slash*/1; x < old_pattern_size+/*skip slash*/1; ++x) tb_change_cell(x, bottom_screen_line, ' ', TB_WHITE, TB_BLACK); tb_set_cursor(/*start of pattern skipping slash*/1, bottom_screen_line); - tb_present(); } else if (key < 128) { // ascii only // update pattern @@ -360,7 +352,6 @@ bool start_search_editor(search_direction dir) { tb_change_cell(x, bottom_screen_line, pattern.at(x-/*slash*/1), TB_WHITE, TB_BLACK); ++col; tb_set_cursor(col, bottom_screen_line); - tb_present(); } } } @@ -444,7 +435,6 @@ void render() { render_line(screen_row, "~", /*cursor_line?*/false); // move cursor back to display row at the end tb_set_cursor(0, Display_row); - tb_present(); } int lines_hidden(int screen_row) { diff --git a/edit/001-editor.mu b/edit/001-editor.mu index d81278ae..a6dde85b 100644 --- a/edit/001-editor.mu +++ b/edit/001-editor.mu @@ -6,10 +6,8 @@ def main text:text [ local-scope load-ingredients open-console - hide-screen 0/screen e:&:editor <- new-editor text, 0/left, 5/right render 0/screen, e - show-screen 0/screen wait-for-event 0/console close-console ] diff --git a/edit/002-typing.mu b/edit/002-typing.mu index 8c48f147..16693429 100644 --- a/edit/002-typing.mu +++ b/edit/002-typing.mu @@ -264,6 +264,7 @@ def insert-at-cursor editor:&:editor, c:char, screen:&:screen -> go-render?:bool def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&:editor [ local-scope load-ingredients + old-top-idx:num <- save-top-idx screen left:num <- get *editor, left:offset right:num <- get *editor, right:offset row:num, column:num <- render screen, editor @@ -272,6 +273,7 @@ def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&: draw-horizontal screen, row, left, right, 9480/horizontal-dotted row <- add row, 1 clear-screen-from screen, row, left, left, right + assert-no-scroll screen, old-top-idx ] scenario editor-handles-empty-event-queue [ @@ -1057,6 +1059,9 @@ after <handle-special-key> [ def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:screen [ local-scope load-ingredients + height:num <- screen-height screen + past-bottom?:bool <- greater-or-equal row, height + return-if past-bottom? style:char, style-found?:bool <- next-ingredient { break-if style-found? diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu index 0d4e907d..606cdfa2 100644 --- a/edit/004-programming-environment.mu +++ b/edit/004-programming-environment.mu @@ -96,7 +96,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources: } # if it's not global and not a touch event, send to appropriate editor { - hide-screen screen sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset { break-if sandbox-in-focus? @@ -117,7 +116,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources: screen <- render-all screen, env, render } screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen } loop } @@ -396,7 +394,7 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr local-scope load-ingredients trace 10, [app], [render all] - hide-screen screen + old-top-idx:num <- save-top-idx screen # top menu trace 11, [app], [render top menu] width:num <- screen-width screen @@ -414,14 +412,14 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr # screen <- render-recipes screen, env, render-editor screen <- render-sandbox-side screen, env, render-editor - <render-components-end> + <render-components-end> # no early returns permitted # recipes:&:editor <- get *env, recipes:offset current-sandbox:&:editor <- get *env, current-sandbox:offset sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env # - show-screen screen + assert-no-scroll screen, old-top-idx ] def render-recipes screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [ diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu index 5f08554d..2e16e05b 100644 --- a/edit/005-sandbox.mu +++ b/edit/005-sandbox.mu @@ -971,10 +971,8 @@ after <global-keypress> [ render-from <- add render-from, 1 *env <- put *env, render-from:offset, render-from } - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] @@ -1003,10 +1001,8 @@ after <global-keypress> [ break-if at-beginning? render-from <- subtract render-from, 1 *env <- put *env, render-from:offset, render-from - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] diff --git a/edit/006-sandbox-copy.mu b/edit/006-sandbox-copy.mu index 9df5e625..d3f82e88 100644 --- a/edit/006-sandbox-copy.mu +++ b/edit/006-sandbox-copy.mu @@ -128,10 +128,8 @@ after <global-touch> [ break-unless copy? copy?, env <- try-copy-sandbox click-row, env break-unless copy? - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] diff --git a/edit/007-sandbox-delete.mu b/edit/007-sandbox-delete.mu index 4fa3c37d..5167b038 100644 --- a/edit/007-sandbox-delete.mu +++ b/edit/007-sandbox-delete.mu @@ -72,10 +72,8 @@ after <global-touch> [ break-unless delete? delete?, env <- try-delete-sandbox click-row, env break-unless delete? - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] diff --git a/edit/008-sandbox-edit.mu b/edit/008-sandbox-edit.mu index dd5c1bb9..2d591ad6 100644 --- a/edit/008-sandbox-edit.mu +++ b/edit/008-sandbox-edit.mu @@ -111,10 +111,8 @@ after <global-touch> [ break-unless edit? edit?, env <- try-edit-sandbox click-row, env break-unless edit? - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] diff --git a/edit/009-sandbox-test.mu b/edit/009-sandbox-test.mu index 023015ed..badd795b 100644 --- a/edit/009-sandbox-test.mu +++ b/edit/009-sandbox-test.mu @@ -130,10 +130,8 @@ after <global-touch> [ # toggle its expected-response, and save session sandbox <- toggle-expected-response sandbox save-sandboxes env, resources - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] diff --git a/edit/010-sandbox-trace.mu b/edit/010-sandbox-trace.mu index 66a321d6..8088577a 100644 --- a/edit/010-sandbox-trace.mu +++ b/edit/010-sandbox-trace.mu @@ -200,10 +200,8 @@ after <global-touch> [ x:bool <- get *sandbox, display-trace?:offset x <- not x *sandbox <- put *sandbox, display-trace?:offset, x - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - show-screen screen loop +next-event } ] diff --git a/sandbox/001-editor.mu b/sandbox/001-editor.mu index d81278ae..a6dde85b 100644 --- a/sandbox/001-editor.mu +++ b/sandbox/001-editor.mu @@ -6,10 +6,8 @@ def main text:text [ local-scope load-ingredients open-console - hide-screen 0/screen e:&:editor <- new-editor text, 0/left, 5/right render 0/screen, e - show-screen 0/screen wait-for-event 0/console close-console ] diff --git a/sandbox/002-typing.mu b/sandbox/002-typing.mu index 8c48f147..16693429 100644 --- a/sandbox/002-typing.mu +++ b/sandbox/002-typing.mu @@ -264,6 +264,7 @@ def insert-at-cursor editor:&:editor, c:char, screen:&:screen -> go-render?:bool def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&:editor [ local-scope load-ingredients + old-top-idx:num <- save-top-idx screen left:num <- get *editor, left:offset right:num <- get *editor, right:offset row:num, column:num <- render screen, editor @@ -272,6 +273,7 @@ def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&: draw-horizontal screen, row, left, right, 9480/horizontal-dotted row <- add row, 1 clear-screen-from screen, row, left, left, right + assert-no-scroll screen, old-top-idx ] scenario editor-handles-empty-event-queue [ @@ -1057,6 +1059,9 @@ after <handle-special-key> [ def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:screen [ local-scope load-ingredients + height:num <- screen-height screen + past-bottom?:bool <- greater-or-equal row, height + return-if past-bottom? style:char, style-found?:bool <- next-ingredient { break-if style-found? diff --git a/sandbox/004-programming-environment.mu b/sandbox/004-programming-environment.mu index 0f1280e3..53f9f846 100644 --- a/sandbox/004-programming-environment.mu +++ b/sandbox/004-programming-environment.mu @@ -79,7 +79,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources: } # not global and not a touch event { - hide-screen screen render?:bool <- handle-keyboard-event screen, current-sandbox, e:event break-unless render? # try to batch up rendering if there are more events queued up @@ -93,7 +92,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources: } +finish-event screen <- update-cursor screen, current-sandbox, env - show-screen screen } loop } @@ -199,7 +197,7 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr local-scope load-ingredients trace 10, [app], [render all] - hide-screen screen + old-top-idx:num <- save-top-idx screen # top menu trace 11, [app], [render top menu] width:num <- screen-width screen @@ -211,12 +209,12 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr print screen, [ run (F4) ], 255/white, 161/reddish # screen <- render-sandbox-side screen, env, render-editor - <render-components-end> + <render-components-end> # no early returns permitted # current-sandbox:&:editor <- get *env, current-sandbox:offset screen <- update-cursor screen, current-sandbox, env # - show-screen screen + assert-no-scroll screen, old-top-idx ] # replaced in a later layer diff --git a/sandbox/005-sandbox.mu b/sandbox/005-sandbox.mu index e9500797..a7df7a54 100644 --- a/sandbox/005-sandbox.mu +++ b/sandbox/005-sandbox.mu @@ -793,9 +793,7 @@ after <global-keypress> [ render-from <- add render-from, 1 *env <- put *env, render-from:offset, render-from } - hide-screen screen screen <- render-sandbox-side screen, env, render - show-screen screen jump +finish-event } ] @@ -822,9 +820,7 @@ after <global-keypress> [ break-if at-beginning? render-from <- subtract render-from, 1 *env <- put *env, render-from:offset, render-from - hide-screen screen screen <- render-sandbox-side screen, env, render - show-screen screen jump +finish-event } ] diff --git a/sandbox/006-sandbox-copy.mu b/sandbox/006-sandbox-copy.mu index 995f4c7c..4835f02e 100644 --- a/sandbox/006-sandbox-copy.mu +++ b/sandbox/006-sandbox-copy.mu @@ -140,10 +140,8 @@ after <global-touch> [ break-unless copy? copy?, env <- try-copy-sandbox click-row, env break-unless copy? - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, current-sandbox, env - show-screen screen loop +next-event } ] diff --git a/sandbox/007-sandbox-delete.mu b/sandbox/007-sandbox-delete.mu index ddfbf692..107c861c 100644 --- a/sandbox/007-sandbox-delete.mu +++ b/sandbox/007-sandbox-delete.mu @@ -69,10 +69,8 @@ after <global-touch> [ break-unless delete? delete?, env <- try-delete-sandbox click-row, env break-unless delete? - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, current-sandbox, env - show-screen screen loop +next-event } ] diff --git a/sandbox/008-sandbox-edit.mu b/sandbox/008-sandbox-edit.mu index cb19ebc4..ec4fd578 100644 --- a/sandbox/008-sandbox-edit.mu +++ b/sandbox/008-sandbox-edit.mu @@ -111,10 +111,8 @@ after <global-touch> [ break-unless edit? edit?, env <- try-edit-sandbox click-row, env break-unless edit? - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, current-sandbox, env - show-screen screen loop +next-event } ] diff --git a/sandbox/009-sandbox-test.mu b/sandbox/009-sandbox-test.mu index d7b8ed62..1c24bcb8 100644 --- a/sandbox/009-sandbox-test.mu +++ b/sandbox/009-sandbox-test.mu @@ -132,10 +132,8 @@ after <global-touch> [ # toggle its expected-response, and save session sandbox <- toggle-expected-response sandbox save-sandboxes env, resources - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, current-sandbox, env - show-screen screen loop +next-event } ] diff --git a/sandbox/010-sandbox-trace.mu b/sandbox/010-sandbox-trace.mu index f81d4151..27f2915a 100644 --- a/sandbox/010-sandbox-trace.mu +++ b/sandbox/010-sandbox-trace.mu @@ -190,10 +190,8 @@ after <global-touch> [ x:bool <- get *sandbox, display-trace?:offset x <- not x *sandbox <- put *sandbox, display-trace?:offset, x - hide-screen screen screen <- render-sandbox-side screen, env, render screen <- update-cursor screen, current-sandbox, env - show-screen screen loop +next-event } ] diff --git a/termbox/termbox.c b/termbox/termbox.c index 1ae275ce..0ee4b283 100644 --- a/termbox/termbox.c +++ b/termbox/termbox.c @@ -23,19 +23,10 @@ extern int wcwidth (wchar_t); #include "output.inl" #include "input.inl" -struct cellbuf { - int width; - int height; - struct tb_cell *cells; -}; - -#define CELL(buf, x, y) (buf)->cells[(y) * (buf)->width + (x)] #define LAST_COORD_INIT -1 static struct termios orig_tios; -static struct cellbuf back_buffer; -static struct cellbuf front_buffer; static struct bytebuffer output_buffer; static struct bytebuffer input_buffer; @@ -45,22 +36,12 @@ static int termh = -1; static int inout; static int winch_fds[2]; -static int lastx = LAST_COORD_INIT; -static int lasty = LAST_COORD_INIT; static int cursor_x = 0; static int cursor_y = 0; static uint16_t background = TB_BLACK; static uint16_t foreground = TB_WHITE; -static void write_cursor(int x, int y); -static void write_sgr(uint16_t fg, uint16_t bg); - -static void cellbuf_init(struct cellbuf *buf, int width, int height); -static void cellbuf_resize(struct cellbuf *buf, int width, int height); -static void cellbuf_clear(struct cellbuf *buf); -static void cellbuf_free(struct cellbuf *buf); - static void update_size(void); static void update_term_size(void); static void send_attr(uint16_t fg, uint16_t bg); @@ -121,11 +102,6 @@ int tb_init(void) send_clear(); update_term_size(); - cellbuf_init(&back_buffer, termw, termh); - cellbuf_init(&front_buffer, termw, termh); - cellbuf_clear(&back_buffer); - cellbuf_clear(&front_buffer); - return 0; } @@ -145,8 +121,6 @@ void tb_shutdown(void) close(winch_fds[0]); close(winch_fds[1]); - cellbuf_free(&back_buffer); - cellbuf_free(&front_buffer); bytebuffer_free(&output_buffer); bytebuffer_free(&input_buffer); termw = termh = -1; @@ -157,76 +131,12 @@ int tb_is_active(void) return termw != -1; } -void tb_present() { - int x,y,w,i; - struct tb_cell *back, *front; - - assert(termw != -1); - - /* invalidate cursor position */ - lastx = LAST_COORD_INIT; - lasty = LAST_COORD_INIT; - - if (buffer_size_change_request) { - update_size(); - buffer_size_change_request = 0; - } - - for (y = 0; y < front_buffer.height; ++y) { - for (x = 0; x < front_buffer.width; ) { - back = &CELL(&back_buffer, x, y); - front = &CELL(&front_buffer, x, y); - w = wcwidth(back->ch); - if (w < 1) w = 1; - if (memcmp(back, front, sizeof(struct tb_cell)) == 0) { - x += w; - continue; - } - memcpy(front, back, sizeof(struct tb_cell)); - send_attr(back->fg, back->bg); - if (w > 1 && x >= front_buffer.width - (w - 1)) { - // Not enough room for wide ch, so send spaces - for (i = x; i < front_buffer.width; ++i) { - send_char(i, y, ' '); - } - } else { - send_char(x, y, back->ch); - for (i = 1; i < w; ++i) { - front = &CELL(&front_buffer, x + i, y); - front->ch = 0; - front->fg = back->fg; - front->bg = back->bg; - } - } - x += w; - } - } - write_cursor(cursor_x, cursor_y); - bytebuffer_flush(&output_buffer, inout); -} - -void tb_set_cursor(int cx, int cy) -{ - assert(termw != -1); - cursor_x = cx; - cursor_y = cy; - write_cursor(cursor_x, cursor_y); -} - void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg) { assert(termw != -1); - if ((unsigned)x >= (unsigned)back_buffer.width) - return; - if ((unsigned)y >= (unsigned)back_buffer.height) - return; - struct tb_cell c = {ch, fg, bg}; - CELL(&back_buffer, x, y) = c; -} - -struct tb_cell *tb_cell_buffer() -{ - return back_buffer.cells; + send_attr(fg, bg); + send_char(x, y, ch); + bytebuffer_flush(&output_buffer, inout); } int tb_poll_event(struct tb_event *event) @@ -263,7 +173,7 @@ void tb_clear(void) update_size(); buffer_size_change_request = 0; } - cellbuf_clear(&back_buffer); + send_clear(); } void tb_set_clear_attributes(uint16_t fg, uint16_t bg) @@ -293,73 +203,14 @@ static int convertnum(uint32_t num, char* buf) { #define WRITE_LITERAL(X) bytebuffer_append(&output_buffer, (X), sizeof(X)-1) #define WRITE_INT(X) bytebuffer_append(&output_buffer, buf, convertnum((X), buf)) -static void write_cursor(int x, int y) { +void tb_set_cursor(int x, int y) { char buf[32]; WRITE_LITERAL("\033["); WRITE_INT(y+1); WRITE_LITERAL(";"); WRITE_INT(x+1); WRITE_LITERAL("H"); -} - -static void write_sgr(uint16_t fg, uint16_t bg) { - char buf[32]; - WRITE_LITERAL("\033[38;5;"); - WRITE_INT(fg); - WRITE_LITERAL("m"); - WRITE_LITERAL("\033[48;5;"); - WRITE_INT(bg); - WRITE_LITERAL("m"); -} - -static void cellbuf_init(struct cellbuf *buf, int width, int height) -{ - buf->cells = (struct tb_cell*)malloc(sizeof(struct tb_cell) * width * height); - assert(buf->cells); - buf->width = width; - buf->height = height; -} - -static void cellbuf_resize(struct cellbuf *buf, int width, int height) -{ - if (buf->width == width && buf->height == height) - return; - - int oldw = buf->width; - int oldh = buf->height; - struct tb_cell *oldcells = buf->cells; - - cellbuf_init(buf, width, height); - cellbuf_clear(buf); - - int minw = (width < oldw) ? width : oldw; - int minh = (height < oldh) ? height : oldh; - int i; - - for (i = 0; i < minh; ++i) { - struct tb_cell *csrc = oldcells + (i * oldw); - struct tb_cell *cdst = buf->cells + (i * width); - memcpy(cdst, csrc, sizeof(struct tb_cell) * minw); - } - - free(oldcells); -} - -static void cellbuf_clear(struct cellbuf *buf) -{ - int i; - int ncells = buf->width * buf->height; - - for (i = 0; i < ncells; ++i) { - buf->cells[i].ch = ' '; - buf->cells[i].fg = foreground; - buf->cells[i].bg = background; - } -} - -static void cellbuf_free(struct cellbuf *buf) -{ - free(buf->cells); + bytebuffer_flush(&output_buffer, inout); } static void get_term_size(int *w, int *h) @@ -402,7 +253,14 @@ static void send_attr(uint16_t fg, uint16_t bg) bytebuffer_puts(&output_buffer, funcs[T_UNDERLINE]); if ((fg & TB_REVERSE) || (bg & TB_REVERSE)) bytebuffer_puts(&output_buffer, funcs[T_REVERSE]); - write_sgr(fgcol, bgcol); + char buf[32]; + WRITE_LITERAL("\033[38;5;"); + WRITE_INT(fgcol); + WRITE_LITERAL("m"); + WRITE_LITERAL("\033[48;5;"); + WRITE_INT(bgcol); + WRITE_LITERAL("m"); + bytebuffer_flush(&output_buffer, inout); lastfg = fg; lastbg = bg; } @@ -413,9 +271,7 @@ static void send_char(int x, int y, uint32_t c) char buf[7]; int bw = tb_utf8_unicode_to_char(buf, c); buf[bw] = '\0'; - if (x-1 != lastx || y != lasty) - write_cursor(x, y); - lastx = x; lasty = y; + tb_set_cursor(x, y); if(!c) buf[0] = ' '; // replace 0 with whitespace bytebuffer_puts(&output_buffer, buf); } @@ -432,16 +288,8 @@ static void send_clear(void) { send_attr(foreground, background); bytebuffer_puts(&output_buffer, funcs[T_CLEAR_SCREEN]); - write_cursor(cursor_x, cursor_y); + tb_set_cursor(cursor_x, cursor_y); bytebuffer_flush(&output_buffer, inout); - - /* we need to invalidate cursor position too and these two vars are - * used only for simple cursor positioning optimization, cursor - * actually may be in the correct place, but we simply discard - * optimization once and it gives us simple solution for the case when - * cursor moved */ - lastx = LAST_COORD_INIT; - lasty = LAST_COORD_INIT; } static void sigwinch_handler(int xxx) @@ -455,9 +303,6 @@ static void sigwinch_handler(int xxx) static void update_size(void) { update_term_size(); - cellbuf_resize(&back_buffer, termw, termh); - cellbuf_resize(&front_buffer, termw, termh); - cellbuf_clear(&front_buffer); send_clear(); } diff --git a/termbox/termbox.h b/termbox/termbox.h index 64c1c4eb..97306142 100644 --- a/termbox/termbox.h +++ b/termbox/termbox.h @@ -8,19 +8,12 @@ extern "C" { /*** 1. Controlling the screen. */ -/* The screen is a 2D array of cells. */ -struct tb_cell { - uint32_t ch; /* unicode character */ - uint16_t fg; /* foreground color (0-255) and attributes */ - uint16_t bg; /* background color (0-255) and attributes */ -}; - -/* Names for some colors in tb_cell.fg and tb_cell.bg. */ +/* Names for some foreground/background colors. */ #define TB_BLACK 232 #define TB_WHITE 255 -/* Colors in tb_cell can be combined using bitwise-OR with multiple - * of the following attributes. */ +/* Some attributes of screen cells that can be combined with colors using + * bitwise-OR. */ #define TB_BOLD 0x0100 #define TB_UNDERLINE 0x0200 #define TB_REVERSE 0x0400 @@ -44,17 +37,6 @@ int tb_is_active(void); int tb_width(void); int tb_height(void); -/* Update the screen with internal state. Most methods below modify just the - * internal state of the screen. Changes won't be visible until you call - * tb_present(). */ -void tb_present(void); - -/* Returns a pointer to the internal screen state: a 1D array of cells in - * raster order. You'll need to call tb_width() and tb_height() for the - * array's dimensions. The array stays valid until tb_clear() or tb_present() - * are called. */ -struct tb_cell *tb_cell_buffer(); - /* Clear the internal screen state using either TB_DEFAULT or the * color/attributes set by tb_set_clear_attributes(). */ void tb_clear(void); @@ -63,8 +45,7 @@ void tb_set_clear_attributes(uint16_t fg, uint16_t bg); /* Move the cursor. Upper-left character is (0, 0). */ void tb_set_cursor(int cx, int cy); -/* Modify a specific cell of the screen. Don't forget to call tb_present() to - * commit your changes. */ +/* Modify a specific cell of the screen. */ void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg); /*** 2. Controlling keyboard events. */ diff --git a/termbox/x.cc b/termbox/x.cc index f6b04693..1b715746 100644 --- a/termbox/x.cc +++ b/termbox/x.cc @@ -1,12 +1,18 @@ #include<iostream> +using std::cout; #include"termbox.h" int main() { tb_init(); + std::setvbuf(stdout, NULL, _IONBF, 0); + cout << tb_width() << ' ' << tb_height(); tb_event x; - tb_poll_event(&x); - std::cout << "a\nb\r\nc\r\n"; - tb_poll_event(&x); + for (int col = 0; col <= tb_width(); ++col) { + tb_set_cursor(col, 1); + tb_poll_event(&x); + cout << "a"; + tb_poll_event(&x); + } tb_shutdown(); return 0; } |