Paste from Pushbutton

This request came from Omnis Developer and SmartList member Rémy Larochelle. He wrote:

Under Omnis7, there was a hash variable #EFLD which stores the identity of the current field. I don’t see it in Omnis Studio
I would like to do something like:

On evClick
  Calculate MYCURRENTFIELDNAME as #EFLD
  Test for window open {L_CODE_TEXTE}
  If flag false
    Open window instance L_CODE_TEXTE/CEN (0,DONO) ; Enterdata mode; user double click on a list, and the window is closed
  Else
    Do $iwindows.L_CODE_TEXTE.$bringtofront()
  End If
  Queue set current field { MYCURRENTFIELDNAME }
  Queue keyboard event {ctrl-V}

As you see, I want to paste a value at the insertionpoint. It works but the value is not pasted in the good field.

Solution

I didn't carry out this entire scenario. Rather, I focused on the problem of using an event handling method in a pushbutton to perform a paste in an Entry field. This is tricky because the action of clicking on the Pushbutton field removes the focus (along with the selection point) out of the Entry field. All the "usual" pointers to the current item ($cfield, $cobj and $ctarget) point to the Pushbutton field during its event cycle. So what to do?

My first suggestion was to define an instance variable (or a variable of whatever is the most reasonable scope) of Character type to contain the name of the most recently entered Entry field. We can do this for all Entry fields on a window instance by putting our code in the window's $control method (and not trapping evBefore at the field level - or at least allowing the evBefore event to "float" up to the window's $control method). The code looks like this:

On evBefore
  If $cobj.$objtype=kEntry
    Calculate currentEntryField as $cobj().$name
  End If

If we want to extend this to Masked Entry and Multiline Entry fields we can add those conditions to the If... statement. But this is only the first part of the solution. We also need to keep track of the insertion point or text selection within that field and re-establish it. This requires two more variables: currFirstSel and currLastSel. The values for these need to be set just as the focus leaves the field, but only if an event that might be the pushbutton click that does the paste is the event that triggered the evAfter. (Got that?)

This event will be an evMouseDown - even if mouse event detection is not switched on. So in the $control method of the window (or in the $event method of each entry field if you want), we would place the following code:

On evAfter
  If pNextCode=evMouseDown&$cobj.$objtype=kEntry
    Calculate currFirstSel as $cobj.$firstsel
    Calculate currLastSel as $cobj.$lastsel
  End If

This only changes the values of these variables if the evAfter event happens to an Entry field and is triggered by an evMouseDown somewhere. Perhaps this could be further refined, but it gets the job done!

Now all we have to do is determine how to get the focus back into that field and re-establish the text selection or insertion point. It's really too simple:

On evClick
  Queue click {[currentEntryField] (currFirstSel,currLastSel)}
  Queue keyboard event {com-v}

The Queue click command has a side effect of putting the focus back into the field mentioned in its parameters, so it is not necessary to also include a Queue set current field command. We need to use square bracket notation to specify the name of the field from the variable currentEntryField because the name is contained in that variable and it has to be evaluated. This command expects to see a string, so square bracket notation is how we get to the value inside the variable.

We use the most general form of this command's parameters, establishing both the $firstsel and $lastsel values. If they are equal (indicating an insertion point rather than a text selection), then an insertion point will be established and none of the existing text will be replaced by the paste.

The example library for this explanation also demonstrates a few more "paste" techniques. I hope you find this useful. You might want to consider obtaining my "Omnis Reference Library" book series. The support I receive from that project helps fund explanations like this one.