home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / database / pk4pak.zip / EVENTMAN.SC < prev    next >
Text File  |  1993-02-03  |  48KB  |  1,131 lines

  1. ;============================================================================
  2. ; (c) Copyright Elect Software International Inc., 1992, Toronto. Anyone can
  3. ; use this code for anything as long as it is not resold as a software
  4. ; development resource, as long as the copyright notice isn't removed, as
  5. ; long as changes are clearly marked as to authorship, and as long as users
  6. ; indemnify Elect from any liability.
  7. ; Comments welcome. Henrik Bechmann, CIS:72701,3717; Tel:416-534-8176.
  8. ;============================================================================
  9.  
  10. ; EventMan Version 1.12 January, 1992.
  11.  
  12. ;============================================================================
  13. ;                            WHAT'S NEW ?
  14. ;============================================================================
  15. ;
  16. ; EventMan version 1.1 introduces types. By setting
  17. ;
  18. ;     EventMan.SetObjectTagProc = "EventMan.SetObjectTagAndType"
  19. ;
  20. ; and
  21. ;
  22. ;     EventMan.DispatchEventTagProc = "EventMan.DispatchEventTagToType"
  23. ;
  24. ; EventMan will check an object's type for an event handler if there isn't one
  25. ; for the object itself.
  26. ;
  27. ; if the application doesn't set a type for the object in
  28. ;
  29. ;              EventMan.ObjectTypeBag[]
  30. ;
  31. ; then EventMan will try to provide one (in SetObjectTagAndType()) with
  32. ; EventMan.GetWindowType(). The standard types are
  33. ;             FLOATING, CANVAS, QUERY, TABLE, FORM, FILE_EDITOR, SCRIPT, MEMO,
  34. ;             FORMDESIGN, REPORTDESIGN, CREATE, GRAPH, PASSWORD, RESTRUCTURE,
  35. ;             INDEX, SORT
  36. ;
  37. ; The type is placed in EventMan.ObjectType.
  38. ;
  39. ; Therefore the developer can develop generalized code for each type, default
  40. ; code for the application as a whole, and limit custom code for each object
  41. ; to special cases.
  42. ;
  43. ; For direct dispatches of messages to objects, use
  44. ;
  45. ;        EventMan.SendMessage(ObjectTag,MessageTag)
  46. ;
  47. ; Since SetObjectTagAndType will set a default object name as well as object
  48. ; type if none is provided for the window, EventMan 1.1 should be code
  49. ; compatible for most applications written for the original version.
  50. ;
  51. ; Version 1.11 adds EventMan.DefaultReturnCodeProc which is set to
  52. ; "EventMan.SetDefaultReturnCode" by default, but can be set to your
  53. ; application's proc which can, for instance, deal with events by type
  54. ; in this procedure.
  55. ;
  56. ;============================================================================
  57. ;                            EVENTMAN DESCRIPTION
  58. ;============================================================================
  59. ;
  60. ; EventMan (Event Manager) is a generic event manager for use in Paradox 4.0
  61. ; applications. The general organization of the scheme is as follows:
  62. ;
  63. ; Procedures (event handlers) are associated with events and objects in a
  64. ; dictionary (a dynarray) in the following general form:
  65. ;
  66. ;         EventMan.Dictionary[ObjectTag + EventTag] = ProcName
  67. ;
  68. ; The idea is to EXECPROC ProcName based on the current object and event.
  69. ;
  70. ; EventMan organizes programming in Paradox 4.0 into 4 phases:
  71. ;         1. Event collection
  72. ;         2. Event analysis
  73. ;         3. Event dispatch
  74. ;         4. Event handling
  75. ;
  76. ; Event collection can take place under either WAIT ... PROC or under
  77. ; GETEVENT. EventMan.DoWait() and EventMan.DoGetEvent() are provided as
  78. ; defaults for this.
  79. ;
  80. ; Event analysis involves several steps:
  81. ;         1. Get target window handle (placed in EventMan.TargetWindow)
  82. ;         2. Set object tag (placed in EventMan.ObjectTag)
  83. ;         3. Set event tag (placed in EventMan.EventTag)
  84. ;
  85. ; EventMan automatically places the target window handle in
  86. ; EventMan.TargetWindow using EventMan.GetTargetWindow(..))
  87. ;
  88. ; EventMan provides a default procedure in EventMan.SetObjectTagProc
  89. ; (EventMan.SetWindowAsObjectTag()) for setting EventMan.ObjectTag. This
  90. ; procedure simply sets EventMan.ObjectTag to StrVal(EventMan.TargetWindow).
  91. ;
  92. ; Your application can substitute a more sophisticated procedure which might,
  93. ; for instance, set EventMan.ObjectTag to "INVOICE".
  94. ; EventMan.SetIndexedObjectTag() is provided for this purpose. It looks
  95. ; up your custom ObjectTag from a list of window numbers. With this
  96. ; alternative, your application must maintain the cross referencing
  97. ; information in the dynarrays EventMan.WindowObjectTag[] and
  98. ; EventMan.ObjectTagWindow[]. The advantage to this is that by avoiding the
  99. ; use of window handles for ObjectTags, EventMan.Dictionary[] updates are not
  100. ; required each time a window is loaded or unloaded.
  101. ;
  102. ; To use more generalized code, set EventMan.SetObjectTagProc to
  103. ; "EventMan.SetObjectTagAndType" and EventMan.DispatchEventTagProc to
  104. ; "EventMan.DispatchEventTagToType". Then when a window is registered, set
  105. ; EventMan.ObjectTypeBag[] for the object to its type. EventMan will set
  106. ; EventMan.ObjectType to the objects type, and will then look
  107. ; for an event handler for the type after looking for an event handler for
  108. ; the object, and before looking for a default event.
  109. ;
  110. ; EventMan sets EventMan.EventTag according to some rules that are easily
  111. ; understood by reading the code of the procedure EventMan.SetEventTag()
  112. ; below.
  113. ;
  114. ; Finally EventMan dispatches the event. EventMan provides a default
  115. ; dispatcher (EventMan.DispatchEventTag()) in EventMan.DispatchEventTagProc,
  116. ; although your application can substitute its own more sophisticated
  117. ; dispatcher (advanced applications only). The default dispatcher first
  118. ; looks for
  119. ;
  120. ;       EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag]
  121. ;
  122. ; and then
  123. ;
  124. ;       EventMan.Dictionary[EvenMan.EventTag]
  125. ;
  126. ; if it didn't find the first form. Therefore default behavior can be
  127. ; provided by your application.
  128. ;
  129. ; If EventMan.DispatchEventTagToType() is used for the dispatcher, then the
  130. ; dispatcher looks for
  131. ;
  132. ;       EventMan.Dictionary[EventMan.ObjectType + EventMan.EventTag]
  133. ;
  134. ; after [Eventman.ObjectTag + EventMan.EventTag].
  135. ;
  136. ; Event handlers, the procedures that are EXECPROC'd by the event dispatcher,
  137. ; must be provided by your application, and must always return the values 0,
  138. ; 1, or 2, according to the rules provided for WAIT PROC commands.
  139. ;
  140. ; Special support is provided for IDLE event processing, and for MOUSE event
  141. ; processing, as well as populating and de-populating EventMan.Dictionary.
  142. ;
  143. ; Look for event packet details in EventMan.EventBag[].
  144. ;
  145. ; For some ideas on how to use EventMan, see EDEMO.SC.
  146. ;
  147. ;============================================================================
  148. ;                            EVENTMAN INTERFACE
  149. ;============================================================================
  150. ;
  151. ; Construction and destruction:
  152. ; -----------------------------
  153. ; EventMan.Constructor() ; execute at start of session
  154. ; EventMan.Destructor() ; execute at end of session
  155. ;
  156. ; The event dictionary and idle proc queue:
  157. ; -----------------------------------------
  158. ; EventMan.SetHandlersFrom(HandlerBag)
  159. ; Eventman.ClearHandlersWith(HandlerBag)
  160. ; EventMan.RegisterIdleServer(ObjectTag,IdleProcName)
  161. ; EventMan.DeRegisterIdleServer(ObjectTag)
  162. ;
  163. ; Event collectors: (use these in your code)
  164. ; ------------------------------------------
  165. ; (For Wait statements...)
  166. ; EventMan.CatchTrigger(EventMan.TriggerTag,EventMan.EventBag,
  167. ;       EventMan.TriggerCycle)
  168. ; (Shell (analog to wait) for EventMan.GetEventProc...)
  169. ; EventMan.DoGetEvent()
  170. ;
  171. ; Event analysis:
  172. ; ---------------
  173. ; EventMan.GetTargetWindow(TriggerTag,EventBag) ; returns 0 or valid window
  174. ; EventMan.SetWindowAsObjectTag() ; Default EventMan.SetObjectTagProc
  175. ; EventMan.SetIndexedObjectTag() ; More sophisticated object identification
  176. ; EventMan.SetObjectTagAndType() ; sets EventMan.ObjectType as well as
  177. ;                                ; EventMan.ObjectTag
  178. ; EventMan.SetEventTag() ; sets EventMan.EventTag from EventMan.EventBag[]
  179. ;
  180. ; Event dispatch:
  181. ; ---------------
  182. ; EventMan.DispatchEventTag() ; default EventMan.DispatchEventTagProc; called
  183. ;                             ; by DispatchEventBag
  184. ; EventMan.DispatchEventTagToType() ; similar to DispatchEventTag() , but
  185. ;                             ; looks for handlers associated with
  186. ;                             ; EventMan.ObjectType after EventMan.ObjectTag
  187. ; EventMan.DoIdleEvent()      ; execprocs next idle server
  188. ; EventMan.DispatchEventBag() ; direct dispatch of an event bag, used by
  189. ;                             ; EventMan.completeMouseSequence()
  190. ;
  191. ; Utility procs:
  192. ; ---------------------
  193. ; EventMan.DoWait() ; default wait statement, uses EventMan.CatchTrigger()
  194. ; EventMan.GetEvent() ; default EventMan.GetEventProc
  195. ; EventMan.EnableEvent() ; returns 0
  196. ; EventMan.DisableEvent() ; returns 1
  197. ; EventMan.SetDefaultReturnCode() ; sets ReturnCode to DefaultReturnCode
  198. ; EventMan.CompleteMouseSequence() ; call after ExecEvent EventBag
  199. ; EventMan.ReturnFromMouseMode() ; call after mouse down when UP is available
  200. ; EventMan.SendMessage(ObjectTag,MessageTag) ; send message to ObjectTag
  201. ;
  202. ; Properties:
  203. ; ------------
  204. ; EventMan.IsActive ; readonly, is EventMan active? (use isAssigned)
  205. ; EventMan.IsGetEvent ; readonly, is this a getevent event? (use isAssigned)
  206. ; EventMan.IsWait ; readonly, is this a wait event? (use isAssigned)
  207. ; EventMan.Dictionary[] ; EventMan.Dictionary[ObjectTag + EventTag] = ProcName
  208. ; EventMan.InterruptBag[] ;
  209. ; EventMan.WindowObjectTag[] ;
  210. ; EventMan.ObjectTagWindow[] ;
  211. ; EvnetMan.ObjectTypeBag[] ;
  212. ; EventMan.EventBag[] ; as collected by wait or getevent
  213. ; EventMan.EventType ; TRIGGER or EventMan.EventBag["Type"]
  214. ; EventMan.MouseModeButton ; Button pressed with last DOWN, or "NONE"
  215. ; EventMan.TargetWindow ; set by collectors from EventMan.GetTargetWindow(..)
  216. ; EventMan.ObjectTag ; string value for EventMan.Dictionary set by
  217. ;                    ; EventMan.SetWindowAsObjectTag() or EventMan.SetObjectTagProc
  218. ; EventMan.ObjectType ; used by EventMan.DispatchEventTagToType()
  219. ; EventMan.EventTag ; sometimes composite string value for
  220. ;                   ; EventMan.Dictionary set by EventMan.SetEventTag()
  221. ; EventMan.ReturnCode ; must be set by DispatchEventTagProc
  222. ; EventMan.DefaultReturnCode ; return code when handler search fails
  223. ; EventMan.GetEventProc ; getevent specs for DoGetEvent
  224. ; EventMan.SetObjectTagProc ; sets EventMan.ObjectTag based on
  225. ;                           ; Eventman.TargetWindow
  226. ; EventMan.DispatchEventTagProc ; dispatches event to EventMan.Dictionary
  227. ; EventMan.DefaultReturnCodeProc ; set default EventMan.ReturnCode
  228. ;
  229. ;============================================================================
  230. ;                         EVENTMAN IMPLEMENTATION
  231. ;============================================================================
  232.  
  233. ;============================================================================
  234. ;                         CONSTRUCTION AND DESTRUCTION
  235. ;============================================================================
  236.  
  237. Proc EventMan.Constructor()
  238.    ;-------------------------------------------------------------------------
  239.    ; General properties
  240.    ;-------------------------------------------------------------------------
  241.    EventMan.IsActive = True
  242.    Dynarray EventMan.Dictionary[]
  243.    Dynarray EventMan.EventBag[]
  244.    Dynarray EventMan.WindowObjectTag[]
  245.    Dynarray EventMan.ObjectTagWindow[]
  246.    Dynarray EventMan.ObjectTypeBag[]
  247.    Dynarray EventMan.InterruptBag[]
  248.    EventMan.MouseModeButton = "NONE"
  249.    EventMan.EventType = ""
  250.    EventMan.EventTag = ""
  251.    EventMan.ObjectTag = ""
  252.    EventMan.ObjectType = ""
  253.    EventMan.ReturnCode = 0
  254.    EventMan.DefaultReturnCode = 0
  255.    ;-------------------------------------------------------------------------
  256.    ; Default action procs
  257.    ;-------------------------------------------------------------------------
  258.    EventMan.GetEventProc = "EventMan.GetEvent"
  259.    EventMan.SetObjectTagProc = "EventMan.SetWindowAsObjectTag"
  260.    EventMan.DispatchEventTagProc = "EventMan.DispatchEventTag"
  261.    EventMan.DefaultReturnCodeProc = "EventMan.SetDefaultReturnCode"
  262.    ;-------------------------------------------------------------------------
  263.    ; Private properties
  264.    ;-------------------------------------------------------------------------
  265.    Dynarray EventMan_IdleServers[]
  266.    Array EventMan_IdleServerProcs[1] ; stub
  267.    EventMan_nIdleServers = 0
  268.    EventMan_IdleServerPtr = 1
  269.  
  270. EndProc ; EventMan.Constructor
  271.  
  272. Proc EventMan.Destructor()
  273. ;   If EventMan.nInstances > 1 Then
  274. ;      EventMan.nInstances = EventMan.nInstances - 1
  275. ;      Return
  276. ;   Endif
  277.    Release Vars
  278.  
  279.       EventMan.IsActive,
  280. ;      EventMan.nInstances,
  281.       EventMan.IsWait,
  282.       EventMan.IsGetEvent,
  283.       EventMan.Dictionary,
  284.       EventMan.InterruptBag,
  285.       EventMan.EventBag,
  286.       EventMan.WindowObjectTag,
  287.       EventMan.ObjectTagWindow,
  288.       EventMan.MouseModeButton,
  289.       EventMan_IdleServers,
  290.       EventMan_IdleServerProcs,
  291.       EventMan_nIdleServers,
  292.       EventMan_IdleServerPtr,
  293.       EventMan.EventType,
  294.       EventMan.EventTag,
  295.       EventMan.ObjectTag,
  296.       EventMan.ObjectType,
  297.       EventMan.ObjectTypeBag,
  298.       EventMan.TargetWindow,
  299.       EventMan.ReturnCode,
  300.       EventMan.DefaultReturnCode,
  301.       EventMan.GetEventProc,
  302.       EventMan.SetObjectTagProc,
  303.       EventMan.DispatchEventTagProc,
  304.       EventMan.DefaultReturnCodeProc
  305.  
  306. EndProc ; EventMan.Destructor
  307.  
  308. ;============================================================================
  309. ;                         DICTIONARY UPDATE
  310. ;============================================================================
  311.  
  312. Proc EventMan.SetHandlersFrom(HandlerBag)
  313.    Private
  314.       EventTag,
  315.       ObjectTag
  316.  
  317.    If IsAssigned(HandlerBag["ObjectTag"]) Then
  318.       ObjectTag = Strval(HandlerBag["ObjectTag"])
  319.       Release Vars HandlerBag["ObjectTag"] ; to avoid screening below
  320.    Else
  321.       ObjectTag = ""
  322.    Endif
  323.  
  324.    Foreach EventTag in HandlerBag
  325.       If (HandlerBag[EventTag] = "") Then
  326.          Release Vars EventMan.Dictionary[ObjectTag + EventTag]
  327.       Else
  328.          EventMan.Dictionary[ObjectTag + EventTag] = HandlerBag[EventTag]
  329.       Endif
  330.    EndForeach
  331.  
  332.    If Not isBlank(ObjectTag) Then
  333.       HandlerBag["ObjectTag"] = ObjectTag
  334.    Endif
  335. EndProc ; EventMan.SetHandlersFrom
  336.  
  337. Proc EventMan.ClearHandlersWith(HandlerBag)
  338.    Private
  339.       EventTag,
  340.       ObjectTag
  341.  
  342.    If IsAssigned(HandlerBag["ObjectTag"]) Then
  343.       ObjectTag = Strval(HandlerBag["ObjectTag"])
  344.       Release Vars HandlerBag["ObjectTag"]
  345.    Else
  346.       ObjectTag = ""
  347.    Endif
  348.  
  349.    Foreach EventTag in HandlerBag
  350.       Release Vars EventMan.Dictionary[ObjectTag + EventTag]
  351.    EndForeach
  352.  
  353.    If Not IsBlank(ObjectTag) Then
  354.       HandlerBag["ObjectTag"] = ObjectTag
  355.    Endif
  356.  
  357. EndProc ; EventMan.ClearHandlersWith
  358.  
  359. ;============================================================================
  360. ;                         IDLE SERVER UPDATE
  361. ;============================================================================
  362.  
  363. Proc EventMan.RegisterIdleServer(ObjectTag,IdleProcName)
  364.    Private
  365.       Element,
  366.       i
  367.    If IsAssigned(EventMan_IdleServers[ObjectTag]) Then
  368.       EventMan_IdleServers[ObjectTag] = IdleProcName
  369.    Else
  370.       EventMan_IdleServers[ObjectTag] = IdleProcName
  371.       If EventMan_nIdleServers = 0 Then
  372.          EventMan.InterruptBag["Idle"] = "EventMan.DoIdleEvent"
  373.       Endif
  374.       EventMan_nIdleServers = EventMan_nIdleServers + 1
  375.       Array EventMan_IdleServerProcs[EventMan_nIdleServers]
  376.       i = 0
  377.       ForEach Element In EventMan_IdleServers
  378.          i = i + 1
  379.          EventMan_IdleServerProcs[i] = EventMan_IdleServers[Element]
  380.       EndForEach
  381.       If EventMan_IdleServerPtr > EventMan_nIdleServers Then
  382.          EventMan_IdleServerPtr = EventMan_nIdleServers
  383.       Endif
  384.    Endif
  385. EndProc ; EventMan.RegisterIdleServer
  386.  
  387. Proc EventMan.DeRegisterIdleServer(ObjectTag)
  388.    Private
  389.       Element,
  390.       i
  391.    Release Vars
  392.       EventMan_IdleServers[ObjectTag]
  393.  
  394.    EventMan_nIdleServers = EventMan_nIdleServers - 1
  395.    If EventMan_nIdleServers > 0 Then
  396.       Array EventMan_IdleServerProcs[EventMan_nIdleServers]
  397.       i = 0
  398.       ForEach Element In EventMan_IdleServers
  399.          i = i + 1
  400.          EventMan_IdleServerProcs[i] = EventMan_IdleServers[Element]
  401.       EndForEach
  402.       If EventMan_IdleServerPtr > EventMan_nIdleServers Then
  403.          EventMan_IdleServerPtr = EventMan_nIdleServers
  404.       Endif
  405.    Else
  406.       Release Vars EventMan.InterruptBag["Idle"]
  407.       EventMan_IdleServerPtr = 1
  408.    Endif
  409. EndProc ; EventMan.DeRegisterIdleServer
  410.  
  411. ;============================================================================
  412. ;                         EVENT COLLECTORS
  413. ;============================================================================
  414.  
  415. ;----------------------------------------------------------------------------
  416. ; The event handlers Return 0, 1 or 2 to determine whether to
  417. ; 0 = process the event with execevent
  418. ; 1 = deny the event but stay in the event loop
  419. ; 2 = deny the event and break out of the event loop
  420. ;----------------------------------------------------------------------------
  421. Proc EventMan.CatchTrigger(EventMan.TriggerTag,EventMan.EventBag,EventMan.TriggerCycle)
  422.    Private
  423.       EventMan.IsGetEvent, ; mask out EventMan.IsGetEvent so that called procedures
  424.                        ; can determine that it is a wait and not a getevent
  425.                        ; that is active.
  426.       EventMan.IsWait
  427.    EventMan.IsWait = True
  428.    If EventMan.TriggerTag = "EVENT" Then
  429.       EventMan.SetEventTag()
  430.    Else
  431.       EventMan.EventType = "TRIGGER"
  432.       EventMan.EventTag = EventMan.TriggerTag
  433.    Endif
  434.    If IsAssigned(EventMan.InterruptBag[EventMan.EventTag]) Then
  435.       ExecProc EventMan.InterruptBag[EventMan.EventTag]
  436.       EventMan.ReturnCode = Retval
  437.    Else
  438.       EventMan.TargetWindow =
  439.          EventMan.GetTargetWindow(EventMan.TriggerTag,EventMan.EventBag)
  440.       ExecProc EventMan.SetObjectTagProc
  441.       ExecProc EventMan.DispatchEventTagProc
  442.    Endif
  443.    Return EventMan.ReturnCode
  444. EndProc ; EventMan.CatchTrigger
  445.  
  446. Proc EventMan.DoGetEvent()
  447.    Private
  448.       EventMan.IsGetEvent,
  449.       EventMan.IsWait
  450.    EventMan.IsGetEvent = True
  451.    EventMan.ReturnCode = 0
  452.    While EventMan.ReturnCode < 2
  453.       ExecProc EventMan.GetEventProc
  454.       EventMan.SetEventTag()
  455.       If IsAssigned(EventMan.InterruptBag[EventMan.EventTag]) Then
  456.          ExecProc EventMan.InterruptBag[EventMan.EventTag]
  457.       Else
  458.          EventMan.TargetWindow =
  459.             EventMan.GetTargetWindow("EVENT",EventMan.EventBag)
  460.          ExecProc EventMan.SetObjectTagProc
  461.          ExecProc EventMan.DispatchEventTagProc
  462.       Endif
  463.       If EventMan.ReturnCode = 0 Then
  464.          ExecEvent EventMan.EventBag
  465.       EndIf
  466.    EndWhile
  467. EndProc ; EventMan.DoGetEvent
  468.  
  469. ;============================================================================
  470. ;                         EVENT ANALYSIS
  471. ;============================================================================
  472.  
  473. ;----------------------------------------------------------------------------
  474. ; Assumes ECHO NORMAL
  475. ;----------------------------------------------------------------------------
  476. Proc EventMan.GetTargetWindow(TriggerTag,EventBag)
  477.    Private
  478.       TargetWindow,
  479.       WindowBag,
  480.       EventType,
  481.       ZOrderGroupChange,
  482.       IsEditor,
  483.       Keycode,
  484.       WindowList,
  485.       SysInfoBag,
  486.       IsCanvasNoneCurrent,
  487.       i,
  488.       Found
  489.    ;---------------------------------------------------------------------
  490.    ; If the trigger is not an event then analyze trigger...
  491.    ;---------------------------------------------------------------------
  492.    If TriggerTag <> "EVENT" Then ; must be a TRIGGER type event
  493.       ;------------------------------------------------------------------
  494.       ; If the trigger is not an ARRIVEWINDOW, then it relates to the
  495.       ; current image.
  496.       ;------------------------------------------------------------------
  497.       If TriggerTag = "ARRIVEWINDOW" Then
  498.          TargetWindow = GetWindow()
  499.       Else
  500.          Window Handle Form to TargetWindow
  501.          If Not isWindow(TargetWindow) Then
  502.             Window Handle Image ImageNo() To TargetWindow
  503.          Endif
  504.       Endif
  505.    ;---------------------------------------------------------------------
  506.    ; ...else this must be an event of type MOUSE, KEY, MESSAGE, or IDLE...
  507.    ;---------------------------------------------------------------------
  508.    Else
  509.       If Not IsWindow(GetWindow()) Then ; There are no windows
  510.          ; NOT!!! THERE COULD BE NOTHING BUT FLOATING WINDOWS, NONE OF THEM
  511.          ; CURRENT!!!!!!!!!!!!!
  512.          TargetWindow = GetWindow()
  513.          Window List To WindowList
  514.          If ArraySize(WindowList) > 0 Then
  515.             IsCanvasNoneCurrent = True
  516.          Else
  517.             IsCanvasNoneCurrent = False
  518.          Endif
  519.       Else
  520.          IsCanvasNoneCurrent = False
  521.       Endif
  522.       If IsWindow(GetWindow()) Or IsCanvasNoneCurrent Then
  523.          EventType = EventBag["Type"]
  524.          Switch
  525.             Case EventType = "MOUSE":
  526.                ;----------------------------------------------------------------
  527.                ; If this is a mouse event, then if it is a DOWN or no-button
  528.                ; event then it belongs to the window over which the mouse
  529.                ; event takes place, otherwise it is a modal event which
  530.                ; belongs to the current window.
  531.                ;----------------------------------------------------------------
  532.                If (EventBag["Action"] = "DOWN") or
  533.                   ((EventBag["Buttons"] = "NONE") And
  534.                   (EventBag["Action"] <> "UP")) Then
  535.                   TargetWindow = WindowAt(EventBag["Row"],EventBag["Col"])
  536.                Else
  537.                   TargetWindow = GetWindow()
  538.                Endif
  539.                ;----------------------------------------------------------------
  540.                ; Except for one special case when the mouse action is DOWN:
  541.                ; If the current window is floating and the target window is not
  542.                ; then expect to select the topmost desktop window as the target
  543.                ; in the course of changing z-orders from floating to desktop,
  544.                ; if the mouse event took place somewhere other than on the menu
  545.                ; bar or the status bar.
  546.                ;----------------------------------------------------------------
  547.                If EventBag["Action"] = "DOWN" And Not IsCanvasNoneCurrent Then
  548.                   Window GetAttributes GetWindow() To WindowBag
  549.                   If WindowBag["Floating"] Then
  550.                      If IsWindow(TargetWindow) Then
  551.                         Window GetAttributes Targetwindow To WindowBag
  552.                         ZOrderGroupChange = (Not WindowBag["Floating"])
  553.                      Else ; see if the mouse hit the prompt/speedbar area...
  554.                         SysInfo To SysInfoBag
  555.                         ZOrderGroupChange =
  556.                            ((SysInfoBag["ScreenHeight"] - 1 <> EventBag["Row"]) And
  557.                            (EventBag["Row"] <> 0))
  558.                      Endif ; The target window exists
  559.                      If ZOrderGroupChange Then
  560.                         Window List To WindowList
  561.                         Found = False
  562.                         For i From 1 To Arraysize(WindowList)
  563.                            Window GetAttributes WindowList[i] To WindowBag
  564.                            If Not WindowBag["Floating"] Then
  565.                               Found = True
  566.                               Quitloop
  567.                            Endif
  568.                         EndFor
  569.                         TargetWindow = IIf(Found,WindowList[i],0)
  570.                      Endif
  571.                   Endif ; The current window is a floating window
  572.                Endif ; If this is a DOWN action
  573.             Case EventType = "KEY":
  574.                Keycode = EventBag["KeyCode"]
  575.                Switch
  576.                   Case KeyCode = Asc("WinResize") or
  577.                      KeyCode = Asc("WinMax") or
  578.                      KeyCode = Asc("WinNext") or
  579.                      KeyCode = Asc("WinClose"):
  580.                      TargetWindow = GetWindow()
  581.                   Case (Keycode = Asc("ClearImage") or
  582.                      Keycode = Asc("ClearAll") or
  583.                      Keycode = Asc("EditKey") or
  584.                      Keycode = Asc("CoEditKey")):
  585.                      If nImages() > 0 Then
  586.                         Window Handle Form to TargetWindow
  587.                         If Not IsWindow(TargetWindow) Then
  588.                            Window Handle Image ImageNo() To TargetWindow
  589.                         Endif
  590.                      Else
  591.                         TargetWindow = 0
  592.                      Endif
  593.                   Otherwise:
  594.                      If Not IsCanvasNoneCurrent Then
  595.                         ;----------------------------------------------------------
  596.                         ; Check to see if the keystrokes belong to a current file or
  597.                         ; memo editor...
  598.                         ;----------------------------------------------------------
  599.                         IsEditor = (IsFieldView() and Substr(FieldType(),1,1) = "M")
  600.                         or SysMode() = "File Editor" or SysMode() = "Script"
  601.                         ;----------------------------------------------------------
  602.                         ; If it does belong to an editor, then find the first non-
  603.                         ; floating window on the desktop. That will be the editor.
  604.                         ;----------------------------------------------------------
  605.                         If IsEditor Then
  606.                            Window List To WindowList
  607.                            For i From 1 to ArraySize(WindowList)
  608.                               Window GetAttributes WindowList[i] To WindowBag
  609.                               If Not WindowBag["Floating"] Then
  610.                                  TargetWindow = WindowList[i]
  611.                                  QuitLoop
  612.                               Endif
  613.                            EndFor
  614.                         Else ; Canvas or image is top window
  615.                            ;-------------------------------------------------------
  616.                            ; if there is an image then it will get the keystroke...
  617.                            ;-------------------------------------------------------
  618.                            If nImages() > 0 Then
  619.                               Window Handle Form To TargetWindow
  620.                               If Not IsWindow(TargetWindow) Then
  621.                                  Window Handle Image ImageNo() To TargetWindow
  622.                               Endif
  623.                            Else
  624.                               ;----------------------------------------------------
  625.                               ; ...otherwise the desktop will get the keystroke
  626.                               ;----------------------------------------------------
  627.                               TargetWindow = 0
  628.                            Endif
  629.                         Endif
  630.                      Else
  631.                         TargetWindow = 0
  632.                      Endif
  633.                EndSwitch
  634.             Otherwise: ; MESSAGE or IDLE
  635.                TargetWindow = GetWindow()
  636.          EndSwitch
  637.       Endif ; There is no window
  638.    Endif ; Trigger
  639.    Return TargetWindow
  640. EndProc ; EventMan.GetTargetWindow
  641.  
  642. ;----------------------------------------------------------------------------
  643. ; Sets ObjectTag to (the strval of)  the target window number, unless the
  644. ; target window number is 0, in which case sets ObjectTag o a blank string...
  645. ;----------------------------------------------------------------------------
  646. Proc EventMan.SetWindowAsObjectTag()
  647.    If EventMan.TargetWindow = 0 Then
  648.       EventMan.ObjectTag = ""
  649.    Else
  650.       EventMan.ObjectTag = StrVal(EventMan.TargetWindow)
  651.    Endif
  652. EndProc ; EventMan.SetWindowAsObjectTag
  653.  
  654. ;------------------------------------------------------------------------------
  655. ;EventMan.ObjectTag is looked up in a dictionary of window object tags. This
  656. ;dictionary must be maintained by the application. If a window is not
  657. ;registered then the EventMan.ObjectTag is set to blank, meaning unknown. This
  658. ;has the effect of causing the default event handlers to be fired.
  659. ;------------------------------------------------------------------------------
  660. Proc EventMan.SetIndexedObjectTag()
  661.    If IsAssigned(EventMan.WindowObjectTag[EventMan.TargetWindow]) Then
  662.       EventMan.ObjectTag = EventMan.WindowObjectTag[EventMan.TargetWindow]
  663.    Else
  664.       EventMan.ObjectTag = ""
  665.    Endif
  666. EndProc ; EventMan.SetIndexedObjectTag
  667.  
  668. ;----------------------------------------------------------------------------
  669. ; First the procedure sets object tag as with SetIndexedObjectTag, or to the
  670. ; string value of the window if no entry is found for the window in
  671. ; EventMan.WindowObjectTag().
  672. ; Then the object type is looked up from EventMan.ObjectTypeBag if there is
  673. ; an entry. If there is no entry, an attempt is made to generate one by
  674. ; using GetWindowType to get a type for the target window.
  675. ; As a last resort objectTag and objectType are both set to blank.
  676. ;----------------------------------------------------------------------------
  677. Proc EventMan.SetObjectTagAndType()
  678.    ; Set EventMan.ObjectTag...
  679.    If Not IsAssigned(EventMan.WindowObjectTag[EventMan.TargetWindow]) Then
  680.       If IsWindow(EventMan.TargetWindow) Then
  681.          EventMan.WindowObjectTag[EventMan.TargetWindow] =
  682.             StrVal(EventMan.TargetWindow)
  683.          EventMan.ObjectTag = EventMan.WindowObjectTag[EventMan.TargetWindow]
  684.       Else
  685.          EventMan.ObjectTag = ""
  686.       Endif
  687.    Else
  688.       EventMan.ObjectTag = EventMan.WindowObjectTag[EventMan.TargetWindow]
  689.    Endif
  690.    ; Set EventMan.ObjectType...
  691.    If IsAssigned(EventMan.ObjectTypeBag[EventMan.ObjectTag]) And
  692.       Not isBlank(EventMan.ObjectTypeBag[EventMan.ObjectTag]) Then
  693.       EventMan.ObjectType = EventMan.ObjectTypeBag[EventMan.ObjectTag]
  694.    Else
  695.       If IsWindow(EventMan.TargetWindow) Then
  696.          EventMan.ObjectType = EventMan.GetWindowType(EventMan.TargetWindow)
  697.          EventMan.ObjectTypeBag[EventMan.ObjectTag] = EventMan.ObjectType
  698.       Else
  699.          EventMan.ObjectType = ""
  700.       Endif
  701.    Endif
  702. EndProc ; EventMan.SetObjectTagAndType
  703.  
  704. Proc EventMan.SetEventTag()
  705.    Private
  706.       Action
  707.    Eventman.EventType = EventMan.EventBag["Type"]
  708.    Switch
  709.       Case EventMan.EventType = "KEY":
  710.          EventMan.EventTag = StrVal(EventMan.EventBag["Keycode"])
  711.       Case EventMan.EventType = "MOUSE":
  712.          Action = EventMan.EventBag["Action"]
  713.          Switch
  714.             Case Action = "DOWN":
  715.                EventMan.EventTag = EventMan.EventBag["Buttons"] +
  716.                   IIf(EventMan.EventBag["DoubleClick"],"DOUBLE","") +
  717.                   Action
  718.                EventMan.MouseModeButton = EventMan.EventBag["Buttons"]
  719.             Case Action = "UP":
  720.                EventMan.EventTag =
  721.                   IIf(EventMan.EventBag["DoubleClick"],"DOUBLE","") +
  722.                   Action
  723.             Case EventMan.EventBag["Buttons"] = "NONE":
  724.                EventMan.EventTag = "NONE" + Action
  725.                EventMan.MouseModeButton = "NONE"
  726.             OtherWise:
  727.                EventMan.EventTag =
  728.                    EventMan.EventBag["Buttons"] + Action
  729.          EndSwitch
  730.       Case EventMan.EventType = "MESSAGE":
  731.          EventMan.EventTag = EventMan.EventBag["Message"]
  732.          If EventMan.EventTag = "MENUSELECT" Then
  733.             EventMan.EventTag = "MENUTAG:" + EventMan.EventBag["MenuTag"]
  734.          Endif
  735.          If EventMan.EventTag = "MENUKEY" Then
  736.             EventMan.EventTag = "MENUKEY:" + EventMan.EventBag["Keycode"]
  737.          Endif
  738.       Case EventMan.EventType = "IDLE":
  739.          EventMan.EventTag = "IDLE"
  740.    EndSwitch
  741. EndProc ; EventMan.SetEventTag
  742.  
  743. ;============================================================================
  744. ;                         EVENT DISPATCH
  745. ;============================================================================
  746.  
  747. ;----------------------------------------------------------------------------
  748. ; Fires EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag] if found,
  749. ; or EventMan.Dictionary[EventMan.EventTag] if found,
  750. ; or just returns (sets) EventMan.DefaultReturnCode
  751. ;----------------------------------------------------------------------------
  752. Proc EventMan.DispatchEventTag()
  753.    Switch
  754.       Case EventMan.ObjectTag <> "" And
  755.          IsAssigned(EventMan.Dictionary[EventMan.ObjectTag +
  756.                       EventMan.EventTag]):
  757.          ExecProc EventMan.Dictionary[EventMan.ObjectTag +
  758.                       EventMan.EventTag]
  759.          EventMan.ReturnCode = Retval
  760.       Case IsAssigned(EventMan.Dictionary[EventMan.EventTag]):
  761.          ExecProc EventMan.Dictionary[EventMan.EventTag]
  762.          EventMan.ReturnCode = Retval
  763.       Otherwise:
  764.          ExecProc EventMan.DefaultReturnCodeProc
  765.    EndSwitch
  766. EndProc ; EventMan.DispatchEventTag
  767.  
  768. ;----------------------------------------------------------------------------
  769. ; Fires EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag] if found,
  770. ; or EventMan.Dictionary[EventMan.ObjectType + EventMan.EventTag] if found,
  771. ; or EventMan.Dictionary[EventMan.EventTag] if found,
  772. ; or just returns (sets) EventMan.DefaultReturnCode
  773. ;----------------------------------------------------------------------------
  774. Proc EventMan.DispatchEventTagToType()
  775.    Switch
  776.       Case EventMan.ObjectTag <> "" And
  777.          IsAssigned(EventMan.Dictionary[EventMan.ObjectTag +
  778.                       EventMan.EventTag]):
  779.          ExecProc EventMan.Dictionary[EventMan.ObjectTag +
  780.                       EventMan.EventTag]
  781.          EventMan.ReturnCode = Retval
  782.       Case IsAssigned(EventMan.Dictionary[EventMan.ObjectType +
  783.                       EventMan.EventTag]):
  784.          ExecProc EventMan.Dictionary[EventMan.ObjectType +
  785.                       EventMan.EventTag]
  786.          EventMan.ReturnCode = Retval
  787.       Case IsAssigned(EventMan.Dictionary[EventMan.EventTag]):
  788.          ExecProc EventMan.Dictionary[EventMan.EventTag]
  789.          EventMan.ReturnCode = Retval
  790.       Otherwise:
  791.          ExecProc EventMan.DefaultReturnCodeProc
  792.    EndSwitch
  793. EndProc ; EventMan.DispatchEventTagToType
  794.  
  795. Proc EventMan.DoIdleEvent()
  796.    If EventMan_nIdleServers > 0 Then
  797.       ExecProc EventMan_IdleServerProcs[EventMan_IdleServerPtr]
  798.       If EventMan_IdleServerPtr = EventMan_nIdleServers Then
  799.          EventMan_IdleServerPtr = 1
  800.       Else
  801.          EventMan_IdleServerPtr = EventMan_IdleServerPtr + 1
  802.       Endif
  803.    Endif
  804.    EventMan.ReturnCode = 1
  805. EndProc ; EventMan.DoIdleEvent
  806.  
  807. ;============================================================================
  808. ;                       UTILITY PROCS
  809. ;============================================================================
  810.  
  811. Proc EventMan.DispatchEventBag()
  812.    EventMan.SetEventTag()
  813.    If IsAssigned(EventMan.InterruptBag[EventMan.EventTag]) Then
  814.       ExecProc EventMan.InterruptBag[EventMan.EventTag]
  815.       EventMan.ReturnCode = Retval
  816.    Else
  817.       ExecProc EventMan.DispatchEventTagProc
  818.    Endif
  819. EndProc ; EventMan.DispatchEventBag
  820.  
  821. ;----------------------------------------------------------------------------
  822. ; Collects all events to EventMan.EventBag[]...
  823. ;----------------------------------------------------------------------------
  824. Proc Eventman.DoWait()
  825.    Echo Normal
  826.    Wait WorkSpace
  827.       Proc "EventMan.CatchTrigger" All
  828.    EndWait
  829. EndProc
  830.  
  831. ;----------------------------------------------------------------------------
  832. ; Collects all events to EventMan.EventBag[]...
  833. ;----------------------------------------------------------------------------
  834. Proc EventMan.GetEvent()
  835.    GetEvent All To EventMan.EventBag
  836. EndProc ; EventMan.GetEvent
  837.  
  838. ;----------------------------------------------------------------------------
  839. ; Calling procedures should in most cases issue ExecEvent EventMan.EventBag
  840. ; to issue the mouse down event that initiated the sequence before calling
  841. ; EventMan.CompleteMouseSequence, to be modal. CompleteMouseSequence always
  842. ; returns 1 or 2. It does NOT refresh EventMan.TargetWindow nor
  843. ; MessageMan.ObjectTag because being modal it refers to the object or window
  844. ; that was current with the defining mouse down event.
  845. ;----------------------------------------------------------------------------
  846. Proc EventMan.CompleteMouseSequence()
  847.    Private
  848.       ObjectTag,
  849.       EventBag,
  850.       Element
  851.    ObjectTag = EventMan.ObjectTag
  852.    EventMan.ReturnCode = 1
  853.    While (EventMan.EventBag["Buttons"] <> "NONE")
  854.       While True
  855.          GetEvent to EventBag
  856.          If EventBag["Type"] = "MOUSE" Then
  857.             Quitloop
  858.          Endif
  859.       EndWhile
  860.       EventMan.ObjectTag = ObjectTag
  861.       ForEach Element in EventMan.EventBag
  862.          Release Vars EventMan.EventBag[Element]
  863.       EndForeach
  864.       ForEach Element in EventBag
  865.          EventMan.EventBag[Element] = EventBag[Element]
  866.       EndforEach
  867.       EventMan.DispatchEventBag()
  868.    EndWhile
  869.    Return EventMan.ReturnCode
  870. EndProc ; EventMan.CompleteMouseSequence
  871.  
  872. Proc EventMan.ReturnFromMouseMode()
  873.    While (EventMan.EventBag["Buttons"] <> "NONE")
  874.       While True
  875.          GetEvent to EventMan.EventBag
  876.          If EventMan.EventBag["Type"] = "MOUSE" Then
  877.             Quitloop
  878.          Endif
  879.       EndWhile
  880.    EndWhile
  881.    EventMan.ReturnCode = 1
  882.    Return EventMan.ReturnCode
  883. EndProc ; EventMan.ReturnFromMouseMode
  884.  
  885. Proc EventMan.SendMessage(ObjectTag,MessageTag)
  886.    EventMan.ObjectTag = ObjectTag
  887.    If IsAssigned(EventMan.ObjectTypeBag[ObjectTag]) Then
  888.       EventMan.ObjectType = EventMan.ObjectTypeBag[ObjectTag]
  889.    Else
  890.       EventMan.ObjectType = ""
  891.    Endif
  892.    EventMan.EventType = "CUSTOM"
  893.    EventMan.EventTag = MessageTag
  894.    ExecProc EventMan.DispatchEventTagProc
  895.    Return EventMan.ReturnCode
  896. EndProc ; EventMan.SendMessage
  897.  
  898. Proc EventMan.DisableEvent()
  899.    Return 1
  900. EndProc
  901.  
  902. Proc EventMan.EnableEvent()
  903.    Return 0
  904. EndProc
  905.  
  906. Proc EventMan.SetDefaultReturnCode()
  907.    EventMan.ReturnCode = EventMan.DefaultReturnCode
  908. EndProc
  909.  
  910. ;------------------------------------------------------------------------------
  911. ; WindowHandle must be the current window, a currently active form or image,
  912. ; a modal window, a floating window, or a canvas window above any currently
  913. ; active form or image. If none of these then GetWindowType() returns ""
  914. ; (blank).
  915. ; Does *not* contemplate dialog box windows.
  916. ;-----------
  917. ; Returns "", FLOATING, CANVAS, QUERY, TABLE, FORM, FILE_EDITOR, SCRIPT, MEMO,
  918. ;             FORMDESIGN, REPORTDESIGN, CREATE, GRAPH, PASSWORD, RESTRUCTURE,
  919. ;             INDEX, SORT
  920. ; Typical useage: ObjectType = EventMan.GetWindowType(GetWindow())
  921. ;---------
  922. ; Windows for which types can be found:
  923. ;--------------------------------------
  924. ; Floating windows.
  925. ; Editor windows which have no forms or images in front of them.
  926. ; Canvases which have no forms or images in front of them.
  927. ; Modal windows (FORMDESIGN, REPORTDESIGN, CREATE, GRAPH, PASSWORD,
  928. ;                RESTRUCTURE, INDEX, SORT).
  929. ; The active form or image window.
  930. ;
  931. ; Windows for which types cannot be found:
  932. ;-----------------------------------------
  933. ; Any windows behind a currently active form, table view, or query
  934. ; Any invalid window handle (IsWindow(WindowHandle) = False)
  935. ;------------------------------------------------------------------------------
  936. Proc EventMan.GetWindowType(WindowHandle)
  937.    Private
  938.       WindowBag,
  939.       WorkspaceHandle,
  940.       IsEditor,
  941.       EditorHandle,
  942.       ImageHandle,
  943.       WindowList,
  944.       WindowTemp,
  945.       CurrentWindow,
  946.       Found,
  947.       WindowPtr,
  948.       i
  949.  
  950.    ;-------------------------------------------------------------------------
  951.    ; If the window handle for which a type is requested is not valid, then
  952.    ; return blank for unknown...
  953.    ;-------------------------------------------------------------------------
  954.    If Not IsWindow(WindowHandle) Then
  955.       Return ""
  956.    Endif
  957.    ;-------------------------------------------------------------------------
  958.    ; If the window handle for which a type is requested is a floating window,
  959.    ; then return "FLOATING".
  960.    ;-------------------------------------------------------------------------
  961.    Window Getattributes WindowHandle to WindowBag
  962.    If WindowBag["Floating"] Then
  963.       Return "FLOATING"
  964.    Endif
  965.    WindowType = ""
  966.    ;-------------------------------------------------------------------------
  967.    ; Now determine if a form or image is active, and if so if it is the one
  968.    ; requested by the call. If it is, then return the type of the window...
  969.    ;-------------------------------------------------------------------------
  970.    If nImages() > 0 Then
  971.       Window Handle Form to ImageHandle
  972.       If IsWindow(ImageHandle) And ImageHandle = WindowHandle Then
  973.          WindowType = "FORM"
  974.       Else
  975.          Window Handle Image ImageNo() To ImageHandle
  976.          If ImageHandle = WindowHandle Then
  977.             WindowType = Upper(ImageType()) ; "Display" or "Query"
  978.             If WindowType = "DISPLAY" Then
  979.                WindowType = "TABLE" ; else "QUERY"
  980.             Endif
  981.          Endif
  982.       Endif
  983.       If WindowType <> "" Then
  984.          Return WindowType
  985.       Else
  986.          WorkspaceHandle = ImageHandle
  987.       Endif
  988.    Else
  989.       WorkspaceHandle = 0
  990.    Endif
  991.    ;-------------------------------------------------------------------------
  992.    ; Now the search can continue, but only up to and not including any
  993.    ; active form or image, so as not to disturb the workspace, so first
  994.    ; identify the window group within which further searches can be made,
  995.    ; up to but not including any form or image...
  996.    ;-------------------------------------------------------------------------
  997.    If IsWindow(WorkspaceHandle) Then
  998.       Found = False
  999.       Window List To WindowTemp
  1000.       For WindowPtr From 1 To ArraySize(WindowTemp)
  1001.          If WindowTemp[WindowPtr] = WorkspaceHandle Then
  1002.             Quitloop
  1003.          Endif
  1004.          If Not found then
  1005.             Found = (WindowTemp[WindowPtr] = WindowHandle)
  1006.          Endif
  1007.       EndFor
  1008.       If Not Found then ; give up
  1009.          Return ""
  1010.       Endif
  1011.       Array WindowList[WindowPtr - 1]
  1012.       For i From 1 To WindowPtr - 1
  1013.          WindowList[i] = WindowTemp[i]
  1014.       EndFor
  1015.    Else
  1016.       Found = False
  1017.       Window List To WindowList
  1018.       For WindowPtr From 1 To ArraySize(WindowList)
  1019.          If WindowList[WindowPtr] = WorkspaceHandle Then
  1020.             Quitloop
  1021.          Endif
  1022.          If Not found then
  1023.             Found = WindowList[i] = WindowHandle
  1024.          Endif
  1025.       EndFor
  1026.       If Not Found Then ; give up
  1027.          Return ""
  1028.       Endif
  1029.    Endif
  1030.    ;-------------------------------------------------------------------------
  1031.    ; See if an editor is visible, and if so get its window handle to
  1032.    ; EditorHandle
  1033.    ;-------------------------------------------------------------------------
  1034.    IsEditor = (IsFieldView() and Substr(FieldType(),1,1) = "M")
  1035.    or SysMode() = "File Editor" or SysMode() = "Script"
  1036.    If IsEditor Then
  1037.       Switch
  1038.          Case Sysmode() = "File Editor":
  1039.             WindowType = "FILE_EDITOR"
  1040.          Case Sysmode() = "Script":
  1041.             WindowType = "SCRIPT"
  1042.          Otherwise:
  1043.             WindowType = "MEMO"
  1044.       EndSwitch
  1045.       ;-----------------------------------------------------------------------
  1046.       ; Now determine what the editor window handle is (the first non-floating
  1047.       ; window) and determine if the requested window appears in the z-order
  1048.       ; as the editor window, or as a window above the editor window. If the
  1049.       ; requested window is the editor , then the type has been successfully
  1050.       ; found.
  1051.       ;-----------------------------------------------------------------------
  1052.       Found = False
  1053.       For WindowPtr From 1 to ArraySize(WindowList)
  1054.          Window GetAttributes WindowList[WindowPtr] To WindowBag
  1055.          If Not Found Then
  1056.             Found = (WindowHandle = WindowList[WindowPtr])
  1057.          Endif
  1058.          If Not WindowBag["Floating"] Then
  1059.             EditorHandle = WindowList[WindowPtr] ; this is a deterministic find
  1060.             Quitloop
  1061.          Endif
  1062.       EndFor
  1063.       If Not (Found And EditorHandle = WindowHandle) Then
  1064.          WindowType = "" ; window is behind current editor
  1065.       Endif
  1066.    Endif
  1067.    ;--------------------------------------------------------------------------
  1068.    ; If the type has not been successfully found, then keep looking, this time
  1069.    ; more aggressively by moving to the window in question...
  1070.    ;--------------------------------------------------------------------------
  1071.    If WindowType = "" Then
  1072.       CurrentWindow = GetWindow()
  1073.       Window Select WindowHandle
  1074.       ;------------------------------------------------------------------------
  1075.       ; Test for one of paradox's modal windows, or editor window ...
  1076.       ;------------------------------------------------------------------------
  1077.       SysmodeType = Upper(Sysmode())
  1078.       If IsFieldView() And Substr(FieldType(),1,1) = "M" Then
  1079.          SysmodeType = "MEMO"
  1080.       Endif
  1081.       If SysmodeType <> "MAIN" And
  1082.          SysmodeType <> "EDIT" And
  1083.          SysmodeType <> "COEDIT" And
  1084.          SysmodeType <> "DATAENTRY" And
  1085.          SysmodeType <> "MULTIENTRY" Then
  1086.          WindowType = SysmodeType ; CREATE, GRAPH, PASSWORD, RESTRUCTURE,
  1087.                                   ; INDEX, SORT, REPORT, FORM, SCRIPT,
  1088.                                   ; FILE EDITOR, MEMO
  1089.          Window GetAttributes WindowHandle To WindowBag
  1090.          If Not WindowBag["Floating"] Then ; should always evaluate to true!
  1091.             WindowBag["Floating"] = True
  1092.             Window SetAttributes WindowHandle From WindowBag
  1093.             Window GetAttributes WindowHandle To WindowBag
  1094.             If WindowBag["Floating"] Then
  1095.                WindowType = "CANVAS"
  1096.                WindowBag["Floating"] = False
  1097.                Window SetAttributes WindowHandle From WindowBag
  1098.             Endif
  1099.          Else
  1100.             Debug ; unexpected floating window find...
  1101.          Endif
  1102.       Else
  1103.          WindowType = "CANVAS"
  1104.       Endif
  1105.       ;------------------------------------------------------
  1106.       ; Return windows to original order...
  1107.       ;------------------------------------------------------
  1108.       For i From ArraySize(WindowList) to 1 Step -1
  1109.          Window Select WindowList[i]
  1110.       EndFor
  1111.       Window Select CurrentWindow
  1112.       If WindowType = "FORM" or WindowType = "REPORT" Then
  1113.          WindowType = WindowType + "DESIGN"
  1114.       Endif
  1115.       If WindowType = "FILE EDITOR" Then
  1116.          WindowType = "FILE_EDITOR"
  1117.       Endif
  1118.    Endif
  1119.    Return WindowType
  1120. EndProc ; EventMan.GetWindowType
  1121.  
  1122. ;============================================================================
  1123. ;                         MAINLINE
  1124. ;============================================================================
  1125. If Not IsAssigned(Librarian.HasControl) Then
  1126.    EventMan.Constructor()
  1127.    SetCanvas Default
  1128.    Echo Normal
  1129.    EventMan.DoGetEvent()
  1130.    EventMan.Destructor()
  1131. Endif