Table of Contents

About

Unfortunately DirectoryOpus 4 cannot correlate the contents of one pane with the other pane. An useful tool to have would be a tool that can deselect all the selected items in one window pane that can also be found amongst the selected items of the other window pane. A good example is when you want to copy new files over from one pane to the other without overwriting the already existing files. This script is an ARexx script that allows you to do that. It is written in pure ARexx and does not require any external utilities.

Download

How to Install

  1. Extract the archive
  2. Place DOpus4-Subtract wherever you see fit (it is tidy, for example, to create an ARexx directory in DOPUS4: and then place your scripts there).
  3. Open DirectoryOpus4 and right-click and go to Project→Configure
  4. On the screen that pops-up, go to Buttons and create a new button somewhere where you see fit.
    1. Give the button a name (Subtract, for example) and create a new entry.
    2. Set the cycler to ARexx and click the magnifying glass to enter the path to the DOpus4-Subtract script.
  5. You do not need to set any flags.
  6. Save and exit and you are done.

How To Use

In DirectoryOpus 4, open up two directories in the two window panes, select some files in one window, select some files in the other window and hit the "Subtract" button that you just created. All operations will be mentioned in the DirectoryOpus 4 top text.

When the subtract process is done you should have only the files selected that are not amongst the selected files in the other window pane.

Developer Notes

The script uses a custom-implementation of some functions which can all be found on the ARexx FUSS page.

Code

DOpus4-Subtract.rexx
/*
 *  $VER: DOpus4-Subtract 1.0 (04 Jul 2015) by Wizardry and Steamworks
 *
 *      © 2015 Wizardry and Steamworks
 *
 *  PROGRAMNAME:
 *      DOpus4-Subtract
 *
 *  FUNCTION:
 *      Deselects all the selected entries in one window pane that can 
 *      also be found amongst the items selected in the other window pane.
 *
 *  USAGE:
 *      ARexx command DOpus4-Subtract.rexx (from DOpus)
 *
 *  $HISTORY:
 *
 *  04 Jul 2015 : 1.0 : initial release
 */
 
Opus = Address()    /* Get the DOpus address. */
Options RESULTS     /* Request results. */
Address value Opus  /* Use the DOpus address. */
 
Busy On
 
Status 3                    /* Get this window. */
ThisWindow = RESULT
ThatWindow = ~ThisWindow    /* That window is not this window. */
 
/* Get this window's selected items. */
TopText "Getting this window's items..."
GetSelectedAll '*' ThisWindow               /* Split entries by delimiter since we may have spaces. */
ThisItems = RESULT
If ThisItems = 'RESULT' Then                /* If no items in this window then bail. */
    Do
        TopText "No items selected in this window!"
        Busy Off
        Exit
    End
 
/* Normalize, heh... */
ThisItems = Upper(Translate(Translate(ThisItems, '/', ' '), ' ', '*'))
 
/* Get all that window's items. */
TopText "Getting that window's items..."
GetSelectedAll '*' ThatWindow               /* Split entries by delimiter since we may have spaces. */
ThatItems = RESULT
If ThatItems = 'RESULT' Then                /* If no items in that window then bail. */
    Do
        TopText "No items selected in that window!"
        Busy Off
        Exit
    End
 
/* Normalize, heh... */
ThatItems = Upper(Translate(Translate(ThatItems, '/', ' '), ' ', '*'))
 
/* Sort this items. */
TopText "Sorting this items... Please wait..."
ThisItems = wasStringQuicksort(ThisItems, 'TopText "Sorting ["Pivot"]"')
 
/* Sort that items. */
TopText "Sorting that items... Please wait..."
ThatItems = wasStringQuicksort(ThatItems, 'TopText "Sorting ["Pivot"]"')
 
/* Subtract that items from this items. */
TopText "Subtracting..."
Subtract = wasSortedSetsSubtract(ThisItems, ThatItems, 'TopText "Subtracting: ["AHead" - "BHead"]"')
 
/* Deselect entries that are not part of the intersection. */
/* Get all the items first, then search the each item in   */
/* the intersection set and deselect non-matching items.   */
TopText "Selecting and deselecting..."
GetAll '*' ThisWindow
AllItems = RESULT
 
/* Normalize, heh... */
AllItems = Translate(Translate(AllItems, '/', ' '), ' ', '*')
 
/* Deselect items... */
TopText "Deselecting items... Please wait..."
Count = Words(AllItems)
Do i = 1 To Count
    ThisName = SubWord(AllItems, i, 1)
    ThisNameUp = Upper(ThisName)
    If Find(Subtract, ThisNameUp) = 0 Then
        Do
            If Find(ThisItems, ThisNameUp) ~= 0 Then
                Do
                    ScrollToShow Translate(ThisName, ' ', '/')
                    SelectEntry i - 1 ||' '|| 0 ||' '|| 1
                End
        End
End
 
TopText "\(^.^)> There you go!"
Busy Off
Exit
 
/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
wasStringCompare: procedure /* Compares two strings lexicographically.   */
    Parse ARG One,Two
 
    Select
        When One = '' & Two ~= '' Then Return 1
        When One ~= '' & Two = '' Then Return -1
        When One = '' & Two = '' Then Return 0
        Otherwise Nop
    End
 
    a = Upper(Left(One, 1));
    b = Upper(Left(Two, 1));
 
    If C2D(a) < C2D(b) Then Return 1
    If C2D(a) > C2D(b) Then Return -1
 
    a = Right(One, Length(One)-1)
    b = Right(Two, Length(Two)-1)
 
Return wasStringCompare(a, b)
 
/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
wasSortedSetsSubtract: procedure /* Subtract two sorted sets: A \ B      */
    Parse ARG A,B,Lambda
 
    If A = '' Then Return ''
    If B = '' Then Return A
 
    Parse VAR A AHead ' ' ATail
    Parse VAR B BHead ' ' BTail
 
    Interpret Lambda
 
    Compare = wasStringCompare(AHead, BHead)
    Select
        When Compare < 0 Then
            Return wasSortedSetsSubtract(A, BTail, Lambda)
        When Compare > 0 Then
            Return AHead' 'wasSortedSetsSubtract(ATail, B, Lambda)
        Otherwise Nop
    End
 
Return wasSortedSetsSubtract(ATail, BTail, Lambda)
 
/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
wasStringQuicksort: procedure /* Sorts strings separated by token.       */
    Parse ARG String,Lambda
 
    Count = Words(String)
 
    If Count <= 1 Then Return String
 
    Middle = Trunc(Count/2)
 
    Pivot = SubWord(String,Middle,1)
    String = DelWord(String,Middle,1)
    Count = Count - 1
 
    Less = ''
    More = ''
    Do i = 1 To Count
        Word = SubWord(String,i,1)
        Compare = wasStringCompare(Word, Pivot)
        Select
            When Compare = 1 Then
                Select
                    When Less ~= '' Then
                        Less = Less||' '||Word
                    Otherwise Less = Word
                End
            Otherwise
                Select
                    When More ~= '' Then
                        More = More||' '||Word
                    Otherwise More = Word
                End
        End
 
    End
 
    Interpret Lambda
 
    Less = wasStringQuicksort(Less,Lambda)
    More = wasStringQuicksort(More,Lambda)
 
    If Less = '' & More ~= '' Then Return Pivot||' '||More
    If Less ~= '' & More = '' Then Return Less||' '||Pivot
 
Return Less||' ' ||Pivot||' '||More