From d0b38926d4771956f3d3e2ab4513a406d784a7e1 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Thu, 29 Jun 2017 15:04:35 +0000 Subject: [PATCH] added more X11 code related to GC handling --- moo/kernel/X11.moo | 268 +++++++++++++++++++++----------- moo/lib/main.c | 6 + moo/lib/moo-cmn.h | 4 + moo/mod/_x11.h | 42 +++-- moo/mod/x11.c | 372 ++++++++++++++++++++++++++++++++++++--------- 5 files changed, 518 insertions(+), 174 deletions(-) diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 3a95ad4..ce42503 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -7,10 +7,6 @@ class X11(Object) from 'x11' ## definition struct x11_t defined in _x11.h ## --------------------------------------------------------------------- var display_base := nil. - var expose_event. - var key_event. - var mouse_event. - var mouse_wheel_event. ## ===================================================================== var shell_container := nil. @@ -24,16 +20,21 @@ class X11(Object) from 'x11' method(#primitive) _get_fd. method(#primitive) _get_llevent(llevent). - method(#primitive) _create_window(parent_window, x, y, width, height, fgcolor, bgcolor). - method(#primitive) _destroy_window(window). + method(#primitive) _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor). + method(#primitive) _destroy_window(window_handle). - ##method(#primitive) _fill_rectangle(window, gc, x, y, width, height). - method(#primitive) _draw_rectangle(window, gc, x, y, width, height). + method(#primitive) _create_gc (window_handle). + method(#primitive) _destroy_gc (gc). ## note this one accepts a GC object. + method(#primitive) _apply_gc (gc). ## note this one accepts a GC object, not a GC handle. - method __create_window(parent_window, x, y, width, height, fgcolor, bgcolor, owner) + method(#primitive) _draw_rectangle(window_handle, gc_handle, x, y, width, height). + method(#primitive) _fill_rectangle(window_handle, gc_handle, x, y, width, height). + method(#primitive) _draw_string(gc, x, y, string). + + method __create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor, owner) { | w | - w := self _create_window(parent_window, x, y, width, height, fgcolor, bgcolor). + w := self _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor). if (w notError) { self.window_registrar at: w put: owner }. ^w } @@ -141,16 +142,41 @@ class X11.ExposeEvent(X11.Event) ## --------------------------------------------------------------------------- ## X11 Context ## --------------------------------------------------------------------------- -class X11.GraphicsContext(Object) +pooldic X11.GCLineStyle { + SOLID := 0. + ON_OFF_DASH := 1. + DOUBLE_DASH := 2. +} + +pooldic X11.GCFillStyle +{ + SOLID := 0. + TILED := 1. + STIPPLED := 2. + OPAQUE_STIPPLED := 3. +} + +class X11.GC(Object) +{ + ## note these fields must match the x11_gc_t structure defined in _x11.h + var(#get) widget := nil, gcHandle := nil. var(#get,#set) foreground := 0, - background := 0, + background := 1, lineWidth := 1, - lineStyle := 0, - fillStyle := 0. + lineStyle := X11.GCLineStyle.SOLID, + fillStyle := X11.GCFillStyle.SOLID, + fontName := nil. + + var fontPtr := nil. + + method(#class) new + { + self messageProhibited: #new. + } method(#class) new: widget { @@ -160,20 +186,47 @@ class X11.GraphicsContext(Object) method __make_gc_on: widget { | gc | +widget displayServer dump. +widget windowHandle dump. gc := widget displayServer _create_gc (widget windowHandle). if (gc isError) { selfns.Exception signal: 'Cannot create a graphics context' }. self.gcHandle := gc. self.widget := widget. } + method drawRectangle(x, y, width, height) + { + ^self.widget displayServer _draw_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height). + } + method fillRectangle(x, y, width, height) { ^self.widget displayServer _fill_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height). } - method drawRectangle(x, y, width, height) + method drawString(x, y, string) { - ^self.widget displayServer _draw_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height). + ^self.widget displayServer _draw_string (self, x, y, string). + } + + method dispose + { + if (self.gcHandle notNil) + { + self.widget displayServer _destroy_gc (self). + self.gcHandle := nil + } + } + + method apply + { + if (self.gcHandle notNil) + { + if (self.widget displayServer _apply_gc (self) isError) + { + X11.Exception signal: 'Cannot apply GC settings' + } + } } } @@ -183,44 +236,71 @@ class X11.GraphicsContext(Object) class X11.Widget(Object) { + var(#get) windowHandle := nil. + var(#get,#set) parent := nil, x := 0, y := 0, width := 0, height := 0, - fgcolor := 0, + fgcolor := 16r1188FF, bgcolor := 0, realized := false. - method displayServer { if (self.parent isNil) { ^nil }. ^self.parent displayServer. } - method windowHandle + method parentWindowHandle { - (* i assume that a widget doesn't' with a low-level window by default. - * if a widget maps to a window, the widget class must implement the - * windowHandle method to return the low-level window handle. - * if it doesn't map to a window, it piggybacks on the parent's window *) if (self.parent isNil) { ^nil }. ^self.parent windowHandle. } - - method realize { } - method dispose + method realize { -'Widget dispose XXXXXXXXXXXXXX' dump. + | disp wind | + + if (self.windowHandle notNil) { ^self }. + + disp := self displayServer. + if (disp isNil) + { + X11.Exception signal: 'Cannot realize a widget not added to a display server' + }. + + wind := disp __create_window(self parentWindowHandle, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor, self). + if (wind isError) + { + self.Exception signal: 'Cannot create widget window'. + }. + + self.windowHandle := wind. } + method dispose + { + | disp | + +'Widget dispose XXXXXXXXXXXXXX' dump. + disp := self displayServer. + if (disp notNil) + { + if (self.windowHandle notNil) + { + disp __destroy_window (self.windowHandle). + self.windowHandle := nil. + }. + } + } method onPaintEvent: paint_event { +System logNl: 'Widget...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'. } method onButtonEvent: event @@ -232,6 +312,7 @@ class X11.Widget(Object) } } + class X11.Label(X11.Widget) { var(#get) text := ''. @@ -242,20 +323,9 @@ class X11.Label(X11.Widget) if (self windowHandle notNil) { self onPaintEvent: nil } } - method onPaintEvent: paint_event - { - | gc | -System logNl: 'LABEL GC.......'. - gc := selfns.GraphicsContext new: self. - gc foreground: 100. - gc drawRectangle (self.x, self.y, self.width, self.height). - ###gc.drawText (self.title) - } - method realize { - ## if i want to use a window to represent it, it must create window here. - ## otherwise, do other works in onPaintEvent:??? + super realize. } method dispose @@ -263,6 +333,25 @@ System logNl: 'LABEL GC.......'. 'Label dispose XXXXXXXXXXXXXX' dump. super dispose. } + + method onPaintEvent: paint_event + { + | gc | +System logNl: 'LABEL GC...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'. + + gc := selfns.GC new: self. + [ + gc foreground: self.fgcolor; + fontName: '-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1'; + apply. + gc drawRectangle (0, 0, self.width - 1, self.height - 1). + ##gc fillRectangle (0, 0, self.width, self.height). + ##gc drawLine (0, y, CTRLWIDE, y). + ##gc drawLine (0, y + CHIGH + 4, CTRLWIDE, Y+CHIGH+4). + + gc drawString(10, 10, self.text). + ] ensure: [ gc dispose ] + } } class X11.Composite(X11.Widget) @@ -303,13 +392,33 @@ class X11.Composite(X11.Widget) ^self.children size } + method realize + { + super realize. + [ + self.children do: [:child | child realize ]. + ] on: System.Exception do: [:ex | + self dispose. + ex pass + ]. + } + method dispose { 'Composite dispose XXXXXXXXXXXXXX' dump. - super dispose. self.children do: [:child | child dispose. self remove: child. + ]. + super dispose + } + + method onPaintEvent: event + { + super onPaintEvent: event. + self.children do: [:child | + ## TODO: adjust event relative to each child... + child onPaintEvent: event. ] } } @@ -318,13 +427,16 @@ class X11.Shell(X11.Composite) { var(#get) title := ''. var(#get,#set) displayServer := nil. - var(#get) windowHandle := nil. method new: title { self.title := title. } +#### TODO: +#### redefine x:, y:, width:, height: to return actual geometry values... +#### + method title: title { self.title := title. @@ -336,50 +448,15 @@ class X11.Shell(X11.Composite) method realize { - | wind | - - if (self.windowHandle notNil) { ^self }. - if (self.displayServer isNil) - { - ## not added to a display server. - X11.Exception signal: 'Cannot realize a shell not added to a display server' - }. - - wind := self.displayServer __create_window(nil, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor, self). - if (wind isError) - { - self.Exception signal: ('Cannot create shell ' & self.title). - }. - - self.windowHandle := wind. - - [ - self.children do: [:child | child realize ]. - ] on: System.Exception do: [:ex | - self.displayServer __destroy_window(wind). - self.windowHandle := nil. - ex pass - ]. - -### call displayOn: from the exposure handler... -self onPaintEvent: nil. +'SHELL REALIZE XXXXXXXXXXX' dump. + super realize. } method dispose { 'Shell dispose XXXXXXXXXXXXXX' dump. - if (self.displayServer notNil) - { - if (self.windowHandle notNil) - { - super dispose. - - self.displayServer __destroy_window (self.windowHandle). - self.windowHandle := nil. - }. - - self.displayServer removeShell: self. - } + super dispose. + self.displayServer removeShell: self. } method onCloseEvent @@ -404,8 +481,7 @@ extend X11 if (self _open_display(name) isError) { self.Exception signal: 'cannot open display' - } -. + }. self.display_base dump. } @@ -420,7 +496,7 @@ extend X11 if (self.display_base notNil) { self _close_display. - ##self.display_base := nil. + self.display_base := nil. }. } @@ -428,11 +504,6 @@ extend X11 { super initialize. - self.expose_event := self.ExposeEvent new. - self.key_event := self.KeyEvent new. - self.mouse_event := self.MouseEvent new. - self.mouse_wheel_event := self.MouseWheelEvent new. - self.shell_container := self.Composite new. self.window_registrar := System.Dictionary new: 100. @@ -519,11 +590,13 @@ extend X11 }. }. +'CLOSING X11 EVENT LOOP' dump. + Processor unsignal: self.event_loop_sem. self.event_loop_sem := nil. self dispose. -'CLOSING X11 EVENT LOOP' dump. + ] fork. } } @@ -561,7 +634,6 @@ extend X11 ^nil }. -(llevent window asString) dump. ^self perform (mthname, llevent, widget). } @@ -571,6 +643,7 @@ extend X11 method __handle_expose: llevent on: widget { + widget onPaintEvent: llevent } method __handle_button_event: event on: widget @@ -583,6 +656,7 @@ extend X11 method __handle_configure_notify: event on: widget { + widget onPaintEvent: event. } method __handle_client_message: event on: widget @@ -609,6 +683,7 @@ class MyObject(Object) method main1 { + | comp1 | self.disp1 := X11 new. self.disp2 := X11 new. @@ -617,7 +692,7 @@ class MyObject(Object) shell3 := (X11.Shell new title: 'Shell 3'). - shell1 x: 10; y: 20; width: 100; height: 100. + shell1 x: 10; y: 20; width: 500; height: 500. shell2 x: 200; y: 200; width: 200; height: 200. shell3 x: 500; y: 200; width: 200; height: 200. @@ -625,7 +700,16 @@ class MyObject(Object) self.disp1 addShell: shell2. self.disp2 addShell: shell3. - self.shell1 add: (X11.Label new text: 'xxxxxxxx'). + comp1 := X11.Composite new x: 10; y: 10; width: 400; height: 500. + self.shell1 add: comp1. + + comp1 add: (X11.Label new text: '간다'; width: 100; height: 100). + comp1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100). + ## self.shell1 add: (X11.Label new text: 'xxxxxxxx'; width: 100; height: 100). + self.shell1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100). + + self.shell2 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100). + self.shell3 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100). self.shell1 realize. self.shell2 realize. self.shell3 realize. diff --git a/moo/lib/main.c b/moo/lib/main.c index b6b112e..f581410 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -92,6 +92,7 @@ # include # include +# include # if defined(USE_THREAD) # include @@ -1758,6 +1759,11 @@ int main (int argc, char* argv[]) } #endif + if (!setlocale (LC_ALL, "")) + { + fprintf (stderr, "Warning: setlocale() error. carrying on.\n"); + } + memset (&vmprim, 0, MOO_SIZEOF(vmprim)); vmprim.dl_open = dl_open; vmprim.dl_close = dl_close; diff --git a/moo/lib/moo-cmn.h b/moo/lib/moo-cmn.h index 1a744f6..8bc9f57 100644 --- a/moo/lib/moo-cmn.h +++ b/moo/lib/moo-cmn.h @@ -276,9 +276,13 @@ typedef char moo_bch_t; typedef int moo_bci_t; +#define MOO_SIZEOF_BCH_T MOO_SIZEOF_CHAR +#define MOO_SIZEOF_BCI_T MOO_SIZEOF_INT typedef moo_uint16_t moo_uch_t; /* TODO ... wchar_t??? */ typedef moo_int32_t moo_uci_t; +#define MOO_SIZEOF_UCH_T 2 +#define MOO_SIZEOF_UCI_T 4 typedef moo_uint8_t moo_oob_t; diff --git a/moo/mod/_x11.h b/moo/mod/_x11.h index b7f5eed..2d46ddc 100644 --- a/moo/mod/_x11.h +++ b/moo/mod/_x11.h @@ -38,13 +38,6 @@ #define MC MOO_METHOD_CLASS #define MI MOO_METHOD_INSTANCE -typedef struct x11_win_t x11_win_t; -struct x11_win_t -{ - Display* disp; - Window wind; -}; - typedef struct x11_llevent_t* oop_x11_llevent_t; struct x11_llevent_t { @@ -54,16 +47,41 @@ struct x11_llevent_t moo_oop_t x, y, width, height; }; +typedef struct x11_gc_t* oop_x11_gc_t; +struct x11_gc_t +{ + MOO_OBJ_HEADER; + + moo_oop_t widget; + moo_oop_t gc_handle; + + moo_oop_t foreground; + moo_oop_t background; + moo_oop_t line_width; + moo_oop_t line_style; + moo_oop_t fill_style; + moo_oop_t font_name; + + moo_oop_t font_ptr; +}; + +typedef struct x11_widget_t* oop_x11_widget_t; +struct x11_widget_t +{ + MOO_OBJ_HEADER; + + moo_oop_t window_handle; /* SmallInteger */ + moo_oop_t parent; + + /* more fields below */ +}; + typedef struct x11_t* oop_x11_t; struct x11_t { MOO_OBJ_HEADER; moo_oop_t display; /* SMPTR of Display */ - moo_oop_t expose_event; - moo_oop_t key_event; - moo_oop_t mouse_event; - /* in fact, there are more fields */ }; @@ -75,8 +93,6 @@ struct x11_trailer_t Atom wm_delete_window; }; - - #if defined(__cplusplus) extern "C" { #endif diff --git a/moo/mod/x11.c b/moo/mod/x11.c index c7eab5d..880f2c5 100644 --- a/moo/mod/x11.c +++ b/moo/mod/x11.c @@ -27,6 +27,7 @@ #include "_x11.h" #include +#include #include #include @@ -37,6 +38,38 @@ struct x11_modctx_t moo_oop_class_t x11_class; }; +/* TODO: bchars_to_xchar2bstr??? */ +static XChar2b* uchars_to_xchar2bstr (moo_t* moo, const moo_uch_t* inptr, moo_oow_t inlen, moo_oow_t* outlen) +{ + moo_uch_t uch; + const moo_uch_t* endptr; + XChar2b* outbuf, * outptr; + + outbuf = moo_allocmem (moo, (inlen + 1) * MOO_SIZEOF(*outptr)); + if (!outbuf) return MOO_NULL; + + outptr = outbuf; + endptr = inptr + inlen; + while (inptr < endptr) + { + uch = *inptr++; + + #if (MOO_SIZEOF_UCH_T > 2) + if (uch > 0xFFFF) uc = 0xFFFD; /* unicode replacement character */ + #endif + + outptr->byte1 = (uch >> 8) & 0xFF; + outptr->byte2 = uch & 0xFF; + outptr++; + } + + outptr->byte1 = 0; + outptr->byte2 = 0; + + if (outlen) *outlen = outptr - outbuf; + return outbuf; +} + /* ------------------------------------------------------------------------ */ static moo_pfrc_t pf_open_display (moo_t* moo, moo_ooi_t nargs) { @@ -181,7 +214,8 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_ooi_t nargs) e->window = MOO_SMOOI_TO_OOP(0); /* if the following is going to trigger GC directly or indirectly, - * e must be proteced with moo_pushtmp() first */ + * e must be proteced with moo_pushtmp(). + * also x11, tr must be refetched from the stack. */ switch (event->type) { @@ -197,11 +231,39 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_ooi_t nargs) case Expose: { + XRectangle rect; + + rect.x = event->xexpose.x; + rect.y = event->xexpose.y; + rect.width = event->xexpose.width; + rect.height = event->xexpose.height; + if (XCheckWindowEvent (disp, event->xexpose.window, ExposureMask, event)) + { + Region reg; + + /* merge all expose events in the event queue */ + reg = XCreateRegion (); + XUnionRectWithRegion (&rect, reg, reg); + + do + { + rect.x = event->xexpose.x; + rect.y = event->xexpose.y; + rect.width = event->xexpose.width; + rect.height = event->xexpose.height; + XUnionRectWithRegion (&rect, reg, reg); + } + while (XCheckWindowEvent (disp, event->xexpose.window, ExposureMask, event)); + + XClipBox (reg, &rect); + XDestroyRegion (reg); + } + e->window = MOO_SMOOI_TO_OOP(event->xexpose.window); - e->x = MOO_SMOOI_TO_OOP(event->xexpose.x); - e->y = MOO_SMOOI_TO_OOP(event->xexpose.y); - e->width = MOO_SMOOI_TO_OOP(event->xexpose.width); - e->height = MOO_SMOOI_TO_OOP(event->xexpose.height); + e->x = MOO_SMOOI_TO_OOP(rect.x); + e->y = MOO_SMOOI_TO_OOP(rect.y); + e->width = MOO_SMOOI_TO_OOP(rect.width); + e->height = MOO_SMOOI_TO_OOP(rect.height); break; } @@ -255,7 +317,7 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs) einval: MOO_DEBUG0 (moo, " Invalid parameters\n"); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); - goto done; + return MOO_PF_SUCCESS; } tr = moo_getobjtrailer (moo, (moo_oop_t)x11, MOO_NULL); @@ -268,19 +330,17 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs) scrn = DefaultScreen (disp); parent = RootWindow (disp, scrn); } + else if (!MOO_OOP_IS_SMOOI(a0)) goto einval; else { - moo_oow_t tmpoow; XWindowAttributes wa; - if (moo_inttooow(moo, a0, &tmpoow) <= 0) goto einval; - parent = tmpoow; + parent = MOO_OOP_TO_SMOOI(a0); XGetWindowAttributes (disp, parent, &wa); - MOO_ASSERT (moo, XRootWindowOfScreen(wa.screen) == parent); scrn = XScreenNumberOfScreen(wa.screen); } - attrs.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; /* TODO: accept it as a parameter??? */ + attrs.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask/* | StructureNotifyMask*/; /* TODO: accept it as a parameter??? */ attrs.border_pixel = BlackPixel (disp, scrn); /* TODO: use a6 */ attrs.background_pixel = WhitePixel (disp, scrn);/* TODO: use a7 */ @@ -299,7 +359,7 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs) if (!wind) { MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR); - goto done; + return MOO_PF_SUCCESS; } if (parent == RootWindow(disp, scrn)) @@ -307,19 +367,18 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs) XSetWMProtocols (disp, wind, &tr->wm_delete_window, 1); } - a0 = moo_oowtoint (moo, wind); - if (!a0) + /*if (!MOO_IN_SMOOI_RANGE ((moo_ooi_t)wind))*/ + if (wind > MOO_SMOOI_MAX) { - MOO_STACK_SETRETTOERRNUM (moo, nargs); - goto done; + XDestroyWindow (disp, wind); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); + return MOO_PF_SUCCESS; } -/* TODO: remvoe this */ -XMapWindow (disp, wind); -XFlush (disp); + XMapWindow (disp, wind); + XFlush (disp); - MOO_STACK_SETRET (moo, nargs, a0); -done: + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(wind)); return MOO_PF_SUCCESS; } @@ -328,12 +387,10 @@ static moo_pfrc_t pf_destroy_window (moo_t* moo, moo_ooi_t nargs) oop_x11_t x11; moo_oop_t a0; - moo_oow_t wind; - x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); a0 = MOO_STACK_GETARG(moo, nargs, 0); /* window - Integer (Window) */ - if (moo_inttooow(moo, a0, &wind) <= 0) + if (!MOO_OOP_IS_SMOOI(a0)) { MOO_DEBUG0 (moo, " Invalid parameters\n"); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); @@ -341,11 +398,13 @@ static moo_pfrc_t pf_destroy_window (moo_t* moo, moo_ooi_t nargs) else { Display* disp; + Window wind; disp = MOO_OOP_TO_SMPTR(x11->display); - XUnmapWindow (disp, (Window)wind); - XDestroyWindow (disp, (Window)wind); -XFlush (disp); /* TODO: is XFlush() needed here? */ + wind = MOO_OOP_TO_SMOOI(a0); + + XUnmapWindow (disp, wind); + XDestroyWindow (disp, wind); MOO_STACK_SETRETTORCV (moo, nargs); } @@ -355,96 +414,269 @@ XFlush (disp); /* TODO: is XFlush() needed here? */ static moo_pfrc_t pf_create_gc (moo_t* moo, moo_ooi_t nargs) { Display* disp; - moo_oow_t wind; + Window wind; + GC gc; + XWindowAttributes wa; oop_x11_t x11; moo_oop_t a0; x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); - disp = MOO_OOP_TO_SMPTR(x11); + disp = MOO_OOP_TO_SMPTR(x11->display); - a0 = MOO_STACK_GETARG(moo, nargs, 0); /* parent window - Integer or nil (Window) */ + a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window - SmallInteger */ - if (moo_inttooow(moo, a0, &wind) <= 0) + if (!MOO_OOP_IS_SMOOI(a0)) { MOO_DEBUG0 (moo, " Invalid parameters\n"); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); + return MOO_PF_SUCCESS; } - else + + wind = MOO_OOP_TO_SMOOI(a0); + + gc = XCreateGC (disp, wind, 0, MOO_NULL); + if (!MOO_IN_SMPTR_RANGE(gc)) { - GC gc; - -/* TODO: copy from default GC(DefaultGC...) explicitly??? */ - gc = XCreateGC (disp, wind, 0, MOO_NULL); - if (!MOO_IN_SMPTR_RANGE(gc)) - { - MOO_DEBUG0 (moo, " GC pointer not in small pointer range\n"); - MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); - } - else - { - MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(gc)); - } + MOO_DEBUG0 (moo, " GC pointer not in small pointer range\n"); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); + return MOO_PF_SUCCESS; } +/* XGetWindowAttributes (disp, wind, &wa); + XCopyGC (disp, DefaultGC(disp, XScreenNumberOfScreen(wa.screen)), GCForeground | GCBackground | GCLineWidth | GCLineStyle, gc);*/ + + MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(gc)); return MOO_PF_SUCCESS; } static moo_pfrc_t pf_destroy_gc (moo_t* moo, moo_ooi_t nargs) { oop_x11_t x11; - moo_oop_t a0; + oop_x11_gc_t gc; + + Display* disp; + x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); - a0 = MOO_STACK_GETARG(moo, nargs, 1); /* GC */ + gc = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); /* GC object */ - if (!MOO_OOP_IS_SMPTR(a0)) + disp = MOO_OOP_TO_SMPTR(x11->display); + if (MOO_OOP_IS_SMPTR(gc->font_ptr)) { - MOO_DEBUG0 (moo, " Invalid parameters\n"); + XFreeFont (disp, MOO_OOP_TO_SMPTR(gc->font_ptr)); + gc->font_ptr = moo->_nil; + } + + if (MOO_OOP_IS_SMPTR(gc->gc_handle)) + { + XFreeGC (disp, MOO_OOP_TO_SMPTR(gc->gc_handle)); + gc->gc_handle= moo->_nil; + } + MOO_STACK_SETRETTORCV (moo, nargs); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t pf_apply_gc (moo_t* moo, moo_ooi_t nargs) +{ + oop_x11_t x11; + oop_x11_gc_t a0; + + Display* disp; + GC gc; + unsigned long int mask = 0; + XGCValues v; + + + x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); + a0 = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); +/* TODO check if a0 is an instance of X11.GC */ + + if (!MOO_OOP_IS_SMPTR(a0->gc_handle)) + { + MOO_DEBUG0 (moo, " Invalid parameters\n"); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); + return MOO_PF_SUCCESS; } - else + + disp = MOO_OOP_TO_SMPTR(x11->display); + gc = MOO_OOP_TO_SMPTR(a0->gc_handle); + + if (MOO_OBJ_IS_CHAR_POINTER(a0->font_name) && MOO_OBJ_GET_SIZE(a0->font_name) > 0) { - Display* disp; - GC gc; - - disp = MOO_OOP_TO_SMPTR(x11->display); - gc = MOO_OOP_TO_SMPTR(a0); - - XFreeGC (disp, gc); - MOO_STACK_SETRETTORCV (moo, nargs); + XFontStruct* font; +/* TODO: .... use font_name */ + font = XLoadQueryFont (disp, "-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1"); + if (font) + { + if (!MOO_IN_SMPTR_RANGE(font)) + { + MOO_DEBUG0 (moo, " Font pointer not in small pointer range\n"); + XFreeFont (disp, font); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); + return MOO_PF_SUCCESS; + } + else + { + XSetFont (disp, gc, font->fid); + if (MOO_OOP_IS_SMPTR(a0->font_ptr)) XFreeFont (disp, MOO_OOP_TO_SMPTR(a0->font_ptr)); + a0->font_ptr = MOO_SMPTR_TO_OOP(font); + } + } + else + { + MOO_DEBUG2 (moo, " Cannot laod font - %.*js\n", MOO_OBJ_GET_SIZE(a0->font_name), MOO_OBJ_GET_CHAR_SLOT(a0->font_name)); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR); + return MOO_PF_SUCCESS; + } } + +/* TODO: accept mask as an option parameter. then only apply fields that matches this given mask */ + if (MOO_OOP_IS_SMOOI(a0->foreground)) + { + mask |= GCForeground; + v.foreground = MOO_OOP_TO_SMOOI(a0->foreground); + } + if (MOO_OOP_IS_SMOOI(a0->background)) + { + mask |= GCBackground; + v.background = MOO_OOP_TO_SMOOI(a0->background); + } + if (MOO_OOP_IS_SMOOI(a0->line_width)) + { + mask |= GCLineWidth; + v.line_width = MOO_OOP_TO_SMOOI(a0->line_width); + } + if (MOO_OOP_IS_SMOOI(a0->line_style)) + { + mask |= GCLineStyle; + v.line_style = MOO_OOP_TO_SMOOI(a0->line_style); + } + if (MOO_OOP_IS_SMOOI(a0->fill_style)) + { + mask |= GCFillStyle; + v.fill_style = MOO_OOP_TO_SMOOI(a0->fill_style); + } + XChangeGC (disp, gc, mask, &v); + + MOO_STACK_SETRETTORCV (moo, nargs); return MOO_PF_SUCCESS; } static moo_pfrc_t pf_draw_rectangle (moo_t* moo, moo_ooi_t nargs) { + oop_x11_t x11; Display* disp; - moo_oow_t wind, gc; moo_oop_t a0, a1, a2, a3, a4, a5; - a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window */ - a1 = MOO_STACK_GETARG(moo, nargs, 1); /* GC */ + x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); + disp = MOO_OOP_TO_SMPTR(x11->display); + + a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window - SmallInteger */ + a1 = MOO_STACK_GETARG(moo, nargs, 1); /* GC - SMPTR */ a2 = MOO_STACK_GETARG(moo, nargs, 2); /* x - SmallInteger */ a3 = MOO_STACK_GETARG(moo, nargs, 3); /* y - SmallInteger */ a4 = MOO_STACK_GETARG(moo, nargs, 4); /* width - SmallInteger */ a5 = MOO_STACK_GETARG(moo, nargs, 5); /* height - SmallInteger */ - if (!MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) || - !MOO_OOP_IS_SMOOI(a4) || !MOO_OOP_IS_SMOOI(a5) || - moo_inttooow(moo, a0, &wind) <= 0 || - moo_inttooow(moo, a1, &gc) <= 0) + if (!MOO_OOP_IS_SMOOI(a0) || !MOO_OOP_IS_SMPTR(a1) || + !MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) || + !MOO_OOP_IS_SMOOI(a4) || !MOO_OOP_IS_SMOOI(a5)) { MOO_DEBUG0 (moo, " Invalid parameters\n"); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); return MOO_PF_SUCCESS; } - disp = MOO_OOP_TO_SMPTR(MOO_STACK_GETRCV(moo,nargs)); - XDrawRectangle (disp, (Window)wind, (GC)gc, + XDrawRectangle (disp, (Window)MOO_OOP_TO_SMOOI(a0), (GC)MOO_OOP_TO_SMPTR(a1), MOO_OOP_TO_SMOOI(a2), MOO_OOP_TO_SMOOI(a3), MOO_OOP_TO_SMOOI(a4), MOO_OOP_TO_SMOOI(a5)); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t pf_fill_rectangle (moo_t* moo, moo_ooi_t nargs) +{ + oop_x11_t x11; + Display* disp; + moo_oop_t a0, a1, a2, a3, a4, a5; + + x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); + disp = MOO_OOP_TO_SMPTR(x11->display); + + a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window - SmallInteger */ + a1 = MOO_STACK_GETARG(moo, nargs, 1); /* GC - SMPTR */ + a2 = MOO_STACK_GETARG(moo, nargs, 2); /* x - SmallInteger */ + a3 = MOO_STACK_GETARG(moo, nargs, 3); /* y - SmallInteger */ + a4 = MOO_STACK_GETARG(moo, nargs, 4); /* width - SmallInteger */ + a5 = MOO_STACK_GETARG(moo, nargs, 5); /* height - SmallInteger */ + + if (!MOO_OOP_IS_SMOOI(a0) || !MOO_OOP_IS_SMPTR(a1) || + !MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) || + !MOO_OOP_IS_SMOOI(a4) || !MOO_OOP_IS_SMOOI(a5)) + { + MOO_DEBUG0 (moo, " Invalid parameters\n"); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); + return MOO_PF_SUCCESS; + } + + XFillRectangle (disp, (Window)MOO_OOP_TO_SMOOI(a0), (GC)MOO_OOP_TO_SMPTR(a1), + MOO_OOP_TO_SMOOI(a2), MOO_OOP_TO_SMOOI(a3), + MOO_OOP_TO_SMOOI(a4), MOO_OOP_TO_SMOOI(a5)); + return MOO_PF_SUCCESS; +} + + +static moo_pfrc_t pf_draw_string (moo_t* moo, moo_ooi_t nargs) +{ + + oop_x11_t x11; + oop_x11_gc_t gc; + moo_oop_t a1, a2, a3; + + Display* disp; + XChar2b* stptr; + moo_oow_t stlen; + int ascent = 0; + + x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); + disp = MOO_OOP_TO_SMPTR(x11->display); + + gc = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); /* GC object */ + a1 = MOO_STACK_GETARG(moo, nargs, 1); /* x - SmallInteger */ + a2 = MOO_STACK_GETARG(moo, nargs, 2); /* y - SmallInteger */ + a3 = MOO_STACK_GETARG(moo, nargs, 3); /* string */ + +/* TODO: check if gc is an instance of X11.GC */ + + if (!MOO_OOP_IS_SMOOI(a1) || !MOO_OOP_IS_SMOOI(a2) || + !MOO_OBJ_IS_CHAR_POINTER(a3)) + { + MOO_DEBUG0 (moo, " Invalid parameters\n"); + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); + return MOO_PF_SUCCESS; + } + +/* TODO: draw string chunk by chunk to avoid memory allocation in uchars_to_xchars2bstr */ + stptr = uchars_to_xchar2bstr (moo, MOO_OBJ_GET_CHAR_SLOT(a3), MOO_OBJ_GET_SIZE(a3), &stlen); + if (!stptr) + { + MOO_DEBUG0 (moo, " Error in converting a string\n"); + MOO_STACK_SETRETTOERRNUM (moo, nargs); + return MOO_PF_SUCCESS; + } + + if (MOO_OOP_IS_SMPTR(gc->font_ptr)) + { + int direction, descent; + XCharStruct overall; + XTextExtents16 (MOO_OOP_TO_SMPTR(gc->font_ptr), stptr, stlen, &direction, &ascent, &descent, &overall); + } + + XDrawString16 (disp, (Window)MOO_OOP_TO_SMOOI(((oop_x11_widget_t)gc->widget)->window_handle), MOO_OOP_TO_SMPTR(gc->gc_handle), + MOO_OOP_TO_SMOOI(a1), MOO_OOP_TO_SMOOI(a2) + ascent, stptr, stlen); + + moo_freemem (moo, stptr); return MOO_PF_SUCCESS; } @@ -452,17 +684,19 @@ static moo_pfrc_t pf_draw_rectangle (moo_t* moo, moo_ooi_t nargs) static moo_pfinfo_t x11_pfinfo[] = { + { MI, { '_','a','p','p','l','y','_','g','c','\0' }, 0, { pf_apply_gc, 1, 1 } }, { MI, { '_','c','l','o','s','e','_','d','i','s','p','l','a','y','\0' }, 0, { pf_close_display, 0, 0 } }, { MI, { '_','c','r','e','a','t','e','_','g','c','\0' }, 0, { pf_create_gc, 1, 1 } }, { MI, { '_','c','r','e','a','t','e','_','w','i','n','d','o','w','\0' }, 0, { pf_create_window, 7, 7 } }, { MI, { '_','d','e','s','t','r','o','y','_','g','c','\0' }, 0, { pf_destroy_gc, 1, 1 } }, { MI, { '_','d','e','s','t','r','o','y','_','w','i','n','d','o','w','\0' }, 0, { pf_destroy_window, 1, 1 } }, + { MI, { '_','d','r','a','w','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_draw_rectangle, 6, 6 } }, - //{ MI, { '_','f','i','l','l','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_fill_rectangle, 6, 6 } }, + { MI, { '_','d','r','a','w','_','s','t','r','i','n','g','\0' }, 0, { pf_draw_string, 4, 4 } }, + { MI, { '_','f','i','l','l','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_fill_rectangle, 6, 6 } }, { MI, { '_','g','e','t','_','f','d','\0' }, 0, { pf_get_fd, 0, 0 } }, { MI, { '_','g','e','t','_','l','l','e','v','e','n','t','\0'}, 0, { pf_get_llevent, 1, 1 } }, { MI, { '_','o','p','e','n','_','d','i','s','p','l','a','y','\0' }, 0, { pf_open_display, 0, 1 } } - }; static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)