001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/**
020 * Implements the CFML Function refind
021 */
022package lucee.runtime.functions.string;
023
024import lucee.commons.io.SystemUtil;
025import lucee.runtime.PageContext;
026import lucee.runtime.exp.ExpressionException;
027import lucee.runtime.exp.FunctionException;
028import lucee.runtime.exp.PageException;
029import lucee.runtime.functions.BIF;
030import lucee.runtime.op.Caster;
031import lucee.runtime.type.Array;
032import lucee.runtime.type.util.ListUtil;
033
034public final class Wrap extends BIF {
035        
036        public static String call(PageContext pc , String string, double limit) throws ExpressionException {
037                return call(pc,string,limit,false);
038        }
039        
040        public static String call(PageContext pc , String string, double limit, boolean strip) throws ExpressionException {
041                if(strip) {
042                    string=REReplace.call(pc,string,"[[:space:]]"," ","all");
043                }
044            int _limit=(int) limit;
045            if(limit<1) throw new FunctionException(pc,"Wrap",2,"limit","value mus be a positive number");
046            return wrap(string,_limit);
047        }
048        
049
050        /**
051         * wraps a String to specified length
052         * @param str string to erap
053         * @param wrapTextLength
054         * @return wraped String
055         */
056        public static String wrap(String str, int wrapTextLength) {
057                if(wrapTextLength<=0)return str;
058                
059                StringBuilder rtn=new StringBuilder();
060                String ls=SystemUtil.getOSSpecificLineSeparator();
061                Array arr = ListUtil.listToArray(str,ls);
062                int len=arr.size();
063                
064                for(int i=1;i<=len;i++) {
065                        rtn.append(wrapLine(Caster.toString(arr.get(i,""),""),wrapTextLength));
066                        if(i+1<len)rtn.append(ls);
067                }
068                return rtn.toString();
069        }
070
071        /**
072         * wrap a single line
073         * @param str
074         * @param wrapTextLength
075         * @return
076         */
077        private static String wrapLine(String str, int wrapTextLength) {
078                int wtl=wrapTextLength;
079                
080                if(str.length()<=wtl) return str;
081                
082                String sub=str.substring(0,wtl);
083                String rest=str.substring(wtl);
084                char firstR=rest.charAt(0);
085                String ls=SystemUtil.getOSSpecificLineSeparator();
086                
087                if(firstR==' ' || firstR=='\t') return sub+ls+wrapLine(rest.length()>1?rest.substring(1):"",wrapTextLength);
088                
089                
090                int indexSpace = sub.lastIndexOf(' ');
091                int indexTab = sub.lastIndexOf('\t');
092                int index=indexSpace<=indexTab?indexTab:indexSpace;
093                
094                if(index==-1) return sub+ls+wrapLine(rest,wrapTextLength);
095                return sub.substring(0,index) + ls + wrapLine(sub.substring(index+1)+rest,wrapTextLength);
096                
097        }
098
099    @Override
100        public Object invoke(PageContext pc, Object[] args) throws PageException {
101        if(args.length==2)
102                        return call(pc, Caster.toString(args[0]), Caster.toDoubleValue(args[1]));
103        if(args.length==3)
104                        return call(pc, Caster.toString(args[0]), Caster.toDoubleValue(args[1]), Caster.toBooleanValue(args[2]));
105
106                throw new FunctionException(pc, "Wrap", 2, 3, args.length);
107        }       
108}