1327 - better error handling in chessboard
Also a bugfix in break to label, because I noticed the screen wasn't being cleaned up on quit.
This commit is contained in:
parent
6b16a2ef6b
commit
4071055aee
|
@ -130,7 +130,8 @@ if (argc > 1) {
|
|||
:(before "End Main")
|
||||
if (!Run_tests) {
|
||||
setup();
|
||||
Trace_stream = new trace_stream;
|
||||
//? Trace_file = "interactive"; //? 1
|
||||
START_TRACING_UNTIL_END_OF_SCOPE;
|
||||
//? Trace_stream->dump_layer = "all"; //? 2
|
||||
transform_all();
|
||||
recipe_number r = Recipe_number[string("main")];
|
||||
|
|
|
@ -42,6 +42,7 @@ Recipe_number["jump-if"] = JUMP_IF;
|
|||
:(before "End Primitive Recipe Implementations")
|
||||
case JUMP_IF: {
|
||||
assert(current_instruction().ingredients.at(1).initialized);
|
||||
trace("AAA") << current_instruction().to_string() << '\n';
|
||||
assert(ingredients.size() == 2);
|
||||
assert(ingredients.at(0).size() == 1); // scalar
|
||||
if (!ingredients.at(0).at(0)) {
|
||||
|
|
|
@ -15,9 +15,8 @@ case ASSERT: {
|
|||
assert(ingredients.at(0).size() == 1); // scalar
|
||||
if (!ingredients.at(0).at(0)) {
|
||||
assert(isa_literal(current_instruction().ingredients.at(1)));
|
||||
//? tb_shutdown(); //? 1
|
||||
tb_shutdown();
|
||||
raise << current_instruction().ingredients.at(1).name << '\n' << die();
|
||||
//? exit(0); //? 1
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ recipe f [
|
|||
//: ingredients unless they're also products. The /same-as-ingredient inside
|
||||
//: the recipe's 'reply' will help catch accidental misuse of such
|
||||
//: 'ingredient-results' (sometimes called in-out parameters in other languages).
|
||||
|
||||
:(scenario reply_same_as_ingredient)
|
||||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
|
@ -90,3 +91,44 @@ string to_string(const vector<long long int>& in) {
|
|||
out << "]";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
//: Conditional reply.
|
||||
|
||||
:(scenario reply_if)
|
||||
recipe main [
|
||||
1:integer <- test1
|
||||
]
|
||||
recipe test1 [
|
||||
reply-if 0:literal, 34:literal
|
||||
reply 35:literal
|
||||
]
|
||||
+mem: storing 35 in location 1
|
||||
|
||||
:(scenario reply_if2)
|
||||
recipe main [
|
||||
1:integer <- test1
|
||||
]
|
||||
recipe test1 [
|
||||
reply-if 1:literal, 34:literal
|
||||
reply 35:literal
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
|
||||
:(before "End Rewrite Instruction(curr)")
|
||||
// rewrite `reply-if a, b, c, ...` to
|
||||
// ```
|
||||
// jump-unless a, 1:offset
|
||||
// reply b, c, ...
|
||||
// ```
|
||||
if (curr.name == "reply-if") {
|
||||
assert(curr.products.empty());
|
||||
curr.operation = Recipe_number["jump-unless"];
|
||||
vector<reagent> results;
|
||||
copy(++curr.ingredients.begin(), curr.ingredients.end(), inserter(results, results.end()));
|
||||
curr.ingredients.resize(1);
|
||||
curr.ingredients.push_back(reagent("1:offset"));
|
||||
result.steps.push_back(curr);
|
||||
curr.clear();
|
||||
curr.operation = Recipe_number["reply"];
|
||||
curr.ingredients.swap(results);
|
||||
}
|
||||
|
|
|
@ -24,25 +24,25 @@ void transform_labels(const recipe_number r) {
|
|||
instruction& inst = Recipe[r].steps.at(i);
|
||||
if (inst.operation == Recipe_number["jump"]) {
|
||||
//? cerr << inst.to_string() << '\n'; //? 1
|
||||
replace_offset(inst.ingredients.at(0), offset, r);
|
||||
replace_offset(inst.ingredients.at(0), offset, i, r);
|
||||
}
|
||||
if (inst.operation == Recipe_number["jump-if"] || inst.operation == Recipe_number["jump-unless"]) {
|
||||
replace_offset(inst.ingredients.at(1), offset, r);
|
||||
replace_offset(inst.ingredients.at(1), offset, i, r);
|
||||
}
|
||||
if ((inst.operation == Recipe_number["loop"] || inst.operation == Recipe_number["break"])
|
||||
&& inst.ingredients.size() == 1) {
|
||||
replace_offset(inst.ingredients.at(0), offset, r);
|
||||
replace_offset(inst.ingredients.at(0), offset, i, r);
|
||||
}
|
||||
if ((inst.operation == Recipe_number["loop-if"] || inst.operation == Recipe_number["loop-unless"]
|
||||
|| inst.operation == Recipe_number["break-if"] || inst.operation == Recipe_number["break-unless"])
|
||||
&& inst.ingredients.size() == 2) {
|
||||
replace_offset(inst.ingredients.at(1), offset, r);
|
||||
replace_offset(inst.ingredients.at(1), offset, i, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:(code)
|
||||
void replace_offset(reagent& x, /*const*/ map<string, index_t>& offset, const recipe_number r) {
|
||||
void replace_offset(reagent& x, /*const*/ map<string, index_t>& offset, const index_t current_offset, const recipe_number r) {
|
||||
//? cerr << "AAA " << x.to_string() << '\n'; //? 1
|
||||
assert(isa_literal(x));
|
||||
//? cerr << "BBB " << x.to_string() << '\n'; //? 1
|
||||
|
@ -52,7 +52,7 @@ void replace_offset(reagent& x, /*const*/ map<string, index_t>& offset, const re
|
|||
//? cerr << "DDD " << x.to_string() << '\n'; //? 1
|
||||
if (offset.find(x.name) == offset.end())
|
||||
raise << "can't find label " << x.name << " in routine " << Recipe[r].name << '\n';
|
||||
x.set_value(offset[x.name]);
|
||||
x.set_value(offset[x.name]-current_offset);
|
||||
}
|
||||
|
||||
:(scenario break_to_label)
|
||||
|
@ -91,3 +91,17 @@ recipe main [
|
|||
+target
|
||||
]
|
||||
-mem: storing 0 in location 1
|
||||
|
||||
:(scenario jump_runs_code_after_label)
|
||||
recipe main [
|
||||
# first a few lines of padding to exercise the offset computation
|
||||
1:integer <- copy 0:literal
|
||||
2:integer <- copy 0:literal
|
||||
3:integer <- copy 0:literal
|
||||
jump +target:offset
|
||||
4:integer <- copy 0:literal
|
||||
+target
|
||||
5:integer <- copy 0:literal
|
||||
]
|
||||
+mem: storing 0 in location 5
|
||||
-mem: storing 0 in location 4
|
||||
|
|
|
@ -88,7 +88,7 @@ time_t mu_time; time(&mu_time);
|
|||
cerr << "\nMu tests: " << ctime(&mu_time);
|
||||
for (index_t i = 0; i < Scenarios.size(); ++i) {
|
||||
//? cerr << Passed << '\n'; //? 1
|
||||
//? cerr << i << ": " << Scenarios.at(i).name << '\n'; //? 1
|
||||
//? cerr << i << ": " << Scenarios.at(i).name << '\n'; //? 2
|
||||
run_mu_scenario(Scenarios.at(i));
|
||||
if (Passed) cerr << ".";
|
||||
}
|
||||
|
@ -294,6 +294,10 @@ recipe main [
|
|||
// Like runs of contiguous '+' lines, order is important. The trace checks
|
||||
// that the lines are present *and* in the specified sequence. (There can be
|
||||
// other lines in between.)
|
||||
//
|
||||
// Be careful not to mix setting Hide_warnings and checking the trace in .mu
|
||||
// files. It'll work in C++ scenarios, but the test failure gets silently
|
||||
// hidden in mu scenarios.
|
||||
|
||||
:(scenario trace_check_warns_on_failure)
|
||||
% Hide_warnings = true;
|
||||
|
@ -319,8 +323,10 @@ case TRACE_SHOULD_CONTAIN: {
|
|||
// simplified version of check_trace_contents() that emits warnings rather
|
||||
// than just printing to stderr
|
||||
bool check_trace(const string& expected) {
|
||||
//? cerr << "AAA " << expected << '\n'; //? 1
|
||||
Trace_stream->newline();
|
||||
vector<pair<string, string> > expected_lines = parse_trace(expected);
|
||||
//? cerr << "BBB " << expected_lines.size() << '\n'; //? 1
|
||||
if (expected_lines.empty()) return true;
|
||||
index_t curr_expected_line = 0;
|
||||
for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
|
||||
|
@ -328,7 +334,10 @@ bool check_trace(const string& expected) {
|
|||
if (expected_lines.at(curr_expected_line).second != p->second.second) continue;
|
||||
// match
|
||||
++curr_expected_line;
|
||||
if (curr_expected_line == expected_lines.size()) return true;
|
||||
if (curr_expected_line == expected_lines.size()) {
|
||||
//? cerr << "ZZZ\n"; //? 1
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
raise << "missing [" << expected_lines.at(curr_expected_line).second << "] "
|
||||
|
|
142
chessboard.mu
142
chessboard.mu
|
@ -152,100 +152,148 @@ container move [
|
|||
to-rank:integer
|
||||
]
|
||||
|
||||
# result:address:move <- read-move stdin:address:channel
|
||||
# result:address:move, quit?:boolean, error?:boolean <- read-move stdin:address:channel, screen:address
|
||||
# prints only error messages to screen
|
||||
recipe read-move [
|
||||
default-space:address:array:location <- new location:type, 30:literal
|
||||
stdin:address:channel <- next-ingredient
|
||||
from-file:integer <- read-file stdin:address:channel
|
||||
screen:address <- next-ingredient
|
||||
#? $print screen:address #? 1
|
||||
from-file:integer, quit?:boolean, error?:boolean <- read-file stdin:address:channel, screen:address
|
||||
reply-if quit?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
reply-if error?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
#? return-to-console #? 1
|
||||
{
|
||||
q-pressed?:boolean <- lesser-than from-file:integer, 0:literal
|
||||
break-unless q-pressed?:boolean
|
||||
reply 0:literal
|
||||
}
|
||||
# construct the move object
|
||||
result:address:move <- new move:literal
|
||||
x:address:integer <- get-address result:address:move/deref, from-file:offset
|
||||
x:address:integer/deref <- copy from-file:integer
|
||||
x:address:integer <- get-address result:address:move/deref, from-rank:offset
|
||||
x:address:integer/deref <- read-rank stdin:address:channel
|
||||
expect-from-channel stdin:address:channel, 45:literal # '-'
|
||||
x:address:integer/deref, quit?:boolean, error?:boolean <- read-rank stdin:address:channel, screen:address
|
||||
reply-if quit?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
reply-if error?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
error?:boolean <- expect-from-channel stdin:address:channel, 45:literal/dash, screen:address
|
||||
reply-if error?:boolean, 0:literal/dummy, 0:literal/quit, error?:boolean
|
||||
x:address:integer <- get-address result:address:move/deref, to-file:offset
|
||||
x:address:integer/deref <- read-file stdin:address:channel
|
||||
x:address:integer/deref, quit?:boolean, error?:boolean <- read-file stdin:address:channel, screen:address
|
||||
reply-if quit?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
reply-if error?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
x:address:integer <- get-address result:address:move/deref, to-rank:offset
|
||||
x:address:integer/deref <- read-rank stdin:address:channel
|
||||
x:address:integer/deref, quit?:boolean, error?:boolean <- read-rank stdin:address:channel, screen:address
|
||||
reply-if quit?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
reply-if error?:boolean, 0:literal/dummy, quit?:boolean, error?:boolean
|
||||
#? $exit #? 1
|
||||
expect-from-channel stdin:address:channel, 13:literal # newline
|
||||
reply result:address:move
|
||||
error?:boolean <- expect-from-channel stdin:address:channel, 13:literal/newline, screen:address
|
||||
reply-if error?:boolean, 0:literal/dummy, 0:literal/quit, error?:boolean
|
||||
reply result:address:move, quit?:boolean, error?:boolean
|
||||
]
|
||||
|
||||
# file:integer, quit:boolean, error:boolean <- read-file stdin:address:channel, screen:address
|
||||
# valid values for file: 0-7
|
||||
recipe read-file [
|
||||
default-space:address:array:location <- new location:type, 30:literal
|
||||
stdin:address:channel <- next-ingredient
|
||||
screen:address <- next-ingredient
|
||||
c:character, stdin:address:channel <- read stdin:address:channel
|
||||
{
|
||||
q-pressed?:boolean <- equal c:character, 81:literal # 'Q'
|
||||
break-unless q-pressed?:boolean
|
||||
reply -1:literal
|
||||
reply 0:literal/dummy, 1:literal/quit, 0:literal/error
|
||||
}
|
||||
{
|
||||
q-pressed?:boolean <- equal c:character, 113:literal # 'q'
|
||||
break-unless q-pressed?:boolean
|
||||
reply -1:literal
|
||||
reply 0:literal/dummy, 1:literal/quit, 0:literal/error
|
||||
}
|
||||
file:integer <- subtract c:character, 97:literal # 'a'
|
||||
#? $print file:integer, [ #? 1
|
||||
#? ] #? 1
|
||||
# 'a' <= file <= 'h'
|
||||
above-min:boolean <- greater-or-equal file:integer, 0:literal
|
||||
assert above-min:boolean [file too low]
|
||||
below-max:boolean <- lesser-than file:integer, 8:literal
|
||||
assert below-max:boolean [file too high]
|
||||
reply file:integer
|
||||
{
|
||||
above-min:boolean <- greater-or-equal file:integer, 0:literal
|
||||
break-if above-min:boolean
|
||||
error-message:address:array:character <- new [file too low: ]
|
||||
print-string screen:address, error-message:address:array:character
|
||||
print-character screen:address, c:character
|
||||
cursor-to-next-line screen:address
|
||||
reply 0:literal/dummy, 0:literal/quit, 1:literal/error
|
||||
}
|
||||
{
|
||||
below-max:boolean <- lesser-than file:integer, 8:literal
|
||||
break-if below-max:boolean
|
||||
error-message:address:array:character <- new [file too high: ]
|
||||
print-string screen:address, error-message:address:array:character
|
||||
print-character screen:address, c:character
|
||||
reply 0:literal/dummy, 0:literal/quit, 1:literal/error
|
||||
}
|
||||
reply file:integer, 0:literal/quit, 0:literal/error
|
||||
]
|
||||
|
||||
# rank:integer <- read-rank stdin:address:channel, screen:address
|
||||
# valid values: 0-7, -1 (quit), -2 (error)
|
||||
recipe read-rank [
|
||||
default-space:address:array:location <- new location:type, 30:literal
|
||||
stdin:address:channel <- next-ingredient
|
||||
screen:address <- next-ingredient
|
||||
c:character, stdin:address:channel <- read stdin:address:channel
|
||||
{
|
||||
q-pressed?:boolean <- equal c:character, 81:literal # 'Q'
|
||||
break-unless q-pressed?:boolean
|
||||
reply -1:literal
|
||||
reply 0:literal/dummy, 1:literal/quit, 0:literal/error
|
||||
}
|
||||
{
|
||||
q-pressed?:boolean <- equal c:character, 113:literal # 'q'
|
||||
break-unless q-pressed?:boolean
|
||||
reply -1:literal
|
||||
reply 0:literal/dummy, 1:literal/quit, 0:literal/error
|
||||
}
|
||||
rank:integer <- subtract c:character, 49:literal # '1'
|
||||
#? $print rank:integer, [ #? 1
|
||||
#? ] #? 1
|
||||
# assert'1' <= rank <= '8'
|
||||
above-min:boolean <- greater-or-equal rank:integer 0:literal
|
||||
assert above-min:boolean [rank too low]
|
||||
below-max:boolean <- lesser-or-equal rank:integer 7:literal
|
||||
assert below-max:boolean [rank too high]
|
||||
reply rank:integer
|
||||
{
|
||||
above-min:boolean <- greater-or-equal rank:integer 0:literal
|
||||
break-if above-min:boolean
|
||||
error-message:address:array:character <- new [rank too low: ]
|
||||
print-string screen:address, error-message:address:array:character
|
||||
print-character screen:address, c:character
|
||||
reply 0:literal/dummy, 0:literal/quit, 1:literal/error
|
||||
}
|
||||
{
|
||||
below-max:boolean <- lesser-or-equal rank:integer 7:literal
|
||||
break-if below-max:boolean
|
||||
error-message:address:array:character <- new [rank too high: ]
|
||||
print-string screen:address, error-message:address:array:character
|
||||
print-character screen:address, c:character
|
||||
reply 0:literal/dummy, 0:literal/quit, 1:literal/error
|
||||
}
|
||||
reply rank:integer, 0:literal/quit, 0:literal/error
|
||||
]
|
||||
|
||||
# read a character from the given channel and check that it's what we expect
|
||||
# return true on error
|
||||
recipe expect-from-channel [
|
||||
default-space:address:array:location <- new location:type, 30:literal
|
||||
stdin:address:channel <- next-ingredient
|
||||
expected:character <- next-ingredient
|
||||
screen:address <- next-ingredient
|
||||
c:character, stdin:address:channel <- read stdin:address:channel
|
||||
match?:boolean <- equal c:character, expected:character
|
||||
assert match?:boolean [expected character not found]
|
||||
{
|
||||
break-if match?:boolean
|
||||
s:address:array:character <- new [expected character not found]
|
||||
print-string screen:address, s:address:array:character
|
||||
}
|
||||
result:boolean <- not match?:boolean
|
||||
reply result:boolean
|
||||
]
|
||||
|
||||
scenario read-move-blocking [
|
||||
assume-screen 20:literal/width, 2:literal/height
|
||||
run [
|
||||
#? $start-tracing #? 1
|
||||
1:address:channel <- init-channel 2:literal
|
||||
#? $print [aaa channel address: ], 1:address:channel, [ #? 1
|
||||
#? ] #? 1
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel, screen:address
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:integer
|
||||
#? $print [bbb channel address: ], 1:address:channel, [ #? 1
|
||||
|
@ -333,9 +381,10 @@ F read-move-blocking: routine failed to terminate on newline]
|
|||
]
|
||||
|
||||
scenario read-move-quit [
|
||||
assume-screen 20:literal/width, 2:literal/height
|
||||
run [
|
||||
1:address:channel <- init-channel 2:literal
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel, screen:address
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:integer
|
||||
3:integer <- routine-state 2:integer/id
|
||||
|
@ -359,10 +408,10 @@ F read-move-quit: routine failed to terminate on 'q']
|
|||
]
|
||||
|
||||
scenario read-move-illegal-file [
|
||||
assume-screen 20:literal/width, 2:literal/height
|
||||
run [
|
||||
hide-warnings
|
||||
1:address:channel <- init-channel 2:literal
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel, screen:address
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:integer
|
||||
3:integer <- routine-state 2:integer/id
|
||||
|
@ -373,16 +422,17 @@ F read-move-file: routine failed to pause after coming up (before any keys were
|
|||
restart 2:integer/routine
|
||||
wait-for-routine 2:integer
|
||||
]
|
||||
trace-should-contain [
|
||||
warn: file too low
|
||||
screen-should-contain [
|
||||
.file too low: 2 .
|
||||
. .
|
||||
]
|
||||
]
|
||||
|
||||
scenario read-move-illegal-rank [
|
||||
assume-screen 20:literal/width, 2:literal/height
|
||||
run [
|
||||
hide-warnings
|
||||
1:address:channel <- init-channel 2:literal
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel
|
||||
2:integer/routine <- start-running read-move:recipe, 1:address:channel, screen:address
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:integer
|
||||
3:integer <- routine-state 2:integer/id
|
||||
|
@ -394,8 +444,9 @@ F read-move-file: routine failed to pause after coming up (before any keys were
|
|||
restart 2:integer/routine
|
||||
wait-for-routine 2:integer
|
||||
]
|
||||
trace-should-contain [
|
||||
warn: rank too high
|
||||
screen-should-contain [
|
||||
.rank too high: a .
|
||||
. .
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -496,15 +547,20 @@ recipe chessboard [
|
|||
msg:address:array:character <- new [Hit 'q' to exit.
|
||||
]
|
||||
print-string 0:literal/screen, msg:address:array:character
|
||||
cursor-to-next-line 0:literal/screen
|
||||
msg:address:array:character <- new [move: ]
|
||||
print-string 0:literal/screen, msg:address:array:character
|
||||
m:address:move <- read-move buffered-stdin:address:channel
|
||||
break-unless m:address:move
|
||||
{
|
||||
cursor-to-next-line 0:literal/screen
|
||||
msg:address:array:character <- new [move: ]
|
||||
print-string 0:literal/screen, msg:address:array:character
|
||||
m:address:move, quit:boolean, error:boolean <- read-move buffered-stdin:address:channel, 0:literal/screen
|
||||
break-if quit:boolean, +quit:offset
|
||||
loop-if error:boolean
|
||||
}
|
||||
board:address:array:address:array:character <- make-move board:address:array:address:array:character, m:address:move
|
||||
clear-screen 0:literal/screen
|
||||
loop
|
||||
}
|
||||
+quit
|
||||
#? $print [aaa] #? 1
|
||||
return-to-console
|
||||
]
|
||||
|
||||
|
|
2
mu.vim
2
mu.vim
|
@ -35,7 +35,7 @@ syntax match muDelimiter "[{}\[\]]" | highlight link muDelimiter Delimiter
|
|||
syntax match muLabel " [^a-zA-Z0-9 \[][a-zA-Z0-9-]\+" | highlight link muLabel Function
|
||||
syntax match muAssign " <- " | highlight link muAssign SpecialChar
|
||||
syntax match muAssign "\<raw\>"
|
||||
syntax keyword muControl reply jump jump-if jump-unless loop loop-if loop-unless break-if break-unless | highlight link muControl Function
|
||||
syntax keyword muControl reply reply-if reply-unless jump jump-if jump-unless loop loop-if loop-unless break-if break-unless | highlight link muControl Function
|
||||
" common keywords
|
||||
syntax keyword muFunc recipe default-space next-ingredient ingredient before after scenario run memory trace screen keyboard stalled finished | highlight link muFunc Statement
|
||||
|
||||
|
|
|
@ -158,6 +158,8 @@ void tb_present(void)
|
|||
int x,y,w,i;
|
||||
struct tb_cell *back, *front;
|
||||
|
||||
assert(termw != -1);
|
||||
|
||||
/* invalidate cursor position */
|
||||
lastx = LAST_COORD_INIT;
|
||||
lasty = LAST_COORD_INIT;
|
||||
|
@ -203,12 +205,11 @@ void tb_present(void)
|
|||
|
||||
void tb_set_cursor(int cx, int cy)
|
||||
{
|
||||
assert(termw != -1);
|
||||
if (IS_CURSOR_HIDDEN(cursor_x, cursor_y) && !IS_CURSOR_HIDDEN(cx, cy))
|
||||
bytebuffer_puts(&output_buffer, funcs[T_SHOW_CURSOR]);
|
||||
|
||||
if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y) && IS_CURSOR_HIDDEN(cx, cy))
|
||||
bytebuffer_puts(&output_buffer, funcs[T_HIDE_CURSOR]);
|
||||
|
||||
cursor_x = cx;
|
||||
cursor_y = cy;
|
||||
if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
|
||||
|
@ -217,6 +218,7 @@ void tb_set_cursor(int cx, int cy)
|
|||
|
||||
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)
|
||||
|
@ -232,6 +234,7 @@ struct tb_cell *tb_cell_buffer()
|
|||
|
||||
int tb_poll_event(struct tb_event *event)
|
||||
{
|
||||
assert(termw != -1);
|
||||
return wait_fill_event(event, 0);
|
||||
}
|
||||
|
||||
|
@ -240,21 +243,25 @@ int tb_peek_event(struct tb_event *event, int timeout)
|
|||
struct timeval tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
|
||||
assert(termw != -1);
|
||||
return wait_fill_event(event, &tv);
|
||||
}
|
||||
|
||||
int tb_width(void)
|
||||
{
|
||||
assert(termw != -1);
|
||||
return termw;
|
||||
}
|
||||
|
||||
int tb_height(void)
|
||||
{
|
||||
assert(termw != -1);
|
||||
return termh;
|
||||
}
|
||||
|
||||
void tb_clear(void)
|
||||
{
|
||||
assert(termw != -1);
|
||||
if (buffer_size_change_request) {
|
||||
update_size();
|
||||
buffer_size_change_request = 0;
|
||||
|
@ -264,6 +271,7 @@ void tb_clear(void)
|
|||
|
||||
void tb_set_clear_attributes(uint16_t fg, uint16_t bg)
|
||||
{
|
||||
assert(termw != -1);
|
||||
foreground = fg;
|
||||
background = bg;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue