<?

/*
    omlsettings.php
    Copyright 2004 by Sylvester Hesp, s.hesp@xs4all.nl
    
    LICENSE INFO
    You can use this source freely for non-commercial purposes, be sure to include this copyright notice if you use
    the source or parts thereof.
    For commercial purposes, mail me, we can probably work something out.
*/


define ("OML_HANDLER"0);
define ("OML_FLAGS"1);
define ("OML_OPTIONS"2);

define ("OML_FLAG_OPEN"1);
define ("OML_FLAG_PRE"2);
define ("OML_FLAG_POST"4);
define ("OML_FLAG_CLOSE"8);
define ("OML_FLAG_SUBTAGS"16);
define ("OML_FLAG_CLOSEOPTIONAL"32);
define ("OML_FLAG_NOINNERTEXT"64);
define ("OML_FLAG_ALIAS"128);
define ("OML_FLAG_REMOVEOPENBR"256);
define ("OML_FLAG_REMOVECLOSEBR"512);

define ("OML_PLAIN_TAG""=plain");


$oml_settings_default = array
(
    
OML_PLAIN_TAG => array (""OML_FLAG_SUBTAGS)
);



function 
_oml_parse_options ($s, &$options)
{
    if (
$s[0] == '=')
    {
        
$r = array ();
        
preg_match_all ("/(?:\"([^\"]*)\"|([^\\s,\"]*))\\s*(?:,|$)/U"substr ($s1), $matchesPREG_SET_ORDER);
        
$i 0;
        
$c count ($options);
        foreach (
$matches as $m)
        {
            
$t = isset ($m[2]) ? $m[2] : $m[1];
            if (
$t != "")
            {
                
$r[$i] = $t;
                if (
$i $c)
                    
$r[$options[$i]] = $r[$i];
            }
            
$i++;
        }
    }
    else
    {
        
$r = array ();
        
preg_match_all ("/(\S+)\s*=\s*(?:([^\"\s]\S+)|\"([^\"]*)\")/"$s$matchesPREG_SET_ORDER);
        foreach (
$matches as $m)
            
$r[strtolower ($m[1])] = isset ($m[3]) ? $m[3] : $m[2];
    }

    return 
$r;
}

function 
_oml_close_tag ($tag$text, &$settings, &$state)
{
    
$handler $settings[$tag[0]][OML_HANDLER];
    
$flags $settings[$tag[0]][OML_FLAGS];
    
    if (
$flags OML_FLAG_OPEN)
        
$handler ($tag[0], $tag[1], 0OML_FLAG_OPEN$state);
        
    
$r "";
    if (
$flags OML_FLAG_PRE)
    {
        foreach (
$text as $t)
        {
            if (
$t[1])
                
$r .= $handler ($tag[0], $tag[1], $t[0], OML_FLAG_PRE$state);
            else
                
$r .= $t[0];
        }
    }
    else foreach (
$text as $t)
        
$r .= $t[0];

    if (
$flags OML_FLAG_POST)
        
$r $handler ($tag[0], $tag[1], $rOML_FLAG_POST$state);
        
    if (
$flags OML_FLAG_CLOSE)
        
$handler ($tag[0], $tag[1], $rOML_FLAG_CLOSE$state);
        
    
$state[$tag[0]]--;
    
    return 
$r;
}

function 
_oml_close_untill ($u, &$tags, &$texts, &$settings, &$state)
{
    
$level 0;

    while (
$u != $tags[0][0])
    {
        
$state[$tags[0][0]]--;
        
        if (
$settings[$tags[0][0]][OML_FLAGS] & OML_FLAG_CLOSEOPTIONAL)
            
$texts[1][] = array ($settings[$tags[0][0]][OML_HANDLER] ($tags[0][0], $tags[0][1], 0OML_FLAG_NOINNERTEXT$state), false);
        else                    
            
$texts[1][] = array ($tags[0][2], true);

        
$texts[1] = array_merge ($texts[1], $texts[0]);
        
array_shift ($tags);
        
array_shift ($texts);
        
$level++;
    }
    
    return 
$level;
}


function 
oml_parse ($text$settings 0$state = array ())
{
    global 
$oml_settings_default;

    if (!
$settings)
        
$settings $oml_settings_default;
        
    foreach (
$settings as $k => $v)
        if (!isset (
$state[$k]) || !is_int ($state[$k]))
            
$state[$k] = 0;
            
    
preg_match_all ("/(.*)(?:(\\[(\\/?)(?:([\\w*]+)(?:\s*([=\s](?:[^\s\"].*|\"[^\"]*\"(?:\"[^\"]*\"\\s*,\\s*)*)))?)?\\]|\\[\\\\\\[\\]|\\[\\\\\\]\\])|$)/sUD"$text$matchesPREG_SET_ORDER);
    
    
$tags = array (array (OML_PLAIN_TAG, array (), ""));
    
$texts = array (array ());
    
$level 0;
    
$tagsettings $settings[$tags[0][0]];
    
$state[OML_PLAIN_TAG]++;
    
$removebr false;
    
    foreach (
$matches as $match)
    {
        if (
$match[0] == "")
            break;

        if (
$removebr && strlen ($match[1]) > 0)
        {
            
$i 0;
            if (
$match[1]{0} == "\n")
                
$i 1;
            else if (
$match[1]{0} == "\r")
            {
                
$i 1;
                if (
strlen ($match[1]) > && $match[1]{1} == "\n")
                    
$i 2;
            }
            if (
$i 0)
                
$match[1] = substr ($match[1], $i);
        }
        
$removebr false;
        
$texts[0][] = array ($match[1], true);
        
$m array_map ("strtolower"$match);
        
        if (isset (
$m[3]) && $m[3] == "/")
        {
            
$t = isset ($m[4]) ? $m[4] : 0;
            if (
$t && isset ($settings[$t]) && ($settings[$t][OML_FLAGS] & OML_FLAG_ALIAS))
                
$t $settings[$t][OML_HANDLER];

            if (
$level && (!$t || (isset ($state[$t]) && $state[$t] > 0)))
            {
                if (
$t && $t != $tags[0][0])
                    
$level -= _oml_close_untill ($t$tags$texts$settings$state);
                
                
$tags[0][1][1] = $match[2];
                
$removebr $settings[$tags[0][0]][OML_FLAGS] & OML_FLAG_REMOVECLOSEBR;
                
$r _oml_close_tag (array_shift ($tags), array_shift ($texts), $settings$state);
                
$tagsettings $settings[$tags[0][0]];
                
$texts[0][] = array ($rfalse);
                
$level--;
            }
            else
                
$texts[0][] = array ($match[2], true);
        }
        
        else if ((
$tagsettings[OML_FLAGS] & OML_FLAG_SUBTAGS) && isset ($m[4]) && isset ($settings[$m[4]]))
        {
            
$t $m[4];
            if (
$settings[$t][OML_FLAGS] & OML_FLAG_ALIAS)
                
$t $settings[$t][OML_HANDLER];

            
$p = isset ($m[5]) ? _oml_parse_options ($match[5], $settings[$t][OML_OPTIONS])  : array ();
            
$p[0] = $match[2];
            
            if (
$settings[$t][OML_FLAGS] & OML_FLAG_NOINNERTEXT)
            {
                
$texts[0][] = array ($settings[$t][OML_HANDLER] ($t$p0OML_FLAG_NOINNERTEXT$state), false);
                
$removebr $settings[$t][OML_FLAGS] & OML_FLAG_REMOVECLOSEBR;
            }
            else
            {
                
array_unshift ($tags, array ($t$p$match[2]));
                
array_unshift ($texts, array ());
                
$state[$t]++;
                
$level++;
                
$tagsettings $settings[$t];
                
$removebr $tagsettings[OML_FLAGS] & OML_FLAG_REMOVEOPENBR;
            }
        }
        
        else if (isset (
$match[2]))
        {
            if (
$match[2] == "[\\[]")
                
$match[2] = "[";
            else if (
$match[2] == "[\\]]")
                
$match[2] = "]";
            
$texts[0][] = array ($match[2], true);
        }
    }
    
    if (
$level 0)    
        
_oml_close_untill (OML_PLAIN_TAG$tags$texts$settings$state);

    return 
_oml_close_tag ($tags[0], $texts[0], $settings$state);
}

function 
oml_escape ($text)
{
    return 
strtr ($text, array ("[" => "[\[]""]" => "[\]]"));
}


?>