=== modified file 'src/com/goldencode/p2j/ui/EventDefinition.java'
--- old/src/com/goldencode/p2j/ui/EventDefinition.java	2022-10-11 14:53:34 +0000
+++ new/src/com/goldencode/p2j/ui/EventDefinition.java	2022-11-15 10:30:19 +0000
@@ -65,6 +65,7 @@
 **     SBI 20211024          Added containsWidget(int) method.
 **     ME  20220928          Rewrite trigger lookup, move some of the logic in EventList.
 **         20221003          Remove 'global anywhere' (derived), use scope self/anywhere on lookup.
+**         20221026          Check function key code in isEventUniversal in case label key code was used.
 **/
 
 /*
@@ -439,6 +440,12 @@
                            eventCode == Keyboard.KA_END_ERROR ||
                            eventCode == Keyboard.KA_STOP);
       
+      if (!universal) {
+         eventCode = Keyboard.eventCode(Keyboard.keyFunction(eventCode));
+         
+         return eventCode != -1 && isEventUniversal(eventCode);
+      }
+      
       return universal;
    }
 

=== modified file 'src/com/goldencode/p2j/ui/EventList.java'
--- old/src/com/goldencode/p2j/ui/EventList.java	2022-10-17 08:50:36 +0000
+++ new/src/com/goldencode/p2j/ui/EventList.java	2022-11-15 10:30:19 +0000
@@ -169,6 +169,7 @@
 **         20221003          Build events bitmap and resolve function key code in lookupWorker, avoid looping 
 **                           through widget's parents chain if there is no event registered for the code.
 **     HC  20221017          Fixed ANYWHERE event lookup.
+**     ME  20221026          Fixed addEvent/ctors in respect to ANYWHERE default.
 */
 
 /*
@@ -616,7 +617,7 @@
    }
    
    /**
-    * Constructor that adds the given event definition.
+    * Constructor that adds the given event definition - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
@@ -625,26 +626,27 @@
     */
    public EventList(String[] event)
    {
-      addEvent(event, (GenericWidget[])null, false);
+      addEvent(event, (GenericWidget[])null, true);
    }
 
    /**
-    * Constructor that adds the given event definition.
+    * Constructor that adds the given event definition - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
     * @param    event
     *           An array of event names.
     * @param    anywhere
-    *           <code>true</code> if the global ANYWHERE option is being set.
+    *           ignored since all non-widget events are global ANYWHERE.
     */
+   @Deprecated
    public EventList(String[] event, boolean anywhere)
    {
-      addEvent(event, (GenericWidget[])null, false);
+      addEvent(event, (GenericWidget[])null, true);
    }
 
    /**
-    * Constructor that adds the given event definition.
+    * Constructor that adds the given event definition - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
@@ -653,23 +655,23 @@
     */
    public EventList(String event)
    {
-      addEvent(new String[] {event}, (GenericWidget[])null, false);
+      addEvent(event, (GenericWidget[])null, true);
    }
 
    /**
-    * Constructor that adds the given event definition. If the ANYWHERE keyword was used, the
-    * appropriate flag is set for this entry.
+    * Constructor that adds the given event definition - global anywhere.
     * <p>
     * Event names are case-insensitive on input and stored uppercased.
     *
     * @param    event
     *           The event name.
     * @param    anywhere
-    *           <code>true</code> if the global ANYWHERE option is being set.
+    *           ignored since all non-widget events are global ANYWHERE.
     */
+   @Deprecated
    public EventList(String event, boolean anywhere)
    {
-      addEvent(new String[] {event}, (GenericWidget[])null, anywhere);
+      addEvent(new String[] {event}, (GenericWidget[])null, true);
    }
 
    /**
@@ -1118,7 +1120,7 @@
    }
    
    /**
-    * Adds an event definition to the list.
+    * Adds an event definition to the list - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
@@ -1127,26 +1129,27 @@
     */
    public void addEvent(String[] event)
    {
-      addEvent(event, (GenericWidget[])null, false);
+      addEvent(event, (GenericWidget[])null, true);
    }
 
    /**
-    * Adds an event definition to the list.
+    * Adds an event definition to the list - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
     * @param    event
     *           An array of event names.
     * @param    anywhere
-    *           <code>true</code> if the global ANYWHERE option is being set.
+    *           ignored since all non-widget events are global ANYWHERE.
     */
+   @Deprecated
    public void addEvent(String[] event, boolean anywhere)
    {
-      addEvent(event, (GenericWidget[])null, false);
+      addEvent(event, (GenericWidget[])null, true);
    }
 
    /**
-    * Adds an event definition to the list.
+    * Adds an event definition to the list - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
@@ -1155,22 +1158,23 @@
     */
    public void addEvent(String event)
    {
-      addEvent(new String[] {event}, (GenericWidget[])null, false);
+      addEvent(new String[] {event}, (GenericWidget[])null, true);
    }
 
    /**
-    * Adds an event definition to the list.
+    * Adds an event definition to the list - global anywhere.
     * <p> 
     * Event names are case-insensitive on input and stored uppercased.
     *
     * @param    event
     *           The event name.
     * @param    anywhere
-    *           <code>true</code> if the global ANYWHERE option is being set.
+    *           ignored since all non-widget events are global ANYWHERE.
     */
+   @Deprecated
    public void addEvent(String event, boolean anywhere)
    {
-      addEvent(new String[] {event}, (GenericWidget[])null, anywhere);
+      addEvent(new String[] {event}, (GenericWidget[])null, true);
    }
 
    /**

=== modified file 'src/com/goldencode/p2j/ui/LogicalTerminal.java'
--- old/src/com/goldencode/p2j/ui/LogicalTerminal.java	2022-11-09 22:48:45 +0000
+++ new/src/com/goldencode/p2j/ui/LogicalTerminal.java	2022-11-15 10:32:10 +0000
@@ -1014,6 +1014,7 @@
 **     EVL 20221007          Adding runtime support for SESSION:LOAD-ICON.
 **     TJD 20220504          Java 11 compatibility related minor changes
 **     SBI 20221110          Added getSupportedHelperApplications().
+**     ME  20221110          Avoid NPE on client when invalid code used in apply.
 */
 
 /*
@@ -7981,6 +7982,12 @@
          return;
       }
 
+      if (eventCode == -1)
+      {
+         // not valid event code, it will throw error on the client
+         return;
+      }
+      
       ScreenBuffer sb[] = null;
       
       LogicalTerminal lt = locate();

=== modified file 'src/com/goldencode/p2j/ui/chui/ThinClient.java'
--- old/src/com/goldencode/p2j/ui/chui/ThinClient.java	2022-11-09 22:48:45 +0000
+++ new/src/com/goldencode/p2j/ui/chui/ThinClient.java	2022-11-15 10:30:54 +0000
@@ -20493,7 +20493,7 @@
          cur = src;
       }
 
-      boolean defaultHelp = true;
+      boolean defaultHelp = action == Keyboard.KA_HELP;
       boolean foundGo = false;
       boolean exceptionalExit = false;
 
@@ -20624,16 +20624,10 @@
          tr = invokeTriggers(src, key, evt.isRealKey());
 
          if (tr.executed)
-         {
+         {  
             evt.setTriggerFired();
-            
-            // if trigger was set for a key that maps to endkey/end-error (ESC) 
-            // consume it and do not handle it like stop
-            if (exceptionalExit)
-            {
-               evt.consume();
-               return;
-            }
+            // reset default help behavior if trigger registered
+            defaultHelp = false;
          }
 
          if (tr.consume)
@@ -20650,93 +20644,42 @@
       }
 
       // other high level events
-      if ((tr == null || !tr.executed) && key != action &&
-          action != Keyboard.SE_ENTRY)
+      if ((tr == null || !tr.consume))
       {
-         Widget target = src;
-         Browse brws = (Browse) src.parent(Browse.class);
-         
-         tr = invokeTriggers(target, event.other(), action, false);
-
-         if (tr.executed)
-         {
-            evt.setTriggerFired();
-         }
-
-         if (action == Keyboard.KA_HELP)
-         {
-            // if there was no widget-level trigger, try the frame
-            // TODO: this needs to be more generic because surely there are
-            //       other events that bubble
-            if (!tr.executed && !(target instanceof Frame))
-            {
-               if (brws != null && target != brws)
-               {
-                  // in this case, try the browse too
-                  tr = invokeTriggers(brws, event.other(), action, false);
-               }
-               
-               if (!tr.executed)
-               {
-                  // TODO: check if child frames/parent frame bubbling works
-                  // TODO: check if the window needs to be supported
-                  Widget<?> frm = UiUtils.locateFrame(target);
-                  
-                  if (frm != null)
-                  {
-                     tr = invokeTriggers(frm, event.other(), action, false);
-                  }
-               }
-            }
-            
-            if (tr.executed)
-            {
-               // execution of a HELP trigger is implicitly RETURN NO-APPLY
-               tr.consume = true;
-               defaultHelp = false;
+         // universal events slip into parent frame only unless consumed
+         if (EventDefinition.isEventUniversal(key))
+         {
+            Widget<?> srcFrame = UiUtils.locateFrame(src);
+
+            if (srcFrame != null)
+            {
+               // use specificWidget as it doesn't need to go up the parents chain
+               tr = invokeTriggers(srcFrame, null, -1, key, true, true, null, null);
             }
          }
 
          // let widget perform "hard" check if necessary
-         if (action == Keyboard.SE_LEAVE && src instanceof FillIn)
+         if (key != action && action == Keyboard.SE_LEAVE && src instanceof FillIn)
          {
             src.processKeyEvent(evt);
 
-            if (evt.isConsumed())
+            if (tr != null && evt.isConsumed())
                tr.consume = true;
          }
 
-         if (tr.consume)
-         {
-            evt.consume();
-
-            if (foundGo)
-            {
-               subGoPending();
-               leaveSent = false;
-            }
-            return;
-         }
-      }
-
-      // check for possible ANY-KEY
-      if ((tr == null || !tr.executed) && evt != null && evt.isRealKey() && evt.id() != EventType.KEY_RELEASED)
-      {
-         tr = invokeTriggers(src, key, true);
-
-         if (tr.consume)
-         {
-            evt.consume();
-
-            if (foundGo)
-            {
-               subGoPending();
-               leaveSent = false;
-            }
-            return;
-         }
-      }
-
+         if (tr != null && tr.consume)
+         {
+            evt.consume();
+
+            if (foundGo)
+            {
+               subGoPending();
+               leaveSent = false;
+            }
+            return;
+         }
+      }
+      
       // disable all following logic if this is a drop-down portion of a
       // combo-box
       if (src instanceof ScrollableList)
@@ -21225,7 +21168,7 @@
       // a standard input key (A, B, and so on)
 
       // HELP action
-      if (isGoPending == 0 && action == Keyboard.KA_HELP && defaultHelp)
+      if (isGoPending == 0 && defaultHelp)
       {
          requestHelp();
       }
@@ -21590,6 +21533,56 @@
                                         Integer   eventX,
                                         Integer   eventY)
    {
+      return invokeTriggers(widget, other, resourceId, evtCode, isKey, false, eventX, eventY);
+   }
+   
+   /**
+    * Check active <code>EventList</code> instance for triggers defined
+    * for this event and widget pair and activate the first one found.
+    * <p>
+    * Triggers are searched either for a specific widget, or, if no widget is
+    * enabled (in focus), for the session window. The latter is also performed
+    * if the specific widget happens to be the session window.
+    * <p>
+    * The specific search is done in the following order:
+    * <ul>
+    *  <li>trigger for the specified widget and event;
+    *  <li>trigger for the specified event anywhere within the frame;
+    *  <li>trigger for the specified event anywhere globally.
+    * </ul>
+    * <p>
+    * The search for the session window is a one step process.
+    * <p>
+    * The first found trigger, if any, gets activated.
+    *
+    * @param   widget
+    *          event source.
+    * @param   other
+    *          a companion widget (for ENTER/LEAVE events).
+    * @param   resourceId
+    *          When not set to -1, is a valid resource ID (for non-widget events).
+    * @param   evtCode
+    *          event code.
+    * @param   isKey
+    *          This flags marks reals keys typed by user.
+    * @param   specificWidget
+    *          This flags checks only for the triggers on specific widget.
+    * @param   eventX
+    *          The value of LAST-EVENT:X attribute; <code>null</code> if not used.
+    * @param   eventY
+    *          The value of LAST-EVENT:Y attribute; <code>null</code> if not used.
+    *
+    * @return  Execution and event consume flags for an executed trigger.
+    */
+   private TriggerResult invokeTriggers(Widget    widget,
+                                        Widget    other,
+                                        long      resourceId,
+                                        int       evtCode,
+                                        boolean   isKey,
+                                        boolean   specificWidget,
+                                        Integer   eventX,
+                                        Integer   eventY)
+   {
       // this method must not be called for mouse events on virtual widgets; for key presses, 
       // this is allowed because ANY-KEY triggers need to be reached.
 
@@ -21653,7 +21646,7 @@
       {
          Widget container = UiUtils.locateContainer(widget);
          
-         currentEventList.lookup(container != null && container != frame ? UiUtils.getWidgetIdAsInt(container) : frameId, widgetId, true, isKey, result);
+         currentEventList.lookup(container != null && container != frame ? UiUtils.getWidgetIdAsInt(container) : frameId, widgetId, true, isKey, specificWidget, result);
       }
 
       // activate trigger

