oscar64/include/c64/charwin.c

629 lines
9.5 KiB
C

#include "charwin.h"
static const unsigned mul40[25] = {
0, 40, 80, 120, 160,
200, 240, 280, 320, 360,
400, 440, 480, 520, 560,
600, 640, 680, 720, 760,
800, 840, 880, 920, 960
};
static void copy_fwd(char * sdp, const char * ssp, char * cdp, const char * csp, char n)
{
for(char i=0; i<n; i++)
{
sdp[i] = ssp[i];
cdp[i] = csp[i];
}
}
#pragma native(copy_fwd)
static void fill_fwd(char * sdp, char * cdp, char ch, char color, char n)
{
for(char i=0; i<n; i++)
{
sdp[i] = ch;
cdp[i] = color;
}
}
#pragma native(fill_fwd)
static void copy_bwd(char * sdp, const char * ssp, char * cdp, const char * csp, char n)
{
while (n)
{
n--;
sdp[n] = ssp[n];
cdp[n] = csp[n];
}
}
#pragma native(copy_bwd)
void cwin_init(CharWin * win, char * screen, char sx, char sy, char wx, char wy)
{
win->sx = sx;
win->sy = sy;
win->wx = wx;
win->wy = wy;
win->cx = 0;
win->cy = 0;
win->sp = screen + mul40[sy] + sx;
win->cp = (char *)0xd800 + mul40[sy] + sx;
}
void cwin_clear(CharWin * win)
{
cwin_fill(win, ' ', 1);
}
void cwin_fill(CharWin * win, char ch, char color)
{
char *sp = win->sp, * cp = win->cp;
for(char y=0; y<win->wy; y++)
{
fill_fwd(sp, cp, ch, color, win->wx);
sp += 40;
cp += 40;
}
}
void cwin_cursor_show(CharWin * win, bool show)
{
char * cp = win->sp + mul40[win->cy] + win->cx;
if (show)
*cp |= 0x80;
else
*cp &= 0x7f;
}
void cwin_cursor_move(CharWin * win, char cx, char cy)
{
win->cx = cx;
win->cy = cy;
}
bool cwin_cursor_left(CharWin * win)
{
if (win->cx > 0)
{
win->cx--;
return true;
}
return false;
}
bool cwin_cursor_right(CharWin * win)
{
if (win->cx + 1 < win->wx)
{
win->cx++;
return true;
}
return false;
}
bool cwin_cursor_up(CharWin * win)
{
if (win->cy > 0)
{
win->cy--;
return true;
}
return false;
}
bool cwin_cursor_down(CharWin * win)
{
if (win->cy + 1 < win->wy)
{
win->cy++;
return true;
}
return false;
}
bool cwin_cursor_newline(CharWin * win)
{
win->cx = 0;
if (win->cy + 1 < win->wy)
{
win->cy++;
return true;
}
return false;
}
bool cwin_cursor_forward(CharWin * win)
{
if (win->cx + 1 < win->wx)
{
win->cx++;
return true;
}
else if (win->cy + 1 < win->wy)
{
win->cx = 0;
win->cy++;
return true;
}
return false;
}
bool cwin_cursor_backward(CharWin * win)
{
if (win->cx > 0)
{
win->cx--;
return true;
}
else if (win->cy > 0)
{
win->cx = win->wx - 1;
win->cy--;
return true;
}
return false;
}
static char p2smap[] = {0x00, 0x20, 0x00, 0x40, 0x00, 0x60, 0x40, 0x60};
static char s2pmap[] = {0x40, 0x20, 0x60, 0xb0, 0x40, 0x20, 0x60, 0xb0};
static inline char p2s(char ch)
{
return (ch & 0x1f) | p2smap[ch >> 5];
}
static inline char s2p(char ch)
{
return (ch & 0x1f) | s2pmap[ch >> 5];
}
void cwin_read_string(CharWin * win, char * buffer)
{
char * sp = win->sp;
char i = 0;
for(char y=0; y<win->wy; y++)
{
for(char x=0; x<win->wx; x++)
{
buffer[i++] = s2p(sp[x]);
}
sp += 40;
}
while (i > 0 && buffer[i - 1] == ' ')
i--;
buffer[i] = 0;
}
void cwin_write_string(CharWin * win, const char * buffer)
{
char * dp = win->sp;
for(char y=0; y<win->wy; y++)
{
for(char x=0; x<win->wx; x++)
{
char ch = *buffer;
if (ch)
{
dp[x] = p2s(ch);
buffer++;
}
else
dp[x] = ' ';
}
dp += 40;
}
}
void cwin_put_char(CharWin * win, char ch, char color)
{
cwin_putat_char(win, win->cx, win->cy, ch, color);
win->cx++;
if (win->cx == win->wx)
{
win->cx = 0;
win->cy++;
}
}
void cwin_put_chars(CharWin * win, const char * chars, char num, char color)
{
cwin_putat_chars(win, win->cx, win->cy, chars, color);
win->cx += num;
if (win->cx >= win->wx)
{
win->cx = 0;
win->cy++;
}
}
char cwin_put_string(CharWin * win, const char * str, char color)
{
char n = cwin_putat_string(win, win->cx, win->cy, str, color);
win->cx += n;
if (win->cx >= win->wx)
{
win->cx = 0;
win->cy++;
}
return n;
}
void cwin_put_char_raw(CharWin * win, char ch, char color)
{
cwin_putat_char_raw(win, win->cx, win->cy, ch, color);
win->cx++;
if (win->cx == win->wx)
{
win->cx = 0;
win->cy++;
}
}
void cwin_put_chars_raw(CharWin * win, const char * chars, char num, char color)
{
cwin_putat_chars_raw(win, win->cx, win->cy, chars, color);
win->cx += num;
if (win->cx >= win->wx)
{
win->cx = 0;
win->cy++;
}
}
void cwin_putat_char(CharWin * win, char x, char y, char ch, char color)
{
int offset = mul40[y] + x;
win->sp[offset] = p2s(ch);
win->cp[offset] = color;
}
#pragma native(cwin_putat_char)
void cwin_putat_chars(CharWin * win, char x, char y, const char * chars, char num, char color)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
char * cp = win->cp + offset;
for(char i=0; i<num; i++)
{
char ch = chars[i];
sp[i] = p2s(ch);
cp[i] = color;
}
}
#pragma native(cwin_putat_chars)
char cwin_putat_string(CharWin * win, char x, char y, const char * str, char color)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
char * cp = win->cp + offset;
char i = 0;
while (char ch = str[i])
{
sp[i] = p2s(ch);
cp[i] = color;
i++;
}
return i;
}
#pragma native(cwin_putat_string)
void cwin_putat_char_raw(CharWin * win, char x, char y, char ch, char color)
{
int offset = mul40[y] + x;
win->sp[offset] = ch;
win->cp[offset] = color;
}
#pragma native(cwin_putat_char_raw)
void cwin_putat_chars_raw(CharWin * win, char x, char y, const char * chars, char num, char color)
{
int offset = mul40[y] + x;
char * sp = win->sp + offset;
char * cp = win->cp + offset;
for(char i=0; i<num; i++)
{
char ch = chars[i];
sp[i] = ch;
cp[i] = color;
}
}
#pragma native(cwin_putat_chars_raw)
char cwin_getat_char(CharWin * win, char x, char y)
{
char * sp = win->sp + mul40[y] + x;
return s2p(*sp);
}
#pragma native(cwin_getat_char)
void cwin_getat_chars(CharWin * win, char x, char y, char * chars, char num)
{
char * sp = win->sp + mul40[y] + x;
for(char i=0; i<num; i++)
{
chars[i] = s2p(sp[i]);
}
}
#pragma native(cwin_getat_chars)
char cwin_getat_char_raw(CharWin * win, char x, char y)
{
char * sp = win->sp + mul40[y] + x;
return *sp;
}
#pragma native(cwin_getat_char_raw)
void cwin_getat_chars_raw(CharWin * win, char x, char y, char * chars, char num)
{
char * sp = win->sp + mul40[y] + x;
for(char i=0; i<num; i++)
{
chars[i] = sp[i];
}
}
#pragma native(cwin_getat_chars_raw)
void cwin_insert_char(CharWin * win)
{
char y = win->wy - 1, rx = win->wx - 1;
char * sp = win->sp + mul40[y];
char * cp = win->cp + mul40[y];
while (y > win->cy)
{
copy_bwd(sp + 1, sp, cp + 1, cp, rx);
sp -= 40;
cp -= 40;
sp[40] = sp[rx];
cp[40] = cp[rx];
y--;
}
sp += win->cx;
cp += win->cx;
rx -= win->cx;
copy_bwd(sp + 1, sp, cp + 1, cp, rx);
sp[0] = ' ';
}
void cwin_delete_char(CharWin * win)
{
char * sp = win->sp + mul40[win->cy];
char * cp = win->cp + mul40[win->cy];
char x = win->cx, rx = win->wx - 1;
copy_fwd(sp + x, sp + x + 1, cp + x, cp + x + 1, rx - x);
char y = win->cy + 1;
while (y < win->wy)
{
sp[rx] = sp[40];
cp[rx] = cp[40];
sp += 40;
cp += 40;
copy_fwd(sp, sp + 1, cp, cp + 1, rx);
y++;
}
sp[rx] = ' ';
}
int cwin_getch(void)
{
__asm
{
L1:
jsr 0xffe4
cmp #0
beq L1
sta accu
lda #0
sta accu + 1
}
}
bool cwin_edit_char(CharWin * win, char ch)
{
switch (ch)
{
case 13:
case 3:
return true;
case 19:
win->cx = 0;
win->cy = 0;
return false;
case 147:
cwin_clear(win);
win->cx = 0;
win->cy = 0;
return false;
case 17:
cwin_cursor_down(win);
return false;
case 145: // CRSR_UP
cwin_cursor_up(win);
return false;
case 29:
cwin_cursor_forward(win);
return false;
case 157:
cwin_cursor_backward(win);
return false;
case 20:
if (cwin_cursor_backward(win))
cwin_delete_char(win);
return false;
default:
if (ch >= 32 && ch < 128 || ch >= 160)
{
if (win->cy + 1 < win->wy || win->cx + 1 < win->wx)
{
cwin_insert_char(win);
cwin_put_char(win, ch, 1);
}
}
return false;
}
}
char cwin_edit(CharWin * win)
{
for(;;)
{
cwin_cursor_show(win, true);
char ch = cwin_getch();
cwin_cursor_show(win, false);
if (cwin_edit_char(win, ch))
return ch;
}
}
void cwin_scroll_left(CharWin * win, char by)
{
char * sp = win->sp;
char * cp = win->cp;
char rx = win->wx - by;
for(char y=0; y<win->wy; y++)
{
copy_fwd(sp, sp + by, cp, cp + by, rx);
}
}
void cwin_scroll_right(CharWin * win, char by)
{
char * sp = win->sp;
char * cp = win->cp;
char rx = win->wx - by;
for(char y=0; y<win->wy; y++)
{
copy_bwd(sp + by, sp, cp + by, cp, rx);
sp += 40;
cp += 40;
}
}
void cwin_scroll_up(CharWin * win, char by)
{
char * sp = win->sp;
char * cp = win->cp;
char rx = win->wx;
int dst = mul40[by];
for(char y=0; y<win->wy - by; y++)
{
copy_fwd(sp, sp + dst, cp, cp + dst, rx);
sp += 40;
cp += 40;
}
}
void cwin_scroll_down(CharWin * win, char by)
{
char * sp = win->sp + mul40[win->wy];
char * cp = win->cp + mul40[win->wy];
char rx = win->wx;
int dst = mul40[by];
for(char y=0; y<win->wy - by; y++)
{
sp -= 40;
cp -= 40;
copy_fwd(sp, sp - dst, cp, cp - dst, rx);
}
}
void cwin_fill_rect_raw(CharWin * win, char x, char y, char w, char h, char ch, char color)
{
if (w > 0)
{
char * sp = win->sp + mul40[y] + x;
char * cp = win->cp + mul40[y] + x;
for(char y=0; y<h; y++)
{
fill_fwd(sp, cp, ch, color, w);
sp += 40;
cp += 40;
}
}
}
void cwin_fill_rect(CharWin * win, char x, char y, char w, char h, char ch, char color)
{
cwin_fill_rect_raw(win, x, y, w, h, p2s(ch), color);
}