*
;
/*
From - Mon Apr 22 15:37:36 1996
Comments: Gated by NETNEWS@AUVM.AMERICAN.EDU
Newsgroups: comp.soft-sys.sas
Date: Thu, 18 Apr 1996 15:03:00 +0000
Reply-To: wood-st@cityscape.co.uk
Sender: "SAS(r) Discussion" 
Comments: Authenticated sender is 
From: Philip & Esther Mason 
Subject: SUGI Programmers Toolkit Update

For those who attended SUGI and got the Programmers Toolkit,

Ian Whitlock has kindly provided a correction to a macro in the SUGI
Programmers Toolkit. Here is the complete version in a working form.

Phil
*/

%macro wordwrap ( inray= ,      /* input array name                    */
                  inlen=200,    /* length of variables in input array  */
                  outray= ,     /* output array name                   */
                  outlen= ,     /* length of variables in output array */
                  debug= ***    /* null value for debugging            */
                ) ;
   %* All parameters null by default are required ;
   %local p q plen qlen blank ;
   %let p = %upcase(&inray) ;
   %let q = %upcase(&outray) ;
   %let plen = &inlen ;
   %let qlen = &outlen ;
   %let blank = %str( ) ;

   %*----------------------------------------------------------------- *;
   %* Purpose:                                                         *;
   %*   Text stored in &inray from a long character string (over 200   *;
   %*   bytes. Array elements are not word boundaries. The text is     *;
   %*   moved to &outray with space filling at the end so that no word *;
   %*   crosses an array element in &outray.                           *;
   %*                                                                  *;
   %* Assumptions:                                                     *;
   %*   Parameters null by default are required                        *;
   %*   When a word in &inray is longer than &outlen abort             *;
   %*                                                                  *;
   %* Working variables:                                               *;
   %*   begin __p when associated with &inray and __q for &outray      *;
   %*     __px, __qx    - index to respective arrays                   *;
   %*     __rpb , __rqb - relative begin pointers within array element *;
   %*     __rpe         - relative end pointer within array element    *;
   %*     __pb , __pe   - absolute (full string) begin and end         *;
   %*                     pointers to substring of &inray              *;
   %*     __pc          - one byte character value from &inray         *;
   %*     __sublen      - length of substring within an array element  *;
   %*                                                                  *;
   %* Basic algorithm:                                                 *;
   %*     initialize __pe = 0                                          *;
   %*     loop over index of &outray until finished                    *;
   %*        __pb = __pe + 1                                           *;
   %*        set __pe to maxium that will fit in &outray               *;
   %*        back up to space when next character is not a space       *;
   %*        move substring to &outray (will require two moves when    *;
   %*             substring begins and ends on different elements      *;
   %*     end loop                                                     *;
   %* ---------------------------------------------------------------- *;

   drop __: ;
   __pe = 0 ;
   do __qx = lbound(&q) to hbound(&q) until ( __pe >= &plen * dim(&p) ) ;
      __pb = __pe + 1 ;
      &debug put __qx= __pb= ;
      if &p ( %px(__pb) ) = " " then
      do ;
         __qx = __qx - 1 ;
         leave ;
      end ;
      else
      do ;
         __pe = min ( &plen * dim ( &p ) , __pb + &qlen - 1 ) ;
         /* skip backup test when pe is at the end of full string */
         if __pe = &plen * dim ( &p ) then ;
         else
         if substr ( &p ( %px(__pe+1) ), %pp(__pe+1), 1 ) ^= "&blank" then
         do ;                        /* back up to first blank */
            do __pe = __pe to __pb by - 1
                     until ( __pc = "&blank" or __pe < __pb ) ;
               &debug __px = %px(__pe) ;
               &debug __rpe = %pp(__pe) ;
               __pc = substr ( &p(%px(__pe)) , %pp(__pe) , 1 ) ;
               &debug put 'backup ' __pe= __pc= __px= __rpe= &p(__px)=;
            end ;
            if __pe < __pb then
            do ;                   /* token to long to process */
               __px = %px ( __pb ) ;
               put 'WORDRAP: token too long - aborting ' /
                   "input: &p(" __px +(-1) ')=' &p ( __px )  $char&plen.. ;
               __px = __px + 1 ;
               put "input: &p(" __px +(-1) ')=' &p ( __px )  $char&plen.. ;
               abort 99 ;
            end ;
         end ;
         /* move substring to q array */
         __rqb = 1 ;
         do while ( %px(__pb) ^= %px(__pe) ) ;
            __px = %px(__pb) ;
            __rpb = %pp(__pb) ;
            __sublen = &plen - __rpb + 1 ;
            &debug put 'partial move ' __px= __rpb= __sublen= ;
            substr ( &q ( __qx ) , __rqb ) =
              substr ( &p(%px(__pb)), __rpb, __sublen ) ;
            &debug put &q(__qx)= ' incomplete' ;
            __rqb = __sublen + 1 ;
            __pb = ( __px ) * &plen + 1 ;
            &debug put 'after partial move ' __pb= __rqb= ;
         end ;
         /* move part on end elelement */
         &debug __rpb = %pp(__pb) ;
         &debug __sublen = __pe - __pb + 1 ;
         &debug __px = %px(__pe) ;
         &debug  put 'completed move '
            __px= __pb= __pe= __rqb= __rpb= __sublen= ;
         substr ( &q ( __qx ) , __rqb ) =
               substr ( &p(%px(__pe)) , %pp(__pb) , __pe - __pb + 1 ) ;
         &debug put &q ( __qx ) = ;
      end ;
   end ;

   do __qx = __qx + 1 to dim ( &q ) ;
      &q ( __qx ) = ' ' ;
   end ;

%mend  wordwrap ;

%macro pp ( ptr ) ;  /* relative pointer to the p array element */
    mod ( ( &ptr - 1 ) , &plen ) + 1
%mend  pp ;

%macro px ( ptr ) ; /* index to the p array */
    int ( ( &ptr - 1 ) / &plen ) + 1
%mend  px ;

/*-----------------------------------------------------------+
! Philip Mason           Email: wood-st@cityscape.co.uk    !
!     Freelance SAS Consultant                             !
!   & SUGI-22 Applications Development co-chair            !
+----------------------------------------------------------+
! 16 Wood Street, Wallingford, OXON., OX10 0AY, England    !
! Phone/Fax: +44 1491 824905                               !
-----------------------------------------------------------+*/

*
;