-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add tb_get_cell
#65
base: master
Are you sure you want to change the base?
add tb_get_cell
#65
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -499,6 +499,21 @@ int tb_set_cell_ex(int x, int y, uint32_t *ch, size_t nch, uintattr_t fg, | |
uintattr_t bg); | ||
int tb_extend_cell(int x, int y, uint32_t ch); | ||
|
||
/* Get cell at specified position. | ||
* | ||
* If position is valid, function returns TB_OK and cell contents are copied to | ||
* `cell`. Note if `nech>0`, then `ech` will be a pointer to memory which may | ||
* be invalid or freed after subsequent library calls. Callers must copy this | ||
* memory if they need to persist it for some reason. Modifying memory at `ech` | ||
* results in undefined behavior. | ||
* | ||
* If `back` is non-zero, return cells from the internal back buffer. Otherwise, | ||
* return cells from the front buffer. Note the front buffer is updated on each | ||
* call to tb_present(), whereas the back buffer is updated immediately by | ||
* tb_set_cell() and other functions that mutate cell contents. | ||
*/ | ||
int tb_get_cell(int x, int y, int back, struct tb_cell *cell); | ||
|
||
/* Sets the input mode. Termbox has two input modes: | ||
* | ||
* 1. TB_INPUT_ESC | ||
|
@@ -1727,6 +1742,15 @@ int tb_set_cell_ex(int x, int y, uint32_t *ch, size_t nch, uintattr_t fg, | |
return TB_OK; | ||
} | ||
|
||
int tb_get_cell(int x, int y, int back, struct tb_cell *cell) { | ||
if_not_init_return(); | ||
int rv; | ||
struct tb_cell *cellp = NULL; | ||
rv = cellbuf_get(back ? &global.back : &global.front, x, y, &cellp); | ||
if (cellp) memcpy(cell, cellp, sizeof(*cell)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for better performance can we avoid memcpy and just return pointer to cell like in cellbuf_get function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I figure it's a trade-off between safety and perf. I was going for by-value semantics here (like If the caller is concerned about an extra Or like you suggest maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have point, I forgot about safety issues that could appear, but I will also prefer the latter. It is going to be more flexible code where one can get what one needs. |
||
return rv; | ||
} | ||
|
||
int tb_extend_cell(int x, int y, uint32_t ch) { | ||
if_not_init_return(); | ||
#ifdef TB_OPT_EGC | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#5[0m[0;32ma[0m | ||
#5[0mset=0[0m | ||
#5[0minvalid_get=-9[0m | ||
#5[0mback_get=0[0m | ||
#5[0mback_ch=a[0m | ||
#5[0mback_fg=3[0m | ||
#5[0mback_bg=0[0m | ||
#5[0mfront1_get=0[0m | ||
#5[0mfront1_ch=[0m | ||
#5[0mfront1_fg=0[0m | ||
#5[0mfront1_bg=0[0m | ||
#5[0mpresent=0[0m | ||
#5[0mfront2_get=0[0m | ||
#5[0mfront2_ch=a[0m | ||
#5[0mfront2_fg=3[0m | ||
#5[0mfront2_bg=0[0m | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
$test->ffi->tb_init(); | ||
|
||
$w = $test->ffi->tb_width(); | ||
$h = $test->ffi->tb_height(); | ||
$green = $test->defines['TB_GREEN']; | ||
$cell = $test->ffi->new('struct tb_cell'); | ||
$back = 1; | ||
$front = 0; | ||
|
||
$result = []; | ||
|
||
$cell->ch = 42; | ||
|
||
$result['set'] = $test->ffi->tb_set_cell(0, 0, ord('a'), $green, 0); // 0 (TB_OK) | ||
|
||
$result['invalid_get'] = $test->ffi->tb_get_cell(-1, -1, $back, FFI::addr($cell)); // -9 (TB_ERR_OUT_OF_BOUNDS) | ||
|
||
$result['back_get'] = $test->ffi->tb_get_cell(0, 0, $back, FFI::addr($cell)); // 0 (TB_OK) | ||
$result['back_ch'] = chr($cell->ch); // 'a' | ||
$result['back_fg'] = $cell->fg; // 3 (green) | ||
$result['back_bg'] = $cell->bg; // 0 | ||
|
||
$result['front1_get'] = $test->ffi->tb_get_cell(0, 0, $front, FFI::addr($cell)); | ||
$result['front1_ch'] = chr($cell->ch); // <space> (front buffer empty) | ||
$result['front1_fg'] = $cell->fg; // 0 | ||
$result['front1_bg'] = $cell->bg; // 0 | ||
|
||
$result['present'] = $test->ffi->tb_present(); // 0 (TB_OK) (front buffer now populated) | ||
|
||
$result['front2_get'] = $test->ffi->tb_get_cell(0, 0, $front, FFI::addr($cell)); // 0 (TB_OK) | ||
$result['front2_ch'] = chr($cell->ch); // 'a' | ||
$result['front2_fg'] = $cell->fg; // 3 (green) | ||
$result['front2_bg'] = $cell->bg; // 0 | ||
|
||
$y = 1; | ||
foreach ($result as $k => $v) $test->ffi->tb_printf(0, $y++, 0, 0, '%s=%s', $k, "$v"); | ||
|
||
$test->ffi->tb_present(); | ||
|
||
$test->screencap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if x or y are out of bounds is it going to fail?
I think it needs check as in tb_set_cell -> if_err_return(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
cellbuf_get
will return an error code if coords are out of bounds. There's a test assertion for this case here: https://github.com/termbox/termbox2/pull/65/files#diff-ff257682d1f1e118ed7186fee4abce09fca625c01728795e04d3c9a4fe95eadfR19