[qwaq] Start work on the actual app

It doesn't look good, but it does have panel based windows working, and
using objects. Won't build reliably right now due to qwaq being in tools
and thus building before ruamoko, but I'll fix that next.
This commit is contained in:
Bill Currie 2020-03-01 00:40:55 +09:00
parent 271d836cd2
commit c079eb851b
10 changed files with 540 additions and 42 deletions

View file

@ -57,11 +57,11 @@ qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS)
r_depfiles_remade=
qwaq_app_dat_SOURCES=qwaq-app.r
qwaq_app_dat_SOURCES=qwaq-app.r qwaq-view.r qwaq-window.r
qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o)
qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo))
qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP)
$(QFCC) $(QCFLAGS) -o $@ $(qwaq_app_obj)
$(QFCC) $(QCFLAGS) -o $@ $(qwaq_app_obj) -lr
include $(qwaq_app_dep) # am--include-marker
r_depfiles_remade += $(qwaq_app_dep)

View file

@ -2,22 +2,33 @@
#define __qwaq_event_h
typedef enum {
qe_idle,
qe_none,
qe_key,
qe_mouse,
qe_command, // application level command
} qwaq_etype;
// right now, this is just a copy of ncurses MEVENT, but all int
typedef enum {
qc_valid,
qc_exit,
qc_error,
} qwaq_command;
typedef struct qwaq_mevent_s {
int x, y;
int buttons;
} qwaq_mevent_t;
typedef struct qwaq_message_s {
qwaq_command command;
} qwaq_message_t;
typedef struct qwaq_event_s {
qwaq_etype event_type;
union {
int key;
qwaq_mevent_t mouse;
qwaq_message_t message;
} e;
} qwaq_event_t;

18
tools/qwaq/qwaq-app.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef __qwaq_app_h
#define __qwaq_app_h
#include "qwaq-view.h"
#include "event.h"
@interface QwaqApplication: Object
{
qwaq_event_t event;
qwaq_command endState;
View *view;
}
-run;
-handleEvent: (qwaq_event_t *) event;
@end
#endif//__qwaq_app_h

View file

@ -1,7 +1,97 @@
#include "color.h"
#include "event.h"
#include <AutoreleasePool.h>
typedef struct window_s *window_t;
#include "color.h"
#include "qwaq-app.h"
#include "qwaq-curses.h"
#include "qwaq-window.h"
static AutoreleasePool *autorelease_pool;
static void
arp_start (void)
{
autorelease_pool = [[AutoreleasePool alloc] init];
}
static void
arp_end (void)
{
[autorelease_pool release];
autorelease_pool = nil;
}
@implementation QwaqApplication
+app
{
return [[[self alloc] init] autorelease];
}
-init
{
if (!(self = [super init])) {
return nil;
}
initialize ();
init_pair (1, COLOR_WHITE, COLOR_BLUE);
init_pair (2, COLOR_WHITE, COLOR_BLACK);
view = [[View viewFromWindow:stdscr] retain];
[view setBackground: COLOR_PAIR (1)];
Rect r = view.rect;
wprintf (view.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen);
r.xpos = r.xlen / 4;
r.ypos = r.ylen / 4;
r.xlen /= 2;
r.ylen /= 2;
wprintf (view.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen);
wrefresh(view.window);
Window *w;
[view addView: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]];
wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen);
return self;
}
-run
{
do {
arp_start ();
update_panels ();
doupdate ();
get_event (&event);
if (event.event_type != qe_none) {
[self handleEvent: &event];
}
arp_end ();
} while (!endState);
return self;
}
-handleEvent: (qwaq_event_t *) event
{
[view handleEvent: event];
if (event.event_type == qe_key && event.e.key == '\x18') {
event.event_type = qe_command;
event.e.message.command = qc_exit;
}
if (event.event_type == qe_command
&& (event.e.message.command == qc_exit
|| event.e.message.command == qc_error)) {
endState = event.e.message.command;
}
return self;
}
@end
int main (int argc, string *argv)
{
id app = [[QwaqApplication app] retain];
[app run];
[app release];
qwaq_event_t event;
get_event (&event); // XXX need a "wait for queue idle"
return 0;
}
window_t stdscr = (window_t) 1;
@ -9,45 +99,21 @@ void initialize (void) = #0;
window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0;
void destroy_window (window_t win) = #0;
void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0;
void wprintf (window_t win, string fmt, ...) = #0;
void wrefresh (window_t win) = #0;
int get_event (qwaq_event_t *event) = #0;
int max_colors (void) = #0;
int max_color_pairs (void) = #0;
int init_pair (int pair, int f, int b) = #0;
void wbkgd (window_t win, int ch) = #0;
int main (int argc, string *argv)
{
int ch = 0;
qwaq_event_t event = { };
initialize ();
init_pair (1, COLOR_WHITE, COLOR_BLUE);
wbkgd (stdscr, COLOR_PAIR(1));
wrefresh (stdscr);
window_t win = create_window (20, 5, 50, 10);
wbkgd (win, COLOR_PAIR(0));
mvwprintf (win, 0, 0, "Hi there! (q to quit)");
mvwprintf (win, 1, 1, "(?)Oo.");
mvwprintf (win, 1, 2, " \\_O>");
mvwprintf (win, 1, 3, " %d %d", max_colors (), max_color_pairs ());
wrefresh (win);
do {
if (get_event (&event)) {
if (event.event_type == qe_key) {
ch = event.e.key;
mvwprintf (win, 1, 1, "key: %d", ch);
} else if (event.event_type == qe_mouse) {
mvwprintf (win, 1, 2, "mouse: %2d %2d %08x",
event.e.mouse.x,
event.e.mouse.y,
event.e.mouse.buttons);
}
wrefresh (win);
}
} while (ch != 'q' && ch != 'Q');
destroy_window (win);
get_event (&event);
return 0;
}
panel_t create_panel (window_t window) = #0;
void destroy_panel (panel_t panel) = #0;
void hide_panel (panel_t panel) = #0;
void show_panel (panel_t panel) = #0;
void top_panel (panel_t panel) = #0;
void bottom_panel (panel_t panel) = #0;
void move_panel (panel_t panel, int x, int y) = #0;
window_t panel_window (panel_t panel) = #0;
void update_panels (void) = #0;
void doupdate (void) = #0;

View file

@ -55,6 +55,7 @@
typedef enum qwaq_commands_e {
qwaq_cmd_newwin,
qwaq_cmd_delwin,
qwaq_cmd_getwrect,
qwaq_cmd_new_panel,
qwaq_cmd_del_panel,
qwaq_cmd_hide_panel,
@ -62,7 +63,11 @@ typedef enum qwaq_commands_e {
qwaq_cmd_top_panel,
qwaq_cmd_bottom_panel,
qwaq_cmd_move_panel,
qwaq_cmd_panel_window,
qwaq_cmd_update_panels,
qwaq_cmd_doupdate,
qwaq_cmd_mvwaddstr,
qwaq_cmd_waddstr,
qwaq_cmd_wrefresh,
qwaq_cmd_init_pair,
qwaq_cmd_wbkgd,
@ -141,6 +146,7 @@ typedef struct window_s {
typedef struct panel_s {
PANEL *panel;
int window_id;
} panel_t;
typedef struct qwaq_resources_s {
@ -297,6 +303,28 @@ cmd_delwin (qwaq_resources_t *res)
window_free (res, window);
}
static void
cmd_getwrect (qwaq_resources_t *res)
{
int window_id = RB_PEEK_DATA (res->command_queue, 2);
int xpos, ypos;
int xlen, ylen;
window_t *window = get_window (res, __FUNCTION__, window_id);
getparyx (window->win, ypos, xpos);
if (xpos == -1 && ypos ==-1) {
getbegyx (window->win, ypos, xpos);
}
getmaxyx (window->win, ylen, xlen);
int cmd_result[] = { qwaq_cmd_getwrect, xpos, ypos, xlen, ylen };
// loop
if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) {
RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result));
}
}
static void
cmd_new_panel (qwaq_resources_t *res)
{
@ -305,6 +333,7 @@ cmd_new_panel (qwaq_resources_t *res)
window_t *window = get_window (res, __FUNCTION__, window_id);
panel_t *panel = panel_new (res);
panel->panel = new_panel (window->win);
panel->window_id = window_id;
int panel_id = panel_index (res, panel);
int cmd_result[] = { qwaq_cmd_new_panel, panel_id };
@ -377,6 +406,34 @@ cmd_move_panel (qwaq_resources_t *res)
panel_free (res, panel);
}
static void
cmd_panel_window (qwaq_resources_t *res)
{
int panel_id = RB_PEEK_DATA (res->command_queue, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
int window_id = panel->window_id;
int cmd_result[] = { qwaq_cmd_panel_window, window_id, };
// loop
if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) {
RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result));
}
}
static void
cmd_update_panels (qwaq_resources_t *res)
{
update_panels ();
}
static void
cmd_doupdate (qwaq_resources_t *res)
{
doupdate ();
}
static void
cmd_mvwaddstr (qwaq_resources_t *res)
{
@ -390,6 +447,17 @@ cmd_mvwaddstr (qwaq_resources_t *res)
release_string (res, string_id);
}
static void
cmd_waddstr (qwaq_resources_t *res)
{
int window_id = RB_PEEK_DATA (res->command_queue, 2);
int string_id = RB_PEEK_DATA (res->command_queue, 3);
window_t *window = get_window (res, __FUNCTION__, window_id);
waddstr (window->win, res->strings[string_id].str);
release_string (res, string_id);
}
static void
cmd_wrefresh (qwaq_resources_t *res)
{
@ -430,6 +498,9 @@ process_commands (qwaq_resources_t *res)
case qwaq_cmd_delwin:
cmd_delwin (res);
break;
case qwaq_cmd_getwrect:
cmd_getwrect (res);
break;
case qwaq_cmd_new_panel:
cmd_new_panel (res);
break;
@ -451,9 +522,21 @@ process_commands (qwaq_resources_t *res)
case qwaq_cmd_move_panel:
cmd_move_panel (res);
break;
case qwaq_cmd_panel_window:
cmd_panel_window (res);
break;
case qwaq_cmd_update_panels:
cmd_update_panels (res);
break;
case qwaq_cmd_doupdate:
cmd_doupdate (res);
break;
case qwaq_cmd_mvwaddstr:
cmd_mvwaddstr (res);
break;
case qwaq_cmd_waddstr:
cmd_waddstr (res);
break;
case qwaq_cmd_wrefresh:
cmd_wrefresh (res);
break;
@ -583,6 +666,37 @@ bi_delwin (progs_t *pr)
}
}
static void
bi_getwrect (progs_t *pr)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq");
int window_id = P_INT (pr, 0);
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_getwrect, 0, window_id, };
command[1] = CMD_SIZE(command);
if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) {
RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command));
}
// XXX should just wait on the mutex
process_commands (res);
process_input (res);
// locking and loop until id is correct
if (RB_DATA_AVAILABLE (res->results)
&& RB_PEEK_DATA (res->results, 0) == qwaq_cmd_getwrect) {
int cmd_result[5];
RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result));
// return xpos, ypos, xlen, ylen
(&R_INT (pr))[0] = cmd_result[1];
(&R_INT (pr))[1] = cmd_result[2];
(&R_INT (pr))[2] = cmd_result[3];
(&R_INT (pr))[3] = cmd_result[4];
}
}
}
static void
bi_new_panel (progs_t *pr)
{
@ -672,6 +786,58 @@ bi_move_panel (progs_t *pr)
}
}
static void
bi_panel_window (progs_t *pr)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq");
int panel_id = P_INT (pr, 0);
if (get_panel (res, __FUNCTION__, panel_id)) {
int command[] = { qwaq_cmd_panel_window, 0, panel_id, };
command[1] = CMD_SIZE(command);
if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) {
RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command));
}
// XXX should just wait on the mutex
process_commands (res);
process_input (res);
// locking and loop until id is correct
if (RB_DATA_AVAILABLE (res->results)
&& RB_PEEK_DATA (res->results, 0) == qwaq_cmd_panel_window) {
int cmd_result[2];
RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result));
(&R_INT (pr))[0] = cmd_result[0];
}
}
}
static void
bi_update_panels (progs_t *pr)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq");
int command[] = { qwaq_cmd_update_panels, 0, };
command[1] = CMD_SIZE(command);
if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) {
RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command));
}
}
static void
bi_doupdate (progs_t *pr)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq");
int command[] = { qwaq_cmd_doupdate, 0, };
command[1] = CMD_SIZE(command);
if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) {
RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command));
}
}
static void
bi_mvwprintf (progs_t *pr)
{
@ -701,6 +867,33 @@ bi_mvwprintf (progs_t *pr)
}
}
static void
bi_wprintf (progs_t *pr)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq");
int window_id = P_INT (pr, 0);
const char *fmt = P_GSTRING (pr, 1);
int count = pr->pr_argc - 2;
pr_type_t **args = pr->pr_params + 2;
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = acquire_string (res);
dstring_t *print_buffer = res->strings + string_id;
int command[] = {
qwaq_cmd_waddstr, 0,
window_id, string_id
};
command[1] = CMD_SIZE(command);
dstring_clearstr (print_buffer);
PR_Sprintf (pr, print_buffer, "waddstr", fmt, count, args);
if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) {
RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command));
}
}
}
static void
bi_wrefresh (progs_t *pr)
{
@ -813,6 +1006,7 @@ static builtin_t builtins[] = {
{"initialize", bi_initialize, -1},
{"create_window", bi_newwin, -1},
{"destroy_window", bi_delwin, -1},
{"getwrect", bi_getwrect, -1},
{"create_panel", bi_new_panel, -1},
{"destroy_panel", bi_del_panel, -1},
{"hide_panel", bi_hide_panel, -1},
@ -820,7 +1014,11 @@ static builtin_t builtins[] = {
{"top_panel", bi_top_panel, -1},
{"bottom_panel", bi_bottom_panel, -1},
{"move_panel", bi_move_panel, -1},
{"panel_window", bi_panel_window, -1},
{"update_panels", bi_update_panels, -1},
{"doupdate", bi_doupdate, -1},
{"mvwprintf", bi_mvwprintf, -1},
{"wprintf", bi_wprintf, -1},
{"wrefresh", bi_wrefresh, -1},
{"get_event", bi_get_event, -1},
{"max_colors", bi_max_colors, -1},

37
tools/qwaq/qwaq-curses.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef __qwaq_curses_h
#define __qwaq_curses_h
#include "event.h"
#ifdef __QFCC__
typedef struct window_s *window_t;
typedef struct panel_s *panel_t;
@extern window_t stdscr;
@extern void initialize (void);
@extern window_t create_window (int xpos, int ypos, int xlen, int ylen);
@extern void destroy_window (window_t win);
@extern void mvwprintf (window_t win, int x, int y, string fmt, ...);
@extern void wprintf (window_t win, string fmt, ...);
@extern void wrefresh (window_t win);
@extern panel_t create_panel (window_t window);
@extern void destroy_panel (panel_t panel);
@extern void hide_panel (panel_t panel);
@extern void show_panel (panel_t panel);
@extern void top_panel (panel_t panel);
@extern void bottom_panel (panel_t panel);
@extern void move_panel (panel_t panel, int x, int y);
@extern window_t panel_window (panel_t panel);
@extern void update_panels (void);
@extern void doupdate (void);
@extern int get_event (qwaq_event_t *event);
@extern int max_colors (void);
@extern int max_color_pairs (void);
@extern int init_pair (int pair, int f, int b);
@extern void wbkgd (window_t win, int ch);
#endif
#endif//__qwaq_curses_h

44
tools/qwaq/qwaq-view.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef __qwaq_view_h
#define __qwaq_view_h
#include <Array.h>
#include <Object.h>
#include "event.h"
#include "qwaq-curses.h"
typedef struct {
int xpos;
int ypos;
int xlen;
int ylen;
} Rect;
typedef struct {
int x;
int y;
} Point;
@extern Rect makeRect (int xpos, int ypos, int xlen, int ylen);
//XXX will not work if point or rect point to a local variabl
@extern int rectContainsPoint (Rect *rect, Point *point);
@extern Rect getwrect (window_t window);
@interface View: Object
{
Rect rect;
Rect absRect;
Array *views;
Point point; // can't be local :(
View *focusedView;
window_t window;
panel_t panel;
}
+viewFromWindow: (window_t) window;
-initWithRect: (Rect) rect;
-handleEvent: (qwaq_event_t *) event;
-addView: (View *) view;
-setBackground: (int) ch;
@end
#endif//__qwaq_view_h

105
tools/qwaq/qwaq-view.r Normal file
View file

@ -0,0 +1,105 @@
#include "qwaq-curses.h"
#include "qwaq-view.h"
Rect
makeRect (int xpos, int ypos, int xlen, int ylen)
{
Rect rect = {xpos, ypos, xlen, ylen};
return rect;
}
int
rectContainsPoint (Rect *rect, Point *point)
{
return ((point.x >= rect.xpos && point.x < rect.xpos + rect.xlen)
&& (point.y >= rect.ypos && point.y < rect.ypos + rect.ylen));
}
@implementation View
+viewFromWindow: (window_t) window
{
return [[[self alloc] initFromWindow: window] autorelease];
}
-initWithRect: (Rect) rect
{
if (!(self = [super init])) {
return nil;
}
self.rect = rect;
self.absRect = rect;
self.window = create_window (rect.xpos, rect.ypos, rect.xlen, rect.ylen);
self.panel = create_panel (self.window);
return self;
}
-initFromWindow: (window_t) window
{
if (!(self = [super init])) {
return nil;
}
rect = getwrect (window);
self.window = window;
self.panel = nil;
return self;
}
-initWithPanel: (panel_t) panel
{
if (!(self = [super init])) {
return nil;
}
self.panel = panel;
self.window = panel_window (panel);
rect = getwrect (window);
return self;
}
-addView: (View *) view
{
[views addObject: view];
return self;
}
-setBackground: (int) ch
{
wbkgd (window, ch);
if (!panel) {
wrefresh (window);
}
return self;
}
-handleEvent: (qwaq_event_t *) event
{
switch (event.event_type) {
case qe_mouse:
point.x = event.e.mouse.x;
point.y = event.e.mouse.y;
for (int i = [views count]; i--> 0; ) {
View *v = [views objectAtIndex: i];
if (rectContainsPoint (&v.absRect, &point)) {
[v handleEvent: event];
break;
}
}
break;
case qe_key:
case qe_command:
if (focusedView) {
[focusedView handleEvent: event];
for (int i = [views count];
event.event_type != qe_none && i--> 0; ) {
View *v = [views objectAtIndex: i];
[v handleEvent: event];
}
}
break;
}
return self;
}
@end
Rect getwrect (window_t window) = #0;

11
tools/qwaq/qwaq-window.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef __qwaq_window_h
#define __qwaq_window_h
#include "qwaq-view.h"
@interface Window: View
{
}
@end
#endif//__qwaq_window_h

8
tools/qwaq/qwaq-window.r Normal file
View file

@ -0,0 +1,8 @@
#include "qwaq-window.h"
@implementation Window
+windowWithRect: (Rect) rect
{
return [[[self alloc] initWithRect: rect] autorelease];
}
@end