home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1993 #2
/
Image.iso
/
database
/
pk4pak.zip
/
EVENTMAN.SC
< prev
next >
Wrap
Text File
|
1993-02-03
|
48KB
|
1,131 lines
;============================================================================
; (c) Copyright Elect Software International Inc., 1992, Toronto. Anyone can
; use this code for anything as long as it is not resold as a software
; development resource, as long as the copyright notice isn't removed, as
; long as changes are clearly marked as to authorship, and as long as users
; indemnify Elect from any liability.
; Comments welcome. Henrik Bechmann, CIS:72701,3717; Tel:416-534-8176.
;============================================================================
; EventMan Version 1.12 January, 1992.
;============================================================================
; WHAT'S NEW ?
;============================================================================
;
; EventMan version 1.1 introduces types. By setting
;
; EventMan.SetObjectTagProc = "EventMan.SetObjectTagAndType"
;
; and
;
; EventMan.DispatchEventTagProc = "EventMan.DispatchEventTagToType"
;
; EventMan will check an object's type for an event handler if there isn't one
; for the object itself.
;
; if the application doesn't set a type for the object in
;
; EventMan.ObjectTypeBag[]
;
; then EventMan will try to provide one (in SetObjectTagAndType()) with
; EventMan.GetWindowType(). The standard types are
; FLOATING, CANVAS, QUERY, TABLE, FORM, FILE_EDITOR, SCRIPT, MEMO,
; FORMDESIGN, REPORTDESIGN, CREATE, GRAPH, PASSWORD, RESTRUCTURE,
; INDEX, SORT
;
; The type is placed in EventMan.ObjectType.
;
; Therefore the developer can develop generalized code for each type, default
; code for the application as a whole, and limit custom code for each object
; to special cases.
;
; For direct dispatches of messages to objects, use
;
; EventMan.SendMessage(ObjectTag,MessageTag)
;
; Since SetObjectTagAndType will set a default object name as well as object
; type if none is provided for the window, EventMan 1.1 should be code
; compatible for most applications written for the original version.
;
; Version 1.11 adds EventMan.DefaultReturnCodeProc which is set to
; "EventMan.SetDefaultReturnCode" by default, but can be set to your
; application's proc which can, for instance, deal with events by type
; in this procedure.
;
;============================================================================
; EVENTMAN DESCRIPTION
;============================================================================
;
; EventMan (Event Manager) is a generic event manager for use in Paradox 4.0
; applications. The general organization of the scheme is as follows:
;
; Procedures (event handlers) are associated with events and objects in a
; dictionary (a dynarray) in the following general form:
;
; EventMan.Dictionary[ObjectTag + EventTag] = ProcName
;
; The idea is to EXECPROC ProcName based on the current object and event.
;
; EventMan organizes programming in Paradox 4.0 into 4 phases:
; 1. Event collection
; 2. Event analysis
; 3. Event dispatch
; 4. Event handling
;
; Event collection can take place under either WAIT ... PROC or under
; GETEVENT. EventMan.DoWait() and EventMan.DoGetEvent() are provided as
; defaults for this.
;
; Event analysis involves several steps:
; 1. Get target window handle (placed in EventMan.TargetWindow)
; 2. Set object tag (placed in EventMan.ObjectTag)
; 3. Set event tag (placed in EventMan.EventTag)
;
; EventMan automatically places the target window handle in
; EventMan.TargetWindow using EventMan.GetTargetWindow(..))
;
; EventMan provides a default procedure in EventMan.SetObjectTagProc
; (EventMan.SetWindowAsObjectTag()) for setting EventMan.ObjectTag. This
; procedure simply sets EventMan.ObjectTag to StrVal(EventMan.TargetWindow).
;
; Your application can substitute a more sophisticated procedure which might,
; for instance, set EventMan.ObjectTag to "INVOICE".
; EventMan.SetIndexedObjectTag() is provided for this purpose. It looks
; up your custom ObjectTag from a list of window numbers. With this
; alternative, your application must maintain the cross referencing
; information in the dynarrays EventMan.WindowObjectTag[] and
; EventMan.ObjectTagWindow[]. The advantage to this is that by avoiding the
; use of window handles for ObjectTags, EventMan.Dictionary[] updates are not
; required each time a window is loaded or unloaded.
;
; To use more generalized code, set EventMan.SetObjectTagProc to
; "EventMan.SetObjectTagAndType" and EventMan.DispatchEventTagProc to
; "EventMan.DispatchEventTagToType". Then when a window is registered, set
; EventMan.ObjectTypeBag[] for the object to its type. EventMan will set
; EventMan.ObjectType to the objects type, and will then look
; for an event handler for the type after looking for an event handler for
; the object, and before looking for a default event.
;
; EventMan sets EventMan.EventTag according to some rules that are easily
; understood by reading the code of the procedure EventMan.SetEventTag()
; below.
;
; Finally EventMan dispatches the event. EventMan provides a default
; dispatcher (EventMan.DispatchEventTag()) in EventMan.DispatchEventTagProc,
; although your application can substitute its own more sophisticated
; dispatcher (advanced applications only). The default dispatcher first
; looks for
;
; EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag]
;
; and then
;
; EventMan.Dictionary[EvenMan.EventTag]
;
; if it didn't find the first form. Therefore default behavior can be
; provided by your application.
;
; If EventMan.DispatchEventTagToType() is used for the dispatcher, then the
; dispatcher looks for
;
; EventMan.Dictionary[EventMan.ObjectType + EventMan.EventTag]
;
; after [Eventman.ObjectTag + EventMan.EventTag].
;
; Event handlers, the procedures that are EXECPROC'd by the event dispatcher,
; must be provided by your application, and must always return the values 0,
; 1, or 2, according to the rules provided for WAIT PROC commands.
;
; Special support is provided for IDLE event processing, and for MOUSE event
; processing, as well as populating and de-populating EventMan.Dictionary.
;
; Look for event packet details in EventMan.EventBag[].
;
; For some ideas on how to use EventMan, see EDEMO.SC.
;
;============================================================================
; EVENTMAN INTERFACE
;============================================================================
;
; Construction and destruction:
; -----------------------------
; EventMan.Constructor() ; execute at start of session
; EventMan.Destructor() ; execute at end of session
;
; The event dictionary and idle proc queue:
; -----------------------------------------
; EventMan.SetHandlersFrom(HandlerBag)
; Eventman.ClearHandlersWith(HandlerBag)
; EventMan.RegisterIdleServer(ObjectTag,IdleProcName)
; EventMan.DeRegisterIdleServer(ObjectTag)
;
; Event collectors: (use these in your code)
; ------------------------------------------
; (For Wait statements...)
; EventMan.CatchTrigger(EventMan.TriggerTag,EventMan.EventBag,
; EventMan.TriggerCycle)
; (Shell (analog to wait) for EventMan.GetEventProc...)
; EventMan.DoGetEvent()
;
; Event analysis:
; ---------------
; EventMan.GetTargetWindow(TriggerTag,EventBag) ; returns 0 or valid window
; EventMan.SetWindowAsObjectTag() ; Default EventMan.SetObjectTagProc
; EventMan.SetIndexedObjectTag() ; More sophisticated object identification
; EventMan.SetObjectTagAndType() ; sets EventMan.ObjectType as well as
; ; EventMan.ObjectTag
; EventMan.SetEventTag() ; sets EventMan.EventTag from EventMan.EventBag[]
;
; Event dispatch:
; ---------------
; EventMan.DispatchEventTag() ; default EventMan.DispatchEventTagProc; called
; ; by DispatchEventBag
; EventMan.DispatchEventTagToType() ; similar to DispatchEventTag() , but
; ; looks for handlers associated with
; ; EventMan.ObjectType after EventMan.ObjectTag
; EventMan.DoIdleEvent() ; execprocs next idle server
; EventMan.DispatchEventBag() ; direct dispatch of an event bag, used by
; ; EventMan.completeMouseSequence()
;
; Utility procs:
; ---------------------
; EventMan.DoWait() ; default wait statement, uses EventMan.CatchTrigger()
; EventMan.GetEvent() ; default EventMan.GetEventProc
; EventMan.EnableEvent() ; returns 0
; EventMan.DisableEvent() ; returns 1
; EventMan.SetDefaultReturnCode() ; sets ReturnCode to DefaultReturnCode
; EventMan.CompleteMouseSequence() ; call after ExecEvent EventBag
; EventMan.ReturnFromMouseMode() ; call after mouse down when UP is available
; EventMan.SendMessage(ObjectTag,MessageTag) ; send message to ObjectTag
;
; Properties:
; ------------
; EventMan.IsActive ; readonly, is EventMan active? (use isAssigned)
; EventMan.IsGetEvent ; readonly, is this a getevent event? (use isAssigned)
; EventMan.IsWait ; readonly, is this a wait event? (use isAssigned)
; EventMan.Dictionary[] ; EventMan.Dictionary[ObjectTag + EventTag] = ProcName
; EventMan.InterruptBag[] ;
; EventMan.WindowObjectTag[] ;
; EventMan.ObjectTagWindow[] ;
; EvnetMan.ObjectTypeBag[] ;
; EventMan.EventBag[] ; as collected by wait or getevent
; EventMan.EventType ; TRIGGER or EventMan.EventBag["Type"]
; EventMan.MouseModeButton ; Button pressed with last DOWN, or "NONE"
; EventMan.TargetWindow ; set by collectors from EventMan.GetTargetWindow(..)
; EventMan.ObjectTag ; string value for EventMan.Dictionary set by
; ; EventMan.SetWindowAsObjectTag() or EventMan.SetObjectTagProc
; EventMan.ObjectType ; used by EventMan.DispatchEventTagToType()
; EventMan.EventTag ; sometimes composite string value for
; ; EventMan.Dictionary set by EventMan.SetEventTag()
; EventMan.ReturnCode ; must be set by DispatchEventTagProc
; EventMan.DefaultReturnCode ; return code when handler search fails
; EventMan.GetEventProc ; getevent specs for DoGetEvent
; EventMan.SetObjectTagProc ; sets EventMan.ObjectTag based on
; ; Eventman.TargetWindow
; EventMan.DispatchEventTagProc ; dispatches event to EventMan.Dictionary
; EventMan.DefaultReturnCodeProc ; set default EventMan.ReturnCode
;
;============================================================================
; EVENTMAN IMPLEMENTATION
;============================================================================
;============================================================================
; CONSTRUCTION AND DESTRUCTION
;============================================================================
Proc EventMan.Constructor()
;-------------------------------------------------------------------------
; General properties
;-------------------------------------------------------------------------
EventMan.IsActive = True
Dynarray EventMan.Dictionary[]
Dynarray EventMan.EventBag[]
Dynarray EventMan.WindowObjectTag[]
Dynarray EventMan.ObjectTagWindow[]
Dynarray EventMan.ObjectTypeBag[]
Dynarray EventMan.InterruptBag[]
EventMan.MouseModeButton = "NONE"
EventMan.EventType = ""
EventMan.EventTag = ""
EventMan.ObjectTag = ""
EventMan.ObjectType = ""
EventMan.ReturnCode = 0
EventMan.DefaultReturnCode = 0
;-------------------------------------------------------------------------
; Default action procs
;-------------------------------------------------------------------------
EventMan.GetEventProc = "EventMan.GetEvent"
EventMan.SetObjectTagProc = "EventMan.SetWindowAsObjectTag"
EventMan.DispatchEventTagProc = "EventMan.DispatchEventTag"
EventMan.DefaultReturnCodeProc = "EventMan.SetDefaultReturnCode"
;-------------------------------------------------------------------------
; Private properties
;-------------------------------------------------------------------------
Dynarray EventMan_IdleServers[]
Array EventMan_IdleServerProcs[1] ; stub
EventMan_nIdleServers = 0
EventMan_IdleServerPtr = 1
EndProc ; EventMan.Constructor
Proc EventMan.Destructor()
; If EventMan.nInstances > 1 Then
; EventMan.nInstances = EventMan.nInstances - 1
; Return
; Endif
Release Vars
EventMan.IsActive,
; EventMan.nInstances,
EventMan.IsWait,
EventMan.IsGetEvent,
EventMan.Dictionary,
EventMan.InterruptBag,
EventMan.EventBag,
EventMan.WindowObjectTag,
EventMan.ObjectTagWindow,
EventMan.MouseModeButton,
EventMan_IdleServers,
EventMan_IdleServerProcs,
EventMan_nIdleServers,
EventMan_IdleServerPtr,
EventMan.EventType,
EventMan.EventTag,
EventMan.ObjectTag,
EventMan.ObjectType,
EventMan.ObjectTypeBag,
EventMan.TargetWindow,
EventMan.ReturnCode,
EventMan.DefaultReturnCode,
EventMan.GetEventProc,
EventMan.SetObjectTagProc,
EventMan.DispatchEventTagProc,
EventMan.DefaultReturnCodeProc
EndProc ; EventMan.Destructor
;============================================================================
; DICTIONARY UPDATE
;============================================================================
Proc EventMan.SetHandlersFrom(HandlerBag)
Private
EventTag,
ObjectTag
If IsAssigned(HandlerBag["ObjectTag"]) Then
ObjectTag = Strval(HandlerBag["ObjectTag"])
Release Vars HandlerBag["ObjectTag"] ; to avoid screening below
Else
ObjectTag = ""
Endif
Foreach EventTag in HandlerBag
If (HandlerBag[EventTag] = "") Then
Release Vars EventMan.Dictionary[ObjectTag + EventTag]
Else
EventMan.Dictionary[ObjectTag + EventTag] = HandlerBag[EventTag]
Endif
EndForeach
If Not isBlank(ObjectTag) Then
HandlerBag["ObjectTag"] = ObjectTag
Endif
EndProc ; EventMan.SetHandlersFrom
Proc EventMan.ClearHandlersWith(HandlerBag)
Private
EventTag,
ObjectTag
If IsAssigned(HandlerBag["ObjectTag"]) Then
ObjectTag = Strval(HandlerBag["ObjectTag"])
Release Vars HandlerBag["ObjectTag"]
Else
ObjectTag = ""
Endif
Foreach EventTag in HandlerBag
Release Vars EventMan.Dictionary[ObjectTag + EventTag]
EndForeach
If Not IsBlank(ObjectTag) Then
HandlerBag["ObjectTag"] = ObjectTag
Endif
EndProc ; EventMan.ClearHandlersWith
;============================================================================
; IDLE SERVER UPDATE
;============================================================================
Proc EventMan.RegisterIdleServer(ObjectTag,IdleProcName)
Private
Element,
i
If IsAssigned(EventMan_IdleServers[ObjectTag]) Then
EventMan_IdleServers[ObjectTag] = IdleProcName
Else
EventMan_IdleServers[ObjectTag] = IdleProcName
If EventMan_nIdleServers = 0 Then
EventMan.InterruptBag["Idle"] = "EventMan.DoIdleEvent"
Endif
EventMan_nIdleServers = EventMan_nIdleServers + 1
Array EventMan_IdleServerProcs[EventMan_nIdleServers]
i = 0
ForEach Element In EventMan_IdleServers
i = i + 1
EventMan_IdleServerProcs[i] = EventMan_IdleServers[Element]
EndForEach
If EventMan_IdleServerPtr > EventMan_nIdleServers Then
EventMan_IdleServerPtr = EventMan_nIdleServers
Endif
Endif
EndProc ; EventMan.RegisterIdleServer
Proc EventMan.DeRegisterIdleServer(ObjectTag)
Private
Element,
i
Release Vars
EventMan_IdleServers[ObjectTag]
EventMan_nIdleServers = EventMan_nIdleServers - 1
If EventMan_nIdleServers > 0 Then
Array EventMan_IdleServerProcs[EventMan_nIdleServers]
i = 0
ForEach Element In EventMan_IdleServers
i = i + 1
EventMan_IdleServerProcs[i] = EventMan_IdleServers[Element]
EndForEach
If EventMan_IdleServerPtr > EventMan_nIdleServers Then
EventMan_IdleServerPtr = EventMan_nIdleServers
Endif
Else
Release Vars EventMan.InterruptBag["Idle"]
EventMan_IdleServerPtr = 1
Endif
EndProc ; EventMan.DeRegisterIdleServer
;============================================================================
; EVENT COLLECTORS
;============================================================================
;----------------------------------------------------------------------------
; The event handlers Return 0, 1 or 2 to determine whether to
; 0 = process the event with execevent
; 1 = deny the event but stay in the event loop
; 2 = deny the event and break out of the event loop
;----------------------------------------------------------------------------
Proc EventMan.CatchTrigger(EventMan.TriggerTag,EventMan.EventBag,EventMan.TriggerCycle)
Private
EventMan.IsGetEvent, ; mask out EventMan.IsGetEvent so that called procedures
; can determine that it is a wait and not a getevent
; that is active.
EventMan.IsWait
EventMan.IsWait = True
If EventMan.TriggerTag = "EVENT" Then
EventMan.SetEventTag()
Else
EventMan.EventType = "TRIGGER"
EventMan.EventTag = EventMan.TriggerTag
Endif
If IsAssigned(EventMan.InterruptBag[EventMan.EventTag]) Then
ExecProc EventMan.InterruptBag[EventMan.EventTag]
EventMan.ReturnCode = Retval
Else
EventMan.TargetWindow =
EventMan.GetTargetWindow(EventMan.TriggerTag,EventMan.EventBag)
ExecProc EventMan.SetObjectTagProc
ExecProc EventMan.DispatchEventTagProc
Endif
Return EventMan.ReturnCode
EndProc ; EventMan.CatchTrigger
Proc EventMan.DoGetEvent()
Private
EventMan.IsGetEvent,
EventMan.IsWait
EventMan.IsGetEvent = True
EventMan.ReturnCode = 0
While EventMan.ReturnCode < 2
ExecProc EventMan.GetEventProc
EventMan.SetEventTag()
If IsAssigned(EventMan.InterruptBag[EventMan.EventTag]) Then
ExecProc EventMan.InterruptBag[EventMan.EventTag]
Else
EventMan.TargetWindow =
EventMan.GetTargetWindow("EVENT",EventMan.EventBag)
ExecProc EventMan.SetObjectTagProc
ExecProc EventMan.DispatchEventTagProc
Endif
If EventMan.ReturnCode = 0 Then
ExecEvent EventMan.EventBag
EndIf
EndWhile
EndProc ; EventMan.DoGetEvent
;============================================================================
; EVENT ANALYSIS
;============================================================================
;----------------------------------------------------------------------------
; Assumes ECHO NORMAL
;----------------------------------------------------------------------------
Proc EventMan.GetTargetWindow(TriggerTag,EventBag)
Private
TargetWindow,
WindowBag,
EventType,
ZOrderGroupChange,
IsEditor,
Keycode,
WindowList,
SysInfoBag,
IsCanvasNoneCurrent,
i,
Found
;---------------------------------------------------------------------
; If the trigger is not an event then analyze trigger...
;---------------------------------------------------------------------
If TriggerTag <> "EVENT" Then ; must be a TRIGGER type event
;------------------------------------------------------------------
; If the trigger is not an ARRIVEWINDOW, then it relates to the
; current image.
;------------------------------------------------------------------
If TriggerTag = "ARRIVEWINDOW" Then
TargetWindow = GetWindow()
Else
Window Handle Form to TargetWindow
If Not isWindow(TargetWindow) Then
Window Handle Image ImageNo() To TargetWindow
Endif
Endif
;---------------------------------------------------------------------
; ...else this must be an event of type MOUSE, KEY, MESSAGE, or IDLE...
;---------------------------------------------------------------------
Else
If Not IsWindow(GetWindow()) Then ; There are no windows
; NOT!!! THERE COULD BE NOTHING BUT FLOATING WINDOWS, NONE OF THEM
; CURRENT!!!!!!!!!!!!!
TargetWindow = GetWindow()
Window List To WindowList
If ArraySize(WindowList) > 0 Then
IsCanvasNoneCurrent = True
Else
IsCanvasNoneCurrent = False
Endif
Else
IsCanvasNoneCurrent = False
Endif
If IsWindow(GetWindow()) Or IsCanvasNoneCurrent Then
EventType = EventBag["Type"]
Switch
Case EventType = "MOUSE":
;----------------------------------------------------------------
; If this is a mouse event, then if it is a DOWN or no-button
; event then it belongs to the window over which the mouse
; event takes place, otherwise it is a modal event which
; belongs to the current window.
;----------------------------------------------------------------
If (EventBag["Action"] = "DOWN") or
((EventBag["Buttons"] = "NONE") And
(EventBag["Action"] <> "UP")) Then
TargetWindow = WindowAt(EventBag["Row"],EventBag["Col"])
Else
TargetWindow = GetWindow()
Endif
;----------------------------------------------------------------
; Except for one special case when the mouse action is DOWN:
; If the current window is floating and the target window is not
; then expect to select the topmost desktop window as the target
; in the course of changing z-orders from floating to desktop,
; if the mouse event took place somewhere other than on the menu
; bar or the status bar.
;----------------------------------------------------------------
If EventBag["Action"] = "DOWN" And Not IsCanvasNoneCurrent Then
Window GetAttributes GetWindow() To WindowBag
If WindowBag["Floating"] Then
If IsWindow(TargetWindow) Then
Window GetAttributes Targetwindow To WindowBag
ZOrderGroupChange = (Not WindowBag["Floating"])
Else ; see if the mouse hit the prompt/speedbar area...
SysInfo To SysInfoBag
ZOrderGroupChange =
((SysInfoBag["ScreenHeight"] - 1 <> EventBag["Row"]) And
(EventBag["Row"] <> 0))
Endif ; The target window exists
If ZOrderGroupChange Then
Window List To WindowList
Found = False
For i From 1 To Arraysize(WindowList)
Window GetAttributes WindowList[i] To WindowBag
If Not WindowBag["Floating"] Then
Found = True
Quitloop
Endif
EndFor
TargetWindow = IIf(Found,WindowList[i],0)
Endif
Endif ; The current window is a floating window
Endif ; If this is a DOWN action
Case EventType = "KEY":
Keycode = EventBag["KeyCode"]
Switch
Case KeyCode = Asc("WinResize") or
KeyCode = Asc("WinMax") or
KeyCode = Asc("WinNext") or
KeyCode = Asc("WinClose"):
TargetWindow = GetWindow()
Case (Keycode = Asc("ClearImage") or
Keycode = Asc("ClearAll") or
Keycode = Asc("EditKey") or
Keycode = Asc("CoEditKey")):
If nImages() > 0 Then
Window Handle Form to TargetWindow
If Not IsWindow(TargetWindow) Then
Window Handle Image ImageNo() To TargetWindow
Endif
Else
TargetWindow = 0
Endif
Otherwise:
If Not IsCanvasNoneCurrent Then
;----------------------------------------------------------
; Check to see if the keystrokes belong to a current file or
; memo editor...
;----------------------------------------------------------
IsEditor = (IsFieldView() and Substr(FieldType(),1,1) = "M")
or SysMode() = "File Editor" or SysMode() = "Script"
;----------------------------------------------------------
; If it does belong to an editor, then find the first non-
; floating window on the desktop. That will be the editor.
;----------------------------------------------------------
If IsEditor Then
Window List To WindowList
For i From 1 to ArraySize(WindowList)
Window GetAttributes WindowList[i] To WindowBag
If Not WindowBag["Floating"] Then
TargetWindow = WindowList[i]
QuitLoop
Endif
EndFor
Else ; Canvas or image is top window
;-------------------------------------------------------
; if there is an image then it will get the keystroke...
;-------------------------------------------------------
If nImages() > 0 Then
Window Handle Form To TargetWindow
If Not IsWindow(TargetWindow) Then
Window Handle Image ImageNo() To TargetWindow
Endif
Else
;----------------------------------------------------
; ...otherwise the desktop will get the keystroke
;----------------------------------------------------
TargetWindow = 0
Endif
Endif
Else
TargetWindow = 0
Endif
EndSwitch
Otherwise: ; MESSAGE or IDLE
TargetWindow = GetWindow()
EndSwitch
Endif ; There is no window
Endif ; Trigger
Return TargetWindow
EndProc ; EventMan.GetTargetWindow
;----------------------------------------------------------------------------
; Sets ObjectTag to (the strval of) the target window number, unless the
; target window number is 0, in which case sets ObjectTag o a blank string...
;----------------------------------------------------------------------------
Proc EventMan.SetWindowAsObjectTag()
If EventMan.TargetWindow = 0 Then
EventMan.ObjectTag = ""
Else
EventMan.ObjectTag = StrVal(EventMan.TargetWindow)
Endif
EndProc ; EventMan.SetWindowAsObjectTag
;------------------------------------------------------------------------------
;EventMan.ObjectTag is looked up in a dictionary of window object tags. This
;dictionary must be maintained by the application. If a window is not
;registered then the EventMan.ObjectTag is set to blank, meaning unknown. This
;has the effect of causing the default event handlers to be fired.
;------------------------------------------------------------------------------
Proc EventMan.SetIndexedObjectTag()
If IsAssigned(EventMan.WindowObjectTag[EventMan.TargetWindow]) Then
EventMan.ObjectTag = EventMan.WindowObjectTag[EventMan.TargetWindow]
Else
EventMan.ObjectTag = ""
Endif
EndProc ; EventMan.SetIndexedObjectTag
;----------------------------------------------------------------------------
; First the procedure sets object tag as with SetIndexedObjectTag, or to the
; string value of the window if no entry is found for the window in
; EventMan.WindowObjectTag().
; Then the object type is looked up from EventMan.ObjectTypeBag if there is
; an entry. If there is no entry, an attempt is made to generate one by
; using GetWindowType to get a type for the target window.
; As a last resort objectTag and objectType are both set to blank.
;----------------------------------------------------------------------------
Proc EventMan.SetObjectTagAndType()
; Set EventMan.ObjectTag...
If Not IsAssigned(EventMan.WindowObjectTag[EventMan.TargetWindow]) Then
If IsWindow(EventMan.TargetWindow) Then
EventMan.WindowObjectTag[EventMan.TargetWindow] =
StrVal(EventMan.TargetWindow)
EventMan.ObjectTag = EventMan.WindowObjectTag[EventMan.TargetWindow]
Else
EventMan.ObjectTag = ""
Endif
Else
EventMan.ObjectTag = EventMan.WindowObjectTag[EventMan.TargetWindow]
Endif
; Set EventMan.ObjectType...
If IsAssigned(EventMan.ObjectTypeBag[EventMan.ObjectTag]) And
Not isBlank(EventMan.ObjectTypeBag[EventMan.ObjectTag]) Then
EventMan.ObjectType = EventMan.ObjectTypeBag[EventMan.ObjectTag]
Else
If IsWindow(EventMan.TargetWindow) Then
EventMan.ObjectType = EventMan.GetWindowType(EventMan.TargetWindow)
EventMan.ObjectTypeBag[EventMan.ObjectTag] = EventMan.ObjectType
Else
EventMan.ObjectType = ""
Endif
Endif
EndProc ; EventMan.SetObjectTagAndType
Proc EventMan.SetEventTag()
Private
Action
Eventman.EventType = EventMan.EventBag["Type"]
Switch
Case EventMan.EventType = "KEY":
EventMan.EventTag = StrVal(EventMan.EventBag["Keycode"])
Case EventMan.EventType = "MOUSE":
Action = EventMan.EventBag["Action"]
Switch
Case Action = "DOWN":
EventMan.EventTag = EventMan.EventBag["Buttons"] +
IIf(EventMan.EventBag["DoubleClick"],"DOUBLE","") +
Action
EventMan.MouseModeButton = EventMan.EventBag["Buttons"]
Case Action = "UP":
EventMan.EventTag =
IIf(EventMan.EventBag["DoubleClick"],"DOUBLE","") +
Action
Case EventMan.EventBag["Buttons"] = "NONE":
EventMan.EventTag = "NONE" + Action
EventMan.MouseModeButton = "NONE"
OtherWise:
EventMan.EventTag =
EventMan.EventBag["Buttons"] + Action
EndSwitch
Case EventMan.EventType = "MESSAGE":
EventMan.EventTag = EventMan.EventBag["Message"]
If EventMan.EventTag = "MENUSELECT" Then
EventMan.EventTag = "MENUTAG:" + EventMan.EventBag["MenuTag"]
Endif
If EventMan.EventTag = "MENUKEY" Then
EventMan.EventTag = "MENUKEY:" + EventMan.EventBag["Keycode"]
Endif
Case EventMan.EventType = "IDLE":
EventMan.EventTag = "IDLE"
EndSwitch
EndProc ; EventMan.SetEventTag
;============================================================================
; EVENT DISPATCH
;============================================================================
;----------------------------------------------------------------------------
; Fires EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag] if found,
; or EventMan.Dictionary[EventMan.EventTag] if found,
; or just returns (sets) EventMan.DefaultReturnCode
;----------------------------------------------------------------------------
Proc EventMan.DispatchEventTag()
Switch
Case EventMan.ObjectTag <> "" And
IsAssigned(EventMan.Dictionary[EventMan.ObjectTag +
EventMan.EventTag]):
ExecProc EventMan.Dictionary[EventMan.ObjectTag +
EventMan.EventTag]
EventMan.ReturnCode = Retval
Case IsAssigned(EventMan.Dictionary[EventMan.EventTag]):
ExecProc EventMan.Dictionary[EventMan.EventTag]
EventMan.ReturnCode = Retval
Otherwise:
ExecProc EventMan.DefaultReturnCodeProc
EndSwitch
EndProc ; EventMan.DispatchEventTag
;----------------------------------------------------------------------------
; Fires EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag] if found,
; or EventMan.Dictionary[EventMan.ObjectType + EventMan.EventTag] if found,
; or EventMan.Dictionary[EventMan.EventTag] if found,
; or just returns (sets) EventMan.DefaultReturnCode
;----------------------------------------------------------------------------
Proc EventMan.DispatchEventTagToType()
Switch
Case EventMan.ObjectTag <> "" And
IsAssigned(EventMan.Dictionary[EventMan.ObjectTag +
EventMan.EventTag]):
ExecProc EventMan.Dictionary[EventMan.ObjectTag +
EventMan.EventTag]
EventMan.ReturnCode = Retval
Case IsAssigned(EventMan.Dictionary[EventMan.ObjectType +
EventMan.EventTag]):
ExecProc EventMan.Dictionary[EventMan.ObjectType +
EventMan.EventTag]
EventMan.ReturnCode = Retval
Case IsAssigned(EventMan.Dictionary[EventMan.EventTag]):
ExecProc EventMan.Dictionary[EventMan.EventTag]
EventMan.ReturnCode = Retval
Otherwise:
ExecProc EventMan.DefaultReturnCodeProc
EndSwitch
EndProc ; EventMan.DispatchEventTagToType
Proc EventMan.DoIdleEvent()
If EventMan_nIdleServers > 0 Then
ExecProc EventMan_IdleServerProcs[EventMan_IdleServerPtr]
If EventMan_IdleServerPtr = EventMan_nIdleServers Then
EventMan_IdleServerPtr = 1
Else
EventMan_IdleServerPtr = EventMan_IdleServerPtr + 1
Endif
Endif
EventMan.ReturnCode = 1
EndProc ; EventMan.DoIdleEvent
;============================================================================
; UTILITY PROCS
;============================================================================
Proc EventMan.DispatchEventBag()
EventMan.SetEventTag()
If IsAssigned(EventMan.InterruptBag[EventMan.EventTag]) Then
ExecProc EventMan.InterruptBag[EventMan.EventTag]
EventMan.ReturnCode = Retval
Else
ExecProc EventMan.DispatchEventTagProc
Endif
EndProc ; EventMan.DispatchEventBag
;----------------------------------------------------------------------------
; Collects all events to EventMan.EventBag[]...
;----------------------------------------------------------------------------
Proc Eventman.DoWait()
Echo Normal
Wait WorkSpace
Proc "EventMan.CatchTrigger" All
EndWait
EndProc
;----------------------------------------------------------------------------
; Collects all events to EventMan.EventBag[]...
;----------------------------------------------------------------------------
Proc EventMan.GetEvent()
GetEvent All To EventMan.EventBag
EndProc ; EventMan.GetEvent
;----------------------------------------------------------------------------
; Calling procedures should in most cases issue ExecEvent EventMan.EventBag
; to issue the mouse down event that initiated the sequence before calling
; EventMan.CompleteMouseSequence, to be modal. CompleteMouseSequence always
; returns 1 or 2. It does NOT refresh EventMan.TargetWindow nor
; MessageMan.ObjectTag because being modal it refers to the object or window
; that was current with the defining mouse down event.
;----------------------------------------------------------------------------
Proc EventMan.CompleteMouseSequence()
Private
ObjectTag,
EventBag,
Element
ObjectTag = EventMan.ObjectTag
EventMan.ReturnCode = 1
While (EventMan.EventBag["Buttons"] <> "NONE")
While True
GetEvent to EventBag
If EventBag["Type"] = "MOUSE" Then
Quitloop
Endif
EndWhile
EventMan.ObjectTag = ObjectTag
ForEach Element in EventMan.EventBag
Release Vars EventMan.EventBag[Element]
EndForeach
ForEach Element in EventBag
EventMan.EventBag[Element] = EventBag[Element]
EndforEach
EventMan.DispatchEventBag()
EndWhile
Return EventMan.ReturnCode
EndProc ; EventMan.CompleteMouseSequence
Proc EventMan.ReturnFromMouseMode()
While (EventMan.EventBag["Buttons"] <> "NONE")
While True
GetEvent to EventMan.EventBag
If EventMan.EventBag["Type"] = "MOUSE" Then
Quitloop
Endif
EndWhile
EndWhile
EventMan.ReturnCode = 1
Return EventMan.ReturnCode
EndProc ; EventMan.ReturnFromMouseMode
Proc EventMan.SendMessage(ObjectTag,MessageTag)
EventMan.ObjectTag = ObjectTag
If IsAssigned(EventMan.ObjectTypeBag[ObjectTag]) Then
EventMan.ObjectType = EventMan.ObjectTypeBag[ObjectTag]
Else
EventMan.ObjectType = ""
Endif
EventMan.EventType = "CUSTOM"
EventMan.EventTag = MessageTag
ExecProc EventMan.DispatchEventTagProc
Return EventMan.ReturnCode
EndProc ; EventMan.SendMessage
Proc EventMan.DisableEvent()
Return 1
EndProc
Proc EventMan.EnableEvent()
Return 0
EndProc
Proc EventMan.SetDefaultReturnCode()
EventMan.ReturnCode = EventMan.DefaultReturnCode
EndProc
;------------------------------------------------------------------------------
; WindowHandle must be the current window, a currently active form or image,
; a modal window, a floating window, or a canvas window above any currently
; active form or image. If none of these then GetWindowType() returns ""
; (blank).
; Does *not* contemplate dialog box windows.
;-----------
; Returns "", FLOATING, CANVAS, QUERY, TABLE, FORM, FILE_EDITOR, SCRIPT, MEMO,
; FORMDESIGN, REPORTDESIGN, CREATE, GRAPH, PASSWORD, RESTRUCTURE,
; INDEX, SORT
; Typical useage: ObjectType = EventMan.GetWindowType(GetWindow())
;---------
; Windows for which types can be found:
;--------------------------------------
; Floating windows.
; Editor windows which have no forms or images in front of them.
; Canvases which have no forms or images in front of them.
; Modal windows (FORMDESIGN, REPORTDESIGN, CREATE, GRAPH, PASSWORD,
; RESTRUCTURE, INDEX, SORT).
; The active form or image window.
;
; Windows for which types cannot be found:
;-----------------------------------------
; Any windows behind a currently active form, table view, or query
; Any invalid window handle (IsWindow(WindowHandle) = False)
;------------------------------------------------------------------------------
Proc EventMan.GetWindowType(WindowHandle)
Private
WindowBag,
WorkspaceHandle,
IsEditor,
EditorHandle,
ImageHandle,
WindowList,
WindowTemp,
CurrentWindow,
Found,
WindowPtr,
i
;-------------------------------------------------------------------------
; If the window handle for which a type is requested is not valid, then
; return blank for unknown...
;-------------------------------------------------------------------------
If Not IsWindow(WindowHandle) Then
Return ""
Endif
;-------------------------------------------------------------------------
; If the window handle for which a type is requested is a floating window,
; then return "FLOATING".
;-------------------------------------------------------------------------
Window Getattributes WindowHandle to WindowBag
If WindowBag["Floating"] Then
Return "FLOATING"
Endif
WindowType = ""
;-------------------------------------------------------------------------
; Now determine if a form or image is active, and if so if it is the one
; requested by the call. If it is, then return the type of the window...
;-------------------------------------------------------------------------
If nImages() > 0 Then
Window Handle Form to ImageHandle
If IsWindow(ImageHandle) And ImageHandle = WindowHandle Then
WindowType = "FORM"
Else
Window Handle Image ImageNo() To ImageHandle
If ImageHandle = WindowHandle Then
WindowType = Upper(ImageType()) ; "Display" or "Query"
If WindowType = "DISPLAY" Then
WindowType = "TABLE" ; else "QUERY"
Endif
Endif
Endif
If WindowType <> "" Then
Return WindowType
Else
WorkspaceHandle = ImageHandle
Endif
Else
WorkspaceHandle = 0
Endif
;-------------------------------------------------------------------------
; Now the search can continue, but only up to and not including any
; active form or image, so as not to disturb the workspace, so first
; identify the window group within which further searches can be made,
; up to but not including any form or image...
;-------------------------------------------------------------------------
If IsWindow(WorkspaceHandle) Then
Found = False
Window List To WindowTemp
For WindowPtr From 1 To ArraySize(WindowTemp)
If WindowTemp[WindowPtr] = WorkspaceHandle Then
Quitloop
Endif
If Not found then
Found = (WindowTemp[WindowPtr] = WindowHandle)
Endif
EndFor
If Not Found then ; give up
Return ""
Endif
Array WindowList[WindowPtr - 1]
For i From 1 To WindowPtr - 1
WindowList[i] = WindowTemp[i]
EndFor
Else
Found = False
Window List To WindowList
For WindowPtr From 1 To ArraySize(WindowList)
If WindowList[WindowPtr] = WorkspaceHandle Then
Quitloop
Endif
If Not found then
Found = WindowList[i] = WindowHandle
Endif
EndFor
If Not Found Then ; give up
Return ""
Endif
Endif
;-------------------------------------------------------------------------
; See if an editor is visible, and if so get its window handle to
; EditorHandle
;-------------------------------------------------------------------------
IsEditor = (IsFieldView() and Substr(FieldType(),1,1) = "M")
or SysMode() = "File Editor" or SysMode() = "Script"
If IsEditor Then
Switch
Case Sysmode() = "File Editor":
WindowType = "FILE_EDITOR"
Case Sysmode() = "Script":
WindowType = "SCRIPT"
Otherwise:
WindowType = "MEMO"
EndSwitch
;-----------------------------------------------------------------------
; Now determine what the editor window handle is (the first non-floating
; window) and determine if the requested window appears in the z-order
; as the editor window, or as a window above the editor window. If the
; requested window is the editor , then the type has been successfully
; found.
;-----------------------------------------------------------------------
Found = False
For WindowPtr From 1 to ArraySize(WindowList)
Window GetAttributes WindowList[WindowPtr] To WindowBag
If Not Found Then
Found = (WindowHandle = WindowList[WindowPtr])
Endif
If Not WindowBag["Floating"] Then
EditorHandle = WindowList[WindowPtr] ; this is a deterministic find
Quitloop
Endif
EndFor
If Not (Found And EditorHandle = WindowHandle) Then
WindowType = "" ; window is behind current editor
Endif
Endif
;--------------------------------------------------------------------------
; If the type has not been successfully found, then keep looking, this time
; more aggressively by moving to the window in question...
;--------------------------------------------------------------------------
If WindowType = "" Then
CurrentWindow = GetWindow()
Window Select WindowHandle
;------------------------------------------------------------------------
; Test for one of paradox's modal windows, or editor window ...
;------------------------------------------------------------------------
SysmodeType = Upper(Sysmode())
If IsFieldView() And Substr(FieldType(),1,1) = "M" Then
SysmodeType = "MEMO"
Endif
If SysmodeType <> "MAIN" And
SysmodeType <> "EDIT" And
SysmodeType <> "COEDIT" And
SysmodeType <> "DATAENTRY" And
SysmodeType <> "MULTIENTRY" Then
WindowType = SysmodeType ; CREATE, GRAPH, PASSWORD, RESTRUCTURE,
; INDEX, SORT, REPORT, FORM, SCRIPT,
; FILE EDITOR, MEMO
Window GetAttributes WindowHandle To WindowBag
If Not WindowBag["Floating"] Then ; should always evaluate to true!
WindowBag["Floating"] = True
Window SetAttributes WindowHandle From WindowBag
Window GetAttributes WindowHandle To WindowBag
If WindowBag["Floating"] Then
WindowType = "CANVAS"
WindowBag["Floating"] = False
Window SetAttributes WindowHandle From WindowBag
Endif
Else
Debug ; unexpected floating window find...
Endif
Else
WindowType = "CANVAS"
Endif
;------------------------------------------------------
; Return windows to original order...
;------------------------------------------------------
For i From ArraySize(WindowList) to 1 Step -1
Window Select WindowList[i]
EndFor
Window Select CurrentWindow
If WindowType = "FORM" or WindowType = "REPORT" Then
WindowType = WindowType + "DESIGN"
Endif
If WindowType = "FILE EDITOR" Then
WindowType = "FILE_EDITOR"
Endif
Endif
Return WindowType
EndProc ; EventMan.GetWindowType
;============================================================================
; MAINLINE
;============================================================================
If Not IsAssigned(Librarian.HasControl) Then
EventMan.Constructor()
SetCanvas Default
Echo Normal
EventMan.DoGetEvent()
EventMan.Destructor()
Endif