2020-03-10 10:27:26 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2020-03-29 17:34:08 +00:00
|
|
|
#include "ui/curses.h"
|
|
|
|
#include "ui/draw.h"
|
2020-03-09 17:39:18 +00:00
|
|
|
|
|
|
|
@implementation DrawBuffer
|
|
|
|
|
2020-03-30 07:30:58 +00:00
|
|
|
+(DrawBuffer *)buffer:(Extent)size
|
2020-03-09 17:39:18 +00:00
|
|
|
{
|
2020-03-30 07:30:58 +00:00
|
|
|
return [[[self alloc] initWithSize: size] autorelease];
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- initWithSize: (Extent) size
|
|
|
|
{
|
|
|
|
if (!(self = [super init])) {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
buffer = obj_malloc (size.width * size.height);
|
|
|
|
self.size = size;
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2020-03-30 07:30:58 +00:00
|
|
|
-(void)dealloc
|
|
|
|
{
|
|
|
|
obj_free (buffer);
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2020-03-10 10:23:51 +00:00
|
|
|
- (Extent) size
|
|
|
|
{
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2020-03-23 11:14:32 +00:00
|
|
|
- (void) resizeTo: (Extent) newSize
|
|
|
|
{
|
|
|
|
size = newSize;
|
|
|
|
buffer = obj_realloc (buffer, size.width * size.height);
|
|
|
|
}
|
|
|
|
|
2020-03-10 10:23:51 +00:00
|
|
|
- (int *) buffer
|
|
|
|
{
|
|
|
|
return buffer;
|
|
|
|
}
|
2020-03-12 17:52:23 +00:00
|
|
|
- (Rect) rect
|
|
|
|
{
|
|
|
|
Rect rect = { nil, size };
|
|
|
|
return rect;
|
|
|
|
}
|
2020-03-10 10:23:51 +00:00
|
|
|
|
2020-03-09 17:39:18 +00:00
|
|
|
- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect
|
|
|
|
{
|
|
|
|
Extent srcSize = srcBuffer.size;
|
2020-03-12 17:09:55 +00:00
|
|
|
Rect r = { {}, size };
|
2020-03-09 17:39:18 +00:00
|
|
|
Rect t = { pos, rect.extent };
|
|
|
|
|
2020-03-17 16:39:12 +00:00
|
|
|
wprintf (stdscr, "src: %p\n", srcBuffer);
|
|
|
|
wprintf (stdscr, "srcSize: %d %d\n", srcSize.width, srcSize.height);
|
|
|
|
|
2020-03-09 17:39:18 +00:00
|
|
|
t = clipRect (r, t);
|
|
|
|
if (t.extent.width < 0 || t.extent.height < 0) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
rect.offset.x += t.offset.x - pos.x;
|
|
|
|
rect.offset.y += t.offset.y - pos.y;
|
|
|
|
rect.extent = t.extent;
|
|
|
|
pos = t.offset;
|
|
|
|
|
|
|
|
r.offset = nil;
|
|
|
|
r.extent = size;
|
|
|
|
|
|
|
|
rect = clipRect (r, rect);
|
|
|
|
if (rect.extent.width < 0 || rect.extent.height < 0) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
int *dst = buffer + pos.y * size.width + pos.x;
|
|
|
|
int *src = srcBuffer.buffer
|
|
|
|
+ rect.offset.y * srcSize.width + rect.offset.x;
|
|
|
|
for (int y = 0; y < rect.extent.height; y++) {
|
|
|
|
int *d = dst;
|
|
|
|
int *s = src;
|
|
|
|
dst += size.width;
|
|
|
|
src += srcSize.width;
|
|
|
|
for (int x = 0; x < rect.extent.width; x++) {
|
|
|
|
// FIXME 1) need memcpy/memmove
|
|
|
|
// 2) the generated code could be better
|
2020-03-17 16:40:58 +00:00
|
|
|
// github issue #3
|
2020-03-09 17:39:18 +00:00
|
|
|
*d++ = *s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2020-03-28 00:41:54 +00:00
|
|
|
- clearReact: (Rect) rect
|
|
|
|
{
|
|
|
|
Point pos = rect.offset;
|
|
|
|
int len = rect.extent.width;
|
|
|
|
int count = rect.extent.height;
|
|
|
|
|
|
|
|
if (pos.x + len > size.width) {
|
|
|
|
len = size.width - pos.x;
|
|
|
|
}
|
|
|
|
if (pos.x < 0) {
|
|
|
|
len += pos.x;
|
|
|
|
pos.x = 0;
|
|
|
|
}
|
|
|
|
if (len < 1) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
if (pos.y + count > size.height) {
|
|
|
|
count = size.height - pos.y;
|
|
|
|
}
|
|
|
|
if (pos.y < 0) {
|
|
|
|
count += pos.y;
|
|
|
|
pos.y = 0;
|
|
|
|
}
|
|
|
|
if (count < 1) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
int width = size.width;
|
|
|
|
int ch = background;
|
|
|
|
if (!(ch & 0xff)) {
|
|
|
|
ch |= ' ';
|
|
|
|
}
|
|
|
|
while (count-- > 0) {
|
|
|
|
int *p = buffer + pos.y * width + pos.x;
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
*p++ = ch;
|
|
|
|
}
|
|
|
|
pos.y++;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2020-03-19 09:37:25 +00:00
|
|
|
- (void) bkgd: (int) ch
|
|
|
|
{
|
|
|
|
background = ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) clear
|
|
|
|
{
|
|
|
|
int ch = background;
|
|
|
|
int *dst = buffer;
|
|
|
|
int *end = buffer + size.width * size.height;
|
|
|
|
|
2020-03-19 11:39:23 +00:00
|
|
|
if (ch && !(ch & 0xff)) {
|
|
|
|
ch |= ' ';
|
|
|
|
}
|
2020-03-19 09:37:25 +00:00
|
|
|
while (dst < end) {
|
|
|
|
*dst++ = ch;
|
|
|
|
}
|
|
|
|
cursor = {0, 0};
|
|
|
|
}
|
|
|
|
|
2020-03-09 17:39:18 +00:00
|
|
|
- (void) printf: (string) fmt, ...
|
|
|
|
{
|
2020-03-10 10:27:26 +00:00
|
|
|
string str = vsprintf (fmt, @args);
|
|
|
|
[self addstr: str];
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) vprintf: (string) fmt, @va_list args
|
|
|
|
{
|
2020-03-10 10:27:26 +00:00
|
|
|
string str = vsprintf (fmt, args);
|
|
|
|
[self addstr: str];
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) addch: (int) ch
|
|
|
|
{
|
2020-03-10 10:27:26 +00:00
|
|
|
if (cursor.x < 0) {
|
|
|
|
cursor.x = 0;
|
|
|
|
}
|
|
|
|
if (cursor.y < 0) {
|
|
|
|
cursor.y = 0;
|
|
|
|
}
|
|
|
|
if (cursor.x >= size.width && cursor.y < size.height) {
|
|
|
|
cursor.x = 0;
|
|
|
|
cursor.y++;
|
|
|
|
}
|
|
|
|
if (cursor.y >= size.height) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (ch == '\n') {
|
|
|
|
cursor.x = 0;
|
|
|
|
cursor.y++;
|
|
|
|
} else if (ch == '\r') {
|
|
|
|
cursor.x = 0;
|
2020-03-19 11:39:23 +00:00
|
|
|
} else {
|
2020-03-19 09:37:25 +00:00
|
|
|
if (!(ch & ~0xff)) {
|
|
|
|
ch |= background & ~0xff;
|
|
|
|
}
|
2020-03-10 10:27:26 +00:00
|
|
|
buffer[cursor.y * size.width + cursor.x++] = ch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) addstr: (string) str
|
|
|
|
{
|
|
|
|
int ind = 0;
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
if (cursor.y >= size.height) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (cursor.x < size.width && (ch = str_char (str, ind++))) {
|
|
|
|
[self addch: ch];
|
|
|
|
}
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) mvprintf: (Point) pos, string fmt, ...
|
|
|
|
{
|
2020-03-10 10:27:26 +00:00
|
|
|
if (pos.x < 0 || pos.x >= size.width
|
|
|
|
|| pos.y < 0 || pos.y >= size.height) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cursor = pos;
|
|
|
|
string str = vsprintf (fmt, @args);
|
|
|
|
[self addstr: str];
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) mvvprintf: (Point) pos, string fmt, @va_list args
|
|
|
|
{
|
2020-03-10 10:27:26 +00:00
|
|
|
if (pos.x < 0 || pos.x >= size.width
|
|
|
|
|| pos.y < 0 || pos.y >= size.height) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cursor = pos;
|
|
|
|
string str = vsprintf (fmt, args);
|
|
|
|
[self addstr: str];
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) mvaddch: (Point) pos, int ch
|
|
|
|
{
|
2020-03-10 10:27:26 +00:00
|
|
|
if (pos.x < 0 || pos.x >= size.width
|
|
|
|
|| pos.y < 0 || pos.y >= size.height) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cursor = pos;
|
|
|
|
[self addch: ch];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) mvaddstr: (Point) pos, string str
|
|
|
|
{
|
|
|
|
if (pos.x < 0 || pos.x >= size.width
|
|
|
|
|| pos.y < 0 || pos.y >= size.height) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cursor = pos;
|
|
|
|
[self addstr: str];
|
2020-03-09 17:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|