// RELATED SOFTWARE: Scilab 
// LICENSE   : CeCILL-C : http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
// FUNCTION  : strrepeat()
// AUTHOR (C): Samuel GOUGEON - private individual
// COPYRIGHT : Samuel GOUGEON - 2015
// RELEASE   : 1.0
// DATE      : 2015-07-26
// DISTRIBUTION: http://fileexchange.scilab.org/toolboxes/365000
// HISTORY   : 
//   1.0 - 2015-07-26: first publication on FileExchange
//
// DISCLAIMER: 
//   This script is provided as is, with NO WARRANTY of any kind.
//   Use it to your own risks & responsability.
//

function r = strrepeat(t, n)
// Repeats a text pattern n times or up to a n-characters length
// 
//SYNTAX
//     strrepeat         // Displays this help
// R = strrepeat(N)      //  R(I) = N(I) blanks
// R = strrepeat(ST)     //  R(I) = length(ST(I)) blanks
// R = strrepeat(T,  N)  //  R(I) = T(I) repeated N(I)>0 times
//                       //  R(I) = T(I) repeated up to |N(I)<0| characters
// R = strrepeat(T, ST)  //  R(I) = T(I) repeated up to length(ST(I)) characters
//                  // ... where I stands for i, or (i,j), or (i,j,k..)
//PARAMETERS
// T : Scalar, vector, matrix or hypermatrix of text to be repeated.
//     By default, T = " ". UTF-8 characters are accepted.
// N : Scalar, vector, matrix or hypermatrix of integers.
//     If N is a scalar while T is not so, N is used for every T components.
//     If T is a scalar while N is not so, T is repeated according to
//      each N component.
//     If N and T are not scalars, they must have the same sizes.
// ST: Scalar, vector, matrix or hypermatrix of texts used as templates,
//      setting N = length(ST).
//     If T and ST are not scalars, they must have the same sizes.
// R : Scalar, vector, matrix or hypermatrix of repeated text. 
//     R has the sizes of the largest input T, N, or ST.
//     R = []  if T, N or ST is [].
//
//DESCRIPTION
// From a character, a word or a text, or from each component of a
// matrix of chars and words and texts, strrepeat() concatenates it
// with itself a) either as many times n as specified, or b) as many 
// times as to reach a given number n of characters. In the latter 
// case, if n is not a multiple of the item's length, the result of
// the concatenation is trimmed on the right to n characters.
// When no item to repeat is specified, " " is considered. Hence,
//  - strrepeat(n) is equivalent to blanks(n). However,
//  - strrepeat() is vectorized, while blanks() is not. 
//  - strrepeat() is applicable to any character or string, whereas
//    blanks() generates exclusively white strings.
//  - strrepeat() can take strings as templates, while blanks() cannot.
//
// NOTE: UTF-8 characters are supported.
// WARNING: If a text is empty and must be repeated to reach a non 
//  null length, an error occurs.
//
//SEE ALSO
// blanks  : http://help.scilab.org/docs/5.5.2/en_US/blanks.html
// strcat  : http://help.scilab.org/docs/5.5.2/en_US/strcat.html
// strsubst: http://fileexchange.scilab.org/toolboxes/294000
//
//REFERENCE: 
//  Comments, scoring and bug reports are welcome on
//  http://fileexchange.scilab.org/toolboxes/365000
//
//EXAMPLES
//// Blanks:
// '|' + strrepeat(9) + '|'
// '|' + strrepeat([ 2 5 ; 4 8]) + '|'
// '|' + strrepeat(['abc' ; '1234567']) + '|'
//
//// Text with UTF-8 characters:
// strrepeat('éüçñ実またちこんфий', 2)
//
//// One text, various repeating rates:
// strrepeat('.', [2 5 ; 0 8])
// strrepeat('-.', [3 -3 ; 5 -5])
// strrepeat('.', ['abc' '1234567'])
// strrepeat(['A' ''], -7)  // => error
//
//// One repeating rate, various texts:
// strrepeat(['-' '~' ; '-.' '~.'], 5)
// strrepeat(['-' '~' ; '-.' '~.'], -9)
// strrepeat(['-' '~' ; '-.' 'ab'], 'abcdefg')
//
//// Element-wise repeating rates:
// '|' + strrepeat(['' '-.' '/\' '0-' 'cB'], [8 5 0 4 -11]) + '|'
//

    fname = "strrepeat"

    // CHECKING PARAMETERS
    // ===================
    //  - number and types
    // -------------------
    // Types of t and n
    if ~isdef("t","l") then
        tt = 0
    else
        if typeof(t)=="hypermat"
            tt = type(t(1))
        else
            tt = type(t)
        end
    end
    if ~isdef("n","l") then
        tn = 0
    else
        if typeof(n)=="hypermat"
            tn = type(n(1))
        else
            tn = type(n)
        end
    end
    
    // No input arg => help
    if  argn(2)==0
        head_comments(fname)
        r = []
        return
        
    // ONE input arg
    elseif argn(2)==1
        if tt==1
            if t==[]
                r = []
                return
            end
            n = t
            t = " "
        elseif tt==10
            n = length(t)
            tn = 1
            t = " "
        elseif tn==1  // named parameter n=value
            t = " "
            tt = 10
        else
            if tt==0 & tn==0
                msg = _("%s: Wrong named input argument : ""t"" or ""n"" possible.\n")
                error(msprintf(msg, fname))
            else
                msg = _("%s: Wrong type of input argument #1: text or positive integer(s) expected.\n")
                error(msprintf(msg, fname))
            end
        end
    elseif argn(2)==2
        if tt==0 // in case of extra useless named parameter
            t = " "
            tt = 10
        end
        if tn==0 // in case of extra useless named parameter
            n = length(t)
            tn = 1
        end
        if tt~=10
            if t==[]
                r = []
                return
            end
            msg = _("%s: Wrong type of input argument #%d: Matrix of text expected.\n")
            error(msprintf(msg, fname, 1))
        end
        if tn==10      // strrepeat(t, tp) syntax
            n = -length(n)
            tn = 1
        end
        if tn~=1
            msg = _("%s: Wrong type of input argument #%d: Matrix of text expected.\n")
            error(msprintf(msg, fname, 2))
        end
    else
        msg = _("%s: Wrong number of input arguments: %d to %d expected.\n")
        error(msprintf(msg, fname, 0, 2))
    end
    //  - authorized format and values
    //  ------------------------------
    if t==[] | n==[] then
        r = []
        return
    end
    if ~isreal(n) then
        msg = _("%s: Wrong type of input argument #%d: Matrix of integers expected.\n")
        error(msprintf(msg, fname, 1))
    else
        n = fix(n)
    end
    if size(t,"*")>1 & size(n,"*")>1 & or(size(t)~=size(n)) then
        msg = _("%s: Input arguments #%d & #%d: Matrices must have the same sizes.\n")
        error(msprintf(msg, fname, 1, 2))
    end
    
    // PROCESSING
    // ==========
    n0 = n
    t0 = t
    n = n(:)
    t = t(:)
    L = length(t)
    
    // Only one string
    // ---------------
    if size(t,"*")==1 then
        r = matrix(emptystr(n0(:)), size(n0));

        // components n>0 
        ip = find(n0>0);
        if ip~=[] & t~='' then
            n = n0(ip)
            tmp = strcat(emptystr(1,sum(n))+t);   // replication
            n = cumsum(n);
            n = n'*L
            if size(n,"*")>1
                tmp = strsplit(tmp, n(1:$-1))
            end
            if size(r,"*")==size(tmp,"*")
                r = matrix(tmp, size(r))
            else
                if size(r,1)==1, tmp = tmp', end
                r(ip) = tmp
            end
        end

        // components n<0
        in = find(n0<0)
        if in~=[] then
            n = -n0(in)
            n = n(:)
            if t=='' then
                msg = _("%s: repeating the empty """" can''t reach %s characters!\n")
                tmp = min(length(n),3)
                tmp = strcat(msprintf("%d\n",n(1:tmp)),"|")+".."
                error(msprintf(msg, fname, tmp))
            end
            N = ceil(n./L)
            stmp = strrepeat(t, N)
            L2 = length(stmp)
            tmp = [ n  L2-n]'
            tmp2 = cumsum(tmp)
            tmp = strsplit(strcat(stmp)+" ", tmp2(1:$-1))
            tmp = tmp(1:2:$)
            if size(r,"*")==size(tmp,"*")
                r = matrix(tmp, size(r))
            else
                if size(r,1)==1, tmp = tmp', end
                r(in) = tmp
            end
        end
        
    // Only one repeating rate
    // -----------------------
    elseif size(n, "*")==1
        r = matrix(emptystr(t0(:)), size(t0));
        emptyStr = find(t=="")
        if n>0
            ne = find(t~="")
            if ne~=[] then
                t = t(ne)
                t = t(:)
                L = L(ne)
                tmp = strcat(strcat(t) + emptystr(1,n))
                tmp2 = cumsum(L*ones(1,n))
                tmp = matrix(strsplit(tmp, tmp2(1:$-1)), -1, n)
                tmp = strcat(tmp, "", "c")
                if size(r,"*")==size(tmp,"*")
                    r = matrix(tmp, size(r))
                else
                    if size(r,1)==1, tmp = tmp', end
                    r(ne) = tmp
                end
            end
        //
        elseif n<0
            if emptyStr~=[] then
                msg = _("%s: repeating the empty """" can''t reach %d characters!\n")
                error(msprintf(msg, fname, -n))
            end
            N    = ceil(-n./L)
            stmp = strrepeat(t, N)
            L2   = length(stmp)'
            tmp2 = -n*ones(1, size(t, "*"))
            tmp  = [ tmp2 ; L2-tmp2 ]
            tmp2 = cumsum(tmp)
            tmp  = strsplit(strcat(stmp)+" ", tmp2(1:$-1))
            r = matrix(tmp(1:2:$), size(t0))
        end

    // Element-wise repeating rates
    // ----------------------------
    else
        emptyStr = find(t=="" & n<0)
        if emptyStr~=[] then
            msg = _("%s: repeating the empty """" can''t reach %s characters!\n")
            tmp = min(length(emptyStr),3)
            tmp = strcat(msprintf("%d\n",n(emptyStr(1:tmp))),"|")+".."
            error(msprintf(msg, fname, tmp))
        end

        r = matrix(emptystr(n0(:)), size(n0));
        
        // components with n>0
        ip = find(n0>0 & t0~="")
        if ip~=[]
            t = t0(ip)
            t = t(:)
            n = n0(ip)
            n = n(:)
            ind = []
            for i=1:length(ip)
                ind = [ ind i*ones(1,n(i)) ];
            end
            tmp = t(ind)
            m = cumsum(length(t).*n)
            tmp = strcat(tmp)
            if size(m,"*")>1
                tmp = strsplit(tmp, m(1:$-1))
            end
            if size(r,"*")==size(tmp,"*")
                r = matrix(tmp, size(r))
            else
                if size(r,1)==1, tmp = tmp', end
                r(ip) = tmp
            end
        end
        
        // components with n<0
        in = find(n0<0)
        if in~=[]
            t = t0(in)
            t = t(:)
            n = -n0(in)
            n = n(:)
            N = ceil(n ./ L(in))
            tmp = strrepeat(t, N)
            L2 = length(tmp)
            tmp2 = [ n  L2-n ]'
            m = cumsum(tmp2)
            tmp = strcat(tmp)
            if size(m,"*")>1
                tmp = strsplit(tmp+" ", m(1:$-1))
            end
            tmp = tmp(1:2:$)
            if size(r,"*")==size(tmp,"*")
                r = matrix(tmp, size(r))
            else
                if size(r,1)==1, tmp = tmp', end
                r(in) = tmp
            end
        end
    end
endfunction

