From d21447d096a320a08b3efb2b8768fad0dcdcfd64 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 5 May 2016 22:28:51 +0100 Subject: move frontends into sub directory --- frontends/atari/gemtk/guiwin.c | 1430 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1430 insertions(+) create mode 100644 frontends/atari/gemtk/guiwin.c (limited to 'frontends/atari/gemtk/guiwin.c') diff --git a/frontends/atari/gemtk/guiwin.c b/frontends/atari/gemtk/guiwin.c new file mode 100644 index 000000000..ea0f8f917 --- /dev/null +++ b/frontends/atari/gemtk/guiwin.c @@ -0,0 +1,1430 @@ +/* + * Copyright 2012 Ole Loots + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include + +#include "gemtk.h" +#include "vaproto.h" + +//#define DEBUG_PRINT(x) printf x +#define DEBUG_PRINT(x) + +struct gemtk_window_s { + + /** The AES handle of the window */ + short handle; + + /** the generic event handler function for events passed to the client */ + gemtk_wm_event_handler_f handler_func; + + /** The toolbar redraw function, if any */ + gemtk_wm_redraw_f toolbar_redraw_func; + + /** window configuration */ + uint32_t flags; + + /** window state */ + uint32_t state; + + /** AES Tree used as toolbar */ + OBJECT *toolbar; + + /** Current edit object selected in the toolbar, if any. */ + short toolbar_edit_obj; + + /** Current selected object in the toolbar, if any. */ + short toolbar_focus_obj; + + /** Describes the start of the toolbar tree (usually 0) */ + short toolbar_idx; + + /** depending on the flag GEMTK_WM_FLAG_HAS_VTOOLBAR this defines the toolbar + height or the toolbar width (GEMTK_WM_FLAG_HAS_VTOOLBAR means width). + */ + short toolbar_size; + + /** AES Object tree to be used for windowed dialogs. */ + OBJECT *form; + + /** Current form edit object, if any. */ + short form_edit_obj; + + /** Current form focus object, if any */ + short form_focus_obj; + + /** Describes the start of the form tree */ + short form_idx; + + /** Scroll state */ + struct gemtk_wm_scroll_info_s scroll_info; + + /** Arbitary data set by the user */ + void *user_data; + + /** linked list items */ + struct gemtk_window_s *next, *prev; +}; + +static GUIWIN * winlist; +static VdiHdl v_vdi_h = -1; +static short work_out[57]; + +static void move_rect(GUIWIN * win, GRECT *rect, int dx, int dy) +{ + INT16 xy[ 8]; + long dum = 0L; + GRECT g; + + VdiHdl vh = gemtk_wm_get_vdi_handle(win); + + while(!wind_update(BEG_UPDATE)); + graf_mouse(M_OFF, 0L); + + /* get intersection with screen area */ + wind_get_grect(0, WF_CURRXYWH, &g); + if(!rc_intersect(&g, rect)){ + goto error; + } + xy[0] = rect->g_x; + xy[1] = rect->g_y; + xy[2] = xy[0] + rect->g_w-1; + xy[3] = xy[1] + rect->g_h-1; + xy[4] = xy[0] + dx; + xy[5] = xy[1] + dy; + xy[6] = xy[2] + dx; + xy[7] = xy[3] + dy; + vro_cpyfm(vh, S_ONLY, xy, (MFDB *)&dum, (MFDB *)&dum); + +error: + graf_mouse(M_ON, 0L); + wind_update(END_UPDATE); +} + +/** +* Handles common events. +* returns 0 when the event was not handled, 1 otherwise. +*/ +static short preproc_wm(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8]) +{ + GRECT g, g_ro, g2; + short retval = 1; + int val = 1; + struct gemtk_wm_scroll_info_s *slid; + + switch(msg[0]) { + + case WM_HSLID: + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + wind_set(gw->handle, WF_HSLIDE, msg[4], 0, 0, 0); + slid = gemtk_wm_get_scroll_info(gw); + val = (float)(slid->x_units-(g.g_w/slid->x_unit_px))/1000*(float)msg[4]; + if(val != slid->x_pos) { + if (val < slid->x_pos) { + val = -(MAX(0, slid->x_pos-val)); + } else { + val = val-slid->x_pos; + } + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, val, false); + } + break; + + case WM_VSLID: + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + wind_set(gw->handle, WF_VSLIDE, msg[4], 0, 0, 0); + slid = gemtk_wm_get_scroll_info(gw); + val = (float)(slid->y_units-(g.g_h/slid->y_unit_px))/1000*(float)msg[4]; + if(val != slid->y_pos) { + if (val < slid->y_pos) { + val = -(slid->y_pos - val); + } else { + val = val -slid->y_pos; + } + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, val, false); + } + break; + + case WM_ARROWED: + if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) { + + slid = gemtk_wm_get_scroll_info(gw); + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + g_ro = g; + + switch(msg[4]) { + + case WA_UPPAGE: + /* scroll page up */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, -(g.g_h/slid->y_unit_px), + true); + break; + + case WA_UPLINE: + /* scroll line up */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, -1, true); + break; + + case WA_DNPAGE: + /* scroll page down */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, g.g_h/slid->y_unit_px, + true); + break; + + case WA_DNLINE: + /* scroll line down */ + gemtk_wm_scroll(gw, GEMTK_WM_VSLIDER, +1, true); + break; + + case WA_LFPAGE: + /* scroll page left */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, -(g.g_w/slid->x_unit_px), + true); + break; + + case WA_LFLINE: + /* scroll line left */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, -1, + true); + break; + + case WA_RTPAGE: + /* scroll page right */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, (g.g_w/slid->x_unit_px), + true); + break; + + case WA_RTLINE: + /* scroll line right */ + gemtk_wm_scroll(gw, GEMTK_WM_HSLIDER, 1, + true); + break; + + default: + break; + } + } + break; + + case WM_TOPPED: + wind_set(gw->handle, WF_TOP, 1, 0, 0, 0); + break; + + case WM_MOVED: + wind_get_grect(gw->handle, WF_CURRXYWH, &g); + wind_set(gw->handle, WF_CURRXYWH, msg[4], msg[5], g.g_w, g.g_h); + + if (gw->form) { + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &g); + slid = gemtk_wm_get_scroll_info(gw); + + gw->form[gw->form_idx].ob_x = g.g_x - + (slid->x_pos * slid->x_unit_px); + + gw->form[gw->form_idx].ob_y = g.g_y - + (slid->y_pos * slid->y_unit_px); + } + + break; + + case WM_SIZED: + case WM_REPOSED: + wind_get_grect(gw->handle, WF_FULLXYWH, &g2); + wind_get_grect(gw->handle, WF_CURRXYWH, &g); + g.g_w = MIN(msg[6], g2.g_w); + g.g_h = MIN(msg[7], g2.g_h); + if(g2.g_w != g.g_w || g2.g_h != g.g_h) { + wind_set(gw->handle, WF_CURRXYWH, g.g_x, g.g_y, g.g_w, g.g_h); + if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) { + if(gemtk_wm_update_slider(gw, GEMTK_WM_VH_SLIDER)) { + gemtk_wm_exec_redraw(gw, NULL); + } + } + } + + + break; + + case WM_FULLED: + wind_get_grect(DESKTOP_HANDLE, WF_WORKXYWH, &g); + wind_get_grect(gw->handle, WF_CURRXYWH, &g2); + if(g.g_w == g2.g_w && g.g_h == g2.g_h) { + wind_get_grect(gw->handle, WF_PREVXYWH, &g); + } + wind_set_grect(gw->handle, WF_CURRXYWH, &g); + if((gw->flags & GEMTK_WM_FLAG_CUSTOM_SCROLLING) == 0) { + if(gemtk_wm_update_slider(gw, GEMTK_WM_VH_SLIDER)) { + gemtk_wm_exec_redraw(gw, NULL); + } + } + break; + + case WM_ICONIFY: + wind_set(gw->handle, WF_ICONIFY, msg[4], msg[5], msg[6], msg[7]); + gw->state |= GEMTK_WM_STATUS_ICONIFIED; + break; + + case WM_UNICONIFY: + wind_set(gw->handle, WF_UNICONIFY, msg[4], msg[5], msg[6], msg[7]); + gw->state &= ~(GEMTK_WM_STATUS_ICONIFIED); + break; + + case WM_SHADED: + gw->state |= GEMTK_WM_STATUS_SHADED; + break; + + case WM_UNSHADED: + gw->state &= ~(GEMTK_WM_STATUS_SHADED); + break; + + case WM_REDRAW: + if ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0 + && (gw->toolbar != NULL)) { + g.g_x = msg[4]; + g.g_y = msg[5]; + g.g_w = msg[6]; + g.g_h = msg[7]; + if((gw->state & GEMTK_WM_STATUS_ICONIFIED) == 0){ + gemtk_wm_toolbar_redraw(gw, WM_REDRAW, &g); + } + } + if (gw->form != NULL) { + g.g_x = msg[4]; + g.g_y = msg[5]; + g.g_w = msg[6]; + g.g_h = msg[7]; + gemtk_wm_form_redraw(gw, &g); + } + break; + + default: + retval = 0; + break; + + } + + return(retval); +} + +/** +* Preprocess mouse events +*/ +static short preproc_mu_button(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0, obj_idx = 0; + + DEBUG_PRINT(("preproc_mu_button\n")); + + // toolbar handling: + if ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0 + && gw->toolbar != NULL) { + + GRECT tb_area; + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area); + + if (POINT_WITHIN(ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y, tb_area)) { + + gw->toolbar[gw->toolbar_idx].ob_x = tb_area.g_x; + gw->toolbar[gw->toolbar_idx].ob_y = tb_area.g_y; + obj_idx = objc_find(gw->toolbar, + gw->toolbar_idx, 8, + ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y); + + gw->toolbar_focus_obj = obj_idx; + + DEBUG_PRINT(("Toolbar index: %d\n", obj_idx)); + if (obj_idx > -1 + && (gw->toolbar[obj_idx].ob_state & OS_DISABLED)== 0 + && ((gw->flags & GEMTK_WM_FLAG_CUSTOM_TOOLBAR) == 0)) { + + uint16_t type = (gw->toolbar[obj_idx].ob_type & 0xFF); + uint16_t nextobj; + + DEBUG_PRINT(("toolbar item type: %d, toolbar_edit_obj: %d\n", + type, gw->toolbar_edit_obj)); + // Report mouse click to the tree: + retval = form_wbutton(gw->toolbar, gw->toolbar_focus_obj, + ev_out->emo_mclicks, &nextobj, + gw->handle); + if (nextobj == obj_idx + && (type == G_FTEXT || type == G_FBOXTEXT)) { + gw->toolbar_edit_obj = obj_idx; + } + else { + gw->toolbar_edit_obj = -1; + } + } + + // send WM_TOOLBAR message + short oldevents = ev_out->emo_events; + short msg_out[8] = {WM_TOOLBAR, gl_apid, + 0, gw->handle, + obj_idx, ev_out->emo_mclicks, + ev_out->emo_kmeta, ev_out->emo_mbutton + }; + ev_out->emo_events = MU_MESAG; + // notify the window about toolbar click: + gw->handler_func(gw, ev_out, msg_out); + ev_out->emo_events = oldevents; + retval = 1; + } else { + if (gw->toolbar_edit_obj != -1) { + gw->toolbar_edit_obj = -1; + } + } + } + + if (gw->form != NULL) { + + GRECT content_area; + struct gemtk_wm_scroll_info_s *slid; + + DEBUG_PRINT(("preproc_mu_button: handling form click.\n")); + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &content_area); + + if (POINT_WITHIN(ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y, content_area)) { + + slid = gemtk_wm_get_scroll_info(gw); + + // adjust form position (considering window and scroll position): + gw->form[gw->form_idx].ob_x = content_area.g_x - + (slid->x_pos * slid->x_unit_px); + gw->form[gw->form_idx].ob_y = content_area.g_y - + (slid->y_pos * slid->y_unit_px); + + obj_idx = objc_find(gw->form, gw->form_idx, 8, + ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y); + gw->form_focus_obj = obj_idx; + DEBUG_PRINT(("Window Form click, obj: %d\n", gw->form_focus_obj)); + if (obj_idx > -1 + && (gw->form[obj_idx].ob_state & OS_DISABLED)== 0) { + + uint16_t type = (gw->form[obj_idx].ob_type & 0xFF); + uint16_t nextobj; + + DEBUG_PRINT(("type: %d\n", type)); + + retval = form_wbutton(gw->form, gw->form_focus_obj, + ev_out->emo_mclicks, &nextobj, + gw->handle); + + if (nextobj == obj_idx + && (type == G_FTEXT || type == G_FBOXTEXT)) { + gw->form_edit_obj = obj_idx; + } + else { + gw->form_edit_obj = -1; + } + + short oldevents = ev_out->emo_events; + short msg_out[8] = { GEMTK_WM_WM_FORM_CLICK, gl_apid, + 0, gw->handle, + gw->form_focus_obj, ev_out->emo_mclicks, + ev_out->emo_kmeta, 0 + }; + ev_out->emo_events = MU_MESAG; + // notify the window about form click: + gw->handler_func(gw, ev_out, msg_out); + ev_out->emo_events = oldevents; + retval = 1; + evnt_timer(150); + } + } + else { + gw->form_edit_obj = -1; + + } + } + + return(retval); +} + +/** +* Preprocess keyboard events (for forms/toolbars) +*/ +static short preproc_mu_keybd(GUIWIN * gw, EVMULT_OUT *ev_out, short msg[8]) +{ + short retval = 0; + + if ((gw->toolbar != NULL) && (gw->toolbar_edit_obj > -1)) { + + short next_edit_obj = gw->toolbar_edit_obj; + short next_char = -1; + short edit_idx; + short r; + + DEBUG_PRINT(("%s, gw: %p, toolbar_edit_obj: %d\n", __FUNCTION__, gw, + gw->toolbar_edit_obj)); + + r = form_wkeybd(gw->toolbar, gw->toolbar_edit_obj, next_edit_obj, + ev_out->emo_kreturn, + &next_edit_obj, &next_char, gw->handle); + + if (next_edit_obj != gw->toolbar_edit_obj) { + gemtk_wm_set_toolbar_edit_obj(gw, next_edit_obj, + ev_out->emo_kreturn); + } else { + if (next_char > 13) { + r = objc_wedit(gw->toolbar, gw->toolbar_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDCHAR, gw->handle); + } + } + //retval = 1; + /*gemtk_wm_send_msg(gw, GEMTK_WM_WM_FORM_KEY, gw->toolbar_edit_obj, + ev_out->emo_kreturn, 0, 0);*/ + } + + if((gw->form != NULL) && (gw->form_edit_obj > -1) ) { + + short next_edit_obj = gw->form_edit_obj; + short next_char = -1; + short edit_idx; + short r; + + r = form_wkeybd(gw->form, gw->form_edit_obj, next_edit_obj, + ev_out->emo_kreturn, + &next_edit_obj, &next_char, gw->handle); + + if (next_edit_obj != gw->form_edit_obj) { + + if(gw->form_edit_obj != -1) { + objc_wedit(gw->form, gw->form_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDEND, gw->handle); + } + + gw->form_edit_obj = next_edit_obj; + + objc_wedit(gw->form, gw->form_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDINIT, gw->handle); + } else { + if(next_char > 13) + r = objc_wedit(gw->form, gw->form_edit_obj, + ev_out->emo_kreturn, &edit_idx, + EDCHAR, gw->handle); + } + } + return(retval); +} + +/** +* Default toolbar redraw function +*/ +static void std_toolbar_redraw(GUIWIN *gw, uint16_t msg, GRECT *clip) +{ + GRECT g, tb_area; + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area); + + assert(gw->toolbar); + assert(gw->toolbar_idx >= 0); + + // Update object position: + gw->toolbar[gw->toolbar_idx].ob_x = tb_area.g_x; + gw->toolbar[gw->toolbar_idx].ob_y = tb_area.g_y; + gw->toolbar[gw->toolbar_idx].ob_width = tb_area.g_w; + gw->toolbar[gw->toolbar_idx].ob_height = tb_area.g_h; + + wind_get_grect(gw->handle, WF_FIRSTXYWH, &g); + while (g.g_h > 0 || g.g_w > 0) { + if(rc_intersect(clip, &g)) { + objc_draw(gw->toolbar, gw->toolbar_idx, 8, g.g_x, g.g_y, + g.g_w, g.g_h); + + } + wind_get_grect(gw->handle, WF_NEXTXYWH, &g); + } +} + +/** +* Event Dispatcher function. The guiwin API doesn't own an event loop, +* so you have to inform it for every event that you want it to handle. +*/ +short gemtk_wm_dispatch_event(EVMULT_IN *ev_in, EVMULT_OUT *ev_out, short msg[8]) +{ + GUIWIN *dest; + short retval = 0; + bool handler_called = false; + + if( (ev_out->emo_events & MU_MESAG) != 0 ) { + DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: %d (%x)\n", msg[0], + msg[0])); + switch (msg[0]) { + case WM_REDRAW: + case WM_CLOSED: + case WM_TOPPED: + case WM_ARROWED: + case WM_HSLID: + case WM_VSLID: + case WM_FULLED: + case WM_SIZED: + case WM_REPOSED: + case WM_MOVED: + case WM_NEWTOP: + case WM_UNTOPPED: + case WM_ONTOP: + case WM_BOTTOM: + case WM_ICONIFY: + case WM_UNICONIFY: + case WM_ALLICONIFY: + case WM_TOOLBAR: + case AP_DRAGDROP: + case AP_TERM: + case AP_TFAIL: + dest = gemtk_wm_find(msg[3]); + if (dest) { + DEBUG_PRINT(("Found WM_ dest: %p (%d), flags: %d, cb: %p\n", + dest, dest->handle, dest->flags, + dest->handler_func)); + if (dest->flags&GEMTK_WM_FLAG_PREPROC_WM) { + retval = preproc_wm(dest, ev_out, msg); + if(((retval == 0)||(dest->flags&GEMTK_WM_FLAG_RECV_PREPROC_WM))) { + retval = dest->handler_func(dest, ev_out, msg); + handler_called = true; + } + } else { + if (dest->handler_func) { + retval = dest->handler_func(dest, ev_out, msg); + handler_called = true; + } + } + + } + break; +// TODO: check code with Thing! Desktop +/* + We receive VA_PROTOSTATUS but AV_START doesn't seem to cause + an TeraDesk response. Check if something happens with Thing! + Desktop. + + case VA_PROTOSTATUS: + case VA_VIEWED: + case AV_STARTED: + gemtk_av_dispatch(msg); + break; +*/ + } + } else { + + short h_aes; + h_aes = wind_find(ev_out->emo_mouse.p_x, ev_out->emo_mouse.p_y); + if(h_aes > 0 && (ev_out->emo_events != MU_TIMER)) { + + dest = gemtk_wm_find(h_aes); + + if (dest == NULL || dest->handler_func == NULL) + return(0); + + DEBUG_PRINT(("Found Event receiver GUIWIN: %p (%d), flags: %d, cb: %p\n", + dest, dest->handle, dest->flags, dest->handler_func)); + + if ((ev_out->emo_events & MU_BUTTON) != 0) { + DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: MU_BUTTON -> " + "%d / %d\n", ev_out->emo_mouse.p_x, + ev_out->emo_mouse.p_y)); + retval = preproc_mu_button(dest, ev_out, msg); + if(retval != 0) { + handler_called = true; + } + } + + if ((ev_out->emo_events & MU_KEYBD)) { + DEBUG_PRINT(("gemtk_wm_handle_event_multi_fast: MU_KEYBD -> %x\n", + ev_out->emo_kreturn)); + retval = preproc_mu_keybd(dest, ev_out, msg); + if(retval != 0) { + handler_called = true; + } + } + + if (handler_called==false) { + retval = dest->handler_func(dest, ev_out, msg); + } + } + } + + return(retval); +} + +/** +* Initialises the guiwin API +*/ +short gemtk_wm_init(void) +{ + if(v_vdi_h == -1) { + short dummy; + short work_in[12] = {Getrez()+2,1,1,1,1,1,1,1,1,1,2,1}; + v_vdi_h=graf_handle(&dummy, &dummy, &dummy, &dummy); + v_opnvwk(work_in, &v_vdi_h, work_out); + } + return(0); +} + +void gemtk_wm_exit(void) +{ + v_clsvwk(v_vdi_h); +} + +/** +* Adds and AES handle to the guiwin list and creates and GUIWIN management +* structure. +* +* \param handle The AES handle +* \param flags Creation flags, configures how the AES window is handled +* \param cb event handler function for that window +*/ +GUIWIN * gemtk_wm_add(short handle, uint32_t flags, gemtk_wm_event_handler_f cb) +{ + + GUIWIN *win = calloc(1, sizeof(GUIWIN)); + + assert(win!=NULL); + DEBUG_PRINT(("gemtk_wm_add: %d, %p, cb: %p\n", handle, win, cb)); + + win->handle = handle; + win->handler_func = cb; + win->flags = flags; + gemtk_wm_link(win); + + DEBUG_PRINT(("Added guiwin: %p, tb: %p\n", win, win->toolbar)); + return(win); +} + +/** +* Returns an GUIWIN* for AES handle, when that AES window is managed by gemtk_wm +*/ +GUIWIN *gemtk_wm_find(short handle) +{ + GUIWIN *g; + DEBUG_PRINT(("guiwin search handle: %d\n", handle)); + for (g = winlist; g != NULL; g=g->next) { + if(g->handle == handle) { + DEBUG_PRINT(("guiwin found handle: %p\n", g)); + return(g); + } + } + return(NULL); +} + +void gemtk_wm_dump_window_info(GUIWIN *win) +{ + + + + char title[255]; + GRECT work_area; + GRECT curr_area; + GRECT gemtk_work_area; + GRECT gemtk_toolbar_area; + GRECT gemtk_free_area; + short handle; + struct gemtk_wm_scroll_info_s *slid; + + handle = gemtk_wm_get_handle(win); + + assert(handle); + + gemtk_wind_get_str(handle, WF_NAME, title, 255); + wind_get_grect(handle, WF_WORKXYWH, &work_area); + wind_get_grect(handle, WF_CURRXYWH, &curr_area); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &gemtk_free_area); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &gemtk_work_area); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &gemtk_toolbar_area); + slid = gemtk_wm_get_scroll_info(win); + + printf ("GEMTK Window: %p (AES handle: %d)\n", win, win->handle); + printf ("Title: %s\n", title); + GEMTK_DBG_GRECT ("WF_WORKXYWH: \n", &work_area) + GEMTK_DBG_GRECT ("WF_CURRXYWH: \n", &curr_area) + GEMTK_DBG_GRECT ("GEMTK_WM_AREA_CONTENT:\n", &gemtk_free_area) + GEMTK_DBG_GRECT ("GEMTK_WM_AREA_WORK:\n", &gemtk_work_area) + GEMTK_DBG_GRECT ("GEMTK_WM_AREA_TOOLBAR:\n", &gemtk_toolbar_area) + printf ("Slider X pos: %d\n", slid->x_pos); + printf ("Slider Y pos: %d\n", slid->y_pos); + printf ("Slider X units: %d\n", slid->x_unit_px); + printf ("Slider Y units: %d\n", slid->y_unit_px); + + +#undef DBG_GRECT +}; + +/** +* Check's if the pointer is managed by the guiwin API. +*/ +GUIWIN *gemtk_wm_validate_ptr(GUIWIN *win) +{ + GUIWIN *g; + for( g = winlist; g != NULL; g=g->next ) { + DEBUG_PRINT(("guiwin gemtk_wm_validate_ptr check: %p\n", g)); + if(g == win) { + DEBUG_PRINT(("gemtk_wm_validate_ptr valid: %p\n", g)); + return(g); + } + } + return(NULL); +} + +/** +* Add the GUIWIN to the list of handled windows. +*/ +GUIWIN *gemtk_wm_link(GUIWIN *win) +{ + /* Make sure the window is not linked: */ + GUIWIN *win_val = gemtk_wm_validate_ptr(win); + if(win_val){ + DEBUG_PRINT(("GUIWIN %p is already linked!\n", win)); + return(NULL); + } + + if (winlist == NULL) { + winlist = win; + win->next = NULL; + win->prev = NULL; + } else { + GUIWIN *tmp = winlist; + while( tmp->next != NULL ) { + tmp = tmp->next; + } + tmp->next = win; + win->prev = tmp; + win->next = NULL; + } + return(win); +} + +/** +* Remove the GUIWIN from the list of handled windows. +*/ +GUIWIN *gemtk_wm_unlink(GUIWIN *win) +{ + GUIWIN * win_val; + + /* Make sure the window is linked: */ + win_val = gemtk_wm_validate_ptr(win); + if (win_val == NULL){ + DEBUG_PRINT(("GUIWIN %p is not linked!\n", win)); + return(NULL); + } + + + /* unlink the window: */ + if(win->prev != NULL ) { + win->prev->next = win->next; + } else { + winlist = win->next; + } + if (win->next != NULL) { + win->next->prev = win->prev; + } + return(win); +} + +/** +* Remove an GUIWIN from the list of managed windows and free the GUIWIN. +* Call this when the AES window is closed or deleted. +*/ +short gemtk_wm_remove(GUIWIN *win) +{ + gemtk_wm_unlink(win); + DEBUG_PRINT(("guiwin free: %p\n", win)); + free(win); + return(0); +} + +/** Calculate & get a well known area within the GUIWIN. +* \param win The GUIWIN ptr. +* \param mode Specifies the area to retrieve. +* \param dest The calculated rectangle. +*/ +void gemtk_wm_get_grect(GUIWIN *win, enum guwin_area_e mode, GRECT *dest) +{ + + assert(win != NULL); + + wind_get_grect(win->handle, WF_WORKXYWH, dest); + + if (mode == GEMTK_WM_AREA_CONTENT) { + GRECT tb_area; + gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &tb_area); + if (win->flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) { + dest->g_x += tb_area.g_w; + dest->g_w -= tb_area.g_w; + } + else { + dest->g_y += tb_area.g_h; + dest->g_h -= tb_area.g_h; + } + } else if (mode == GEMTK_WM_AREA_TOOLBAR) { + if (win->toolbar) { + if (win->flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) { + dest->g_w = win->toolbar_size; + } else { + dest->g_h = win->toolbar_size; + } + } + else { + dest->g_w = 0; + dest->g_h = 0; + } + } +} + + +/** +* Scroll the content area (GEMTK_WM_AREA_CONTENT) in the specified dimension +* (GEMTK_WM_VSLIDER, GEMTK_WM_HSLIDER) +* \param win The GUIWIN +* \param orientation GEMTK_WM_VSLIDER or GEMTK_WM_HSLIDER +* \param units the amout to scroll (pass negative values to scroll up) +* \param refresh Sliders will be updated when this flag is set +*/ +void gemtk_wm_scroll(GUIWIN *win, short orientation, int units, bool refresh) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win); + int oldpos = 0, newpos = 0, vis_units=0, pix = 0; + int abs_pix = 0; + GRECT *redraw=NULL, g, g_ro; + + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &g); + g_ro = g; + + if (orientation == GEMTK_WM_VSLIDER) { + pix = units*slid->y_unit_px; + abs_pix = abs(pix); + oldpos = slid->y_pos; + vis_units = g.g_h/slid->y_unit_px; + newpos = slid->y_pos = MIN(slid->y_units-vis_units, + MAX(0, slid->y_pos+units)); + if(newpos < 0) { + newpos = slid->y_pos = 0; + } + if(oldpos == newpos) + return; + + if (units>=vis_units || gemtk_wm_has_intersection(win, &g_ro)) { + // send complete redraw + redraw = &g_ro; + } else { + // only adjust ypos when scrolling down: + if(pix < 0 ) { + // blit screen area: + g.g_h -= abs_pix; + move_rect(win, &g, 0, abs_pix); + g.g_y = g_ro.g_y; + g.g_h = abs_pix; + redraw = &g; + } else { + // blit screen area: + g.g_y += abs_pix; + g.g_h -= abs_pix; + move_rect(win, &g, 0, -abs_pix); + g.g_y = g_ro.g_y + g_ro.g_h - abs_pix; + g.g_h = abs_pix; + redraw = &g; + } + } + } else { + pix = units*slid->x_unit_px; + abs_pix = abs(pix); + oldpos = slid->x_pos; + vis_units = g.g_w/slid->x_unit_px; + newpos = slid->x_pos = MIN(slid->x_units-vis_units, + MAX(0, slid->x_pos+units)); + + if(newpos < 0) { + newpos = slid->x_pos = 0; + } + + if(oldpos == newpos) + return; + if (units>=vis_units || gemtk_wm_has_intersection(win, &g_ro)) { + // send complete redraw + redraw = &g_ro; + } else { + // only adjust ypos when scrolling down: + if(pix < 0 ) { + // blit screen area: + g.g_w -= abs_pix; + move_rect(win, &g, abs_pix, 0); + g.g_x = g_ro.g_x; + g.g_w = abs_pix; + redraw = &g; + } else { + // blit screen area: + g.g_x += abs_pix; + g.g_w -= abs_pix; + move_rect(win, &g, -abs_pix, 0); + g.g_x = g_ro.g_x + g_ro.g_w - abs_pix; + g.g_w = abs_pix; + redraw = &g; + } + } + } + + if (refresh) { + gemtk_wm_update_slider(win, orientation); + } + + if ((redraw != NULL) && (redraw->g_h > 0)) { + gemtk_wm_exec_redraw(win, redraw); + } +} + +/** +* Refresh the sliders of the window. +* \param win the GUIWIN +* \param mode bitmask, valid bits: GEMTK_WM_VSLIDER, GEMTK_WM_HSLIDER +*/ +bool gemtk_wm_update_slider(GUIWIN *win, short mode) +{ + GRECT viewport; + struct gemtk_wm_scroll_info_s * slid; + unsigned long size, pos; + int old_x, old_y; + + short handle = gemtk_wm_get_handle(win); + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &viewport); + slid = gemtk_wm_get_scroll_info(win); + + old_x = slid->x_pos; + old_y = slid->y_pos; + + // TODO: check if the window has sliders of that direction...? + + if((mode & GEMTK_WM_VSLIDER) && (slid->y_unit_px > 0)) { + if ( slid->y_units < (long)viewport.g_h/slid->y_unit_px) { + size = 1000L; + } else + size = MAX( 50L, (unsigned long)viewport.g_h*1000L/ + (unsigned long)(slid->y_unit_px*slid->y_units)); + wind_set(handle, WF_VSLSIZE, (int)size, 0, 0, 0); + + if (slid->y_units > (long)viewport.g_h/slid->y_unit_px) { + pos = (unsigned long)slid->y_pos *1000L/ + (unsigned long)(slid->y_units-viewport.g_h/slid->y_unit_px); + wind_set(handle, WF_VSLIDE, (int)pos, 0, 0, 0); + } else if (slid->y_pos) { + slid->y_pos = 0; + wind_set(handle, WF_VSLIDE, 0, 0, 0, 0); + } + } + if((mode & GEMTK_WM_HSLIDER) && (slid->x_unit_px > 0)) { + if ( slid->x_units < (long)viewport.g_w/slid->x_unit_px) + size = 1000L; + else + size = MAX( 50L, (unsigned long)viewport.g_w*1000L/ + (unsigned long)(slid->x_unit_px*slid->x_units)); + wind_set(handle, WF_HSLSIZE, (int)size, 0, 0, 0); + + if( slid->x_units > (long)viewport.g_w/slid->x_unit_px) { + pos = (unsigned long)slid->x_pos*1000L/ + (unsigned long)(slid->x_units-viewport.g_w/slid->x_unit_px); + wind_set(handle, WF_HSLIDE, (int)pos, 0, 0, 0); + } else if (slid->x_pos) { + slid->x_pos = 0; + wind_set(handle, WF_HSLIDE, 0, 0, 0, 0); + } + } + + if(old_x != slid->x_pos || old_y != slid->y_pos) { + return(true); + } + return(false); +} + +/** +* Return the AES handle for the GUIWIN. +*/ +short gemtk_wm_get_handle(GUIWIN *win) +{ + return(win->handle); +} + +/** +* Return the VDI handle for an GUIWIN. +*/ +VdiHdl gemtk_wm_get_vdi_handle(GUIWIN *win) +{ + return(v_vdi_h); +} + +/** +* Returns the state bitmask of the window +*/ +uint32_t gemtk_wm_get_state(GUIWIN *win) +{ + return(win->state); +} + +/** +* Set and new event handler function. +*/ +void gemtk_wm_set_event_handler(GUIWIN *win,gemtk_wm_event_handler_f cb) +{ + win->handler_func = cb; +} + +/** +* Configure the window so that it shows an toolbar or at least reserves +* an area to draw an toolbar. +* \param win The GUIWIN +* \param toolbar the AES form +* \param idx index within the toolbar tree (0 in most cases...) +* \param flags optional configuration flags +*/ +//TODO: document flags +void gemtk_wm_set_toolbar(GUIWIN *win, OBJECT *toolbar, short idx, uint32_t flags) +{ + win->toolbar = toolbar; + win->toolbar_idx = idx; + win->toolbar_edit_obj = -1; + if (flags & GEMTK_WM_FLAG_HAS_VTOOLBAR) { + win->flags |= GEMTK_WM_FLAG_HAS_VTOOLBAR; + win->toolbar_size = win->toolbar[idx].ob_width; + } + else { + win->toolbar_size = win->toolbar[idx].ob_height; + } + gemtk_wm_set_toolbar_redraw_func(win, std_toolbar_redraw); +} + +/** Update width/height of the toolbar region +* \param win the GUIWIN +* \param s the width or height, depending on the flag GEMTK_WM_FLAG_HAS_VTOOLBAR +*/ +void gemtk_wm_set_toolbar_size(GUIWIN *win, uint16_t s) +{ + win->toolbar_size = s; +} + +short gemtk_wm_get_toolbar_edit_obj(GUIWIN *win) +{ + return(win->toolbar_edit_obj); +} + +/** Set the current active edit object */ +void gemtk_wm_set_toolbar_edit_obj(GUIWIN *win, uint16_t obj, short kreturn) +{ + short edit_idx; + + DEBUG_PRINT(("%s, win: %p, obj: %d, kret: %d\n", __FUNCTION__, + win, obj, kreturn)); + + if (obj != win->toolbar_edit_obj) { + + DEBUG_PRINT(("%s, current edit obj: %d\n", __FUNCTION__, + win->toolbar_edit_obj)); + + if(win->toolbar_edit_obj != -1) { + objc_wedit(win->toolbar, win->toolbar_edit_obj, kreturn, &edit_idx, + EDEND, win->handle); + } + + win->toolbar_edit_obj = obj; + + objc_wedit(win->toolbar, win->toolbar_edit_obj, kreturn, &edit_idx, + EDINIT, win->handle); + } else { + DEBUG_PRINT(("%s, nothing to do!\n", __FUNCTION__)); + } +} + +/** Set an custom toolbar redraw function which is called instead of +* default drawing routine. +* \param win the GUIWIN +* \param func the custom redraw function +*/ +void gemtk_wm_set_toolbar_redraw_func(GUIWIN *win, gemtk_wm_redraw_f func) +{ + win->toolbar_redraw_func = func; +} + +/** +* Attach an arbitary pointer to the GUIWIN +*/ +void gemtk_wm_set_user_data(GUIWIN *win, void *data) +{ + win->user_data = data; +} + +/** +* Retrieve the user_data pointer attached to the GUIWIN. +*/ +void *gemtk_wm_get_user_data(GUIWIN *win) +{ + return(win->user_data); +} + +/** Get the scroll management structure for a GUIWIN +*/ +struct gemtk_wm_scroll_info_s *gemtk_wm_get_scroll_info(GUIWIN *win) { + return(&win->scroll_info); +} + +/** +* Get the amount of content dimensions within the window +* which is calculated by using the scroll_info attached to the GUIWIN. +*/ +void gemtk_wm_set_scroll_grid(GUIWIN * win, short x, short y) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win); + + assert(slid != NULL); + + slid->y_unit_px = x; + slid->x_unit_px = y; +} + + +/** Set the size of the content measured in content units +* \param win the GUIWIN +* \param x horizontal size +* \param y vertical size +*/ +void gemtk_wm_set_content_units(GUIWIN * win, short x, short y) +{ + struct gemtk_wm_scroll_info_s *slid = gemtk_wm_get_scroll_info(win); + + assert(slid != NULL); + + slid->x_units = x; + slid->y_units = y; +} + +/** Send an Message to a GUIWIN using AES message pipe +* \param win the GUIWIN which shall receive the message +* \param msg_type the WM_ message definition +* \param a the 4th parameter to appl_write +* \param b the 5th parameter to appl_write +* \param c the 6th parameter to appl_write +* \param d the 7th parameter to appl_write +*/ +void gemtk_wm_send_msg(GUIWIN *win, short msg_type, short a, short b, short c, + short d) +{ + short msg[8]; + + msg[0] = msg_type; + msg[1] = gl_apid; + msg[2] = 0; + msg[3] = (win != NULL) ? win->handle : 0; + msg[4] = a; + msg[5] = b; + msg[6] = c; + msg[7] = d; + + appl_write(gl_apid, 16, &msg); +} + +/** Directly execute an Message to a GUIWIN using the internal dispatcher function. +* This only works for managed windows which have the, + GEMTK_WM_FLAG_PREPROC_WM flag set. + This call does not send any AES messages. +* \param win the GUIWIN which shall receive the message +* \param msg_type the WM_ message definition +* \param a the 4th parameter to appl_write +* \param b the 5th parameter to appl_write +* \param c the 6th parameter to appl_write +* \param d the 7th parameter to appl_write +*/ +short gemtk_wm_exec_msg(GUIWIN *win, short msg_type, short a, short b, short c, + short d) +{ + short msg[8], retval; + + EVMULT_OUT event_out; + + msg[0] = msg_type; + msg[1] = gl_apid; + msg[2] = 0; + msg[3] = win->handle; + msg[4] = a; + msg[5] = b; + msg[6] = c; + msg[7] = d; + + event_out.emo_events = MU_MESAG; + retval = preproc_wm(win, &event_out, msg); + if (retval == 0 || (win->flags & GEMTK_WM_FLAG_PREPROC_WM) != 0){ + retval = win->handler_func(win, &event_out, msg); + } + + return(retval); +} + +void gemtk_wm_exec_redraw(GUIWIN *win, GRECT *area) +{ + GRECT work; + + if (area == NULL) { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &work); + if (work.g_w < 1 || work.g_h < 1) { + if (win->toolbar != NULL) { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_TOOLBAR, &work); + if (work.g_w < 1 || work.g_h < 1) { + return; + } + } + } + area = &work; + } + + gemtk_wm_exec_msg(win, WM_REDRAW, area->g_x, area->g_y, area->g_w, + area->g_h); +} + +/** Attach an AES FORM to the GUIWIN, similar feature like the toolbar +*/ +void gemtk_wm_set_form(GUIWIN *win, OBJECT *tree, short index) +{ + DEBUG_PRINT(("Setting form %p (%d) for window %p\n", tree, index, win)); + win->form = tree; + win->form_edit_obj = -1; + win->form_focus_obj = -1; + win->form_idx = index; +} + +/** Checks if a GUIWIN is overlapped by other windows. +*/ +bool gemtk_wm_has_intersection(GUIWIN *win, GRECT *work) +{ + GRECT area, mywork; + bool retval = true; + + if (work == NULL) { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &mywork); + work = &mywork; + } + + wind_get_grect(win->handle, WF_FIRSTXYWH, &area); + while (area.g_w) { + //GRECT * ptr = &area; + if (RC_WITHIN(work, &area)) { + retval = false; + } + wind_get_grect(win->handle, WF_NEXTXYWH, &area); + } + + return(retval); +} + +/** Execute an toolbar redraw +* \param msg specifies the AES message which initiated the redraw, or 0 when +* the function was called without AES message context. +*/ +void gemtk_wm_toolbar_redraw(GUIWIN *gw, uint16_t msg, GRECT *clip) +{ + GRECT tb_area, tb_area_ro; + + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_TOOLBAR, &tb_area_ro); + + if(clip == NULL) { + clip = &tb_area_ro; + } + + tb_area = tb_area_ro; + + if (rc_intersect(clip, &tb_area)) { + gw->toolbar_redraw_func(gw, msg, &tb_area); + } +} + +/** Execute FORM redraw +*/ +void gemtk_wm_form_redraw(GUIWIN *gw, GRECT *clip) +{ + GRECT area, area_ro, g; + struct gemtk_wm_scroll_info_s *slid; + //int new_x, new_y, old_x, old_y; + + DEBUG_PRINT(("gemtk_wm_form_redraw\n")); + + // calculate form coordinates, include scrolling: + gemtk_wm_get_grect(gw, GEMTK_WM_AREA_CONTENT, &area_ro); + slid = gemtk_wm_get_scroll_info(gw); + + // Update form position: + gw->form[gw->form_idx].ob_x = area_ro.g_x - (slid->x_pos * slid->x_unit_px); + gw->form[gw->form_idx].ob_y = area_ro.g_y - (slid->y_pos * slid->y_unit_px); + + if(clip == NULL) { + clip = &area_ro; + } + + area = area_ro; + + /* Walk the AES rectangle list and redraw the visible areas of the window:*/ + if(rc_intersect(clip, &area)) { + + wind_get_grect(gw->handle, WF_FIRSTXYWH, &g); + while (g.g_h > 0 || g.g_w > 0) { + if(rc_intersect(&area, &g)) { + objc_draw(gw->form, gw->form_idx, 8, g.g_x, g.g_y, + g.g_w, g.g_h); + + } + wind_get_grect(gw->handle, WF_NEXTXYWH, &g); + } + } +} + + +/** Fill the content area with white color +*/ +void gemtk_wm_clear(GUIWIN *win) +{ + GRECT area, g; + short pxy[4]; + VdiHdl vh; + + vh = gemtk_wm_get_vdi_handle(win); + + if(win->state & GEMTK_WM_STATUS_ICONIFIED) { + // also clear the toolbar area when iconified: + gemtk_wm_get_grect(win, GEMTK_WM_AREA_WORK, &area); + } else { + gemtk_wm_get_grect(win, GEMTK_WM_AREA_CONTENT, &area); + } + + vsf_interior(vh, FIS_SOLID); + vsf_color(vh, 0); + vswr_mode(vh, MD_REPLACE); + wind_get_grect(win->handle, WF_FIRSTXYWH, &g); + while (g.g_h > 0 || g.g_w > 0) { + if(rc_intersect(&area, &g)) { + pxy[0] = g.g_x; + pxy[1] = g.g_y; + pxy[2] = g.g_x+g.g_w-1; + pxy[3] = g.g_y+g.g_h-1; + v_bar(vh, pxy); + } + wind_get_grect(win->handle, WF_NEXTXYWH, &g); + } +} -- cgit v1.2.3