/*- * Copyright (c) 1997-2002 The Protein Laboratory, University of Copenhagen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: Widget.c,v 1.137 2007/05/23 17:50:57 dk Exp $ */ #include "apricot.h" #include "Application.h" #include "Icon.h" #include "Popup.h" #include "Widget.h" #include "Window.h" #include #ifdef __cplusplus extern "C" { #endif #undef my #define inherited CDrawable #define enter_method PWidget_vmt selfvmt = ((( PWidget) self)-> self) #define my selfvmt #define var (( PWidget) self) typedef Bool ActionProc ( Handle self, Handle item, void * params); typedef ActionProc *PActionProc; #define his (( PWidget) child) /* local defines */ typedef struct _SingleColor { Color color; int index; } SingleColor, *PSingleColor; static Bool find_dup_msg( PEvent event, int * cmd); static Bool pquery ( Handle window, Handle self, void * v); static Bool get_top_current( Handle self); static Bool sptr( Handle window, Handle self, void * v); static Handle find_tabfoc( Handle self); static Bool showhint_notify ( Handle self, Handle child, void * data); static Bool hint_notify ( Handle self, Handle child, SV * hint); extern void Widget_pack_slaves( Handle self); extern void Widget_place_slaves( Handle self); extern Bool Widget_size_notify( Handle self, Handle child, const Rect* metrix); extern Bool Widget_move_notify( Handle self, Handle child, Point * moveTo); /* init, done & update_sys_handle */ void Widget_init( Handle self, HV * profile) { enter_method; SV * sv; inherited-> init( self, profile); list_create( &var-> widgets, 0, 8); var-> tabOrder = -1; var-> geomInfo. side = 3; /* default pack side is 'top', anchor ='center' */ var-> geomInfo. anchorx = var-> geomInfo. anchory = 1; my-> update_sys_handle( self, profile); /* props init */ /* font and colors */ SvHV_Font( pget_sv( font), &Font_buffer, "Widget::init"); my-> set_widgetClass ( self, pget_i( widgetClass )); my-> set_color ( self, pget_i( color )); my-> set_backColor ( self, pget_i( backColor )); my-> set_font ( self, Font_buffer); opt_assign( optOwnerBackColor, pget_B( ownerBackColor)); opt_assign( optOwnerColor , pget_B( ownerColor)); opt_assign( optOwnerFont , pget_B( ownerFont)); opt_assign( optOwnerHint , pget_B( ownerHint)); opt_assign( optOwnerShowHint , pget_B( ownerShowHint)); opt_assign( optOwnerPalette , pget_B( ownerPalette)); my-> colorIndex( self, true, ciHiliteText, pget_i( hiliteColor) ); my-> colorIndex( self, true, ciHilite, pget_i( hiliteBackColor) ); my-> colorIndex( self, true, ciDisabledText, pget_i( disabledColor) ); my-> colorIndex( self, true, ciDisabled, pget_i( disabledBackColor)); my-> colorIndex( self, true, ciLight3DColor, pget_i( light3DColor) ); my-> colorIndex( self, true, ciDark3DColor, pget_i( dark3DColor) ); my-> set_palette( self, pget_sv( palette)); /* light props */ my-> set_autoEnableChildren ( self, pget_B( autoEnableChildren)); my-> set_briefKeys ( self, pget_B( briefKeys)); my-> set_buffered ( self, pget_B( buffered)); my-> set_cursorVisible ( self, pget_B( cursorVisible)); my-> set_growMode ( self, pget_i( growMode)); my-> set_helpContext ( self, pget_sv( helpContext)); my-> set_hint ( self, pget_sv( hint)); my-> set_firstClick ( self, pget_B( firstClick)); { Point hotSpot; Handle icon = pget_H( pointerIcon); prima_read_point( pget_sv( pointerHotSpot), (int*)&hotSpot, 2, "RTC0087: Array panic on 'pointerHotSpot'"); if ( icon != nilHandle && !kind_of( icon, CIcon)) { warn("RTC083: Illegal object reference passed to Widget::pointerIcon"); icon = nilHandle; } apc_pointer_set_user( self, icon, hotSpot); } my-> set_pointerType ( self, pget_i( pointerType)); my-> set_selectingButtons ( self, pget_i( selectingButtons)); my-> set_selectable ( self, pget_B( selectable)); my-> set_showHint ( self, pget_B( showHint)); my-> set_tabOrder ( self, pget_i( tabOrder)); my-> set_tabStop ( self, pget_i( tabStop)); my-> set_text ( self, pget_sv( text)); opt_assign( optScaleChildren, pget_B( scaleChildren)); /* subcomponents props */ my-> popupColorIndex( self, true, ciFore, pget_i( popupColor) ); my-> popupColorIndex( self, true, ciBack, pget_i( popupBackColor) ); my-> popupColorIndex( self, true, ciHiliteText, pget_i( popupHiliteColor) ); my-> popupColorIndex( self, true, ciHilite, pget_i( popupHiliteBackColor) ); my-> popupColorIndex( self, true, ciDisabledText, pget_i( popupDisabledColor) ); my-> popupColorIndex( self, true, ciDisabled, pget_i( popupDisabledBackColor) ); my-> popupColorIndex( self, true, ciLight3DColor, pget_i( popupLight3DColor) ); my-> popupColorIndex( self, true, ciDark3DColor, pget_i( popupDark3DColor) ); SvHV_Font( pget_sv( popupFont), &Font_buffer, "Widget::init"); my-> set_popup_font ( self, Font_buffer); if ( SvTYPE( sv = pget_sv( popupItems)) != SVt_NULL) my-> set_popupItems( self, sv); if ( SvTYPE( sv = pget_sv( accelItems)) != SVt_NULL) my-> set_accelItems( self, sv); /* size, position, enabling, visibliity etc. runtime */ { Point set, set2; AV * av; SV ** holder; NPoint ds = {1,1}; prima_read_point( pget_sv( sizeMin), (int*)&set, 2, "RTC0082: Array panic on 'sizeMin'"); prima_read_point( pget_sv( sizeMax), (int*)&set2, 2, "RTC0083: Array panic on 'sizeMax'"); var-> sizeMax = set2; my-> set_sizeMin( self, set); my-> set_sizeMax( self, set2); prima_read_point( pget_sv( cursorSize), (int*)&set, 2, "RTC0084: Array panic on 'cursorSize'"); my-> set_cursorSize( self, set); prima_read_point( pget_sv( cursorPos), (int*)&set, 2, "RTC0085: Array panic on 'cursorPos'"); my-> set_cursorPos( self, set); av = ( AV *) SvRV( pget_sv( designScale)); holder = av_fetch( av, 0, 0); ds. x = holder ? SvNV( *holder) : 1; if ( !holder) warn("RTC0086: Array panic on 'designScale'"); holder = av_fetch( av, 1, 0); ds. y = holder ? SvNV( *holder) : 1; if ( !holder) warn("RTC0086: Array panic on 'designScale'"); my-> set_designScale( self, ds); } my-> set_enabled ( self, pget_B( enabled)); if ( !pexist( originDontCare) || !pget_B( originDontCare)) { Point pos; pos. x = pget_i( left); pos. y = pget_i( bottom); my-> set_origin( self, pos); } else var-> pos = my-> get_origin( self); if ( !pexist( sizeDontCare ) || !pget_B( sizeDontCare )) { Point size; size. x = pget_i( width); size. y = pget_i( height); my-> set_size( self, size); } else var-> virtualSize = my-> get_size( self); var-> geomSize = var-> virtualSize; { Bool x = 0, y = 0; if ( pget_B( centered)) { x = 1; y = 1; }; if ( pget_B( x_centered) || ( var-> growMode & gmXCenter)) x = 1; if ( pget_B( y_centered) || ( var-> growMode & gmYCenter)) y = 1; if ( x || y) my-> set_centered( self, x, y); } opt_assign( optPackPropagate, pget_B( packPropagate)); my-> set_packInfo( self, pget_sv( packInfo)); my-> set_placeInfo( self, pget_sv( placeInfo)); my-> set_geometry( self, pget_i( geometry)); my-> set_shape ( self, pget_H( shape)); my-> set_visible ( self, pget_B( visible)); if ( pget_B( capture)) my-> set_capture( self, 1, nilHandle); if ( pget_B( current)) my-> set_current( self, 1); CORE_INIT_TRANSIENT(Widget); { SV * widgets = pget_sv( widgets); if ( SvTYPE( widgets) != SVt_NULL) { dSP; ENTER; SAVETMPS; PUSHMARK( sp); XPUSHs( var-> mate); XPUSHs( sv_2mortal( newSVsv( widgets))); PUTBACK; perl_call_method( "widgets", G_DISCARD); SPAGAIN; PUTBACK; FREETMPS; LEAVE; } } } void Widget_update_sys_handle( Handle self, HV * profile) { enter_method; Handle owner; Bool clipOwner; ApiHandle parentHandle; if (!( pexist( owner) || pexist( syncPaint) || pexist( clipOwner) || pexist( transparent) )) return; owner = pexist( owner) ? pget_H( owner) : var-> owner; clipOwner = pexist( clipOwner) ? pget_B( clipOwner) : my-> get_clipOwner( self); parentHandle = pexist( parentHandle) ? pget_i( parentHandle) : apc_widget_get_parent_handle( self); if ( parentHandle) { if (( owner != application) && clipOwner) croak("RTC008D: Cannot accept 'parentHandle' for non-application child and clip-owner widget"); } if ( !apc_widget_create( self, owner, pexist( syncPaint) ? pget_B( syncPaint) : my-> get_syncPaint( self), clipOwner, pexist( transparent) ? pget_B( transparent): my-> get_transparent( self), parentHandle )) croak( "RTC0080: Cannot create widget"); pdelete( transparent); pdelete( syncPaint); pdelete( clipOwner); pdelete( parentHandle); } void Widget_done( Handle self) { free( var-> text); apc_widget_destroy( self); free( var-> helpContext); free( var-> hint); var-> text = nil; var-> helpContext = nil; var-> hint = nil; if ( var-> owner) { Handle * enum_lists = PWidget( var-> owner)-> enum_lists; while ( enum_lists) { unsigned int i, count; count = (unsigned int) enum_lists[1]; for ( i = 2; i < count + 2; i++) { if ( self == enum_lists[i]) enum_lists[i] = nilHandle; } enum_lists = ( Handle*) enum_lists[0]; } } list_destroy( &var-> widgets); inherited-> done( self); } /* ::a */ void Widget_attach( Handle self, Handle objectHandle) { if ( objectHandle == nilHandle) return; if ( var-> stage > csNormal) return; if ( kind_of( objectHandle, CWidget)) { if ( list_index_of( &var-> widgets, objectHandle) >= 0) { warn( "RTC0040: Object attach failed"); return; } list_add( &var-> widgets, objectHandle); } inherited-> attach( self, objectHandle); } /*::b */ Bool Widget_begin_paint( Handle self) { Bool ok; if ( !inherited-> begin_paint( self)) return false; if ( !( ok = apc_widget_begin_paint( self, false))) inherited-> end_paint( self); return ok; } Bool Widget_begin_paint_info( Handle self) { Bool ok; if ( is_opt( optInDraw)) return true; if ( !inherited-> begin_paint_info( self)) return false; if ( !( ok = apc_widget_begin_paint_info( self))) inherited-> end_paint_info( self); return ok; } void Widget_bring_to_front( Handle self) { if ( opt_InPaint) return; apc_widget_set_z_order( self, nilHandle, true); } /*::c */ Bool Widget_can_close( Handle self) { enter_method; Event ev = { cmClose}; return ( var-> stage <= csNormal) ? my-> message( self, &ev) : true; } void Widget_cleanup( Handle self) { Handle ptr; enter_method; /* disconnect all geometry slaves */ ptr = var-> packSlaves; while ( ptr) { PWidget( ptr)-> geometry = gtDefault; ptr = PWidget( ptr)-> geomInfo. next; } var-> packSlaves = nilHandle; ptr = var-> placeSlaves; while ( ptr) { PWidget( ptr)-> geometry = gtDefault; ptr = PWidget( ptr)-> geomInfo. next; } var-> placeSlaves = nilHandle; my-> set_geometry( self, gtDefault); if ( application && (( PApplication) application)-> hintUnder == self) my-> set_hintVisible( self, 0); { int i; for ( i = 0; i < var-> widgets. count; i++) Object_destroy( var-> widgets. items[i]); } my-> detach( self, var-> accelTable, true); var-> accelTable = nilHandle; my-> detach( self, var-> popupMenu, true); var-> popupMenu = nilHandle; inherited-> cleanup( self); } Bool Widget_close( Handle self) { Bool canClose; enter_method; if ( var-> stage > csNormal) return true; if (( canClose = my-> can_close( self))) { Object_destroy( self); } return canClose; } Bool Widget_custom_paint( Handle self) { PList list; void * ret; enter_method; if ( my-> on_paint != Widget_on_paint) return true; if ( var-> eventIDs == nil) return false; ret = hash_fetch( var-> eventIDs, "Paint", 5); if ( ret == nil) return false; list = var-> events + PTR2UV( ret) - 1; return list-> count > 0; } /*::d */ void Widget_detach( Handle self, Handle objectHandle, Bool kill) { enter_method; if ( kind_of( objectHandle, CWidget)) { list_delete( &var-> widgets, objectHandle); if ( var-> currentWidget == objectHandle && objectHandle != nilHandle) my-> set_currentWidget( self, nilHandle); } inherited-> detach( self, objectHandle, kill); } /*::e */ void Widget_end_paint( Handle self) { if ( !is_opt( optInDraw)) return; apc_widget_end_paint( self); inherited-> end_paint( self); } void Widget_end_paint_info( Handle self) { if ( !is_opt( optInDrawInfo)) return; apc_widget_end_paint_info( self); inherited-> end_paint_info( self); } /*::f */ SV* Widget_fetch_resource( char *className, char *name, char *classRes, char *res, Handle owner, int resType) { char *str = nil; Color clr; void *parm; Font font; SV * ret; switch ( resType) { case frColor: parm = &clr; break; case frFont: parm = &font; bzero( &font, sizeof( font)); break; default: parm = &str; resType = frString; } if ( !apc_fetch_resource( prima_normalize_resource_string( className, true), prima_normalize_resource_string( name, false), prima_normalize_resource_string( classRes, true), prima_normalize_resource_string( res, false), owner, resType, parm)) return nilSV; switch ( resType) { case frColor: ret = newSViv( clr); break; case frFont: ret = sv_Font2HV( &font); break; default: ret = str ? newSVpv( str, 0) : nilSV; free( str); } return ret; } Handle Widget_first( Handle self) { return apc_widget_get_z_order( self, zoFirst); } Handle Widget_first_that( Handle self, void * actionProc, void * params) { Handle child = nilHandle; int i, count = var-> widgets. count; Handle * list; if ( actionProc == nil || count == 0) return nilHandle; if (!(list = allocn( Handle, count + 2))) return nilHandle; list[0] = (Handle)( var-> enum_lists); list[1] = (Handle)( count); var-> enum_lists = list; memcpy( list + 2, var-> widgets. items, sizeof( Handle) * count); for ( i = 2; i < count + 2; i++) { if ( list[i] && (( PActionProc) actionProc)( self, list[ i], params)) { child = list[ i]; break; } } var-> enum_lists = (Handle*)(*list); free( list); return child; } /*::g */ /*::h */ void Widget_handle_event( Handle self, PEvent event) { enter_method; #define evOK ( var-> evStack[ var-> evPtr - 1]) #define objCheck if ( var-> stage > csNormal) return inherited-> handle_event ( self, event); objCheck; switch ( event-> cmd) { case cmCalcBounds: { Point min, max; min = var-> sizeMin; max = var-> sizeMax; if (( min. x > 0) && ( min. x > event-> gen. R. right )) event-> gen. R. right = min. x; if (( min. y > 0) && ( min. y > event-> gen. R. top )) event-> gen. R. top = min. y; if (( max. x > 0) && ( max. x < event-> gen. R. right )) event-> gen. R. right = max. x; if (( max. y > 0) && ( max. y < event-> gen. R. top )) event-> gen. R. top = max. y; } break; case cmSetup: if ( !is_opt( optSetupComplete)) { opt_set( optSetupComplete); my-> notify( self, " repaint( self); break; case cmPaint : if ( !opt_InPaint && !my-> get_locked( self)) if ( inherited-> begin_paint( self)) { if ( apc_widget_begin_paint( self, true)) { my-> notify( self, " end_paint( self); } else inherited-> end_paint( self); } break; case cmEnable : my-> notify( self, " notify( self, " notify( self, " notify( self, " notify( self, " notify( self, " notify( self, " gen. B); break; case cmClose : if ( my-> first_that( self, (void*)pquery, nil)) { my-> clear_event( self); return; } objCheck; my-> notify( self, " notify( self, " notify( self, " gen. source, CPopup)) my-> notify( self, " gen. i); else var-> popupColor[ event-> gen. i] = apc_menu_get_color( event-> gen. source, event-> gen. i); break; case cmFontChanged: if ( !kind_of( event-> gen. source, CPopup)) my-> notify( self, " gen. source, &var-> popupFont); break; case cmMenu: if ( event-> gen. H) { char buffer[16], *context; context = ((( PAbstractMenu) event-> gen. H)-> self)-> make_id_context( event-> gen. H, event-> gen. i, buffer); my-> notify( self, " gen. H, context); } break; case cmMouseClick: my-> notify( self, " pos. button, event-> pos. mod, event -> pos. where, event-> pos. dblclk); break; case cmMouseDown: if ((( PApplication) application)-> hintUnder == self) my-> set_hintVisible( self, 0); objCheck; if (((event-> pos. button & var-> selectingButtons) != 0) && my-> get_selectable( self)) my-> set_selected( self, true); objCheck; my-> notify( self, " pos. button, event-> pos. mod, event -> pos. where); break; case cmMouseUp: my-> notify( self, " pos. button, event-> pos. mod, event -> pos. where); break; case cmMouseMove: if ((( PApplication) application)-> hintUnder == self) my-> set_hintVisible( self, -1); objCheck; my-> notify( self, " pos. mod, event -> pos. where); break; case cmMouseWheel: my-> notify( self, " pos. mod, event -> pos. where, event-> pos. button); /* +n*delta == up, -n*delta == down */ break; case cmMouseEnter: my-> notify( self, " pos. mod, event -> pos. where); objCheck; if ( application && is_opt( optShowHint) && ((( PApplication) application)-> options. optShowHint) && var-> hint[0]) { PApplication app = ( PApplication) application; app-> self-> set_hint_action( application, self, true, true); } break; case cmMouseLeave: if ( application && is_opt( optShowHint)) { PApplication app = ( PApplication) application; app-> self-> set_hint_action( application, self, false, true); } my-> notify( self, " key. repeat; if ( is_opt( optBriefKeys)) rep = 1; else event-> key. repeat = 1; for ( i = 0; i < rep; i++) { my-> notify( self, " key.code, event-> key. key, event-> key. mod, event-> key. repeat); objCheck; if ( evOK) { Event ev = *event; ev. key. source = self; ev. cmd = var-> owner ? cmDelegateKey : cmTranslateAccel; ev. key. subcmd = 0; if ( !my-> message( self, &ev)) { my-> clear_event( self); return; } objCheck; } if ( !evOK) break; { Handle next = nilHandle; switch( event-> key. key) { case kbF1: case kbHelp: my-> help( self); my-> clear_event( self); return; case kbLeft: next = my-> next_positional( self, -1, 0); break; case kbRight: next = my-> next_positional( self, 1, 0); break; case kbUp: next = my-> next_positional( self, 0, 1); break; case kbDown: next = my-> next_positional( self, 0, -1); break; case kbTab: next = my-> next_tab( self, true); break; case kbBackTab: next = my-> next_tab( self, false); break; default:; } if ( next) { CWidget( next)-> set_selected( next, true); objCheck; my-> clear_event( self); return; } } } } break; case cmDelegateKey: switch ( event-> key. subcmd) { case 0: { Event ev = *event; ev. cmd = cmTranslateAccel; if ( !my-> message( self, &ev)) { my-> clear_event( self); return; } objCheck; if ( my-> first_that( self, (void*)accel_notify, &ev)) { my-> clear_event( self); return; } objCheck; ev. cmd = cmDelegateKey; ev. key. subcmd = 1; if ( my-> first_that( self, (void*)accel_notify, &ev)) { my-> clear_event( self); return; } if ( var-> owner) { if ( var-> owner == application) ev. cmd = cmTranslateAccel; else ev. key. subcmd = 0; ev. key. source = self; if (!(((( PWidget) var-> owner)-> self)-> message( var-> owner, &ev))) { objCheck; my-> clear_event( self); return; } } } break; case 1: { Event ev = *event; ev. cmd = cmTranslateAccel; if ( my-> first_that( self, (void*)accel_notify, &ev)) { my-> clear_event( self); return; } objCheck; ev = *event; if ( my-> first_that( self, (void*)accel_notify, &ev)) { my-> clear_event( self); return; } } break; } break; case cmTranslateAccel: { int key = CAbstractMenu-> translate_key( nilHandle, event-> key. code, event-> key. key, event-> key. mod); if ( my-> first_that_component( self, (void*)find_accel, &key)) { my-> clear_event( self); return; } objCheck; } my-> notify( self, " key.code, event-> key. key, event-> key. mod); break; case cmKeyUp: my-> notify( self, " key.code, event-> key. key, event-> key. mod); break; case cmMenuCmd: if ( event-> gen. source) ((( PAbstractMenu) event-> gen. source)-> self)-> sub_call_id( event-> gen. source, event-> gen. i); break; case cmMove: { Bool doNotify = false; Point oldP; if ( var-> stage == csNormal && var-> evQueue == nil) { doNotify = true; } else if ( var-> stage > csNormal) { break; } else if ( var-> evQueue != nil) { int i = list_first_that( var-> evQueue, (void*)find_dup_msg, &event-> cmd); PEvent n; if ( i < 0) { if ( !( n = alloc1( Event))) goto MOVE_EVENT; memcpy( n, event, sizeof( Event)); n-> gen. B = 1; n-> gen. R. left = n-> gen. R. bottom = 0; list_add( var-> evQueue, ( Handle) n); } else n = ( PEvent) list_at( var-> evQueue, i); n-> gen. P = event-> gen. P; } MOVE_EVENT:; if ( !event-> gen. B) my-> first_that( self, (void*) Widget_move_notify, &event-> gen. P); if ( doNotify) oldP = var-> pos; var-> pos = event-> gen. P; if ( doNotify && (oldP. x != event-> gen. P. x || oldP. y != event-> gen. P. y)) { my-> notify( self, " gen. P); objCheck; if ( var-> growMode & gmCenter) my-> set_centered( self, var-> growMode & gmXCenter, var-> growMode & gmYCenter); } } break; case cmPopup: { Handle org = self; my-> notify( self, " gen. B, event-> gen. P. x, event-> gen. P. y); objCheck; if ( evOK) { while ( self) { PPopup p = ( PPopup) CWidget( self)-> get_popup( self); if ( p && p-> self-> get_autoPopup(( Handle) p)) { Point px = event-> gen. P; apc_widget_map_points( org, true, 1, &px); apc_widget_map_points( self, false, 1, &px); p-> self-> popup(( Handle) p, px. x, px. y ,0,0,0,0); CWidget( org)-> clear_event( org); return; } self = var-> owner; } } } break; case cmSize: /* expecting new size in P, old & new size in R. */ { Bool doNotify = false; if ( var-> stage == csNormal && var-> evQueue == nil) { doNotify = true; } else if ( var-> stage > csNormal) { break; } else if ( var-> evQueue != nil) { int i = list_first_that( var-> evQueue, (void*)find_dup_msg, &event-> cmd); PEvent n; if ( i < 0) { if ( !( n = alloc1( Event))) goto SIZE_EVENT; memcpy( n, event, sizeof( Event)); n-> gen. B = 1; n-> gen. R. left = n-> gen. R. bottom = 0; list_add( var-> evQueue, ( Handle) n); } else n = ( PEvent) list_at( var-> evQueue, i); n-> gen. P. x = n-> gen. R. right = event-> gen. P. x; n-> gen. P. y = n-> gen. R. top = event-> gen. P. y; } SIZE_EVENT:; if ( var-> growMode & gmCenter) my-> set_centered( self, var-> growMode & gmXCenter, var-> growMode & gmYCenter); if ( !event-> gen. B) my-> first_that( self, (void*) Widget_size_notify, &event-> gen. R); if ( doNotify) { Point oldSize; oldSize. x = event-> gen. R. left; oldSize. y = event-> gen. R. bottom; my-> notify( self, " gen. P); } Widget_pack_slaves( self); Widget_place_slaves( self); } break; } } void Widget_hide( Handle self) { enter_method; my-> set_visible( self, false); } void Widget_hide_cursor( Handle self) { enter_method; if ( my-> get_cursorVisible( self)) my-> set_cursorVisible( self, false); else var-> cursorLock++; } /*::i */ void Widget_insert_behind ( Handle self, Handle widget) { apc_widget_set_z_order( self, widget, 0); } void Widget_invalidate_rect( Handle self, Rect rect) { enter_method; if ( !opt_InPaint && ( var-> stage == csNormal) && !my-> get_locked( self)) apc_widget_invalidate_rect( self, &rect); } Bool Widget_is_child( Handle self, Handle owner) { if ( !owner) return false; while ( self) { if ( self == owner) return true; self = var-> owner; } return false; } /*::j */ /*::k */ void Widget_key_event( Handle self, int command, int code, int key, int mod, int repeat, Bool post) { Event ev; if ( command != cmKeyDown && command != cmKeyUp) return; memset( &ev, 0, sizeof( ev)); if ( repeat <= 0) repeat = 1; ev. cmd = command; ev. key. code = code; ev. key. key = key; ev. key. mod = mod; ev. key. repeat = repeat; apc_message( self, &ev, post); } /*::l */ Handle Widget_last( Handle self) { return apc_widget_get_z_order( self, zoLast); } Bool Widget_lock( Handle self) { var-> lockCount++; return true; } /*::m */ void Widget_mouse_event( Handle self, int command, int button, int mod, int x, int y, Bool dbl, Bool post) { Event ev; if ( command != cmMouseDown && command != cmMouseUp && command != cmMouseClick && command != cmMouseMove && command != cmMouseWheel && command != cmMouseEnter && command != cmMouseLeave ) return; memset( &ev, 0, sizeof( ev)); ev. cmd = command; ev. pos. where. x = x; ev. pos. where. y = y; ev. pos. mod = mod; ev. pos. button = button; if ( command == cmMouseClick) ev. pos. dblclk = dbl; apc_message( self, &ev, post); } /*::n */ Handle Widget_next( Handle self) { return apc_widget_get_z_order( self, zoNext); } static void fill_tab_candidates( PList list, Handle level) { int i; PList w = &(PWidget( level)-> widgets); for ( i = 0; i < w-> count; i++) { Handle x = w-> items[i]; if ( CWidget( x)-> get_visible( x) && CWidget( x)-> get_enabled( x)) { if ( CWidget( x)-> get_selectable( x) && CWidget( x)-> get_tabStop( x)) list_add( list, x); fill_tab_candidates( list, x); } } } Handle Widget_next_positional( Handle self, int dx, int dy) { Handle horizon = self; int i, maxDiff = INT_MAX; Handle max = nilHandle; List candidates; Point p[2]; int minor[2], major[2], axis, extraDiff, ir[4]; /* In order to compute positional difference, using four penalties. To simplify algorithm, Rect will be translated to int[4] and minor, major and extraDiff assigned to array indices for those steps - minor for first and third, major for second and extraDiff for last one. */ axis = ( dx == 0) ? dy : dx; minor[0] = ( dx == 0) ? 0 : 1; minor[1] = minor[0] + 2; extraDiff = major[(axis < 0) ? 0 : 1] = ( dx == 0) ? 1 : 0; major[(axis < 0) ? 1 : 0] = extraDiff + 2; extraDiff = ( dx == 0) ? (( axis < 0) ? 0 : 2) : (( axis < 0) ? 1 : 3); while ( PWidget( horizon)-> owner) { if ( ( PWidget( horizon)-> options. optSystemSelectable) || /* fast check for CWindow */ ( PWidget( horizon)-> options. optModalHorizon) ) break; horizon = PWidget( horizon)-> owner; } if ( !CWidget( horizon)-> get_visible( horizon) || !CWidget( horizon)-> get_enabled( horizon)) return nilHandle; list_create( &candidates, 64, 64); fill_tab_candidates( &candidates, horizon); p[0].x = p[0].y = 0; p[1] = CWidget( self)-> get_size( self); apc_widget_map_points( self, true, 2, p); apc_widget_map_points( horizon, false, 2, p); ir[0] = p[0].x; ir[1] = p[0].y; ir[2] = p[1].x; ir[3] = p[1].y; for ( i = 0; i < candidates. count; i++) { int diff, ix[4]; Handle x = candidates. items[i]; if ( x == self) continue; p[0].x = p[0].y = 0; p[1] = CWidget( x)-> get_size( x); apc_widget_map_points( x, true, 2, p); apc_widget_map_points( horizon, false, 2, p); ix[0] = p[0].x; ix[1] = p[0].y; ix[2] = p[1].x; ix[3] = p[1].y; /* First step - checking if the widget is subject to comparison. It is not, if it's minor axis is not contiguous with self's */ if ( ix[ minor[0]] > ir[ minor[1]] || ix[ minor[1]] < ir[ minor[0]]) continue; /* Using x100 penalty for distance in major axis - and discarding those that of different sign */ diff = ( ix[ major[ 1]] - ir[ major[0]]) * 100 * axis; if ( diff < 0) continue; /* Adding x10 penalty for incomplete minor axis congruence. Addition goes in tenths, in a way to not allow congruence overweight major axis distance */ if ( ix[ minor[0]] > ir[ minor[0]]) diff += ( ix[ minor[0]] - ir[ minor[0]]) * 100 / ( ir[ minor[1]] - ir[ minor[0]]); if ( ix[ minor[1]] < ir[ minor[1]]) diff += ( ir[ minor[1]] - ix[ minor[1]]) * 100 / ( ir[ minor[1]] - ir[ minor[0]]); /* Adding 'distance from level' x1 penalty */ if (( ix[ extraDiff] - ir[ extraDiff]) * axis < 0) diff += abs( ix[ extraDiff] - ir[ extraDiff]); if ( diff < maxDiff) { max = x; maxDiff = diff; } } list_destroy( &candidates); return max; } static int compare_taborders_forward( const void *a, const void *b) { if ((*(PWidget*) a)-> tabOrder < (*(PWidget*) b)-> tabOrder) return -1; else if ((*(PWidget*) a)-> tabOrder > (*(PWidget*) b)-> tabOrder) return 1; else return 0; } static int compare_taborders_backward( const void *a, const void *b) { if ((*(PWidget*) a)-> tabOrder < (*(PWidget*) b)-> tabOrder) return 1; else if ((*(PWidget*) a)-> tabOrder > (*(PWidget*) b)-> tabOrder) return -1; else return 0; } static int do_taborder_candidates( Handle level, Handle who, int (*compareProc)(const void *, const void *), int * stage, Handle * result) { int i, fsel = -1; PList w = &(PWidget( level)-> widgets); Handle * ordered; if ( w-> count == 0) return true; ordered = ( Handle *) malloc( w-> count * sizeof( Handle)); if ( !ordered) return true; memcpy( ordered, w-> items, w-> count * sizeof( Handle)); qsort( ordered, w-> count, sizeof( Handle), compareProc); /* finding current widget in the group */ for ( i = 0; i < w-> count; i++) { Handle x = ordered[i]; if ( CWidget( x)-> get_current( x)) { fsel = i; break; } } if ( fsel < 0) fsel = 0; for ( i = 0; i < w-> count; i++) { int j; Handle x; j = i + fsel; if ( j >= w-> count) j -= w-> count; x = ordered[j]; if ( CWidget( x)-> get_visible( x) && CWidget( x)-> get_enabled( x)) { if ( CWidget( x)-> get_selectable( x) && CWidget( x)-> get_tabStop( x)) { if ( *result == nilHandle) *result = x; switch( *stage) { case 0: /* nothing found yet */ if ( x == who) *stage = 1; break; default: /* next widget after 'who' is ours */ *result = x; free( ordered); return false; } } if ( !do_taborder_candidates( x, who, compareProc, stage, result)) { free( ordered); return false; /* fall through */ } } } free( ordered); return true; } Handle Widget_next_tab( Handle self, Bool forward) { Handle horizon = self, result = nilHandle; int stage = 0; while ( PWidget( horizon)-> owner) { if ( ( PWidget( horizon)-> options. optSystemSelectable) || /* fast check for CWindow */ ( PWidget( horizon)-> options. optModalHorizon) ) break; horizon = PWidget( horizon)-> owner; } if ( !CWidget( horizon)-> get_visible( horizon) || !CWidget( horizon)-> get_enabled( horizon)) return nilHandle; do_taborder_candidates( horizon, self, forward ? compare_taborders_forward : compare_taborders_backward, &stage, &result); if ( result == self) result = nilHandle; return result; } /*::o */ /*::p */ void Widget_post_message( Handle self, SV * info1, SV * info2) { PPostMsg p; Event ev = { cmPost}; if ( var-> stage > csNormal) return; if (!( p = alloc1( PostMsg))) return; p-> info1 = newSVsv( info1); p-> info2 = newSVsv( info2); p-> h = self; if ( var-> postList == nil) var-> postList = plist_create( 8, 8); list_add( var-> postList, ( Handle) p); ev. gen. p = p; ev. gen. source = ev. gen. H = self; apc_message( self, &ev, true); } Handle Widget_prev( Handle self) { return apc_widget_get_z_order( self, zoPrev); } Bool Widget_process_accel( Handle self, int key) { enter_method; if ( my-> first_that_component( self, (void*)find_accel, &key)) return true; return kind_of( var-> owner, CWidget) ? ((( PWidget) var-> owner)-> self)->process_accel( var-> owner, key) : false; } /*::q */ /*::r */ void Widget_repaint( Handle self) { enter_method; if ( !opt_InPaint && ( var-> stage == csNormal) && !my-> get_locked( self)) apc_widget_invalidate_rect( self, nil); } /*::s */ void Widget_scroll( Handle self, int dx, int dy, Rect *confine, Rect *clip, Bool withChildren) { enter_method; if ( !opt_InPaint && ( var-> stage == csNormal) && !my-> get_locked( self)) apc_widget_scroll( self, dx, dy, confine, clip, withChildren); } void Widget_scroll_REDEFINED( Handle self, int dx, int dy, Rect *confine, Rect *clip, Bool withChildren) { warn("Invalid call of Widget::scroll"); } XS( Widget_scroll_FROMPERL) { dXSARGS; Handle self; int dx, dy; Rect *confine = nil; Rect *clip = nil; Rect confine_rect, clip_rect; Bool withChildren = false; HV *profile; int rect[4]; if ( items < 3 || (items - 3) % 2) goto invalid_usage; if (!( self = gimme_the_mate( ST(0)))) goto invalid_usage; dx = SvIV( ST(1)); dy = SvIV( ST(2)); profile = parse_hv( ax, sp, items, mark, 3, "Widget::scroll"); if ( pexist( confineRect)) { prima_read_point( pget_sv( confineRect), rect, 4, "RTC008B: Array panic on 'confineRect'"); confine = &confine_rect; confine-> left = rect[0]; confine-> bottom = rect[1]; confine-> right = rect[2]; confine-> top = rect[3]; } if ( pexist( clipRect)) { prima_read_point( pget_sv( clipRect), rect, 4, "RTC008C: Array panic on 'clipRect'"); clip = &clip_rect; clip-> left = rect[0]; clip-> bottom = rect[1]; clip-> right = rect[2]; clip-> top = rect[3]; } if ( pexist( withChildren)) withChildren = pget_B( withChildren); sv_free((SV*)profile); Widget_scroll( self, dx, dy, confine, clip, withChildren); SPAGAIN; SP -= items; PUTBACK; XSRETURN_EMPTY; invalid_usage: croak ("Invalid usage of %s", "Widget::scroll"); } void Widget_send_to_back( Handle self) { apc_widget_set_z_order( self, nilHandle, false); } void Widget_set( Handle self, HV * profile) { enter_method; Handle postOwner = nilHandle; AV *order = nil; int geometry = gtDefault; if ( pexist(__ORDER__)) order = (AV*)SvRV(pget_sv( __ORDER__)); if ( pexist( owner)) { if ( !my-> validate_owner( self, &postOwner, profile)) croak( "Illegal 'owner' reference passed to %s::%s", my-> className, "set"); if ( postOwner != var-> owner) { if ( is_opt( optOwnerColor)) { my-> set_color( self, CWidget( postOwner)-> get_color( postOwner)); opt_set( optOwnerColor); } if ( is_opt( optOwnerBackColor)) { my-> set_backColor( self, CWidget( postOwner)-> get_backColor( postOwner)); opt_set( optOwnerBackColor); } if ( is_opt( optOwnerShowHint)) { Bool newSH = ( postOwner == application) ? 1 : CWidget( postOwner)-> get_showHint( postOwner); my-> set_showHint( self, newSH); opt_set( optOwnerShowHint); } if ( is_opt( optOwnerHint)) { my-> set_hint( self, CWidget( postOwner)-> get_hint( postOwner)); opt_set( optOwnerHint); } if ( is_opt( optOwnerFont)) { my-> set_font ( self, CWidget( postOwner)-> get_font( postOwner)); opt_set( optOwnerFont); } } if ( var-> geometry != gtDefault) { geometry = var-> geometry; my-> set_geometry( self, gtDefault); } } /* geometry manipulations */ { #define iLEFT 0 #define iRIGHT 1 #define iTOP 2 #define iBOTTOM 3 #define iWIDTH 4 #define iHEIGHT 5 int i, count; Bool exists[ 6]; int values[ 6]; if ( pexist( origin)) { int set[2]; if (order && !pexist(left)) av_push( order, newSVpv("left",0)); if (order && !pexist(bottom)) av_push( order, newSVpv("bottom",0)); prima_read_point( pget_sv( origin), set, 2, "RTC0087: Array panic on 'origin'"); pset_i( left, set[0]); pset_i( bottom, set[1]); pdelete( origin); } if ( pexist( rect)) { int rect[4]; if (order && !pexist(left)) av_push( order, newSVpv("left",0)); if (order && !pexist(bottom)) av_push( order, newSVpv("bottom",0)); if (order && !pexist(width)) av_push( order, newSVpv("width",0)); if (order && !pexist(height)) av_push( order, newSVpv("height",0)); prima_read_point( pget_sv( rect), rect, 4, "RTC0088: Array panic on 'rect'"); pset_i( left, rect[0]); pset_i( bottom, rect[1]); pset_i( width, rect[2] - rect[0]); pset_i( height, rect[3] - rect[1]); pdelete( rect); } if ( pexist( size)) { int set[2]; if (order && !pexist(width)) av_push( order, newSVpv("width",0)); if (order && !pexist(height)) av_push( order, newSVpv("height",0)); prima_read_point( pget_sv( size), set, 2, "RTC0089: Array panic on 'size'"); pset_i( width, set[0]); pset_i( height, set[1]); pdelete( size); } if (( exists[ iLEFT] = pexist( left))) values[ iLEFT] = pget_i( left); if (( exists[ iRIGHT] = pexist( right))) values[ iRIGHT] = pget_i( right); if (( exists[ iTOP] = pexist( top))) values[ iTOP] = pget_i( top); if (( exists[ iBOTTOM] = pexist( bottom ))) values[ iBOTTOM] = pget_i( bottom); if (( exists[ iWIDTH] = pexist( width))) values[ iWIDTH] = pget_i( width); if (( exists[ iHEIGHT] = pexist( height))) values[ iHEIGHT] = pget_i( height); count = 0; for ( i = 0; i < 6; i++) if ( exists[ i]) count++; if ( count > 1) { if ( exists[ iWIDTH] && exists[ iRIGHT] && exists[ iLEFT]) { exists[ iRIGHT] = 0; count--; } if ( exists[ iHEIGHT] && exists[ iTOP] && exists[ iBOTTOM]) { exists[ iTOP] = 0; count--; } if ( exists[ iRIGHT] && exists[ iLEFT]) { exists[ iWIDTH] = 1; values[ iWIDTH] = values[ iRIGHT] - values[ iLEFT]; exists[ iRIGHT] = 0; } if ( exists[ iTOP] && exists[ iBOTTOM]) { exists[ iHEIGHT] = 1; values[ iHEIGHT] = values[ iTOP] - values[ iBOTTOM]; exists[ iTOP] = 0; } if ( ( count == 2) && ( ( exists[ iLEFT] && exists[ iBOTTOM]) || ( exists[ iWIDTH] && exists[ iHEIGHT]) ) ) { Point p; if ( exists[ iLEFT]) { p. x = values[ iLEFT]; p. y = values[ iBOTTOM]; my-> set_origin( self, p); } else { p. x = values[ iWIDTH]; p. y = values[ iHEIGHT]; my-> set_size( self, p); } } else { Rect r; if ( !exists[ iWIDTH] || !exists[ iHEIGHT]) { Point sz; sz = my-> get_size( self); if ( !exists[ iWIDTH]) values[ iWIDTH] = sz. x; if ( !exists[ iHEIGHT]) values[ iHEIGHT] = sz. y; exists[ iWIDTH] = exists[ iHEIGHT] = 1; } if ( ( !exists[ iLEFT] && !exists[ iRIGHT]) || ( !exists[ iBOTTOM] && !exists[ iTOP])) { Point pos; pos = my-> get_origin( self); if ( !exists[ iLEFT]) values[ iLEFT] = pos. x; if ( !exists[ iBOTTOM]) values[ iBOTTOM] = pos. y; exists[ iLEFT] = exists[ iBOTTOM] = 1; } if ( !exists[ iLEFT]) { exists[ iLEFT] = 1; values[ iLEFT] = values[ iRIGHT] - values[ iWIDTH]; } if ( !exists[ iBOTTOM]) { exists[ iBOTTOM] = 1; values[ iBOTTOM] = values[ iTOP] - values[ iHEIGHT]; } r. left = values[ iLEFT]; r. bottom = values[ iBOTTOM]; r. right = values[ iLEFT] + values[ iWIDTH]; r. top = values[ iBOTTOM] + values[ iHEIGHT]; my-> set_rect( self, r); } pdelete( left); pdelete( right); pdelete( top); pdelete( bottom); pdelete( width); pdelete( height); } /* count > 1 */ } if ( pexist( popupFont)) { SvHV_Font( pget_sv( popupFont), &Font_buffer, "Widget::set"); my-> set_popup_font( self, Font_buffer); pdelete( popupFont); } if ( pexist( pointerIcon) && pexist( pointerHotSpot)) { Point hotSpot; Handle icon = pget_H( pointerIcon); prima_read_point( pget_sv( pointerHotSpot), (int*)&hotSpot, 2, "RTC0087: Array panic on 'pointerHotSpot'"); if ( icon != nilHandle && !kind_of( icon, CIcon)) { warn("RTC083: Illegal object reference passed to Widget.set_pointer_icon"); icon = nilHandle; } apc_pointer_set_user( self, icon, hotSpot); if ( var-> pointerType == crUser) my-> first_that( self, (void*)sptr, nil); pdelete( pointerIcon); pdelete( pointerHotSpot); } if ( pexist( designScale)) { AV * av = ( AV *) SvRV( pget_sv( designScale)); SV ** holder = av_fetch( av, 0, 0); NPoint ds = {1,1}; ds. x = holder ? SvNV( *holder) : 1; if ( !holder) warn("RTC0086: Array panic on 'designScale'"); holder = av_fetch( av, 1, 0); ds. y = holder ? SvNV( *holder) : 1; if ( !holder) warn("RTC0086: Array panic on 'designScale'"); my-> set_designScale( self, ds); pdelete( designScale); } if ( pexist( sizeMin)) { Point set; prima_read_point( pget_sv( sizeMin), (int*)&set, 2, "RTC0082: Array panic on 'sizeMin'"); my-> set_sizeMin( self, set); pdelete( sizeMin); } if ( pexist( sizeMax)) { Point set; prima_read_point( pget_sv( sizeMax), (int*)&set, 2, "RTC0083: Array panic on 'sizeMax'"); my-> set_sizeMax( self, set); pdelete( sizeMax); } if ( pexist( cursorSize)) { Point set; prima_read_point( pget_sv( cursorSize), (int*)&set, 2, "RTC0084: Array panic on 'cursorSize'"); my-> set_cursorSize( self, set); pdelete( cursorSize); } if ( pexist( cursorPos)) { Point set; prima_read_point( pget_sv( cursorPos), (int*)&set, 2, "RTC0085: Array panic on 'cursorPos'"); my-> set_cursorPos( self, set); pdelete( cursorPos); } if ( pexist( geomSize)) { Point set; prima_read_point( pget_sv( geomSize), (int*)&set, 2, "RTC0089: Array panic on 'geomSize'"); my-> set_geomSize( self, set); pdelete( geomSize); } inherited-> set( self, profile); if ( postOwner) { my-> set_tabOrder( self, var-> tabOrder); my-> set_geometry( self, geometry); } } void Widget_setup( Handle self) { enter_method; if ( get_top_current( self) && my-> get_enabled( self) && my-> get_visible( self)) my-> set_selected( self, true); inherited-> setup( self); } void Widget_show( Handle self) { enter_method; my-> set_visible( self, true); } void Widget_show_cursor( Handle self) { enter_method; if ( var-> cursorLock-- <= 0) { my-> set_cursorVisible( self, true); var-> cursorLock = 0; } } /*::t */ /*::u */ static Bool repaint_all( Handle owner, Handle self, void * dummy) { enter_method; my-> repaint( self); my-> first_that( self, (void*)repaint_all, nil); return false; } Bool Widget_unlock( Handle self) { if ( --var-> lockCount <= 0) { var-> lockCount = 0; repaint_all( var-> owner, self, nil); } return true; } void Widget_update_view( Handle self) { if ( !opt_InPaint) apc_widget_update( self); } /*::v */ Bool Widget_validate_owner( Handle self, Handle * owner, HV * profile) { *owner = pget_H( owner); if ( !kind_of( *owner, CWidget)) return false; return inherited-> validate_owner( self, owner, profile); } /*::w */ /*::x */ /*::y */ /*::z */ /* get_props() */ Font Widget_get_default_font( char * dummy) { Font font; apc_widget_default_font( &font); return font; } Font Widget_get_default_popup_font( char * dummy) { Font f; apc_popup_default_font( &f); return f; } NPoint Widget_designScale( Handle self, Bool set, NPoint designScale) { if ( !set) return var-> designScale; if ( designScale. x < 0) designScale. x = 0; if ( designScale. y < 0) designScale. y = 0; var-> designScale = designScale; return designScale; } int Widget_growMode( Handle self, Bool set, int growMode) { enter_method; Bool x = false, y = false; if ( !set) return var-> growMode; var-> growMode = growMode; if ( var-> growMode & gmXCenter) x = true; if ( var-> growMode & gmYCenter) y = true; if ( x || y) my-> set_centered( self, x, y); return var-> growMode; } SV * Widget_get_handle( Handle self) { char buf[ 256]; snprintf( buf, 256, "0x%08lx", apc_widget_get_handle( self)); return newSVpv( buf, 0); } SV * Widget_get_parent_handle( Handle self) { char buf[ 256]; snprintf( buf, 256, "0x%08lx", apc_widget_get_parent_handle( self)); return newSVpv( buf, 0); } int Widget_hintVisible( Handle self, Bool set, int hintVisible) { Bool wantVisible; if ( !set) return PApplication( application)-> hintVisible; if ( var-> stage >= csDead) return false; wantVisible = ( hintVisible != 0); if ( wantVisible == PApplication( application)-> hintVisible) return false; if ( wantVisible) { if ( strlen( var-> hint) == 0) return false; if ( hintVisible > 0) PApplication(application)-> hintActive = -1; /* immediate */ } CApplication( application)-> set_hint_action( application, self, wantVisible, false); return false; } Bool Widget_get_locked( Handle self) { while ( self) { if ( var-> lockCount != 0) return true; self = var-> owner; } return false; } Handle Widget_get_parent( Handle self) { enter_method; return my-> get_clipOwner( self) ? var-> owner : application; } Point Widget_get_pointer_size( char*dummy) { return apc_pointer_get_size( nilHandle); } Font Widget_get_popup_font( Handle self) { return var-> popupFont; } Handle Widget_get_selectee( Handle self) { if ( var-> stage > csFrozen) return nilHandle; if ( is_opt( optSelectable)) return self; else if ( var-> currentWidget) { PWidget w = ( PWidget) var-> currentWidget; if ( w-> options. optSystemSelectable && !w-> self-> get_clipOwner(( Handle) w)) return ( Handle) w; else return w-> self-> get_selectee(( Handle) w); } else if ( is_opt( optSystemSelectable)) return self; else return find_tabfoc( self); } Point Widget_get_virtual_size( Handle self) { return var-> virtualSize; } /* set_props() */ void Widget_set_capture( Handle self, Bool capture, Handle confineTo) { if ( opt_InPaint) return; apc_widget_set_capture( self, capture, confineTo); } void Widget_set_centered( Handle self, Bool x, Bool y) { enter_method; Handle parent = my-> get_parent( self); Point size = CWidget( parent)-> get_size( parent); Point mysize = my-> get_size ( self); Point mypos = my-> get_origin( self); if ( x) mypos. x = ( size. x - mysize. x) / 2; if ( y) mypos. y = ( size. y - mysize. y) / 2; my-> set_origin( self, mypos); } void Widget_set_font( Handle self, Font font) { enter_method; if ( var-> stage > csFrozen) return; if ( !opt_InPaint) my-> first_that( self, (void*)font_notify, &font); if ( var-> handle == nilHandle) return; /* aware of call from Drawable::init */ apc_font_pick( self, &font, & var-> font); if ( opt_InPaint) apc_gp_set_font ( self, & var-> font); else { opt_clear( optOwnerFont); apc_widget_set_font( self, & var-> font); my-> repaint( self); } } void Widget_set_popup_font( Handle self, Font font) { apc_font_pick( self, &font, &var-> popupFont); } /* event handlers */ void Widget_on_paint( Handle self, SV * canvas) { int i; dSP; ENTER; SAVETMPS; PUSHMARK( sp); XPUSHs( canvas); for ( i = 0; i < 4; i++) XPUSHs( sv_2mortal( newSViv( -1))); PUTBACK; PERL_CALL_METHOD( "clear", G_DISCARD); SPAGAIN; PUTBACK; FREETMPS; LEAVE; } /* void Widget_on_click( Handle self) {} void Widget_on_change( Handle self) {} void Widget_on_close( Handle self) {} void Widget_on_colorchanged( Handle self, int colorIndex){} void Widget_on_disable( Handle self) {} void Widget_on_dragdrop( Handle self, Handle source , int x , int y ) {} void Widget_on_dragover( Handle self, Handle source , int x , int y , int state ) {} void Widget_on_enable( Handle self) {} void Widget_on_enddrag( Handle self, Handle target , int x , int y ) {} void Widget_on_fontchanged( Handle self) {} void Widget_on_enter( Handle self) {} void Widget_on_keydown( Handle self, int code , int key , int shiftState, int repeat ) {} void Widget_on_keyup( Handle self, int code , int key , int shiftState ) {} void Widget_on_menu( Handle self, Handle menu, char * variable) {} void Widget_on_setup( Handle self) {} void Widget_on_size( Handle self, Point oldSize, Point newSize) {} void Widget_on_move( Handle self, Point oldPos, Point newPos) {} void Widget_on_show( Handle self) {} void Widget_on_hide( Handle self) {} void Widget_on_hint( Handle self, Bool show) {} void Widget_on_translateaccel( Handle self, int code , int key , int shiftState ) {} void Widget_on_zorderchanged( Handle self) {} void Widget_on_popup( Handle self, Bool mouseDriven, int x, int y) {} void Widget_on_mouseclick( Handle self, int button , int shiftState , int x , int y , Bool dbl ) {} void Widget_on_mousedown( Handle self, int button , int shiftState , int x , int y ) {} void Widget_on_mouseup( Handle self, int button , int shiftState , int x , int y ) {} void Widget_on_mousemove( Handle self, int shiftState , int x , int y ) {} void Widget_on_mousewheel( Handle self, int shiftState , int x , int y, int z ) {} void Widget_on_mouseenter( Handle self, int shiftState , int x , int y ) {} void Widget_on_mouseleave( Handle self ) {} void Widget_on_leave( Handle self) {} */ /* static iterators */ Bool kill_all( Handle self, Handle child, void * dummy) { Object_destroy( child); return 0; } static Bool find_dup_msg( PEvent event, int * cmd) { return event-> cmd == *cmd; } Bool accel_notify ( Handle group, Handle self, PEvent event) { enter_method; if (( self != event-> key. source) && my-> get_enabled( self)) return ( var-> stage <= csNormal) ? !my-> message( self, event) : false; else return false; } static Bool pquery ( Handle window, Handle self, void * v) { enter_method; Event ev = {cmClose}; return ( var-> stage <= csNormal) ? !my-> message( self, &ev) : false; } Bool find_accel( Handle self, Handle item, int * key) { return ( kind_of( item, CAbstractMenu) && CAbstractMenu(item)-> sub_call_key( item, *key)); } static Handle find_tabfoc( Handle self) { int i; Handle toRet; for ( i = 0; i < var-> widgets. count; i++) { PWidget w = ( PWidget)( var-> widgets. items[ i]); if ( w-> self-> get_selectable(( Handle) w) && w-> self-> get_enabled(( Handle) w) ) return ( Handle) w; } for ( i = 0; i < var-> widgets. count; i++) if (( toRet = find_tabfoc( var-> widgets. items[ i]))) return toRet; return nilHandle; } static Bool get_top_current( Handle self) { PWidget o = ( PWidget) var-> owner; Handle me = self; while ( o) { if ( o-> currentWidget != me) return false; me = ( Handle) o; o = ( PWidget) o-> owner; } return true; } static Bool sptr( Handle window, Handle self, void * v) { enter_method; /* does nothing but refreshes system pointer */ if ( var-> pointerType == crDefault) my-> set_pointerType( self, crDefault); return false; } /* static iterators for ownership notifications */ Bool font_notify ( Handle self, Handle child, void * font) { if ( his-> options. optOwnerFont) { his-> self-> set_font ( child, *(( PFont) font)); his-> options. optOwnerFont = 1; } return false; } static Bool showhint_notify ( Handle self, Handle child, void * data) { if ( his-> options. optOwnerShowHint) { his-> self-> set_showHint ( child, *(( Bool *) data)); his-> options. optOwnerShowHint = 1; } return false; } static Bool hint_notify ( Handle self, Handle child, SV * hint) { if ( his-> options. optOwnerHint) { his-> self-> set_hint( child, hint); his-> options. optOwnerHint = 1; } return false; } Bool single_color_notify ( Handle self, Handle child, void * color) { PSingleColor s = ( PSingleColor) color; if ( his-> options. optOwnerColor && ( s-> index == ciFore)) { his-> self-> colorIndex ( child, true, s-> index, s-> color); his-> options. optOwnerColor = 1; } else if (( his-> options. optOwnerBackColor) && ( s-> index == ciBack)) { his-> self-> colorIndex ( child, true, s-> index, s-> color); his-> options. optOwnerBackColor = 1; } else if ( s-> index > ciBack) his-> self-> colorIndex ( child, true, s-> index, s-> color); return false; } Bool prima_read_point( SV *rv_av, int * pt, int number, char * error) { SV ** holder; int i; AV *av; Bool result = true; if ( !rv_av || !SvROK( rv_av) || ( SvTYPE( SvRV( rv_av)) != SVt_PVAV)) { result = false; if ( error) croak( error); } else { av = (AV*)SvRV(rv_av); for ( i = 0; i < number; i++) { holder = av_fetch( av, i, 0); if ( holder) pt[i] = SvIV( *holder); else { pt[i] = 0; result = false; if ( error) croak( error); } } } return result; } static Bool auto_enable_children( Handle self, Handle child, void * enable) { apc_widget_set_enabled( child, PTR2UV( enable)); return false; } /* properties section */ SV * Widget_accelItems( Handle self, Bool set, SV * accelItems) { enter_method; if ( var-> stage > csFrozen) return nilSV; if ( !set) return var-> accelTable ? CAbstractMenu( var-> accelTable)-> get_items( var-> accelTable, "") : nilSV; if ( var-> accelTable == nilHandle) { HV * profile = newHV(); if ( SvTYPE( accelItems)) pset_sv( items, accelItems); pset_H ( owner, self); my-> set_accelTable( self, create_instance( "Prima::AccelTable")); sv_free(( SV *) profile); } else CAbstractMenu( var-> accelTable)-> set_items( var-> accelTable, accelItems); return nilSV; } Handle Widget_accelTable( Handle self, Bool set, Handle accelTable) { enter_method; if ( var-> stage > csFrozen) return nilHandle; if ( !set) return var-> accelTable; if ( accelTable && !kind_of( accelTable, CAbstractMenu)) return nilHandle; if ( accelTable && (( PAbstractMenu) accelTable)-> owner != self) my-> set_accelItems( self, CAbstractMenu( accelTable)-> get_items( accelTable, "")); else var-> accelTable = accelTable; return accelTable; } Color Widget_backColor( Handle self, Bool set, Color color) { enter_method; if (!set) return my-> colorIndex( self, false, ciBack, 0); my-> colorIndex( self, true, ciBack, color); return color; } int Widget_bottom( Handle self, Bool set, int bottom) { enter_method; Point p = my-> get_origin( self); if ( !set) return p. y; p. y = bottom; my-> set_origin( self, p); return 0; } Bool Widget_autoEnableChildren( Handle self, Bool set, Bool autoEnableChildren) { if ( !set) return is_opt( optAutoEnableChildren); opt_assign( optAutoEnableChildren, autoEnableChildren); return false; } Bool Widget_briefKeys( Handle self, Bool set, Bool briefKeys) { if ( !set) return is_opt( optBriefKeys); opt_assign( optBriefKeys, briefKeys); return false; } Bool Widget_buffered( Handle self, Bool set, Bool buffered) { if ( !set) return is_opt( optBuffered); if ( !opt_InPaint) opt_assign( optBuffered, buffered); return false; } Bool Widget_clipOwner( Handle self, Bool set, Bool clipOwner) { HV * profile; enter_method; if ( !set) return apc_widget_get_clip_owner( self); profile = newHV(); pset_i( clipOwner, clipOwner); my-> set( self, profile); sv_free(( SV *) profile); return false; } Color Widget_color( Handle self, Bool set, Color color) { enter_method; if (!set) return my-> colorIndex( self, false, ciFore, 0); return my-> colorIndex( self, true, ciFore, color); } Color Widget_colorIndex( Handle self, Bool set, int index, Color color) { if ( !set) { if ( index < 0 || index > ciMaxId) return clInvalid; switch ( index) { case ciFore: return opt_InPaint ? inherited-> get_color ( self) : apc_widget_get_color( self, ciFore); case ciBack: return opt_InPaint ? inherited-> get_backColor ( self) : apc_widget_get_color( self, ciBack); default: return apc_widget_get_color( self, index); } } else { enter_method; SingleColor s; s. color = color; s. index = index; if (( index < 0) || ( index > ciMaxId)) return clInvalid; if ( !opt_InPaint) my-> first_that( self, (void*)single_color_notify, &s); if ( var-> handle == nilHandle) return clInvalid; /* aware of call from Drawable::init */ if ((( color & clSysFlag) != 0) && (( color & wcMask) == 0)) color |= var-> widgetClass; if ( opt_InPaint) { switch ( index) { case ciFore: inherited-> set_color ( self, color); break; case ciBack: inherited-> set_backColor ( self, color); break; default: apc_widget_set_color ( self, color, index); } } else { switch ( index) { case ciFore: opt_clear( optOwnerColor); break; case ciBack: opt_clear( optOwnerBackColor); break; } apc_widget_set_color( self, color, index); my-> repaint( self); } } return 0; } Bool Widget_current( Handle self, Bool set, Bool current) { PWidget o; if ( var-> stage > csFrozen) return false; if ( !set) return var-> owner && ( PWidget( var-> owner)-> currentWidget == self); o = ( PWidget) var-> owner; if ( o == nil) return false; if ( current) o-> self-> set_currentWidget( var-> owner, self); else if ( o-> currentWidget == self) o-> self-> set_currentWidget( var-> owner, nilHandle); return current; } Handle Widget_currentWidget( Handle self, Bool set, Handle widget) { enter_method; if ( var-> stage > csFrozen) return nilHandle; if ( !set) return var-> currentWidget; if ( widget) { if ( !widget || ( PWidget( widget)-> stage > csFrozen) || ( PWidget( widget)-> owner != self) ) return nilHandle; var-> currentWidget = widget; } else var-> currentWidget = nilHandle; /* adjust selection if we're in currently selected chain */ if ( my-> get_selected( self)) my-> set_selectedWidget( self, widget); return nilHandle; } Point Widget_cursorPos( Handle self, Bool set, Point cursorPos) { if ( !set) return apc_cursor_get_pos( self); apc_cursor_set_pos( self, cursorPos. x, cursorPos. y); return cursorPos; } Point Widget_cursorSize( Handle self, Bool set, Point cursorSize) { if ( !set) return apc_cursor_get_size( self); apc_cursor_set_size( self, cursorSize. x, cursorSize. y); return cursorSize; } Bool Widget_cursorVisible( Handle self, Bool set, Bool cursorVisible) { if ( !set) return apc_cursor_get_visible( self); return apc_cursor_set_visible( self, cursorVisible); } Bool Widget_enabled( Handle self, Bool set, Bool enabled) { if ( !set) return apc_widget_is_enabled( self); if ( !apc_widget_set_enabled( self, enabled)) return false; if ( is_opt( optAutoEnableChildren)) CWidget(self)-> first_that( self, (void*)auto_enable_children, INT2PTR(void*,enabled)); return true; } Bool Widget_firstClick( Handle self, Bool set, Bool firstClick) { return set ? apc_widget_set_first_click( self, firstClick) : apc_widget_get_first_click( self); } Bool Widget_focused( Handle self, Bool set, Bool focused) { enter_method; if ( var-> stage > csNormal) return false; if ( !set) return apc_widget_is_focused( self); if ( focused) { PWidget x = ( PWidget)( var-> owner); Handle current = self; while ( x) { x-> currentWidget = current; current = ( Handle) x; x = ( PWidget) x-> owner; } var-> currentWidget = nilHandle; if ( var-> stage == csNormal) apc_widget_set_focused( self); } else if ( var-> stage == csNormal && my-> get_selected( self)) apc_widget_set_focused( nilHandle); return focused; } SV * Widget_helpContext( Handle self, Bool set, SV *helpContext) { if ( set) { if ( var-> stage > csFrozen) return nilSV; free( var-> helpContext); var-> helpContext = duplicate_string( SvPV_nolen( helpContext)); opt_assign( optUTF8_helpContext, SvUTF8(helpContext)); } else { helpContext = newSVpv( var-> helpContext ? var-> helpContext : "", 0); if ( is_opt( optUTF8_helpContext)) SvUTF8_on( helpContext); return helpContext; } return nilSV; } SV * Widget_hint( Handle self, Bool set, SV *hint) { enter_method; if ( set) { if ( var-> stage > csFrozen) return nilSV; my-> first_that( self, (void*)hint_notify, (void*)hint); free( var-> hint); var-> hint = duplicate_string( SvPV_nolen( hint)); opt_assign( optUTF8_hint, SvUTF8(hint)); if ( application && (( PApplication) application)-> hintVisible && (( PApplication) application)-> hintUnder == self) { SV * hintText = my-> get_hint( self); Handle hintWidget = (( PApplication) application)-> hintWidget; if ( strlen( var-> hint) == 0) my-> set_hintVisible( self, 0); if ( hintWidget) CWidget(hintWidget)-> set_text( hintWidget, hintText); sv_free( hintText); } opt_clear( optOwnerHint); } else { hint = newSVpv( var-> hint ? var-> hint : "", 0); if ( is_opt( optUTF8_hint)) SvUTF8_on( hint); return hint; } return nilSV; } int Widget_left( Handle self, Bool set, int left) { enter_method; Point p = my-> get_origin( self); if ( !set) return p. x; p. x = left; my-> set_origin( self, p); return 0; } Point Widget_origin( Handle self, Bool set, Point origin) { if ( !set) return apc_widget_get_pos( self); apc_widget_set_pos( self, origin.x, origin.y); return origin; } Bool Widget_ownerBackColor( Handle self, Bool set, Bool ownerBackColor) { enter_method; if ( !set) return is_opt( optOwnerBackColor); opt_assign( optOwnerBackColor, ownerBackColor); if ( is_opt( optOwnerBackColor) && var-> owner) { my-> set_backColor( self, ((( PWidget) var-> owner)-> self)-> get_backColor( var-> owner)); opt_set( optOwnerBackColor); my-> repaint ( self); } return false; } Bool Widget_ownerColor( Handle self, Bool set, Bool ownerColor) { enter_method; if ( !set) return is_opt( optOwnerColor); opt_assign( optOwnerColor, ownerColor); if ( is_opt( optOwnerColor) && var-> owner) { my-> set_color( self, ((( PWidget) var-> owner)-> self)-> get_color( var-> owner)); opt_set( optOwnerColor); my-> repaint( self); } return false; } Bool Widget_ownerFont( Handle self, Bool set, Bool ownerFont ) { enter_method; if ( !set) return is_opt( optOwnerFont); opt_assign( optOwnerFont, ownerFont); if ( is_opt( optOwnerFont) && var-> owner) { my-> set_font ( self, ((( PWidget) var-> owner)-> self)-> get_font ( var-> owner)); opt_set( optOwnerFont); my-> repaint ( self); } return false; } Bool Widget_ownerHint( Handle self, Bool set, Bool ownerHint ) { enter_method; if ( !set) return is_opt( optOwnerHint); opt_assign( optOwnerHint, ownerHint); if ( is_opt( optOwnerHint) && var-> owner) { my-> set_hint( self, ((( PWidget) var-> owner)-> self)-> get_hint ( var-> owner)); opt_set( optOwnerHint); } return false; } Bool Widget_ownerPalette( Handle self, Bool set, Bool ownerPalette) { enter_method; if ( !set) return is_opt( optOwnerPalette); if ( ownerPalette) my-> set_palette( self, nilSV); opt_assign( optOwnerPalette, ownerPalette); return false; } Bool Widget_ownerShowHint( Handle self, Bool set, Bool ownerShowHint ) { enter_method; if ( !set) return is_opt( optOwnerShowHint); opt_assign( optOwnerShowHint, ownerShowHint); if ( is_opt( optOwnerShowHint) && var-> owner) { my-> set_showHint( self, CWidget( var-> owner)-> get_showHint ( var-> owner)); opt_set( optOwnerShowHint); } return false; } SV * Widget_palette( Handle self, Bool set, SV * palette) { int colors; if ( !set) return inherited-> palette( self, set, palette); if ( var-> stage > csFrozen) return nilSV; if ( var-> handle == nilHandle) return nilSV; /* aware of call from Drawable::init */ colors = var-> palSize; free( var-> palette); var-> palette = read_palette( &var-> palSize, palette); opt_clear( optOwnerPalette); if ( colors == 0 && var-> palSize == 0) return nilSV; /* do not bother apc */ if ( opt_InPaint) apc_gp_set_palette( self); else apc_widget_set_palette( self); return nilSV; } Handle Widget_pointerIcon( Handle self, Bool set, Handle icon) { enter_method; Point hotSpot; if ( var-> stage > csFrozen) return nilHandle; if ( !set) { HV * profile = newHV(); Handle icon = Object_create( "Prima::Icon", profile); sv_free(( SV *) profile); apc_pointer_get_bitmap( self, icon); --SvREFCNT( SvRV((( PAnyObject) icon)-> mate)); return icon; } if ( icon != nilHandle && !kind_of( icon, CIcon)) { warn("RTC083: Illegal object reference passed to Widget::pointerIcon"); return nilHandle; } hotSpot = my-> get_pointerHotSpot( self); apc_pointer_set_user( self, icon, hotSpot); if ( var-> pointerType == crUser) my-> first_that( self, (void*)sptr, nil); return nilHandle; } Point Widget_pointerHotSpot( Handle self, Bool set, Point hotSpot) { enter_method; Handle icon; if ( !set) return apc_pointer_get_hot_spot( self); if ( var-> stage > csFrozen) return hotSpot; icon = my-> get_pointerIcon( self); apc_pointer_set_user( self, icon, hotSpot); if ( var-> pointerType == crUser) my-> first_that( self, (void*)sptr, nil); return hotSpot; } int Widget_pointerType( Handle self, Bool set, int type) { enter_method; if ( var-> stage > csFrozen) return 0; if ( !set) return var-> pointerType; var-> pointerType = type; apc_pointer_set_shape( self, type); my-> first_that( self, (void*)sptr, nil); return type; } Point Widget_pointerPos( Handle self, Bool set, Point p) { if ( !set) { p = apc_pointer_get_pos( self); apc_widget_map_points( self, false, 1, &p); return p; } apc_widget_map_points( self, true, 1, &p); apc_pointer_set_pos( self, p. x, p. y); return p; } Handle Widget_popup( Handle self, Bool set, Handle popup) { enter_method; if ( var-> stage > csFrozen) return nilHandle; if ( !set) return var-> popupMenu; if ( popup && !kind_of( popup, CPopup)) return nilHandle; if ( popup && PAbstractMenu( popup)-> owner != self) my-> set_popupItems( self, CAbstractMenu( popup)-> get_items( popup, "")); else var-> popupMenu = popup; return nilHandle; } Color Widget_popupColorIndex( Handle self, Bool set, int index, Color color) { if (( index < 0) || ( index > ciMaxId)) return clInvalid; if ( !set) return var-> popupColor[ index]; if ((( color & clSysFlag) != 0) && (( color & wcMask) == 0)) color |= wcPopup; var-> popupColor[ index] = color; return color; } SV * Widget_popupItems( Handle self, Bool set, SV * popupItems) { enter_method; if ( var-> stage > csFrozen) return nilSV; if ( !set) return var-> popupMenu ? CAbstractMenu( var-> popupMenu)-> get_items( var-> popupMenu, "") : nilSV; if ( var-> popupMenu == nilHandle) { if ( SvTYPE( popupItems)) { HV * profile = newHV(); pset_sv( items, popupItems); pset_H ( owner, self); my-> set_popup( self, create_instance( "Prima::Popup")); sv_free(( SV *) profile); } } else CAbstractMenu( var-> popupMenu)-> set_items( var-> popupMenu, popupItems); return popupItems; } Rect Widget_rect( Handle self, Bool set, Rect r) { enter_method; if ( !set) { Point p = my-> get_origin( self); Point s = my-> get_size( self); r. left = p. x; r. bottom = p. y; r. right = p. x + s. x; r. top = p. y + s. y; } else apc_widget_set_rect( self, r. left, r. bottom, r. right - r. left, r. top - r. bottom); return r; } int Widget_right( Handle self, Bool set, int right) { enter_method; Point p; Rect r = my-> get_rect( self); if ( !set) return r. right; p. x = r. left - r. right + right; p. y = r. bottom; my-> set_origin( self, p); return 0; } Bool Widget_scaleChildren( Handle self, Bool set, Bool scaleChildren) { if ( !set) return is_opt( optScaleChildren); opt_assign( optScaleChildren, scaleChildren); return false; } Bool Widget_selectable( Handle self, Bool set, Bool selectable) { if ( !set) return is_opt( optSelectable); opt_assign( optSelectable, selectable); return false; } Bool Widget_selected( Handle self, Bool set, Bool selected) { enter_method; if ( !set) return my-> get_selectedWidget( self) != nilHandle; if ( var-> stage > csFrozen) return selected; if ( selected) { if ( is_opt( optSelectable) && !is_opt( optSystemSelectable)) { my-> set_focused( self, true); } else if ( var-> currentWidget) { PWidget w = ( PWidget) var-> currentWidget; if ( w-> options. optSystemSelectable && !w-> self-> get_clipOwner(( Handle) w)) w-> self-> bring_to_front(( Handle) w); /* <- very uncertain !!!! */ else w-> self-> set_selected(( Handle) w, true); } else if ( is_opt( optSystemSelectable)) { /* nothing to do with Widget, reserved for Window */ } else { PWidget toFocus = ( PWidget) find_tabfoc( self); if ( toFocus) toFocus-> self-> set_selected(( Handle) toFocus, 1); else { /* if group has no selectable widgets and cannot be selected by itself, */ /* process chain of bring_to_front(), followed by set_focused(1) call, if available */ PWidget x = ( PWidget) var-> owner; List lst; int i; list_create( &lst, 8, 8); while ( x) { if ( !toFocus && x-> options. optSelectable) { toFocus = x; /* choose closest owner to focus */ break; } if (( Handle) x != application && !kind_of(( Handle) x, CWindow)) list_insert_at( &lst, ( Handle) x, 0); x = ( PWidget) x-> owner; } if ( toFocus) toFocus-> self-> set_focused(( Handle) toFocus, 1); for ( i = 0; i < lst. count; i++) { PWidget v = ( PWidget) list_at( &lst, i); v-> self-> bring_to_front(( Handle) v); } list_destroy( &lst); } } /* end set_selected( true); */ } else my-> set_focused( self, false); return selected; } Handle Widget_selectedWidget( Handle self, Bool set, Handle widget) { if ( var-> stage > csFrozen) return nilHandle; if ( !set) { if ( var-> stage <= csNormal) { Handle foc = apc_widget_get_focused(); PWidget f = ( PWidget) foc; while( f) { if (( Handle) f == self) return foc; f = ( PWidget) f-> owner; } } return nilHandle; /* classic solution should be recursive and inheritant call */ /* of get_selected() here, when Widget would return state of */ /* child-group selected state until Widget::selected() called; */ /* thus, each of them would call apc_widget_get_focused - that's expensive, */ /* so that's the reason not to use classic object model here. */ } if ( widget) { if ( PWidget( widget)-> owner == self) CWidget( widget)-> set_selected( widget, true); } else { /* give selection up to hierarchy chain */ Handle s = self; while ( s) { if ( CWidget( s)-> get_selectable( s)) { CWidget( s)-> set_selected( s, true); break; } s = PWidget( s)-> owner; } } return nilHandle; } int Widget_selectingButtons( Handle self, Bool set, int sb) { if ( !set) return var-> selectingButtons; return var-> selectingButtons = sb; } Handle Widget_shape( Handle self, Bool set, Handle mask) { if ( var-> stage > csFrozen) return nilHandle; if ( !set) { if ( apc_widget_get_shape( self, nilHandle)) { HV * profile = newHV(); Handle i = Object_create( "Prima::Image", profile); sv_free(( SV *) profile); apc_widget_get_shape( self, i); --SvREFCNT( SvRV((( PAnyObject) i)-> mate)); return i; } else return nilHandle; } if ( mask && !kind_of( mask, CImage)) { warn("RTC008A: Illegal object reference passed to Widget::shape"); return nilHandle; } if ( mask && (( PImage( mask)-> type & imBPP) != imbpp1)) { Handle i = CImage( mask)-> dup( mask); ++SvREFCNT( SvRV( PImage( i)-> mate)); CImage( i)-> set_conversion( i, ictNone); CImage( i)-> set_type( i, imBW); apc_widget_set_shape( self, i); --SvREFCNT( SvRV( PImage( i)-> mate)); Object_destroy( i); } else apc_widget_set_shape( self, mask); return nilHandle; } Bool Widget_showHint( Handle self, Bool set, Bool showHint ) { enter_method; Bool oldShowHint = is_opt( optShowHint); if ( !set) return oldShowHint; my-> first_that( self, (void*)showhint_notify, &showHint); opt_clear( optOwnerShowHint); opt_assign( optShowHint, showHint); if ( application && !is_opt( optShowHint) && oldShowHint) my-> set_hintVisible( self, 0); return false; } Point Widget_size( Handle self, Bool set, Point size) { if ( !set) return apc_widget_get_size( self); apc_widget_set_size( self, size.x, size.y); return size; } Bool Widget_syncPaint( Handle self, Bool set, Bool syncPaint) { HV * profile; enter_method; if ( !set) return apc_widget_get_sync_paint( self); profile = newHV(); pset_i( syncPaint, syncPaint); my-> set( self, profile); sv_free(( SV *) profile); return false; } int Widget_tabOrder( Handle self, Bool set, int tabOrder) { int count; PWidget owner; if ( var-> stage > csFrozen) return 0; if ( !set) return var-> tabOrder; owner = ( PWidget) var-> owner; count = owner-> widgets. count; if ( tabOrder < 0) { int i, maxOrder = -1; /* finding maximal tabOrder value among the siblings */ for ( i = 0; i < count; i++) { PWidget ctrl = ( PWidget) owner-> widgets. items[ i]; if ( self == ( Handle) ctrl) continue; if ( maxOrder < ctrl-> tabOrder) maxOrder = ctrl-> tabOrder; } if ( maxOrder < INT_MAX) { var-> tabOrder = maxOrder + 1; return 0; } /* maximal value found, but has no use; finding gaps */ { int j = 0; Bool match = 1; while ( !match) { for ( i = 0; i < count; i++) { PWidget ctrl = ( PWidget) owner-> widgets. items[ i]; if ( self == ( Handle) ctrl) continue; if ( ctrl-> tabOrder == j) { match = 1; break; } } j++; } var-> tabOrder = j - 1; } } else { int i; Bool match = 0; /* finding exact match among the siblings */ for ( i = 0; i < count; i++) { PWidget ctrl = ( PWidget) owner-> widgets. items[ i]; if ( self == ( Handle) ctrl) continue; if ( ctrl-> tabOrder == tabOrder) { match = 1; break; } } if ( match) /* incrementing all tabOrders that greater than ours */ for ( i = 0; i < count; i++) { PWidget ctrl = ( PWidget) owner-> widgets. items[ i]; if ( self == ( Handle) ctrl) continue; if ( ctrl-> tabOrder >= tabOrder) ctrl-> tabOrder++; } var-> tabOrder = tabOrder; } return 0; } Bool Widget_tabStop( Handle self, Bool set, Bool stop) { if ( !set) return is_opt( optTabStop); opt_assign( optTabStop, stop); return false; } Bool Widget_transparent( Handle self, Bool set, Bool transparent) { HV * profile; enter_method; if ( !set) return apc_widget_get_transparent( self); profile = newHV(); pset_i( transparent, transparent); my-> set( self, profile); sv_free(( SV *) profile); return false; } SV * Widget_text( Handle self, Bool set, SV *text) { if ( set) { if ( var-> stage > csFrozen) return nilSV; free( var-> text); var-> text = duplicate_string( SvPV_nolen( text)); opt_assign( optUTF8_text, SvUTF8(text)); } else { text = newSVpv( var-> text ? var-> text : "", 0); if ( is_opt( optUTF8_text)) SvUTF8_on( text); return text; } return nilSV; } int Widget_top( Handle self, Bool set, int top) { enter_method; Point p; Rect r = my-> get_rect( self); if ( !set) return r. top; p. x = r. left; p. y = r. bottom - r. top + top; my-> set_origin( self, p); return 0; } Bool Widget_visible( Handle self, Bool set, Bool visible) { return set ? apc_widget_set_visible( self, visible) : apc_widget_is_visible( self); } int Widget_widgetClass( Handle self, Bool set, int widgetClass) { enter_method; if ( !set) return var-> widgetClass; var-> widgetClass = widgetClass; my-> repaint( self); return 0; } /* XS section */ XS( Widget_client_to_screen_FROMPERL) { dXSARGS; Handle self; int i, count; Point * points; if (( items % 2) != 1) croak ("Invalid usage of Widget::client_to_screen"); SP -= items; self = gimme_the_mate( ST( 0)); if ( self == nilHandle) croak( "Illegal object reference passed to Widget::client_to_screen"); count = ( items - 1) / 2; if ( !( points = allocn( Point, count))) { PUTBACK; return; } for ( i = 0; i < count; i++) { points[i]. x = SvIV( ST( i * 2 + 1)); points[i]. y = SvIV( ST( i * 2 + 2)); } apc_widget_map_points( self, true, count, points); EXTEND( sp, count * 2); for ( i = 0; i < count; i++) { PUSHs( sv_2mortal( newSViv( points[i].x))); PUSHs( sv_2mortal( newSViv( points[i].y))); } PUTBACK; free( points); return; } XS( Widget_screen_to_client_FROMPERL) { dXSARGS; Handle self; int i, count; Point * points; if (( items % 2) != 1) croak ("Invalid usage of Widget::screen_to_client"); SP -= items; self = gimme_the_mate( ST( 0)); if ( self == nilHandle) croak( "Illegal object reference passed to Widget::screen_to_client"); count = ( items - 1) / 2; if ( !( points = allocn( Point, count))) { PUTBACK; return; } for ( i = 0; i < count; i++) { points[i]. x = SvIV( ST( i * 2 + 1)); points[i]. y = SvIV( ST( i * 2 + 2)); } apc_widget_map_points( self, false, count, points); EXTEND( sp, count * 2); for ( i = 0; i < count; i++) { PUSHs( sv_2mortal( newSViv( points[i].x))); PUSHs( sv_2mortal( newSViv( points[i].y))); } PUTBACK; free( points); return; } XS( Widget_get_widgets_FROMPERL) { dXSARGS; Handle self; Handle * list; int i, count; if ( items != 1) croak ("Invalid usage of Widget.get_widgets"); SP -= items; self = gimme_the_mate( ST( 0)); if ( self == nilHandle) croak( "Illegal object reference passed to Widget.get_widgets"); count = var-> widgets. count; list = var-> widgets. items; EXTEND( sp, count); for ( i = 0; i < count; i++) PUSHs( sv_2mortal( newSVsv((( PAnyObject) list[ i])-> mate))); PUTBACK; return; } void Widget_get_widgets ( Handle self) { warn("Invalid call of Widget::get_widgets"); } void Widget_get_widgets_REDEFINED( Handle self) { warn("Invalid call of Widget::get_widgets"); } void Widget_screen_to_client ( Handle self) { warn("Invalid call of Widget::screen_to_client"); } void Widget_screen_to_client_REDEFINED ( Handle self) { warn("Invalid call of Widget::screen_to_client"); } void Widget_client_to_screen ( Handle self) { warn("Invalid call of Widget::screen_to_client"); } void Widget_client_to_screen_REDEFINED ( Handle self) { warn("Invalid call of Widget::screen_to_client"); } #ifdef __cplusplus } #endif