Category Archives: LiveCode Desktop

Command prompt blocking policies and the shell function

This week I had a report of an application locking up while executing the shell function. Actually it was executing shell(“ipconfig /all”) in my modification of Ken Ray’s GetMACAddress function to return the machine’s LAN ip.

System administrators tend to like to turn things off so normal human beings can’t make a mess of their nice machines. One thing they can do is set a Windows registry entry to disable cmd.exe for the user. So by checking HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\DisableCMD”=dword:1 we can find out if cmd.exe is disabled for the current user. What this does is when cmd.exe is run it opens the console but all you get is a blocked by admin message and no command prompt. If Bill would just change this so it stopped cmd.exe from launching at all then we wouldn’t have such a problem. LiveCode is therefore able to run cmd.exe and just sits there waiting for it to terminate but it never does.

So I wrote a safer shell function to check for this situation and also possible execution errors from hash rules and renaming of cmd.exe etc. If the registry setting is there it will attempt to execute the command directly using process commands rather than via shell.

<span class="storage storage_type storage_type_handler storage_type_handler_rev">function</span><span> safeShell pCommand</span>
<span>   </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- assume the shellCommand has been set appropriately</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">hideConsoleWindows</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="keyword keyword_control keyword_control_rev">true</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">itemDel</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"\"</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">-</span><span class="constant constant_numeric constant_numeric_rev">1</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">shellCommand</span><span> </span><span class="keyword keyword_control keyword_control_rev">is</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"cmd.exe"</span><span> </span><span class="keyword keyword_control keyword_control_rev">AND</span><span> \ </span>
<span>          </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">charToNum</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="entity entity_name entity_name_handler entity_name_handler_rev">queryRegistry</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\DisableCMD"</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">))</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span> </span><span class="constant constant_numeric constant_numeric_rev">1</span><span> then</span>
<span>      </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- don't use cmd.exe because shell() won't return</span>
<span>      </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- don't revert to command.com because there seems to be a problem in the engine</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">return</span><span> executeProcess</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pCommand</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">else</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">try</span>
<span>         </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- still check for empty if your are expecting a result</span>
<span>         </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- because there's no execution error on os x</span>
<span>         </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">return</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">shell</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pCommand</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">catch</span><span> e</span>
<span>         </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- execution error on windows shellCommand doesn't exist</span>
<span>         </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- hopefully this catches hash rule blocks</span>
<span>         </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">return</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"Error executing command"</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">try</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> safeShell</span>


<span class="storage storage_type storage_type_handler storage_type_handler_rev">function</span><span> executeProcess pProcess</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>pElevate</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">local</span><span> tReturn</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">if</span><span> pElevate then</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">open</span><span> </span><span class="keyword keyword_control keyword_control_rev">elevated</span><span> </span><span class="keyword keyword_control keyword_control_rev">process</span><span> pProcess </span><span class="keyword keyword_control keyword_control_rev">for</span><span> </span><span class="support support_command support_command_rev">text</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">read</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">else</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">open</span><span> </span><span class="keyword keyword_control keyword_control_rev">process</span><span> pProcess </span><span class="keyword keyword_control keyword_control_rev">for</span><span> </span><span class="support support_command support_command_rev">text</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">read</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">repeat</span><span> </span><span class="keyword keyword_control keyword_control_rev">forever</span>
<span>      </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev"># Loop until there are no more lines to read.</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">read</span><span> </span><span class="keyword keyword_control keyword_control_rev">from</span><span> </span><span class="keyword keyword_control keyword_control_rev">process</span><span> pProcess </span><span class="keyword keyword_control keyword_control_rev">for</span><span> </span><span class="constant constant_numeric constant_numeric_rev">1</span><span> </span><span class="keyword keyword_control keyword_control_rev">line</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">result</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">""</span><span> </span><span class="keyword keyword_control keyword_control_rev">or</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">result</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"timed out"</span><span> then</span>
<span>         </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- something to add</span>
<span>         </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> it </span><span class="keyword keyword_control keyword_control_rev">after</span><span> tReturn</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">else</span>
<span>         </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">close</span><span> </span><span class="keyword keyword_control keyword_control_rev">process</span><span> pProcess</span>
<span>         </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">return</span><span> tReturn</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">repeat</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> executeProcess</span>

LiveCode DataGrid Drag & Drop Reordering

I have a project where using a data grid form really simplifies things, however, it’s critical that the user can re-order the list in arbitrary way. To do this I needed to add drag and drop to the data grid.

First I wrote rolled my own:

There two main limitations with this code are that it will only work for a data grid form (not table) and only if the cache controls property is true.

<span class="entity entity_name entity_name_handler entity_name_handler_rev">local</span><span> sDragImage</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>sControlIndexMap</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>sOriginalIndexes</span>

<span class="storage storage_type storage_type_handler storage_type_handler_rev">on</span><span> dragStart</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">local</span><span> tControl</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tItem</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragData</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"private"</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgDragIndex"</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">&&</span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgHilitedIndex </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgDataControlOfIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgHilitedIndex </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tControl</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">lock</span><span> </span><span class="support support_command support_command_rev">screen</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">import</span><span> </span><span class="keyword keyword_control keyword_control_rev">snapshot</span><span> </span><span class="keyword keyword_control keyword_control_rev">from</span><span> tControl</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">long</span><span> </span><span class="support support_command support_command_rev">id</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="keyword keyword_control keyword_control_rev">last</span><span> </span><span class="keyword keyword_control keyword_control_rev">image</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> sDragImage</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">visible</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> sDragImage </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="keyword keyword_control keyword_control_rev">false</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragImage</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">short</span><span> </span><span class="support support_command support_command_rev">id</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> sDragImage</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgIndexes </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> sOriginalIndexes</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">delete</span><span> </span><span class="keyword keyword_control keyword_control_rev">variable</span><span> sControlIndexMap</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">repeat</span><span> </span><span class="keyword keyword_control keyword_control_rev">for</span><span> </span><span class="keyword keyword_control keyword_control_rev">each</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> tItem </span><span class="keyword keyword_control keyword_control_rev">in</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgIndexes </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> tItem </span><span class="keyword keyword_control keyword_control_rev">into</span><span> sControlIndexMap</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgDataControlOfIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span>tItem</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">repeat</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">allowableDragActions</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"move"</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">pass</span><span> dragStart</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> dragStart</span>

<span class="storage storage_type storage_type_handler storage_type_handler_rev">on</span><span> dragMove pX</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>pY</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">local</span><span> tDragIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tNewIndexes</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tOverIndex</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_control keyword_control_rev">word</span><span> </span><span class="constant constant_numeric constant_numeric_rev">1</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragData</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"private"</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgDragIndex"</span><span> then</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">unlock</span><span> </span><span class="support support_command support_command_rev">screen</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">lock</span><span> </span><span class="support support_command support_command_rev">cursor</span><span> </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- refresh bug workaround on setting the dgIndexes the dragAction seems to get set to none</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="keyword keyword_control keyword_control_rev">word</span><span> </span><span class="constant constant_numeric constant_numeric_rev">2</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragData</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"private"</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tDragIndex</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragAction</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"move"</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">if</span><span> pY </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">></span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">bottom</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">-</span><span class="constant constant_numeric constant_numeric_rev">20</span><span> then</span>
<span>         </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="constant constant_numeric constant_numeric_rev">2</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgVisibleLines </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev"><</span><span>  </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgNumberOfLines </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">or</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">scroll</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">is</span><span> </span><span class="keyword keyword_control keyword_control_rev">not</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgFormattedHeight </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> then </span>
<span>            </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgVscroll </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">min</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgVscroll </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">+</span><span> </span><span class="constant constant_numeric constant_numeric_rev">20</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgFormattedHeight </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span>
<span>         </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">else</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span><span>  pY </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev"><</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">top</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">+</span><span class="constant constant_numeric constant_numeric_rev">20</span><span> then</span>
<span>         </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="constant constant_numeric constant_numeric_rev">1</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgVisibleLines </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">></span><span>  </span><span class="constant constant_numeric constant_numeric_rev">1</span><span> </span><span class="keyword keyword_control keyword_control_rev">or</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">scroll</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">is</span><span> </span><span class="keyword keyword_control keyword_control_rev">not</span><span> </span><span class="constant constant_numeric constant_numeric_rev">0</span><span> then </span>
<span>            </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgVscroll </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">max</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgVscroll </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">-</span><span> </span><span class="constant constant_numeric constant_numeric_rev">20</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span class="constant constant_numeric constant_numeric_rev">0</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span>
<span>         </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">repeat</span><span> </span><span class="keyword keyword_control keyword_control_rev">with</span><span> X</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span class="constant constant_numeric constant_numeric_rev">1</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">number</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">groups</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span>
<span>         </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">visible</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">and</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">short</span><span> </span><span class="support support_command support_command_rev">name</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">owner</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">is</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> then</span>
<span>            </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pY </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">>=</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">top</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">and</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pY </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev"><</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">top</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">+(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">bottom</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">-</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">top</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">div</span><span> </span><span class="constant constant_numeric constant_numeric_rev">2</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">))</span><span> then</span>
<span>               </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- place above index</span>
<span>               </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> sControlIndexMap</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">long</span><span> </span><span class="support support_command support_command_rev">id</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tOverIndex</span>
<span>               </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">--put "over"&&tOverIndex</span>
<span>               </span><span class="keyword keyword_control keyword_control_rev">if</span><span> tDragIndex </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span> tOverIndex then </span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> sOriginalIndexes </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tNewIndexes</span>
<span>               </span><span class="keyword keyword_control keyword_control_rev">else</span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> sOriginalIndexes </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tNewIndexes</span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">delete</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">itemOffset</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>tDragIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tNewIndexes</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> tNewIndexes</span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> tDragIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">&</span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">","</span><span> </span><span class="keyword keyword_control keyword_control_rev">before</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">itemOffset</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>tOverIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tNewIndexes</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> tNewIndexes</span>
<span>               </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>               </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgIndexes </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> tNewIndexes</span>
<span>               </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> tNewIndexes </span><span class="keyword keyword_control keyword_control_rev">into</span><span> sOriginalIndexes</span>
<span>            </span><span class="keyword keyword_control keyword_control_rev">else</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pY </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev"><=</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">bottom</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">and</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pY </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">></span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">top</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">+(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">bottom</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">-</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">top</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">div</span><span> </span><span class="constant constant_numeric constant_numeric_rev">2</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">))</span><span> then</span>
<span>               </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- place below index</span>
<span>               </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> sControlIndexMap</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">long</span><span> </span><span class="support support_command support_command_rev">id</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> X </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">group</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"dgList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tOverIndex</span>
<span>               </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">--put "over"&&tOverIndex</span>
<span>               </span><span class="keyword keyword_control keyword_control_rev">if</span><span> tDragIndex </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">=</span><span> tOverIndex then </span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> sOriginalIndexes </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tNewIndexes</span>
<span>               </span><span class="keyword keyword_control keyword_control_rev">else</span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> sOriginalIndexes </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tNewIndexes</span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">delete</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">itemOffset</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>tDragIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tNewIndexes</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> tNewIndexes</span>
<span>                  </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">","</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">&</span><span>tDragIndex </span><span class="keyword keyword_control keyword_control_rev">after</span><span> </span><span class="keyword keyword_control keyword_control_rev">item</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">itemOffset</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>tOverIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span>tNewIndexes</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> tNewIndexes</span>
<span>               </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>               </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgIndexes </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> tNewIndexes</span>
<span>               </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> tNewIndexes </span><span class="keyword keyword_control keyword_control_rev">into</span><span> sOriginalIndexes</span>
<span>            </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>         </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>      </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">repeat</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">pass</span><span> dragMove</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> dragMove</span>

<span class="storage storage_type storage_type_handler storage_type_handler_rev">on</span><span> dragEnd</span>
<span>   </span><span class="comment comment_line comment_line_number-sign comment_line_number-sign_rev">-- clean up</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">if</span><span> sDragImage </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev"><></span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">""</span><span> then</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">delete</span><span> sDragImage</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">""</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> sDragImage</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">pass</span><span> dragEnd</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> dragEnd</span>

Then I had a poke around the data grid behavior script and found undocumented support for drag and drop. So here’s the new script that does not have the limitations of the above and is obviously far less verbose:

<span class="storage storage_type storage_type_handler storage_type_handler_rev">on</span><span> dragStart</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">local</span><span> tIndex</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgHeader </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">target</span><span> </span><span class="keyword keyword_control keyword_control_rev">is</span><span> </span><span class="keyword keyword_control keyword_control_rev">empty</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> then</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">put</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgIndex </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgDataControl </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">target</span><span> </span><span class="keyword keyword_control keyword_control_rev">into</span><span> tIndex</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgDragImageIndex </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> tIndex</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragData</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"private"</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="keyword keyword_control keyword_control_rev">empty</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> dgTrackDragReorder</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">[</span><span>tIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">]</span><span> </span><span class="keyword keyword_control keyword_control_rev">of</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="keyword keyword_control keyword_control_rev">true</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> dragStart</span>

<span class="storage storage_type storage_type_handler storage_type_handler_rev">on</span><span> DragReorderDrop pOriginatingIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span> pStartLine</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span> pDroppedOnLine</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">if</span><span> </span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">(</span><span>pStartLine </span><span class="keyword keyword_control keyword_control_rev">is</span><span> </span><span class="keyword keyword_control keyword_control_rev">not</span><span> pDroppedOnLine</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">)</span><span> then</span>
<span>      SetLineOfIndex pOriginatingIndex</span><span class="keyword keyword_operator keyword_operator_symbolic keyword_operator_symbolic_rev">,</span><span> pDroppedOnLine</span>
<span>      </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">send</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"RefreshList"</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">me</span><span> </span><span class="keyword keyword_control keyword_control_rev">in</span><span> </span><span class="constant constant_numeric constant_numeric_rev">0</span><span> </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">secs</span>
<span>   </span><span class="keyword keyword_control keyword_control_rev">end</span><span> </span><span class="keyword keyword_control keyword_control_rev">if</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> DragReorderDrop</span>

<span class="storage storage_type storage_type_handler storage_type_handler_rev">on</span><span> dragMove</span>
<span>   </span><span class="entity entity_name entity_name_handler entity_name_handler_rev">set</span><span> </span><span class="keyword keyword_control keyword_control_rev">the</span><span> </span><span class="support support_command support_command_rev">dragaction</span><span> </span><span class="keyword keyword_control keyword_control_rev">to</span><span> </span><span class="string string_quoted string_quoted_double string_quoted_double_transcript">"move"</span>
<span class="keyword keyword_control keyword_control_rev">end</span><span> dragMove</span>

revObjective 1.1 released!

A new behavior script and custom control manager plugin for Revolution.

Features include:

  • Adds an object placing menu button to the tools palette for both revObjective and standard Revolution object libraries.
  • Add, Delete, Clone, Place, Edit Script, Edit Controls, Name, Describe, Author, Version your custom controls.
  • Drag and drop objects onto your stacks from the object list.
  • Drag and drop revObjective files to and from the object list to share.
  • Searches stacks during standalone building and finds revObjective behaviors and copies over the behavior scripts in a way that is not file path dependant.
  • Packaged with revObjective are MacOS X Search Field, Integer Field, Decimal Number Field and Placeholder Text Field

[Download not found]

This plugin is donationware. If you decide it fits into your workflow then please consider donating to encourage further development. [mp:id=6]

Create a disabled version of an image

After a correction on my greyscale formula in my last post from Mark on facebook I reviewed the results of my code and decided the disabled look wasn’t quite right. What I wanted was a a washed out looking version. This code and plugin modifies the alphaData of the image to 33% of the original and greys the imageData 15% more. You can modify the constants in the button code if you want different ratios. Here’s the code:

<code>constant kTranslucencyRatio = 0.33
constant kGreyRatio = 0.15

on fadeImage pImageID
   local tAlphaData,tOffset,tWidth,tHeight,tAlpha
   lock screen
   put the width of pImageID into tWidth
   put the height of pImageID onto tHeight
   put the alphaData of pImageID into tAlphaData
   repeat with tOffset = 0 to tWidth *tHeight
      put charToNum(char tOffset of tAlphaData) into tAlpha
      -- handle cases of very low alpha for edge smoothing
      if round(tAlpha*kTranslucencyRatio) > 0 then
         put NumToChar(round(tAlpha*kTranslucencyRatio)) into char tOffset of tAlphaData
      end if
   end repeat
   set the alphaData of pImageID to tAlphaData
end fadeImage

on greyImage pImageID
   local tImageData, tRed, tGreen, tBlue, tGrey, tOffset,tWidth,tHeight
   lock screen
   put the width of pImageID into tWidth
   put the height of pImageID onto tHeight
   put the imageData of pImageID into tImageData
   repeat with tOffset = 0 to tWidth *tHeight * 4 step 4
      put charToNum(char tOffset + 2 of tImageData) into tRed
      put charToNum(char tOffset + 3 of tImageData) into tGreen
      put charToNum(char tOffset + 4 of tImageData) into tBlue
      put (30*tRed+59*tGreen+11*tBlue)/100 into tGrey
      put round(tGrey*kGreyRatio+tRed*(1-kGreyRatio)) into tRed
      put round(tGrey*kGreyRatio+tGreen*(1-kGreyRatio)) into tGreen
      put round(tGrey*kGreyRatio+tBlue*(1-kGreyRatio)) into tBlue
      put NumToChar(tRed) into char tOffset + 2 of tImageData
      put NumToChar(tGreen) into char tOffset + 3 of tImageData
      put NumToChar(tBlue) into char tOffset + 4 of tImageData
   end repeat
   set the imageData of pImageID to tImageData
end greyImage</code>

[dm]10[/dm]

Greyscale an image

Now that I’ve got all my icons into the image library (see my recursive image library creation post) I wanted to limit the number of times I need to go back to an image editor to mess with the original files to create variations. One of the most common variations for button icons is the greyed out disabled icon so I wrote a little rev plugin to greyscale the selected images.

The plugin uses the following command:

<code>on greyscale pImageID
   local tImageData, tRed, tGreen, tBlue, tGrey, tOffset,tWidth,tHeight
   lock screen
   put the width of pImageID into tWidth
   put the height of pImageID onto tHeight
   put the imageData of pImageID into tImageData
   repeat with tOffset = 0 to tWidth *tHeight * 4 step 4
      put charToNum(char tOffset + 2 of tImageData) into tRed
      put charToNum(char tOffset + 3 of tImageData) into tGreen
      put charToNum(char tOffset + 4 of tImageData) into tBlue
      --correction for better greyscale from Mark 
      --put (tRed+tGreen+tBlue) div 3 into tGrey
      put (tRed*30+tGreen*59+tBlue*11) / 100 into tGrey
      put NumToChar(tGrey) into char tOffset + 2 of tImageData
      put NumToChar(tGrey) into char tOffset + 3 of tImageData
      put NumToChar(tGrey) into char tOffset + 4 of tImageData
   end repeat
   set the imageData of pImageID to tImageData
end greyscale</code>

[dm]9[/dm]

revTools mod to add an object library menu

After having a play with the Image Library in Revolution I remembered seeing a cool concept in a screencast from Shao Sean where a button was added in a handy empty spot on the tools palette to pull up a menu for inserting custom objects into stacks. Here I have applied the idea to the Object Library in Revolution.

Shao Sean’s original concept is seen here

The object library menu button in action

[dm]8[/dm]

Recursive Image Library Creation In Revolution

I use an icon collection that is a whole pile (around 2000) of png images stored in a hierarchy of folders (eg Objects and People/48×48/plain/). It has become annoying finding and importing these images one by one into my applications as needed so I wrote a little drag and drop plugin to import images into a stack whenever they are dropped. It works until you have an app your working on that uses drag and drop and then it fails so I thought I’d give the rev image library setup a go. Rather than import images into libraries by hand I decided to slap together a little recursive image library from folder script. Copy the code to a button then click it. The library name is built out of the names of the folders starting with the one you selected.

<code>on mouseUp
   local tLibraryFileA
   answer folder "Choose a folder:"
   if the result is "cancel" then exit mouseUp
   recursiveImageLibrary it,"",tLibraryFileA
   repeat for each line tLine in the keys of tLibraryFileA
      createImageLibrary tLine,tLibraryFileA[tLine]
   end repeat
end mouseUp

on recursiveImageLibrary pFolder,pLibraryName,@pLibraryFileA
   local tOldFolder
   put the defaultFolder into tOldFolder
   set the defaultFolder to pFolder
   set the itemDel to "/"
   if pLibraryName <> "" then put " " after pLibraryName
   put item -1 of pFolder after pLibraryName
   set the itemDel to "."
   repeat for each line tFile in the files
      if item -1 of tFile is among the items of "jpg.png.gif" then
         put pFolder&"/"&tFile&cr after pLibraryFileA[pLibraryName]
      end if
   end repeat
   repeat for each line tFolder in line 2 to -1 of the folders
      recursiveImageLibrary pFolder&"/"&tFolder,pLibraryName,pLibraryFileA
   end repeat
end recursiveImageLibrary

on createImageLibrary pLibraryName,pLibraryFiles
   local tHighID,tList
   -- create the stack
   put 230000 into tHighID
   if char 1 to 6 of pLibraryName is not "revLib" then put "revLib" before pLibraryName
   if there is a stack pLibraryName then
      answer error "A library with the same name ("&pLibraryName&") as this library already exists." with "Cancel"
      exit createImageLibrary
   end if
   put revAbsoluteFolderListing(revEnvironmentUserResourcesPath("Icon Libraries",true)) into tList
   put cr & "revGeneralIcons" & cr & "revCompatibilityIcons1" after tList
   repeat for each line l in tList
      if l is empty or there is not a stack l then next repeat
      if the name of stack l is pLibraryName then
         answer error "That library already exists." with "Cancel"
         exit createImageLibrary
      end if
      put the ID of stack l into item (the number of items in tHighID+1) of tHighID
   end repeat
   if there is a file (pLibraryName & ".rev") then
      answer error "A library with the name" && pLibraryName & ".rev" && "already exists." with "Cancel"
      exit createImageLibrary
   end if
   set the name of the templateStack to pLibraryName
   set the destroyStack of the templateStack to false
   lock messages
   set the style of the templateStack to "modeless"
   create invisible stack
   reset the templateStack
   set the mainStack of stack pLibraryName to pLibraryName
   set the ID of stack pLibraryName to (max(tHighID)+1)
   set the fileName of stack pLibraryName to revEnvironmentUserResourcesPath("Icon Libraries") & "/" & pLibraryName & ".rev"
   set the defaultStack to pLibraryName -- just to make sure
   -- now import all the images
   repeat for each line tImage in pLibraryFiles
      if there is a file tImage then
         if tImage is not empty then
            import paint from file tImage
         end if
      end if
   end repeat
   compact stack pLibraryName
   save stack pLibraryName
   close stack pLibraryName
   unlock messages
end createImageLibrary</code>

OK, once you are done there are two IDE mods that you should make.

If you had a big hierarchy of folders like me you will probably want to sort the image library list so choose View > Revolution UI Elements In Lists from the menu then open up the application browser and find the images card of the revImageLibrary stack and edit the script. Just after “delete last char of tStacksList” add “sort tStacksList”

Next for some reason way back in the depths of time the good people at RunRev forgot to upgrade the icon chooser to support image libraries. “What’s the point of image libraries without them being in the icon chooser?” I hear you ask. Very good question.

Replace the preOpenStack handler in revIconChooser card 1 with:

<code>on preOpenStack
   put revAbsoluteFolderListing(revEnvironmentResourcesPath("Icon Libraries")) into tEnvironmentIcons
   put revAbsoluteFolderListing(revEnvironmentUserResourcesPath("Icon Libraries")) into tUserIcons
   put revCombineFilePaths(tUserIcons,tEnvironmentIcons) into tList
   repeat for each line l in tList
      if there is not a stack l then next repeat -- windows placeholder
      if char 1 to 6 of the short name of stack l is "revLib" then put char 7 to -1 of the short name of stack l & cr after tStacksList
      else if char 1 to 3 of the short name of stack l is "rev" then put char 4 to -1 of the short name of stack l & cr after tStacksList
      else put the short name of stack l & cr after tStacksList
   end repeat
   delete last char of tStacksList
   sort tStacksList
    put the text of btn "library chooser" into tText
  if the platform is "MacOS"
   then put "-" into tDivider
   else put empty into tDivider
   if tStacksList is not empty
   then put line 1 to 5 tText & cr & tDivider & cr & tStacksList into btn "library chooser"
   else put line 1 to 5 of tText into btn "library chooser"
   send "menuPick" && the label of btn "library chooser" to btn "library chooser"
   set the thumbPosition of scrollbar "iconchooserscrollbar" to 0
   put the cCurrentIcon of this stack into fld "ID"
   
   # TH-2008-03-06 : Fix for bug 5987
   set the pageIncrement of scrollbar "iconchooserscrollbar" to 20
   set the lineIncrement of scrollbar "iconchooserscrollbar" to 10
end preOpenStack</code>

Then edit the script of the “library chooser” button on that card. Where it says:

<code>else  put "rev" & pWhich into tStackName</code>

Change to

<code>else 
      put "rev" & pWhich into tStackName
      if there is not a stack tStackName then
         put "revLib"&pWhich into tStackName
      end if
   end if</code>

Database functions and commands

Some handy little general database functions and commands I wrote for an app I’m working on. They need some extra error handling but they are good for getting up and running quickly.

<code>function getTable pTable
   local tReturn,tSQL
   put "SELECT * FROM "&pTable into tSQL
   put revDataFromQuery(tab ,cr ,sDB ,tSQL) into tReturn
   if tReturn contains "revdberr" then return ""
   set the itemDel to tab
   return tReturn
end getTable

function getTableRecord pTable,pKey,pID
   local tReturn,tSQL,tQuery
   put "SELECT * FROM "&pTable&" WHERE "&pKey&" = "&pID into tSQL
   put revQueryDatabase(sDB,tSQL) into tQuery
   if not revdb_iseof(tQuery) then 
      revMoveToFirstRecord tQuery
      repeat for each item tColumn in revDatabaseColumnNames(tQuery) 
         put unSQLString(revDatabaseColumnNamed(tQuery,tColumn)) into tReturn[tColumn]
      end repeat
   end if
   revCloseCursor tQuery
   return tReturn
end getTableRecord

command deleteTableRecord pTable,pKey,pID
   local tReturn,tSQL,tQuery
   put "DELETE FROM "&pTable&" WHERE "&pKey&" = "&pID into tSQL
    revExecuteSQL sDB,tSQL
end deleteTableRecord

on updateTableRecord pTable,pKey,pID,pRecordA
   local tSQL,tField
   put "UPDATE "&pTable&" SET" into tSQL
   repeat for each line tField in keys(pRecordA)
      if pRecordA[tField] is a number then
          put " "&tField&"="&pRecordA[tField]&"," after tSQL
      else
         put " "&tField&"="&sqlString(pRecordA[tField])&"," after tSQL
      end if
   end repeat
   delete char -1 of tSQL
   put " WHERE "&pKey&"="&pID into tSQL
   revExecuteSQL sDB,tSQL
end updateTableRecord</code>

Finding out the LAN IP

I had to work out the LAN IP for the machine my app is running on because the IP is needed to enter into an iPhone app so it can sync to the desktop. This is just an temporary measure while we implement zeroconf. Here’s a little modification of Ken Ray’s great GetMACAddress function to return the LAN IP.

<code>function getLANIP
   -- value to return
   local retVal,tCard,ifConfigs,winExists,sys32Exists,temp
   set the itemDel to "."
   switch (the platform)
      case "MacOS"
         if item 1 of the systemVersion <10 then
            return ""
         else
            -- OS X
            repeat with X=1 to 10
               put "en"&X into tCard
               put shell("ifconfig "&tCard) into ifConfigs
               if char 1 to 9 of ifConfigs = "ifconfigs:" then
                  exit repeat
               else if char 1 to 4 of ifConfigs = "zsh:" then
                  return ""
               else
                  get matchText(ifconfigs,"(?s)inet (.*?) ",retVal) -- These are spaces on either side of (.*?)
                  if it is false then
                     return ""
                  else
                     exit repeat
                  end if
               end if
            end repeat
         end if
         break
      case "Win32"
         -- All Windows
         put (there is a file (specialFolderPath("system") & "/IPCONFIG.EXE")) into winExists
         put (there is a file (specialFolderPath("system") & "/SYSTEM32/IPCONFIG.EXE")) into sys32Exists
         if winExists or sys32Exists then
            set the hideConsoleWindows to true
            put shell("ipconfig /all") into temp
            if word 2 of systemVersion() < 6 then
               get matchText(temp,"IP Address[\. ]*: ([A-Z0-9-.]*)",retVal)
            else
               get matchText(temp,"IPv4 Address[\. ]*: ([A-Z0-9-.]*)",retVal)
            end if
         else
            return ""
         end if
         break
   end switch
   return retVal
end getLANIP</code>