#format python
"""
MoinMoin macro to specify columns
Columns.py
ark  06/14/04  0.1

    ***********
    by Antti Kuntsi <antti@kuntsi.com>

    As far as the author is concerned, this code is released to the public
    domain, but some restrictions in the MoinMoin COPYING file may apply. Ask a
    lawyer.
    ***********
    This code has not been tested exhaustively. Use at your own risk.
    ***********

    This macro generates containers, that can be used with CSS to create
    columns.

    Usage:
        [[Columns(mode,name,keywordargs)]]

        mode            start, next or end.

        name            Name of the div id. <div id="name">

        keywordargs     Zero or more key="value" arguments for the HTML div
                        tag.

    Examples:

        [[Columns(start, leftcolumn)]]
                This text is in the left column.
        [[Columns(next, rightcolumn)]]
                This text is in the right column.
        [[Columns(end)]]

   requires class definitions in CSS for the used column names, eg

#leftcolumn {
        position: relative;
        background: transparent;
        float: left;
        width: 45%;
        border-right: 1px solid gray;
        padding-left: 5%;
        padding-right: 1%;
        margin: 0px;
}

#rightcolumn {
        position: relative;
        background: transparent;
        float: right;
        width: 42%;
        padding-right: 1%;
        margin: 0px;
}


    Demo. Try pasting the above examples into a MoinMoin sandbox page and the
    current CSS.


"""


import string
from MoinMoin import wikiutil, config


DEFAULT_KEYWORD_ARGS = {}

def execute(macro, args):
    '''handle the Columns Macro. return the generated display HTML'''
    # parse the arguments
    if args==None:
        args = ''
    parseargs = _parse_arguments(args, ',', '"')
    #print parseargs, '<BR>'
    if len(parseargs)<1:
        return '<p><strong class="error">Columns macro must have at least one argument!</strong></p>'
    if parseargs[0] not in ("start", "next", "end"):
        return '<p><strong class="error">Unknown mode "<i>%s</i>"!</strong></p>'%(parseargs[0])
    mode = parseargs[0]

    if mode != "end":
        classname = parseargs[1].strip()
    else:
        classname=""
    kwargs = _parse_keyword_arguments(parseargs[2:], DEFAULT_KEYWORD_ARGS)
    # generate a string containing the keyword arguments
    kwstring = ''
    for key in kwargs.keys():
        kwstring = '%s %s="%s"'%(kwstring, key, kwargs[key])
    # generate a string specifying the location of the image
    divtag=""
    if mode in ("end", "next"):
            divtag += '</div>'
	    if mode == "end":
	    	divtag += '<br clear="both">'
    if mode in ("start", "next"):
            divtag += '<div id="%s"%s>'%(classname, kwstring)
    # combine target location, image location, and keyword arguments into HTML IMG tag
    result=[macro.formatter.paragraph(0),
    	macro.formatter.rawHTML(divtag),
	macro.formatter.paragraph(1)
	]

    return "".join(result)


def _parse_arguments(argstring, delimchar=',', quotechar='"'):
    '''parse argstring into separate arguments originally separated by delimchar.
    occurrences of delimchar found within quotechars are ignored.
    This parser is not particularly elegant. Improvements are welcome.
    jjk  03/28/01'''
    # replace delimiters not in quotes with a special delimiter
    delim2 = chr(0)
    inquote = 0
    for i1 in range(len(argstring)):
        cchar = argstring[i1]
        if cchar==quotechar:
            inquote = not inquote
        elif (not inquote) and cchar==delimchar:
            argstring = argstring[:i1] + delim2 + argstring[i1+1:]
    # split the argument string on the special delimiter, and remove external quotes
    args = string.split(argstring, delim2)
    for i1 in range(len(args)):
        arg = args[i1]
        if arg[:1]==quotechar and arg[-1:]==quotechar:
            args[i1] = arg[1:-1]
    return args


def _parse_keyword_arguments(raw_kw_args=[], default={}):
    '''given a list of 'key=value' and/or 'key="value"',
    answer a dictionary of {key:value}
    jjk  03/28/01'''
    kwargs = {}
    kwargs.update(default)
    for keyvalstr in raw_kw_args:
        keyval = string.split(keyvalstr, '=')
        if len(keyval)==0:
            continue
        elif len(keyval)==1:
            key = keyval[0]
            value = ''
        elif len(keyval)==2:
            key = keyval[0]
            value = keyval[1]
        elif len(keyval)>2:
            key = keyval[0]
            value = string.join(keyval[1:],'=')
        if value[:1]=='"':
            value = value[1:]
        if value[-1:]=='"':
            value = value[:-1]
        kwargs[string.lower(key)] = value
    return kwargs


def _is_URL(aString):
    '''answer true if aString is a URL.
    The method used here is pretty dumb. Improvements are welcome.
    jjk  03/28/01'''
    return string.find(aString, '://')>0
