/* REXX exec to programatically edit any ISPF clipboard               */
/*** trace ?r ***************************************************** \| *
*               (C) Copyright Robert AH Prins, 2009-2012               *
************************************************************************
*  ------------------------------------------------------------------  *
* | Date       | By   | Remarks                                      | *
* |------------+------+----------------------------------------------| *
* |            |      |                                              | *
* |------------+------+----------------------------------------------| *
* | 2012-07-09 | RAHP | LMINIT cannot handle concatenation with more | *
* |            |      | than 16 data sets                            | *
* |------------+------+----------------------------------------------| *
* | 2010-01-13 | RAHP | *ENDREXX must be uppercase on old versions   | *
* |            |      | of z/OS                                      | *
* |------------+------+----------------------------------------------| *
* | 2009-07-02 | RAHP | Allow selection of Clipboard                 | *
* |------------+------+----------------------------------------------| *
* | 2009-06-15 | RAHP | Initial version                              | *
* |------------+------+----------------------------------------------| *
************************************************************************
* EDITCLIP is a REXX exec/edit macro to edit any ISPF clipboard        *
* without manual intervention with a user-specified macro, or manually *
* if no macro is specified.                                            *
*                                                                      *
* The method of automagically processing the ISPF default clipboard    *
* by replacing the ISRECUTL panel was inspired by Doug Nadel's macro   *
* (See <http://sillysot.com/ftp/sdsf_highlighting.txt) to create a     *
* customised ISFPCU41 panel that adds smart highlighting to SDSF.      *
************************************************************************
* Send questions, suggestions and/or bug reports to:                   *
*                                                                      *
* robert@prino.org / robert.ah.prins@gmail.com                         *
*                                                                      *
* Robert AH Prins                                                      *
* Taboralaan 46                                                        *
* 8400 Oostende                                                        *
* Belgium                                                              *
************************************************************************
* This program is free software: you can redistribute it and/or        *
* modify it under the terms of the GNU General Public License as       *
* published by the Free Software Foundation, either version 3 of       *
* the License, or (at your option) any later version.                  *
*                                                                      *
* This program is distributed in the hope that it will be useful,      *
* but WITHOUT ANY WARRANTY; without even the implied warranty of       *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
* GNU General Public License for more details.                         *
*                                                                      *
* You should have received a copy of the GNU General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>  *
***********************************************************************/
parse source source
parse value source with . . moi .

"ispexec control errors return"

arg parm
"isredit macro (parm)"

parse value translate(space(parm, 0)) with board '/' clipmac

"ispexec vget (editclip)"
if rc = 0 then
  do
    "ispexec verase (editclip)"

    select
      when left(editclip, 1) = x2c(00) then
        do
          editclip = substr(editclip, 2)

          select
            when editclip = 'BUILD_ISRECUTL' then
              call build_isrecutl

            otherwise
          end
        end

      otherwise
    end
  end
else
  do
    /*******************************************************************
    * Build a copy of 'ISRECUTL' with a bit of extra code that allows  *
    * unattended processing of the selected clipboard                  *
    *******************************************************************/
    drop plib

    editclip = x2c(0)'BUILD_ISRECUTL'
    "ispexec vput (editclip)"

    "ispexec lminit dataid(plib) ddname(ispplib) enq(shr)"
    if rc = 0 then
      do
        "ispexec view dataid("plib") member(isrecutl) macro("moi")"
        "ispexec lmfree dataid("plib")"

        ok = 1
      end
    else
      do
        "ispexec qbaselib ispplib id(ispplib)"
        ispplib = space(translate(ispplib, '  ', "',"))

        ok = 0
        do until ok | ispplib = ''
          parse value ispplib with dsn ispplib

          ok = sysdsn("'"dsn"(isrecutl)'") = 'OK'

          if ok then
            "ispexec edit dataset('"dsn"(isrecutl)') macro("moi")"
        end
      end

    if ok then
      do
        /***************************************************************
        * Set up the initial macro                                     *
        ***************************************************************/
        "ispexec vget (zusermac) profile"
        savemac  = zusermac
        zusermac = strip(left(clipmac, 8))

        "ispexec vput (board)"
        "ispexec vput (zusermac) profile"
        "ispexec select pgm(isrclipb)"

        zusermac = savemac
        "ispexec vput (zusermac) profile"

        /***************************************************************
        * Clean up                                                     *
        ***************************************************************/
        "ispexec qlibdef ispplib id(id)"
        "ispexec libdef ispplib"
        "free f("id")"
      end
    else
      do
        zedsmsg = ''
        zedlmsg = 'A severe error has occurred,' moi ' processing has',
                  'terminated. The developer may be able to provide a',
                  'solution to the problem.'

        "ispexec setmsg msg(ISRZ001)"
      end
  end
exit

/***********************************************************************
* BUILD_ISRECUTL:                                                      *
*                                                                      *
* This procedure retrieves the original ISRECUTL panel, provided it is *
* in a dataset allocated to ISPPLIB. It adds some code to the panel to *
* enable editing the clipboard without user intervention. The modified *
* panel is saved into a temporary dataset that is subsequently used in *
* a LIBDEF of ISPPLIB.                                                 *
***********************************************************************/
build_isrecutl:
  "isredit macro"

  dynlib = 'pan'random(99999)
  alloc  = "alloc fi("dynlib") rtdsn(sysdsname) "   ||,
                     "lrecl(80) blksize(0) dir(5) " ||,
                     "new delete reuse "            ||,
                     "space(1,1)"
  rc = bpxwdyn(alloc)

  if rc = 0 then
    ispdyn = sysdsname
  else
    ispdyn = 'NOT FOUND'

  "newstack"

  "isredit (ZL) = linenum .zl"

  do i = 1 to zl
    "isredit (L) = line" i

    if left(l, 5) = ')PROC' then
      do
        /***************************************************************
        * Insert additional code into the 'INIT' section               *
        ***************************************************************/
        queue '/* Additional INIT code */'
        queue 'vget (board)'
        queue ' '
        queue '*REXX(zcutlist,board,autoclip)'
        queue '  ok = 0'
        queue ' '
        queue '  if autoclip \= ''OK'' then'
        queue '    do cb = 5 by 63 to length(zcutlist) until ok'
        queue '      ok = strip(substr(zcutlist, cb, 8)) = board'
        queue '    end'
        queue ' '
        queue '  if \ok then'
        queue '    zcutlist = overlay(''E'', zcutlist, 3)'
        queue '  else'
        queue '    zcutlist = overlay(''E'', zcutlist, cb - 2)'
        queue '*ENDREXX'
        queue ' '
        queue 'if (&autoclip = &z)'
        queue '  .resp=enter'
        queue 'else'
        queue '  .resp=end'

        queue l

        /***************************************************************
        * Insert additional code into the 'PROC' section               *
        ***************************************************************/
        queue '/* Additional PROC code */'
        queue '&autoclip = OK'
      end
    else
      queue l
  end

  tfil = 'tfil'random(9999)

  "alloc f("tfil") da('"ispdyn"(isrecutl)') shr reu"
  "execio" queued() "diskw "tfil" (finis"
  "free f("tfil")"

  "delstack"

  "isredit can"

  "ispexec libdef ispplib library id("dynlib") stack"
return
/***********************************************************************
Structure of zcutlist, for clarity the actual attribute characters 01,
02, 03 and 04 have been replaced by {, }, $ and !. The three rows below
are all concatenated|

{ 01 TYPE(DATAOUT)
} 02 TYPE(DATAOUT) INTENS(LOW)
$ 03 TYPE(DATAIN)  JUST(LEFT) HILITE(USCORE)
! 04 TYPE(DATAIN)  CAPS(ON)   HILITE(USCORE)
....v....1....v....2....v....3....v....4....v....5....v....6...
 ! {DEFAULT }      21$ISPF Default Clipboard                  {
 ! {WHATEVER}      20$A user defined clipboard                {
 ! {ANOTHER }      20$Another user defined clipboard          {
***********************************************************************/