/* REXX */ /* */ /* AUTHOR: Mark Zelden */ /* */ /* Last Updated 08/23/2007 */ /***************************************************************/ /* */ /* THIS EDIT MACRO CAN PERFORM 2 DIFFERENT FUNCTIONS: */ /* */ /* A) MOVE, COPY or SWAP data from one range of */ /* columns to another (default is MOVE). */ /* Excluded lines are always omitted. */ /* */ /* B) SHIFT data LEFT or RIGHT a specified */ /* number of columns - same as the "((" or "))" ISPF */ /* editor line commands. */ /* Excluded lines are always omitted. */ /* */ /***************************************************************/ /* COMMAND SYNTAX: */ /* */ /* MOVE FORMAT: */ /* */ /* COLUTIL begcol endcol tgtcol (MOVE) (.label1) (.label2) */ /* */ /* COPY FORMAT: */ /* */ /* COLUTIL begcol endcol tgtcol COPY (.label1) (.label2) */ /* */ /* SWAP FORMAT: */ /* */ /* COLUTIL begcol endcol tgtcol SWAP (.label1) (.label2) */ /* */ /* SHIFT FORMAT: */ /* */ /* COLUTIL amount (.label1) (.label2) */ /* */ /* ** NOTE 1: If using line range labels for a MOVE */ /* operation - "MOVE" must be specified */ /* as the 4th positional parameter. */ /* */ /* ** NOTE 2: COPY, MOVE, SWAP, LEFT and RIGHT can be */ /* abbreviated by using one or more of their */ /* characters. */ /* */ /* ** NOTE 3: Excluded lines are ALWAYS omitted. */ /* */ /* ** NOTE 4: On a SWAP operation, the length of the */ /* endcol-begcol determines to number of */ /* columns swapped starting with the tgtcol. */ /* For example, "COLUTIL 10 15 20 SWAP" will */ /* swap columns 10-15 with 20-25. */ /* */ /* ** NOTE 5: On a SWAP operation, if there are overlapping */ /* columns, for example: "COLUTIL 10 20 15 SWAP", */ /* columns 15-25 will replace 10-20, then */ /* the original data from columns 10-20 will */ /* replace columns 15-25. */ /* */ /***************************************************************/ /* MOVE EXAMPLES: */ /* COLUTIL 10 20 30 */ /* COLUTIL 45 55 10 M */ /* COLUTIL 45 55 10 MOVE */ /* COLUTIL 45 55 10 MOVE .A .B */ /* */ /* COPY EXAMPLES: */ /* COLUTIL 10 15 20 C */ /* COLUTIL 10 15 20 COPY */ /* COLUTIL 45 50 15 COPY .A .B */ /* */ /* SWAP EXAMPLES: */ /* COLUTIL 20 25 50 S */ /* COLUTIL 40 45 10 SWAP */ /* COLUTIL 45 50 15 SWAP .A .B */ /* */ /* SHIFT EXAMPLES: */ /* COLUTIL R 4 */ /* COLUTIL L 6 */ /* COLUTIL RIGHT 10 */ /* COLUTIL RIGHT 10 .A .B */ /* COLUTIL LEFT 12 */ /* COLUTIL LEFT 25 .A .B */ /***************************************************************/ /* TRACE ?R */ Address ISREDIT "MACRO (begcol endcol tgtcol type label1 label2)" /* Address ISPEXEC "CONTROL ERRORS RETURN" */ /***********************************************/ /* VERIFY INPUT PARAMETERS */ /***********************************************/ begcol = Translate(begcol) /* chage to upper case if alpha */ "(width) = DATA_WIDTH " /* length of line */ width = Format(width) /* remove leading zeros */ shift = 'NO' /* shift flag */ If begcol = '' then do zedsmsg = 'MISSING PARAMETER' zedlmsg = 'A SHIFT TYPE OR BEGINNING COLUMN NUMBER', 'MUST BE SPECIFIED.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End Select When Datatype(begcol,Number) = 1 & endcol = '' then do zedsmsg = 'NO ENDING COLUMN' zedlmsg = 'AN ENDING COLUMN FOR THE', 'OPERATION MUST BE SPECIFIED.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End /* when */ When Datatype(begcol,Number) =1 & Datatype(endcol,Number) <>1 then do zedsmsg = 'END COLUMN NOT NUMERIC' zedlmsg = 'THE ENDING COLUMN FOR THE', 'OPERATION MUST BE NUMERIC.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End /* when */ When Datatype(begcol,Number) =1 & Datatype(endcol,Number) =1 then do If endcol < begcol then do zedsmsg = 'END COL < START COL' zedlmsg = 'THE ENDING COLUMN MUST BE GREATER THAN OR', 'EQUAL TO THE STARTING COLUMN.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If tgtcol <> '' then do If Datatype(tgtcol,Number) <> 1 then do zedsmsg = 'TARGET COL NOT NUMERIC' zedlmsg = 'THE TARGET COLUMN FOR THE', 'OPERATION MUST BE NUMERIC.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End If tgtcol = '' then do zedsmsg = 'NO TARGET COLUMN' zedlmsg = 'YOU MUST SPECIFY A TARGET COLUMN', 'FOR THE OPERATION.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If type = '' then type = 'MOVE' else do type = Translate(type) /* change to upper case */ If Abbrev('MOVE',type,1) = 0 & , Abbrev('COPY',type,1) = 0 & , Abbrev('SWAP',type,1) = 0 then do zedsmsg = 'INVALID OPERATION' zedlmsg = 'OPERATION MUST BE "MOVE", "COPY", OR "SWAP".' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End /* else do */ If begcol < 1 | endcol < 1 | tgtcol < 1 then do zedsmsg = 'INVALID COLUMN NUMBER' zedlmsg = 'ALL COLUMN SPECIFICATIONS MUST BE' , 'BETWEEN 1 AND' width Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If begcol > width | endcol > width | tgtcol > width then do zedsmsg = 'INVALID COLUMN NUMBER' zedlmsg = 'ALL COLUMN SPECIFICATIONS MUST BE' , 'BETWEEN 1 AND' width Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If begcol = tgtcol then do zedsmsg = 'NO ACTION TAKEN' zedlmsg = 'THE STARTING COLUMN AND TARGET COLUMN', 'CAN NOT BE THE SAME.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End /* when */ Otherwise shift = 'YES' If Abbrev('LEFT',begcol,1) = 0 & , Abbrev('RIGHT',begcol,1) = 0 then do zedsmsg = 'INVALID SHIFT DIRECTION' zedlmsg = 'A SHIFT DIRECTION OF "LEFT" OR "RIGHT"', 'MUST BE SPECIFIED' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If endcol = '' then do zedsmsg = 'NO SHIFT AMOUNT' zedlmsg = 'A SHIFT AMOUNT FOR THE', 'OPERATION MUST BE SPECIFIED.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End Else do If Datatype(endcol,Number) <> 1 then do zedsmsg = 'SHIFT AMOUNT NOT NUMERIC' zedlmsg = 'THE SHIFT AMOUNT SPECIFIED FOR THE', 'OPERATION MUST BE NUMERIC.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If endcol > width - 1 | endcol < 1 then do zedsmsg = 'INVALID SHIFT AMOUNT' zedlmsg = 'THE SHIFT AMOUNT SPECIFIED MUST', 'BE BETWEEN 1 AND' width - 1 || '.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End End /* else do */ End /* select */ /***********************************************/ /* SHIFT PROCESSING SETUP */ /***********************************************/ If shift = 'YES' then do label1 = tgtcol label2 = type shiftamt = endcol type = 'MOVE' /* shift is really a MOVE operation */ If Abbrev('LEFT',begcol,1) <> 0 then do /* left shift */ shifttyp = 'LEFT' begcol = shiftamt + 1 endcol = width tgtcol = 1 End Else do /* right shift */ shifttyp = 'RIGHT' begcol = 1 endcol = width tgtcol = shiftamt + 1 End End /* if shift = 'YES' */ /***********************************************/ /* FIND OUT IF LABELS ARE BEING USED */ /***********************************************/ Call FIND_LABELS /***************************************************/ /* INITIALIZE VARIABLES NEEDED IN PROCESSING LOOP */ /***************************************************/ count = 0 /* count of changed lines */ tgtlen = endcol-begcol+1 /* length of operation */ /***********************************************/ /* BEGIN COLUMN MANIPULATION LOOP */ /***********************************************/ Do until lastln = firstln-1 /* copy the data in the current line to variable 'data1' */ "(data1) = LINE "firstln "ISREDIT (chkexcl) = XSTATUS" firstln If chkexcl = "NX" then do count = count + 1 tgtdata = Substr(data1,begcol,tgtlen) If shift = 'YES' & shifttyp = 'LEFT' then , /* clr data for left */ data1 = Overlay(' ',data1,width-shiftamt,shiftamt+1) /* shift */ If Abbrev('MOVE',type,1) <> 0 then , /* clear data for */ data1 = Overlay(' ',data1,begcol,tgtlen) /* column MOVE */ If Abbrev('SWAP',type,1) <> 0 then do /* */ data2 = Substr(data1,tgtcol,tgtlen) /* */ data1 = Overlay(data2,data1,begcol,tgtlen) /* */ End data1 = Overlay(tgtdata,data1,tgtcol,tgtlen) /* COPY data */ End /* copy the modified line back into the current line */ "LINE" firstln "= (data1)" firstln = firstln + 1 End /* do until */ /***********************************************/ /* END COLUMN MANIPULATION LOOP */ /***********************************************/ If shift <> 'YES' then do If Abbrev('MOVE',type,1) <> 0 then msgtype = 'MOVED' If Abbrev('SWAP',type,1) <> 0 then msgtype = 'SWAPPED' else msgtype = 'COPIED' If tgtlen+tgtcol-1 <= width then do /* no truncation */ zedsmsg = count 'LINES CHANGED' zedlmsg = 'COLUMNS' begcol 'THROUGH' endcol 'ON' count , 'LINES WERE' msgtype 'TO COLUMN' tgtcol || '.' Address ISPEXEC "SETMSG MSG(ISRZ000)" /* msg - no alarm */ Exit 0 End Else do zedsmsg = count 'LINES TRUNCATED' zedlmsg = 'COLUMNS' begcol 'THROUGH' endcol 'ON' count , 'LINES WERE' msgtype 'TO COLUMN' tgtcol 'AND TRUNCATED.' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 4 End End Else do /* total messages for shift */ zedsmsg = count 'LINES SHIFTED' zedlmsg = count 'LINES WERE SHIFTED' shiftamt 'COLUMNS' , 'TO THE' shifttyp || '.' Address ISPEXEC "SETMSG MSG(ISRZ000)" /* msg - no alarm */ Exit 0 End /*********************************/ /* SUB-ROUTINE TO FIND LABELS */ /*********************************/ FIND_LABELS: If label1 = '' then do firstln = 1 "(lastln) = LINENUM .ZLAST" End Else do If label2 = '' then label2 = label1 firstsv = 'NOTFOUND' lastsv = 'NOTFOUND' label1 = Translate(label1) label2 = Translate(label2) "(saveln) = DISPLAY_LINES" "UP MAX" Do forever "LOCATE LAB NEXT" if rc <> 0 then leave "(labline,junk) = DISPLAY_LINES" "(lab,junk) = LABEL" labline if lab = label1 then firstsv = labline if lab = label2 then lastsv = labline End If label1 ='.ZFIRST' | label1 = '.ZF' then firstsv = 1 If label1 ='.ZLAST' | label1 = '.ZL' then , "(firstsv) = LINENUM .ZLAST" If label2 ='.ZFIRST' | label2 = '.ZF' then lastsv = 1 If label2 ='.ZLAST' | label2 = '.ZL' then , "(lastsv) = LINENUM .ZLAST" /* */ /* return display lines to originial position */ /* */ "UP MAX" If saveln <> 1 then "DOWN " saveln /* don't scroll if at top */ /* */ If firstsv = 'NOTFOUND' then do zedsmsg = 'RANGE LABEL ERROR' zedlmsg = 'THE SPECIFIED RANGE LABEL "' || label1 '" WAS', 'NOT FOUND' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End If lastsv = 'NOTFOUND' then do zedsmsg = 'RANGE LABEL ERROR' zedlmsg = 'THE SPECIFIED RANGE LABEL "' || label2 '" WAS', 'NOT FOUND' Address ISPEXEC "SETMSG MSG(ISRZ001)" /* msg - with alarm */ Exit 12 End firstln = Min(firstsv,lastsv) lastln = Max(firstsv,lastsv) End Return