<?
/** kalki template 0.02 alpha !!!
 *  date 2001.06.19
 *  autor daniel poelzleithner kalki@poelzi.org
 *  www   http://kalki.poelzi.org
 *  kalkitemplate is written on the white horse to destroy the overloaded grafik world
 *  to belt the world with <pre> 
*/

// 1  = strip tags = remove all <tags> from from string, don't count it
// 2  = break at word = look for the nearest " " (space) charakter to the maxlength and break there 
// 4  = ignore endtag = end on the size or word. don't enlarge to the endtag
// 8  = end of the string on a breakline (\n)
if(!defined("KALKI_SKIP_TAGS")) {
    
define("KALKI_SKIP_TAGS",1);
    
define("KALKI_BREAKWORD",2);
    
define("KALKI_IRGNORE_ENDTAG",4);
    
define("KALKI_LINEBREAK",8);
    
define("KALKI_LTRIM",16);
    
define("KALKI_RTRIM",32);
    
define("KALKI_RM_NSPACE",64);
}


class 
kalkitemplate {
    
    
// load a 
    
var    $data;
    var 
$depth;
    var 
$template;
    var 
$elements;

    
// stop after maxloops <kteof> tags.
    
var $maxloops 1000;
    
    var 
$default = array("options" => array(
                             
KALKI_BREAKWORD => true,
                             
KALKI_LINEBREAK => true,
                             
KALKI_RM_NSPACE => false,
                             
KALKI_SKIP_TAGS => true
                            
)
                        );
    
    function 
getResult($template "") {
        
$this->wdata $this->data;
        
$this->wtemplate $this->template
        return 
preg_replace ("/(<\/?kt(.*) )(.*)(?(?=e\/>)e\/>|<\/kt\\2>)/iUse",'$'."this->handleKT('\\3','\\2')",$this->template);

    }

    function 
handleKT($string,$tag) {
        if(
defined("DEBUG"))
            echo 
"handle:".$tag."[".$string."]\r\n";
        if(
$tag == "") { // normal single tag
            
$args $this->mkargs($string);
            return 
$this->singleKT($args);
        
// handle eof tag
        
} elseif($tag == "eof") { // end of file tag
            
$args $this->mkargs($string);
            
$result "";
            if(
trim($args["_data"]) == "")
                return 
"";
            if(
$args["text"] != "") {
                if(!
$args["max"])
                    
$args["max"] = 0;
                
$control explode(",",$args["text"]);
                
$break 0;
                
$oldsize 1;
                
$newsize 0;
                for(
$i 0; (($i $args["max"]) || $args["max"] == 0) && ($break != 1); $i++) {
                    
$newsize 0;
                    
$break 0;
                    for(
reset($control);list(,$test)  = each($control);) {
                        if(
$this->wdata[$test] == "" && ($break == 0)) {
                            
$break 1;
                        } elseif(
$this->wdata[$test] != "") {
                            
$break 2;
                            
$newsize += strlen($this->wdata[$test]);
                        }
                    }
                    if(
$oldsize == $newsize) {
                        if(
defined("DEBUG"))
                            echo 
"DEATHLOOP";
                        
$break 1;
                    }
                    
$result .= preg_replace ("/(<kt(.*) )(.*)\/>/iUe",'$'."this->handleKT('\\3','\\2')",$args["_data"]); 
                    
$oldsize $newsize;
                }
            }
            return 
$result;
        
// handle perferences tag    
        
} elseif($tag == "p") {
            
$this->default $this->mkargs($string);
        }
        
    }

    function 
mkargs($string) {
        
        
$string stripslashes($string);
        
        
$args = array();
        
$tag "";
        
$escape "";
        
$value "";
        
$hasvalue false;
        
$break false;
        for(
$i 0; ($i strlen($string)) && !$break$i++) {
            
$char $string[$i];
            if(
$escape == "") {
                if((
$char == " ") || ($char == ">") || ($char == "/")) {
                    if(
$tag != "" && $hasvalue) {
                        
$args[$tag] = $value;
                        
$tag "";
                        
$value "";
                        
$hasvalue false;
                    }
                } elseif((
$char == "'") || ($char == '"')) {
                    
$escape $char;
                    
$hasvalue true;
                } else {
                    if((
$char != "=") && ($char != ">")) {
                        
$tag .= trim($char); 
                    }
                } 
                if((
$i+1) == strlen($string) || (($char == ">") && ($escape == ""))) {
                    if(
trim($tag) != "") {
                        
$op $tag;
                        if(
substr($op,-1) == "/")
                            
$op substr($op,0,-1);
                        
$args["options"] = $op;
                    }
                    
$pos $i;
                    
$args["_data"] = substr($string,($i+1));
//                    echo "datt:".$args["_data"]."|<br>";
                    
$break true;
                    continue;
                }
            } else {
                if(
$char == $escape) {
                    
$escape "";
                } else {
                    
$value .= $char;
                }
            }
            
        }
        
        if(isset(
$args["m"]))
            
$args["mode"] = $args["m"];

        if(isset(
$args["s"]))
            
$args["size"] = $args["s"];

        if(!isset(
$args["mode"])) {
            if(isset(
$args["size"])) {
                
$args["mode"] = "size";
            }
        }

        if(isset(
$args["t"]))
            
$args["text"] = $args["t"];
        if(isset(
$args["a"]))
            
$args["align"] = $args["a"];
        if(isset(
$args["f"]))
            
$args["fill"] = $args["f"];
        if(isset(
$args["b"]))
            
$args["break"] = $args["b"];
        if(isset(
$args["m"]))
            
$args["must"] = $args["m"];
        if(isset(
$args["t"]))
            
$args["tags"] = $args["t"];

        
// now we not the atributes. progress handle and return it
        
        
return $args;

    }

    function 
singleKT($att) {
        
        
$pt ""// print text (without <> tags, if stripped)
        
$ct ""// complete text
        
        // merge default values with current
        
$att["options"] = $att["options"].$this->default["options"];
        
$att array_merge($this->default,$att);
        

        
$opps = array();
        
$options 0;

        if(
$att["text"] == ""// required
            
return false;

        for(
$i 0$i strlen($att["options"]); $i++) {
            switch(
$att["options"][$i]) {
                case 
"L"$opps[KALKI_LTRIM]= true; break;
                case 
"l"$opps[KALKI_LTRIM]= false; break;
                case 
"R"$opps[KALKI_RTRIM]= true; break;
                case 
"r"$opps[KALKI_LTRIM]= false; break;
                case 
"B"$opps[KALKI_LINEBREAK] = true; break; // enables ignore of breakline
                
case "b"$opps[KALKI_LINEBREAK] = false; break;
                case 
"I"$opps[KALKI_IRGNORE_ENDTAG] = true; break; // enables ignore of entags
                
case "i"$opps[KALKI_IRGNORE_ENDTAG] = false; break;
                case 
"W"$opps[KALKI_BREAKWORD] = true; break; // enables word breaks
                
case "w"$opps[KALKI_BREAKWORD] = false; break;
                case 
"S"$opps[KALKI_SKIP_TAGS] = true; break; // skip tags
                
case "s"$opps[KALKI_SKIP_TAGS] = false; break;
                case 
"n"$opps[KALKI_RM_NSPACE] = false; break;
                case 
"N"$opps[KALKI_RM_NSPACE] = true; break;
            }
        }
        while(list(
$c,$t) = each($opps))
            
$t $options += $c true;

        if(
substr($att["size"],0,1) == "l") {
            
$np strpos($this->wdata[$att["text"]],"\r"); // find first breakline
            
$result["string"] = $substr($this->wdata[$att["text"]],0,$np); // echo current line
            
$result["visible"] = $result["string"];
            
$result["length"] = strlen($result["string"]);
            
$this->wdata[$att["text"]] = substr($this->wdata[$att["text"]],$np); // remove printed text form work array
        
} else {
            
// handle size argument
            
            // options
            // change to form string
            
$result $this->formString($this->wdata[$att["text"]],$att["size"],$options);
            
//$result["string"] = substr($this->wdata[$att["text"]],0,$result["length"]);
            
$this->wdata[$att["text"]] = substr($this->wdata[$att["text"]],$result["length"]);
        }
        if(
defined("DEBUG"))
            
drawArray($result);
        
        
$pre ""// prefill buffer
        
$suf ""// suffix buffer

        
if(strlen($result["visible"]) < $att["size"]) {
            if(!isset(
$att["fill"]))
                
$att["fill"] = " ";
            if(
$att["fill"] != "") {
                switch(
$att["align"]) {
                    case 
"r":
                    case 
"right":
                        
$pre str_repeat($att["fill"], ($att["size"] - strlen($result["visible"])));
                        
//$pre = substr($pre,($att["size"] - strlen($pt)));
                        
break;
                    case 
"c":
                    case 
"center":
                        
$tot 
                        
$tot $att["size"] - strlen($result["visible"]);
                        
$pco = (integer)($tot/2);
                        
$pre str_repeat($att["fill"], $pco);
                        
$suf str_repeat($att["fill"], ($tot-$pre));
                    default:
                        
$suf str_repeat($att["fill"], ($att["size"] - strlen($result["visible"])));
                        
//$suf = substr($pre,($att["size"] - strlen($pt)));
                        
break;
                }
            }    
        }
        if(
defined("DEBUG"))
            echo 
"result:".$pre.$result["string"].$suf.":endresult";
        
$endresult $pre.$result["string"].$suf;
        if(
$options KALKI_LTRIM) {
            if(
defined("DEBUG"))
                echo 
" LTRIM ";
            
$endresult ltrim($endresult);
        }
        if(
$options KALKI_RTRIM) {
            if(
defined("DEBUG"))
                echo 
" RTRIM ";
            
$endresult rtrim($endresult);
        }
        return 
$endresult;
        
    }
    
    function 
formString($text,$length,$options) {
        
// options
        // 1  = strip tags = remove all <tags> from from string, don't count it
        // 2  = break at word = look for the nearest " " (space) charakter to the maxlength and break there 
        // 4  = ignore endtag = end on the size or word. don't enlarge to the endtag
        // 8  = end of the string on a breakline (\n)
        
        
$stop false;

//        $length = "";

        
$visible "";
        
$stripped ""// striped strings
        
        
$end false// end of loop
        // count string delimiter " '
        
$escape "";
        
// in a tag or not
        
$intag false;
        
// look for the element name
        
$begin false;

        
// current tagname
        
$ctag  ""
        
// count unclosed tags
        
$tags  = array();
        
// remember the last space charakter position
        
$lastwhite 0;
        
$string "";
        
$lengthadd 0;

        if(
defined("DEBUG"))
            echo 
"options:".$options;
        
        for(
$i 1;($i <= strlen($text)) && !$end;($end true $i++ )) {
            
$char $text[($i-1)];
            switch(
$char) {
                case 
"<":
                    
$stripped .= $char;
                    
$string   .= $char;
                    if(
$escape == "") {
                        
$intag true;
                        
$begin true;
                    }
                    break;
                case 
">":
                    
$stripped .= $char;
                    
$string   .= $char;
                    if(
$escape == "") {
                        
// last charakter was not / and the tag is not in the single tag array. we need to be aware them
                        
if(substr($ctag,0,1) == "/") {
                            
$_found false;
                            
$_last  0;
                            
reset($tags);
                            while(list(
$_i,$_n) = each($tags)) {
                                if(
$_n == substr($ctag,1)) {
                                    
$_last max($_last,$_i);
                                    
$_found true;
                                }
                            }
                            if(
$_found) {
                                unset(
$tags[$_last]);
                            }
                            unset(
$_found);
                            unset(
$_last);
                            unset(
$_i);
                            unset(
$_n);
                        } elseif((
substr($stripped,-1) != "/") && !in_array($ctag,kalkitemplate::singleTags())) {
                            
// this tag need a endtag. its needed for the size limit
                            
$tags[] = $ctag;
                            
$ctag "";
                        } 
                        
// tag end here
                        
$intag false;
                        
$begin false;
                    }
                    break;
                case 
"'":
                case 
'"':
                    
// if currently in tag an the last escape is current charakter
                    
if($intag && ($escape == $char)) { 
                        
$escape     ""// remove last
                        
$stripped  .= $char;
                        
$string    .= $char;
                    } elseif(
$intag) {
                        
$stripped  .= $char;
                        
$escape     $char;
                        
$string       .= $char;
                    } else {
                        
$visible .= $char;
                        
$string  .= $char;
                    }
                        
                    break;
                default: 
                    
// if begin = true. a < tag name is currently parsed
                    
if($begin) {
                        
// this 
                        
if($char == " ") {
                            
//$tags[] = $ctag; // put into tag array
                            
$begin false// tag finished
                            
$stripped .= $char;
                            
$string   .= $char;
                        } else {
                            
$ctag .= $char;
                            
$stripped .= $char;
                            
$string   .= $char;
                        }
                        continue;
                    }
                    
// breakline = end of string
                    
if(($options KALKI_LINEBREAK) && (($char == "\n") || ($char == "\r"))) {
                        if(
defined(DEBUG))
                            echo 
"endofline(\\n)";
                        
$lengthadd++;
                        if((
$char == "\r") && ($text[$i] == "\n"))
                            
$lengthadd++;
                        
$end true;
                        continue;
                    }
                    if(
$escape != "") {
                        
$stripped .= $char;
                        
$string   .= $char;
                    } elseif(
$intag) {
                        
$stripped .= $char;
                        
$string   .= $char;
                    } else {
                        if((
strlen($visible) <= ($length)) || ($length 1)) {
                            
$visible .= $char;
                            
$string  .= $char;
                            if(((
$char == " ") || ($char == "\t")) && (count($tags) == 0)) {
                                if(
defined("DEBUG"))
                                    echo 
"foundspace:".$i;
                                
$lastwhite = array($i,$stripped,$visible,$string); // remember the last white character
                            
}
                        } else {
                            if(!(
$options KALKI_IRGNORE_ENDTAG) && (count($tags) > 0)) {
                                
// need to enlarge. a non single tag had not ended
                                
$visible .= $char;
                                
$string   .= $char;
                                
                                
// handeling options for wordwrapping
                            
} elseif($options KALKI_BREAKWORD) {
                                if(
defined("DEBUG"))
                                    echo 
"ww";
                                if((
$char == " ") || ($char == "\t")) { 
                                    
//$i = $i-1;
                                    // thats perfect. next chrakter is a space and we should break here
                                    
$end true;
                                } elseif(
count($lastwhite) > 0) {
                                    
// set all back to the last whitespace charakter
                                    
$i = ($lastwhite[0]);
                                    
$stripped $lastwhite[1];
                                    
$visible $lastwhite[2];
                                    
$string  $lastwhite[3];
                                    if(
defined("DEBUG"))
                                         echo 
"Backtolastspace".$i;
                                    if(
$options KALKI_RM_NSPACE) {
                                        if((
$text[$i] == " ") || ($text[$i] == "\t")) {
//                                            $lengthadd++;
//                                            echo "hoho";
                                            //$stripped .= $text[$i];
                                            //$string .= $text[$i];
                                        
}
                                    }
                                    
$end true;
                                } else {
                                    if(
defined("DEBUG"))
                                         echo 
"Linetosmall";
                                    
// all work for nothing. the tag is to small for word breaking
                                    
$i 0;
                                    
$stripped "";
                                    
$visible "";
                                    
$string  "";
                                    
$end true;
                                }
                            } else {
                                
$end true;
                            }
                        }
                    } 
            }            
            
        }
        
$l 0;
        if(
$visible != "" || $stripped != "")
            
$l $i;
        return array(
"string"   => $string,
                     
"length"     => strlen($stripped)+strlen($visible)+$lengthadd,
                     
"stripped" => $stripped,
                     
"visible"     => $visible);
    }
    
    function 
loadTemplate($file) {
        if(
$fp fopen($file,"r")) {
            
$this->template    fread($fp,filesize($file));
            
fclose($fp);
            return 
true;
        } else {
            
trigger_error("mardon: can't open template file:".$fileE_USER_ERROR);
        }
    }
    
    function 
setTemplate($data) {
        
$this->template    $data;
        return 
true;
    }
    
    function 
setData($name,$data) {
        if(
$name != "") {
            if(
$data == false) {
                unset(
$this->data[$name]);
            } else {
                
$this->data[$name] = $data;
            }
        }
    }
    
    function 
getData($name) {
        return 
$this->data[$name];
    }

    function 
kalki($template "") {
        
$this->setTemplate($template);
        
        
$this->data     = array();
        
$this->depth     = array();
        
$this->template    false;
        
$this->elements = array();
    }
    
    function 
singleTags() {
        return     array(
"img","option");
    }
    
}
?>