"""
    EventCalendar.py  Version 0.90  2005. 11. 15.
                                                                                                           
    This macro gives a list of the events recorded in the sub-pages in the form of monthly view and list view.
                                                                                                           
    @copyright: 2005 by Seungik Lee <seungiklee<at>gmail.com>  http://cds.icu.ac.kr/~silee/
    @license: GPL

    For more information, please visit http://moinmoin.wikiwikiweb.de/MacroMarket/EventCalendar

    Usage: 
        To list the events in a page, just insert [[EventCalendar]]
        To insert an event, enclose the information about the event with 'eventcal' in the page or its subpages.
        
            E.g., 
                {{{#!eventcal
                    = [Title] =
                    [Start Date] ... [End Date]
                    [Start Time] ... [End Time]
                }}}
            
            [Title] should be enclosed with heading marker ('='), double quatation mark ("), wiki italic or bold ('', ''')
                Title can be omitted and it will be titled as 'No Title'
                e.g., == Title ==, === Title ===, "Title", ''Title'', '''Title'''
            
            [Start|End Date] should be in YYYY/MM/DD or YYYY-MM-DD. End date can be omitted.
                e.g, 2005/10/20, 2005-10-20
            
            [Start|End Time] should be in HH:MM in 24-hour format. Both of start|end Time can be omitted but not either of them.
                e.g., 08:00, 12:00, 18:00
            
            In the parsing block of eventcal, it pops out first two date formatted text (startdate and enddate), 
            two time formatted text (starttime, endtime), and quoted or heading titie. 
            
            It ignores further occurrence of the targeted string. 
            The order of each fields (date, time, title) does not matter .
            The start date|time should precede the end date|time in the occurrence respectively.
        
        Use 'eventcal.py' to get a parsed format of the event which will be shown at the EventCalendar macro.
        To insert an administrative event, just click the [New Event] and input the information. It will be stored in a text file.
        
    Features:
        Monthly, List, Item view of events 
        Handles daily and timely events 
        Uses wiki subpages for storing normal event data 
        Fields included: Title, Start/End Date/Time, Reference Page in wiki 

    Notes:
        'MonthCalendar.py' developed by Thomas Waldmann <ThomasWaldmann@gmx.de> has inspired this macro.
        Much buggy.. :please report bugs and suggest your ideas.
        If you missed to add css for EventCalender, monthly view may not readable.
            Insert the EventCalendar css classes into the common.css of appropriate theme.

"""

from MoinMoin import wikiutil, config
from MoinMoin.Page import Page
from MoinMoin.parser import wiki
import re, calendar, time, datetime
import codecs, os, urllib, StringIO


# The following line sets the calendar to have either Sunday or Monday as
# the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
# valid here.  All other values will not make good calendars.
# XXX change here ----------------vvvvvv
calendar.setfirstweekday(calendar.SUNDAY)

class Globs:
    month_style_us = 1  # 1: October 2005; 2: 2005 / 10
    adminmsg=''
    pagepath = ''
    admin=''
    baseurl=''
    subname=''
    wkend = ''
    months = ''
    wkdays = ''
    today = ''
    request=''
    cal_action=''
    adjustimage = 0


class Params:
    pagedepth = 0
    pagename = ''
    menubar = 0
    messages = 0
    monthlywidth = ''
    simplewidth = ''
    firstview = ''
    curdate = ''
    bgcolor = ''

def execute(macro, args):
    
    # INITIALIZATION ----------------------------------------
    setglobalvalues(macro)
    getparams(args)
    setinternalvalues(macro)
    
    # allowed actions
    allowed_action = ['monthly', 'list', 'simple']
    default_action = Params.firstview
    
    # Internal variables
    cal_action = ''
    form_vals = {}

    # PROCESSING ARGUEMENTS ----------------------------------------
    if args:
        args=macro.request.getText(args)

    for item in macro.form.items():
        if not form_vals.has_key(item[0]):
	    try:
		    form_vals[item[0]]=item[1][0]
	    except AttributeError:
	        pass
    
    # PROCESSING ACTIONS ----------------------------------------
    cal_action = form_vals.get('calaction', default_action)
    
    if not cal_action in allowed_action:
        cal_action = default_action
    
    form_vals['calaction'] = cal_action

    # CONTROL FUNCTIONS ----------------------------------------
    
    html = []
    html_result = ''
    
    request = macro.request
    formatter = macro.formatter
    
    Globs.cal_action = cal_action
    
    # redirect to the appropriate view
    if cal_action == 'monthly':
        html_result = showcalendar(macro, form_vals)
        
    if cal_action == 'list':
        html_result = showeventlist(macro, form_vals)

    if cal_action == 'simple':
        html_result = showsimplecalendar(macro, form_vals)
    
    
    # format output
    html.append( showmessage() )
    html.append( html_result )
    html.append( showmenubar(form_vals) )
    
    return formatter.rawHTML(u''.join(html))


def setinternalvalues(macro):
    # do nothing now    
    nothing = ''

def getparams(args):
    # process arguments
    
    params = {}
    if args:
        # Arguments are comma delimited key=value pairs
        sargs = args.split(',')
    
        for item in sargs:
            sitem = item.split('=')
        
            if len(sitem) == 2:
                key, value = sitem[0], sitem[1]
                params[key.strip()] = value.strip()

    # page name: the page which the events will be resolved from
    # default: the page itself which the macro locates
    Params.pagename = params.get('pagename', Globs.pagename)
    
    # page depth: how much depth from the pagename when reading events
    # default: 0
    try:
        Params.pagedepth = int(params.get('pagedepth', 0))
    except ValueError:
        Params.pagedepth = 0

    # menu bar: shows menubar or not (1: show, 0: no menubar)
    # default: 1
    try:
        Params.menubar = int(params.get('menubar', 1))
    except ValueError:
        Params.menubar = 1
        
    # message: shows messages or not (1: show, 0: no message)
    # default: 1
    try:
        Params.messages = int(params.get('messages', 1))
    except ValueError:
        Params.messages = 1
    
    # calendar width in pixel or percent (monthly)
    # default: 600px
    Params.monthlywidth = params.get('monthlywidth', '600')
    if Params.monthlywidth:
        # Params.monthlywidth = Params.monthlywidth.replace('%', '%%')
        Params.monthlywidth = ' width="%s" ' % Params.monthlywidth
        
    # calendar width in pixel or percent (simply)
    # default: 150px
    Params.simplewidth = params.get('simplewidth', '150')
    if Params.simplewidth:
        # Params.simplewidth = Params.simplewidth.replace('%', '%%')
        Params.simplewidth = ' width="%s" ' % Params.simplewidth
    
    # calendar view: monthly, list, simple
    # default: 'monthly'
    Params.firstview = params.get('firstview', 'monthly')

    # calendar date: in YYYYMM format (in monthly, simple view)
    # default: current month
    Params.curdate = params.get('curdate', '')

    # default bgcolor
    Params.bgcolor = '#ddffdd'

def setglobalvalues(macro):
    
    request = macro.request
    
    # Useful variables
    Globs.baseurl = macro.request.getBaseURL() + '/'
    Globs.pagename = macro.formatter.page.page_name
    Globs.request = request
    Globs.formatter = macro.formatter
    
    # This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
    Globs.subname = Globs.pagename.split('/')[-1]

    pagepath = macro.formatter.page.getPagePath()
    Globs.pagepath = macro.formatter.page.getPagePath()
    
    # Figure out if we have delete privs
    try:
        # If a user can delete the page containing the EventCalendar, then they are considered a EventCalendar administrator
        if macro.request.user.may.delete(macro.formatter.page.page_name):
            Globs.admin = 'true'
    except AttributeError:
        pass
    
    # european / US differences
    months = ('January','February','March','April','May','June','July','August','September','October','November','December')
    
    # Set things up for Monday or Sunday as the first day of the week
    if calendar.firstweekday() == calendar.MONDAY:
        wkend = 6
        wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
    elif calendar.firstweekday() == calendar.SUNDAY:
        wkend = 0
        wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
    
    Globs.months = months
    Globs.wkdays = wkdays
    Globs.wkend = wkend

    year, month, day, h, m, s, wd, yd, ds = request.user.getTime(time.time())
    Globs.today = datetime.date(year, month, day)


def showReferPageParsed(event, targettext='refer'):
    request = Globs.request
    pagename = Params.pagename
    
    refer = event['refer']
    title = event['title']
    targettext = event[targettext]
    startdate = event['startdate']
    
    bookmark = u'%s%s' % (title.replace(' ', ''), startdate)
    bookmark = urllib.quote_plus(bookmark.encode(config.charset))
    targetlink = Page(request, refer).link_to(request, text=targettext.strip(), querystr='action=show', anchor=bookmark)
    
    return targetlink



def getquerystring(form_vals, req_fields):
    
    m_query = []
    tmp_form_vals = form_vals
    
    # format querystring
    # action should be poped out
    for field in req_fields:
        if tmp_form_vals.has_key(field):
            m_query.append(u'%s=%s' % (field, tmp_form_vals[field]) )
    
    if 'prevcalaction' in req_fields:
        if not tmp_form_vals.has_key('prevcalaction'):
            m_query.append(u'%s=%s' % ('prevcalaction', tmp_form_vals['calaction']) )
            
    m_query = u'&'.join(m_query)
    return m_query

# bottom menu bar
def showmenubar(form_vals):
    
    cal_action = Globs.cal_action
    
    if not Params.menubar: return ''

    if cal_action == 'simple':
        menuwidth = Params.simplewidth
    elif cal_action == 'monthly':
        menuwidth = Params.monthlywidth
    else:
        menuwidth = ''
    
    left_menu_selected = []
    right_menu_selected = []
    
    # Go Today
    year, month, day = gettodaydate()
    mnu_curmonthcal = u'<a href="?calaction=%s&caldate=%d%02d">[Today]</a>' % (cal_action, year, month)
    
    # List View
    mnu_listview = u'<a href="?calaction=list">[List]</a>'
    
    # Monthly View
    mnu_monthview = u'<a href="?calaction=monthly&%s">[Monthly]</a>' % getquerystring(form_vals, ['caldate'])
    
    # Simple Calendar View
    mnu_simpleview = u'<a href="?calaction=simple&%s">[Simple]</a>' % getquerystring(form_vals, ['caldate'])

    html = [
        u'\r\n',
        u'<table class="eventcalendar_menubar" %s>',
        u'  <tr>',
        u'  <td class="eventcalendar_menubar" align="left">%s</td>',
        u'  <td class="eventcalendar_menubar" align="right">%s</td>',
        u'  </tr>',
        u'</table>',
        ]
        
    if cal_action == 'list':
        left_menu_selected.append(mnu_monthview)
        left_menu_selected.append(mnu_simpleview)

    elif cal_action == 'simple':
        left_menu_selected.append(mnu_monthview)
        left_menu_selected.append(mnu_listview)
        right_menu_selected.append(mnu_curmonthcal)

    else:
        left_menu_selected.append(mnu_listview)
        left_menu_selected.append(mnu_simpleview)
        right_menu_selected.append(mnu_curmonthcal)

    left_menu_selected = u'\r\n'.join(left_menu_selected)
    right_menu_selected = u'\r\n'.join(right_menu_selected)
    
    html = u'\r\n'.join(html)
    html = html % (menuwidth, left_menu_selected, right_menu_selected)

    return html
        

def getdatefield(str_date):
    str_year = ''
    str_month = ''
    str_day = ''
    
    if len(str_date) == 6:
        # year+month
        str_year = str_date[:4]
        str_month = str_date[4:]
        str_day = '1'

    elif len(str_date) == 8:
        # year+month+day
        str_year = str_date[:4]
        str_month = str_date[4:6]
        str_day = str_date[6:]
    
    elif len(str_date) == 10:
        # year+?+month+?+day
        str_year = str_date[:4]
        str_month = str_date[5:7]
        str_day = str_date[8:]
    
    else:
        raise ValueError
    
    # It raises exception if the input date is incorrect
    temp = datetime.date(int(str_year), int(str_month), int(str_day))

    return temp.year, temp.month, temp.day


def gettimefield(str_time):
    str_hour = ''
    str_min = ''
    
    if len(str_time) == 4:
        # hour+minute
        str_hour = str_time[:2]
        str_min = str_time[2:]
    
    elif len(str_time) == 5:
        # hour+?+minute
        str_hour = str_time[:2]
        str_min = str_time[3:]
        
    else:
        raise ValueError
    
    # It raises exception if the input date is incorrect
    temp = datetime.time(int(str_hour), int(str_min))

    return temp.hour, temp.minute

def showmessage():
    if not Params.messages: return ''
    
    if Globs.adminmsg:
        return u'<table class="eventcalendar_msg"><tr><td class="eventcalendar_msg">%s</td></tr></table>' % Globs.adminmsg
    else:
        return ''

def gettodaydate():
    today = Globs.today
    return today.year, today.month, today.day    


def cal_listhead():

    html = [
        u'  <tr>',
        u'      <td class="list_head">Title</td>',
        u'      <td class="list_head">Start Date</td>',
        u'      <td class="list_head">Start Time</td>',
        u'      <td class="list_head">End Date</td>',
        u'      <td class="list_head">End Time</td>',
        u'      <td class="list_head">Reference</td>',
        u'  </tr>',
        ]
        
    return u'\r\n'.join(html)


def showeventlist(macro, form_vals):
    
    request = macro.request
    formatter = macro.formatter
    
    html_event_rows = []
    html_list_header = cal_listhead()
    
    # read all the events from data file
    events, cal_events = loadEvents(macro)
    
    # sort events
    sorted_eventids = events.keys()
    sorted_eventids.sort(cmp=lambda x,y: cmp(events[x]['startdate'], events[y]['startdate']))
    
    for eid in sorted_eventids:
        html_event_rows.append( listshow_event(events[eid], form_vals) )
    
    html_event_rows = u'\r\n'.join(html_event_rows)
    
    html_list_table = [
        u'\r\n<div id="eventlist">',
        u'<table class="eventlist">',
        u'%s' % html_list_header,
        u'%s' % html_event_rows,
        u'</table>',
        u'</div>',
        ]
    html_list_table = u'\r\n'.join(html_list_table)
        
    return html_list_table
        

def listshow_event(event, form_vals):
    
    syear, smonth, sday = getdatefield(event['startdate'])
    eyear, emonth, eday = getdatefield(event['enddate'])
    
    time_info = 1
    try:
        shour, smin = gettimefield(event['starttime'])
        ehour, emin = gettimefield(event['endtime'])
    except ValueError:
        time_info = 0
    
        
    if time_info:
        html = [
            u'  <tr>',
            u'  <td class="list_entry">%s%s</td>' % (geticonurl(event['icon']), converttext(event['title'])),
            u'  <td class="list_entry">%d %02d/%02d</td>' % (syear, smonth, sday),
            u'  <td class="list_entry">%02d:%02d</td>' % (shour, smin),
            u'  <td class="list_entry">%d %02d/%02d</td>' % (eyear, emonth, eday),
            u'  <td class="list_entry">%02d:%02d</td>' % (ehour, emin),
            u'  <td class="list_entry">%s</td>' % showReferPageParsed(event, 'refer'),
            u'  </tr>',
            ]
    
    else:
        html = [
            u'  <tr>',
            u'  <td class="list_entry">%s%s</td>' % (geticonurl(event['icon']), converttext(event['title'])),
            u'  <td class="list_entry">%d %02d/%02d</td>' % (syear, smonth, sday),
            u'  <td class="list_entry">&nbsp;</td>',
            u'  <td class="list_entry">%d %02d/%02d</td>' % (eyear, emonth, eday),
            u'  <td class="list_entry">&nbsp;</td>',
            u'  <td class="list_entry">%s</td>' % showReferPageParsed(event, 'refer'),
            u'  </tr>',
            ]
        
    return u'\r\n'.join(html)


def geticonurl(icon):
    if not icon:
        return ''
    
    request = Globs.request
    formatter = Globs.formatter
    
    
    out = StringIO.StringIO()
    request.redirect(out)
    wikiizer = wiki.Parser(icon, request)
    wikiizer.format(formatter)
    iconurl = out.getvalue()
    request.redirect()
    del out
    
    if Globs.adjustimage:
        regex_icon_height = r'height="[0-9]+"'
        pattern = re.compile(regex_icon_height, re.UNICODE + re.IGNORECASE)
        iconurl = pattern.sub('height="10"', iconurl)
        
        regex_icon_width = r'width="[0-9]+"'
        pattern = re.compile(regex_icon_width, re.UNICODE + re.IGNORECASE)
        iconurl = pattern.sub('', iconurl)
        
    iconurl = iconurl.replace('<p>', '')
    iconurl = iconurl.replace('</p>', '')
    
    return iconurl

def showcalendar(macro, form_vals):
    
    request = macro.request
    formatter = macro.formatter
    
    if form_vals.has_key('caldate'):
        try:
            year, month, str_temp = getdatefield(form_vals['caldate'])
        except ValueError:
            message('Invalid target date: e.g., "200510"')
            year, month, dy = gettodaydate()
    elif Params.curdate:
        try:
            year, month, str_temp = getdatefield(Params.curdate)
        except ValueError:
            message('Invalid target date: e.g., "200510"')
            year, month, dy = gettodaydate()
            
    else:
        year, month, dy = gettodaydate()
    
    html = showeventcalendar(macro, year, month)
    
    return u''.join(html)
    
def showsimplecalendar(macro, form_vals):
    
    request = macro.request
    formatter = macro.formatter
    
    if form_vals.has_key('caldate'):
        try:
            year, month, str_temp = getdatefield(form_vals['caldate'])
        except ValueError:
            message('Invalid target date: e.g., "200510"')
            year, month, dy = gettodaydate()
    elif Params.curdate:
        try:
            year, month, str_temp = getdatefield(Params.curdate)
        except ValueError:
            message('Invalid target date: e.g., "200510"')
            year, month, dy = gettodaydate()
    else:
        year, month, dy = gettodaydate()
    
    html = showsimpleeventcalendar(macro, year, month)
    
    return u''.join(html)


# load events from wiki pages
def loadEvents(macro, datefrom='', dateto=''):
    
    events, cal_events = loadEventsFromWikiPage(macro, datefrom, dateto)
    
    Globs.events = events
    Globs.cal_events = cal_events
    
    return events, cal_events

# count events from wiki pages for simple view
def countEvents(macro, datefrom='', dateto=''):
    
    cal_events = countEventsFromWikiPage(macro, datefrom, dateto)
    
    Globs.cal_events = cal_events
    
    return cal_events

# sort cal_events by length of days
def comp_cal_events(xid, yid):
    events = Globs.events
    
    if events[xid]['date_len'] > events[yid]['date_len']:
        return -1
    elif events[xid]['date_len'] == events[yid]['date_len']:
        if events[xid]['date_len'] == 1:
            return cmp(events[xid]['starttime'], events[yid]['starttime'])
        else:
            return 0
    else:
        return 1
        


def loadEventsFromWikiPage(macro, datefrom, dateto):
    
    events = {}
    cal_events = {}
    
    request = macro.request
    depth = Params.pagedepth
    parent = Params.pagename
    
    try:
        datefrom, dateto = int(datefrom), int(dateto)
    except ValueError:
        datefrom, dateto = 0, 0
    
    # reads events from child pages
    children = getPages(request, '^%s/' % parent)
    
    # append the page itself
    children.append(parent)
    
    id = 0
    for child in children:
        shortname = child[len(parent):]
        # possibly limit depth
        if shortname.count('/') > depth:
            continue
        
        p = Page(request, child)
        page_content = p.get_raw_body()
        
        for evtrecord in getEventRecordFromPage(page_content):
            try:
                e_start_date, e_start_time, e_end_date, e_end_time, e_title, e_view, e_bgcolor, e_icon = geteventfield(evtrecord)
            except ValueError:
                # message('An event data is corrupted: invalid event format')
                continue
            
            try:
                e_start_year, e_start_month, e_start_day = getdatefield(e_start_date)
                e_end_year, e_end_month, e_end_day = getdatefield(e_end_date)
            except ValueError:
                # message('An event data is corrupted: invalid date format')
                continue
            
            if e_start_time and e_end_time:
                try:
                    e_start_time_hour, e_start_time_min = gettimefield(e_start_time)
                    e_end_time_min, e_end_time_min = gettimefield(e_end_time)
                except ValueError:
                    # message('An event data is corrupted: invalid time format')
                    continue
            
            e_ref = p.page_name
            
            if not e_start_date:
                # message('An event data is corrupted: invalid time format')
                continue
            
            if datefrom and dateto:
                if int(e_end_date) < datefrom or int(e_start_date) > dateto:
                    continue
            
            id += 1
            e_id = u'evt%d' % id
            
            # store event information
            events[e_id] = {}
            events[e_id]['id'] = e_id
            events[e_id]['startdate'] = e_start_date
            events[e_id]['starttime'] = e_start_time
            events[e_id]['enddate'] = e_end_date
            events[e_id]['endtime'] = e_end_time
            events[e_id]['title'] = e_title
            events[e_id]['refer'] = e_ref
            events[e_id]['bgcolor'] = e_bgcolor
            events[e_id]['icon'] = e_icon
            events[e_id]['date_len'] = diffday(e_start_date, e_end_date) + 1
            # events[e_id]['view'] = e_view
            
            # message('event %s: %s' % (e_id, events[e_id]))
            
            # records event information for each date b/w start and end
            cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day)
            day_delta = datetime.timedelta(days=1)
            
            while 1:
                tmp_record_date = formatDate(cur_datetime.year, cur_datetime.month, cur_datetime.day)
                
                if datefrom and dateto:
                    if int(tmp_record_date) < datefrom:
                        cur_datetime = cur_datetime + day_delta
                        continue
                    elif int(tmp_record_date) > dateto:
                        break
                        
                if not cal_events.has_key(tmp_record_date):
                    cal_events[tmp_record_date] = []
                cal_events[tmp_record_date].append(e_id)
                
                if tmp_record_date == e_end_date:
                    break
                
                cur_datetime = cur_datetime + day_delta
    
    return events, cal_events


def countEventsFromWikiPage(macro, datefrom, dateto):
    
    cal_events = {}
    
    request = macro.request
    depth = Params.pagedepth
    parent = Params.pagename
    
    try:
        datefrom, dateto = int(datefrom), int(dateto)
    except ValueError:
        datefrom, dateto = 0, 0
    
    # reads events from child pages
    children = getPages(request, '^%s/' % parent)
    
    # append the page itself
    children.append(parent)
    
    id = 0
    for child in children:
        shortname = child[len(parent):]
        # possibly limit depth
        if shortname.count('/') > depth:
            continue
        
        p = Page(request, child)
        page_content = p.get_raw_body()
        
        for evtrecord in getEventRecordFromPage(page_content):
            try:
                e_start_date, e_start_time, e_end_date, e_end_time, e_title, e_view, e_bgcolor, e_icon = geteventfield(evtrecord)
            except ValueError:
                # message('An event data is corrupted: invalid event format')
                continue
            
            try:
                e_start_year, e_start_month, e_start_day = getdatefield(e_start_date)
                e_end_year, e_end_month, e_end_day = getdatefield(e_end_date)
            except ValueError:
                # message('An event data is corrupted: invalid date format')
                continue
            
            if e_start_time and e_end_time:
                try:
                    e_start_time_hour, e_start_time_min = gettimefield(e_start_time)
                    e_end_time_min, e_end_time_min = gettimefield(e_end_time)
                except ValueError:
                    # message('An event data is corrupted: invalid time format')
                    continue
            
            e_ref = p.page_name
            
            if not e_start_date:
                # message('An event data is corrupted: invalid time format')
                continue
            
            if datefrom and dateto:
                if int(e_end_date) < datefrom or int(e_start_date) > dateto:
                    continue
                    
            id += 1
            e_id = u'evt%d' % id
            
            # records event information for each date b/w start and end
            cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day)
            day_delta = datetime.timedelta(days=1)
            
            while 1:
                tmp_record_date = formatDate(cur_datetime.year, cur_datetime.month, cur_datetime.day)
                
                if datefrom and dateto:
                    if int(tmp_record_date) < datefrom:
                        cur_datetime = cur_datetime + day_delta
                        continue
                    elif int(tmp_record_date) > dateto:
                        break
                        
                if not cal_events.has_key(tmp_record_date):
                    cal_events[tmp_record_date] = []
                cal_events[tmp_record_date].append(e_id)
                
                if tmp_record_date == e_end_date:
                    break
                
                cur_datetime = cur_datetime + day_delta
    
    return cal_events


def getEventRecordFromPage(pagecontent):
    
    eventrecords = []
    eventitem = {}
    
    # format specified page
    regex_eventcal = r'^#FORMAT eventcal(\s*.*)'
    pattern = re.compile(regex_eventcal, re.UNICODE + re.MULTILINE + re.IGNORECASE)
    match = pattern.findall(pagecontent)
    
    if match:
        
        regex_params = r'^#FORMAT eventcal(\s*.*)$'
        pattern = re.compile(regex_params, re.UNICODE + re.MULTILINE + re.IGNORECASE)
        match_option = pattern.findall(pagecontent)
        
        if match_option:
            view, bgcolor, icon = parseparamsinline(match_option[0])
        else:
            view, bgcolor, icon = '', '', ''

        regex_eventcal = r'[\{]{3}#!eventcal[^\n]*.(\s*.*?[^\}]+)[\}]{3}'
        pattern_eventcal = re.compile(regex_eventcal, re.UNICODE + re.MULTILINE + re.IGNORECASE)
        
        # ignores #!eventcal blocks
        pagecontent = pattern_eventcal.sub(r'\n##eventcal\n\1\n##eventcal\n', pagecontent)

        # split events
        linesall = pagecontent.split(u'##eventcal\n')
        
        for eventtext in linesall:
            
            eventitem = {}
            eventtexttemp = eventtext.strip()
            if not eventtexttemp: 
                continue
            
            eventitem['view'] = view
            eventitem['bgcolor'] = bgcolor
            eventitem['icon'] = icon
            eventitem['text'] = eventtext
            
            eventrecords.append(eventitem)
    
    else:
    
        # parsing block
        # regex_eventcal = r'[\{]{3}#!eventcal[^\n]*(\s*.*?[^\}]+)[\}]{3}'
        # regex_eventcal = r'[\{]{3}(#!eventcal[^\n]*[\s*.*?[^\}]+]+[\}]{3}'
        regex_eventcal = r'[\{]{3}(#!eventcal[^\n]*\s*.*?[^\}]+)[\}]{3}'
        pattern = re.compile(regex_eventcal, re.UNICODE + re.MULTILINE + re.IGNORECASE)
        match = pattern.findall(pagecontent)
        
        if match:
            
            for blocktext in match:
                
                regex_params = r'^#!eventcal(\s*.*)$'
                pattern = re.compile(regex_params, re.UNICODE + re.MULTILINE + re.IGNORECASE)
                match_option = pattern.findall(blocktext)
                            
                if match_option:
                    view, bgcolor, icon = parseparamsinline(match_option[0])
                else:
                    view, bgcolor, icon = '', '', ''
                
                # split events
                linesall = blocktext.split(u'##eventcal\n')
                
                for eventtext in linesall:
                    
                    eventitem = {}
                    eventtext = eventtext.strip()
                    if not eventtext: 
                        continue
                    
                    eventitem['view'] = view
                    eventitem['bgcolor'] = bgcolor
                    eventitem['icon'] = icon
                    eventitem['text'] = eventtext
                    
                    eventrecords.append(eventitem)
        
    return eventrecords
    

def parseparamsinline(lines):
    
    option_args = {}
    
    for arg in lines.split():
        try:
            key, value = arg.split('=')
            option_args[key.strip()] = value.strip()
        except ValueError:
            pass
            
    bgcolor = option_args.get('bgcolor', '')
    icon = option_args.get('icon', '')
    view = option_args.get('view', '')
    
    return view, bgcolor, icon

def geteventfield(eventitem):
    
    lines = eventitem['text']
    view = eventitem['view']
    bgcolor = eventitem['bgcolor']
    icon = eventitem['icon']
    
    # need help on regular expressions for more efficient/flexible form
    regex_date = r'(\d{4}[/-]\d{2}[/-]\d{2})'
    regex_time = r'(\d{2}[:]\d{2})'
    regex_title = r'["]+(\s*.*?)["]+|[\']{2,}(\s*.*?)[\']{2,}|^[=]+(\s*.*?)[=]+$'
    regex_bgcolor = r'^##bgcolor (\s*.*?)$'
    regex_icon = r'^##icon (\s*.*?)$'
    regex_view= r'^##view (\s*.*?)$'
    
    # compile regular expression objects
    pattern_date = re.compile(regex_date, re.UNICODE)
    pattern_time = re.compile(regex_time, re.UNICODE)
    pattern_title = re.compile(regex_title, re.UNICODE + re.DOTALL + re.MULTILINE)
    pattern_bgcolor = re.compile(regex_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE)
    pattern_icon = re.compile(regex_icon, re.UNICODE + re.MULTILINE + re.IGNORECASE)
    pattern_view = re.compile(regex_view, re.UNICODE + re.MULTILINE + re.IGNORECASE)
    
    # retrieve date
    match = pattern_date.findall(lines)
    
    if not len(match):
        # message('at least one date field should be specified')
        # self.printoutput('Parse Error', msg, '')
        # ERROR
        return '','','','','','','',''
    
    # month, day only should be handled
    
    startdate = match[0]
    if len(match) > 1:
        enddate = match[1]
    else:
        enddate = ''
    
    # retrieve time
    match = pattern_time.findall(lines)
    
    if len(match) >= 2:
        starttime = match[0]
        endtime = match[1]
    elif len(match) == 0:
        starttime = ''
        endtime = ''
    else:
        # message('no or 2 time field should be specified')
        # ERROR
        return '','','','','','','',''
        
    # retrieve title
    match = pattern_title.search(lines)
    
    if not match:
        title = 'No title'
    else:
        for item in match.groups():
            if item:
                title = item
                break

    # retrieve bgcolor
    match = pattern_bgcolor.search(lines)
    if match:
        bgcolor = match.group(0)[10:]
    
    # retrieve icon
    match = pattern_icon.search(lines)
    if match:
        icon = match.group(0)[7:]
        
    # retrieve view
    match = pattern_view.search(lines)
    if match:
        view = match.group(0)[7:]

    # if no time, it's 1-day event
    if not enddate:
        enddate = startdate
    
    # check the validity of date/time
    try:
        syear, smonth, sday = getdatefield(startdate)
        eyear, emonth, eday = getdatefield(enddate)
    except ValueError:
        # message('invalid date format: %s, %s' % (startdate, enddate))
        return '','','','','','','',''
    
    if startdate and enddate:
        if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday):
            # message('startdate should precede enddate')
            return '','','','','','','',''
    
    # format date
    startdate = u'%4d%02d%02d' %(syear, smonth, sday)
    enddate = u'%4d%02d%02d' %(eyear, emonth, eday)
    
    if (starttime and endtime):
        try:
            shour, smin = gettimefield(starttime)
            ehour, emin = gettimefield(endtime)
        except ValueError:
            # message('invalid time format: %s, %s' % (startdate, enddate))
            return '','','','','','','',''
        
        if startdate == enddate:
            if datetime.time(shour, smin) > datetime.time(ehour, emin):
                # message('starttime should precede endtime')
                return '','','','','','','',''
                
        # format time
        starttime = u'%02d%02d' %(shour, smin)
        endtime = u'%02d%02d' %(ehour, emin)
    
    return startdate, starttime, enddate, endtime, title, view, bgcolor, icon



def converttext(targettext):
    # Converts some special characters of html to plain-text style
    # What else to handle?

    targettext = targettext.replace(u'&', '&amp')
    targettext = targettext.replace(u'>', '&gt;')
    targettext = targettext.replace(u'<', '&lt;')
    targettext = targettext.replace(u'\n', '<br>')
    targettext = targettext.replace(u'"', '&quot;')
    targettext = targettext.replace(u'\t', '&nbsp;&nbsp;&nbsp;&nbsp')
    targettext = targettext.replace(u'  ', '&nbsp;&nbsp;')
        
    return targettext

# monthly view
def showeventcalendar(macro, year, month):
    
    request = macro.request
    formatter = macro.formatter
    _ = request.getText
    
    wkend = Globs.wkend
    months= Globs.months
    wkdays = Globs.wkdays
    
    # get the calendar
    monthcal = calendar.monthcalendar(year, month)

    # shows current year & month
    html_header_curyearmonth = calhead_yearmonth(year, month, 'head_yearmonth')
    
    r7 = range(7)
    
    # shows header of week days
    html_header_weekdays = []
    
    for wkday in r7:
        wday = _(wkdays[wkday])
        html_header_weekdays.append( calhead_weekday(wday, 'head_weekday') )
    html_header_weekdays = '    <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
 
    # pending events for next row
    next_pending = []
    
    # gets previous, next month
    day_delta = datetime.timedelta(days=-1)
    cur_month = datetime.date(year, month, 1)
    prev_month = cur_month + day_delta
    
    day_delta = datetime.timedelta(days=15)
    cur_month_end = datetime.date(year, month, 25)
    next_month = cur_month_end + day_delta
    
    prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
    next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
    
    # shows days
    html_week_rows = []
    
    # set ranges of events
    datefrom = u'%04d%02d22' % (prev_month.year, prev_month.month)
    dateto = u'%04d%02d06' % (next_month.year, next_month.month)
    
    # read all the events from data file
    events, cal_events = loadEvents(macro, datefrom, dateto)
    # message(u'total # of events: %d' % len(events))
    
    # sort cal_events
    for eachdate in cal_events.keys():
        # cal_events[eachdate].sort(cmp=lambda x,y: cmp(events[y]['date_len'], events[x]['date_len']))
        cal_events[eachdate].sort(comp_cal_events)
    
    for week in monthcal:
        
        # day head rows
        html_headday_cols = []
        html_events_rows = []
        
        for wkday in r7:
             
            day = week[wkday]
            
            if not day:
                if week == monthcal[0]:
                    nb_day = prev_monthcal[-1][wkday]
                else:
                    nb_day = next_monthcal[0][wkday]
                    
                html_headday_cols.append( calhead_day_nbmonth(nb_day) )
            else:
                html_headday_cols.append( calhead_day(year, month, day, wkday) )
        
        html_headday_row = '    <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
        html_week_rows.append(html_headday_row)
        
        # dummy rows
        html_headdummy_cols = []
        
        for wkday in r7:
            day = week[wkday]
            if not day:
                html_headdummy_cols.append( calshow_blankbox('head_dummy_nbmonth') )
            else:
                html_headdummy_cols.append( calshow_blankbox('head_dummy') )
        
        html_headdummy_cols = u'\r\n'.join(html_headdummy_cols)
        html_week_rows.append(' <tr>\r\n%s </tr>\r\n' % html_headdummy_cols)
        
        # pending events for next row
        pending = next_pending
        next_pending = []
        
        # show events
        while 1: 
            event_left = 7
            colspan = -1
            html_events_cols = []

            for wkday in r7:
             
                day = week[wkday]
                
                if not day:
                    if week == monthcal[0]:
                        cur_date = formatDate(prev_month.year, prev_month.month, prev_monthcal[-1][wkday])
                    else:
                        cur_date = formatDate(next_month.year, next_month.month, next_monthcal[0][wkday])
                else:
                    cur_date = formatDate(year, month, day)

                # if an event is already displayed with colspan
                if colspan > 0:
                    colspan -= 1
                    if cal_events.has_key(cur_date) and lastevent in cal_events[cur_date]:
                        cal_events[cur_date].remove(lastevent)
                    
                    continue
                    
                # if there is any event for this date
                if cal_events.has_key(cur_date):
                    if len(cal_events[cur_date]) > 0:
                        
                        if wkday == 0 and len(pending) > 0:
                            todo_event_id = pending.pop(0)
                            if todo_event_id in cal_events[cur_date]:
                                cur_event = events[todo_event_id]
                                temp_len = diffday(cur_date, cur_event['enddate']) + 1
                                
                                # calculate colspan value
                                if (7-wkday) < temp_len:
                                    colspan = 7 - wkday
                                    next_pending.append(cur_event['id'])
                                    html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )

                                else:
                                    colspan = temp_len
                                    html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
                                
                                
                                cal_events[cur_date].remove(todo_event_id)

                                colspan -= 1
                                lastevent = todo_event_id
                            else:
                                message('FATAL ERROR')
                            continue
                            
                        # if the start date of the event is current date    
                        
                        for e_id in cal_events[cur_date]:
                            if events[e_id]['startdate'] == cur_date:
                                cur_event = events[cal_events[cur_date].pop(cal_events[cur_date].index(e_id))]
                                
                                # calculate colspan value
                                if (7-wkday) < cur_event['date_len']:
                                    colspan = 7 - wkday
                                    next_pending.append(cur_event['id'])
                                    html_events_cols.append( calshow_eventbox(cur_event, colspan, 'pending', cur_date) )

                                else:
                                    colspan = cur_event['date_len']
                                    html_events_cols.append( calshow_eventbox(cur_event, colspan, '', cur_date) )
                                
                                colspan -= 1
                                lastevent = cur_event['id']
                                break
                            
                        # if the start date of the event is NOT current date
                        else:
                            if day == 0 and wkday == 0 and week == monthcal[0]:
                                cur_event = events[cal_events[cur_date].pop(0)]
                                temp_len = diffday(cur_date, cur_event['enddate']) + 1
                                
                                # calculate colspan value
                                if (7-wkday) < temp_len:
                                    colspan = 7 - wkday
                                    next_pending.append(cur_event['id'])
                                    html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
                                else:
                                    colspan = temp_len
                                    html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
                                
                                
                                colspan -= 1
                                lastevent = cur_event['id']
                            else:
                                if not day:
                                    html_events_cols.append( calshow_blankbox('cal_nbmonth') )
                                else:
                                    html_events_cols.append( calshow_blankbox('cal_noevent') )
                                event_left -= 1
                                
                    else:
                        if not day:
                            html_events_cols.append( calshow_blankbox('cal_nbmonth') )
                        else:
                            html_events_cols.append( calshow_blankbox('cal_noevent') )
                        
                        event_left -= 1        
                
                # if there is NO event for this date
                else:
                    if not day:
                        html_events_cols.append( calshow_blankbox('cal_nbmonth') )
                    else:
                        html_events_cols.append( calshow_blankbox('cal_noevent') )
                        
                    event_left -= 1
            
            # if no event for this entry
            if not event_left:
                # ignore the previous entry
                break
            else:
                html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
            
        # show dummy blank slots for week height
        left_blank_rows = 2 - len(html_events_rows)
        
        # message('%d: left_blank_rows=%d' % (day, left_blank_rows))
        
        # remove the followings
        if left_blank_rows > 0 and 0:
            for i in range(left_blank_rows):
                html_events_cols = []
                for wkday in r7:
                    day = week[wkday]
                    if not day:
                        html_events_cols.append( calshow_blankbox('cal_nbmonth') )
                    else:
                        html_events_cols.append( calshow_blankbox('cal_noevent') )
                
                html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
        
        
        # close the week slots
        html_events_cols = []
        for wkday in r7:
            day = week[wkday]
            if not day:
                html_events_cols.append( calshow_blankbox('cal_last_nbmonth') )
            else:
                html_events_cols.append( calshow_blankbox('cal_last_noevent') )
    
        html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
        
        html_events_rows = u'\r\n'.join(html_events_rows)
        html_week_rows.append(html_events_rows)
            
    html_calendar_rows = u'\r\n'.join(html_week_rows)
    
    html_cal_table = [
        u'\r\n<div id="eventcalendar">',
        u'<table class="eventcalendar" %s>' % Params.monthlywidth,
        u'%s' % html_header_curyearmonth,
        u'%s' % html_header_weekdays,
        u'%s' % html_calendar_rows,
        u'</table>',
        u'</div>',
        ]
    html_cal_table = u'\r\n'.join(html_cal_table)
        
    return html_cal_table

# simple view
def showsimpleeventcalendar(macro, year, month):
    
    request = macro.request
    formatter = macro.formatter
    _ = request.getText
    
    wkend = Globs.wkend
    months= Globs.months
    wkdays = Globs.wkdays
    
    # get the calendar
    monthcal = calendar.monthcalendar(year, month)

    # shows current year & month
    html_header_curyearmonth = calhead_yearmonth(year, month, 'simple_yearmonth')
    
    r7 = range(7)
    
    # shows header of week days
    html_header_weekdays = []
    
    for wkday in r7:
        wday = wkdays[wkday]
        html_header_weekdays.append( calhead_weekday(wday, 'simple_weekday') )
    html_header_weekdays = '    <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
 
    # gets previous, next month
    day_delta = datetime.timedelta(days=-1)
    cur_month = datetime.date(year, month, 1)
    prev_month = cur_month + day_delta
    
    day_delta = datetime.timedelta(days=15)
    cur_month_end = datetime.date(year, month, 25)
    next_month = cur_month_end + day_delta
    
    prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
    next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
    
    # shows days
    html_week_rows = []
    
    # set ranges of events
    datefrom = u'%04d%02d22' % (prev_month.year, prev_month.month)
    dateto = u'%04d%02d06' % (next_month.year, next_month.month)
    
    # read all the events from data file
    cal_events = countEvents(macro, datefrom, dateto)
    
    for week in monthcal:
        
        # day head rows
        html_headday_cols = []
        html_events_rows = []
        
        for wkday in r7:
             
            day = week[wkday]
            
            if not day:
                if week == monthcal[0]:
                    nb_day = prev_monthcal[-1][wkday]
                else:
                    nb_day = next_monthcal[0][wkday]
                    
                html_headday_cols.append( simple_eventbox(year, month, day, nb_day, 'simple_nb') )
            else:
                cur_date = formatDate(year, month, day)
                if cal_events.has_key(cur_date):
                    html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_event') )
                else:
                    html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_noevent') )
        
        html_headday_row = '    <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
        html_week_rows.append(html_headday_row)
            
    html_calendar_rows = u'\r\n'.join(html_week_rows)
    
    html_cal_table = [
        u'\r\n<div id="eventcalendar">',
        u'<table class="simplecalendar" %s>' % Params.simplewidth,
        u'%s' % html_header_curyearmonth,
        u'%s' % html_header_weekdays,
        u'%s' % html_calendar_rows,
        u'</table>',
        u'</div>',
        ]
    html_cal_table = u'\r\n'.join(html_cal_table)
        
    return html_cal_table


# show weekday
def calhead_yearmonth(year, month, headclass):
    
    months = Globs.months
    monthstyle_us = Globs.month_style_us
    cal_action = Globs.cal_action
    
    nextyear, nextmonth = yearmonthplusoffset(year, month, 1)
    prevyear, prevmonth = yearmonthplusoffset(year, month, -1)
    
    prevlink = u'?calaction=%s&caldate=%d%02d' % (cal_action, prevyear, prevmonth)
    nextlink = u'?calaction=%s&caldate=%d%02d' % (cal_action, nextyear, nextmonth)
    
    if monthstyle_us:
        stryearmonth = u'%s %d' % (months[month-1], year)
    else:
        stryearmonth = u'%d / %02d' % (year, month)
    
    html = [
        u'  <tr>',
        u'      <td class="%s"><a href="%s">&lt;</a></td>' % (headclass, prevlink),
        u'      <td colspan="5" class="%s">%s</td>' % (headclass, stryearmonth),
        u'      <td class="%s"><a href="%s">&gt;</a></td>' % (headclass, nextlink),
        u'  </tr>',
        ]
        
    return u'\r\n'.join(html)

# show days in simple
def simple_eventbox(year, month, day, wkday, boxclass):
    wkend = Globs.wkend
    if wkday == wkend:
        html_text = u'<font color="#aa7744">%s</font>' % day
    else:
        html_text = u'%s' % day
    
    cyear, cmonth, cday = gettodaydate()
    
    if boxclass == 'simple_nb':
        html = u'  <td class="%s">&nbsp;</td>\r\n' % boxclass
    else:
        if cyear == year and cmonth == month and cday == day:
            html = u'  <td class="%s_today">%s</td>\r\n' % (boxclass, html_text)
        else:
            html = u'  <td class="%s">%s</td>\r\n' % (boxclass, html_text)
       
    return html


# show weekday
def calhead_weekday(wday, headclass):
    if headclass == 'simple_weekday':
        html = u'       <td class="%s">%s</td>\r\n' % (headclass, wday[0])
    else:
        html = u'       <td class="%s">%s</td>\r\n' % (headclass, wday)

    return html


# show days of current month
def calhead_day(year, month, day, wkday):
    wkend = Globs.wkend
    if wkday == wkend:
        html_text = u'<font color="#FF3300">%s</font>' % day
    else:
        html_text = u'%s' % day
    
    cyear, cmonth, cday = gettodaydate()
    
    if cyear == year and cmonth == month and cday == day:
        html = u'  <td class="head_day_today">&nbsp;%s</td>\r\n' % html_text
    else:
        html = u'  <td class="head_day">&nbsp;%s</td>\r\n' % html_text
       
    return html


# show days of previous or next month
def calhead_day_nbmonth(day):
    html = u'  <td class="head_day_nbmonth">&nbsp;%s</td>\r\n' % day
    return html

    
# show blank calendar box
def calshow_blankbox(classname):
    html = u'  <td class="%s">&nbsp;</td>' % classname
    return html

# show eventbox
def calshow_eventbox(event, colspan, status, cur_date):
    if status:
        status = u'_%s' % status
    
    title = event['title']
    eid = event['id']
    startdate = event['startdate']
    enddate = event['enddate']
    starttime = event['starttime']
    endtime = event['endtime']
    icon = event['icon']
    bgcolor = event['bgcolor']
    
    year, month, day = getdatefield(cur_date)
    
    if bgcolor:
        bgcolor = 'background-color: %s;' % bgcolor
    else:
        bgcolor = 'background-color: %s;' % Params.bgcolor
    
    if (startdate == enddate) and starttime:
        shour, smin = gettimefield(starttime)
        
        link = [
            u'<table width="100%%" style="border-width: 0px; padding: 0px; margin: 0px;"><tr>\r\n',
            u'<td width="10" nowrap style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top; font-size: 7pt; color: #000000;">%02d:%02d&nbsp;</td>\r\n' % (shour, smin),
            # u'<td>&nbsp;</td>',
            u'<td style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top;font-size: 8pt;">',
            u'%s%s' % (geticonurl(event['icon']), showReferPageParsed(event, 'title')),
            u'</td>\r\n</tr></table>',
            ]
        link = u''.join(link)
    else:
        link = u'%s%s' % (geticonurl(event['icon']), showReferPageParsed(event, 'title'))
    
    
    html = [
        u'  <td class="cal_eventbox" colspan="%d"><table class="cal_event">' % colspan,
        u'      <tr><td id="cal_event_%s" class="cal_event%s" style="%s">%s</td></tr>' % (eid, status, bgcolor, link),
        u'      </table></td>',
        ]
        
    return u'\r\n'.join(html)
        


# date format should be like '20051004' for 2005, Oct., 04
def diffday(date1, date2):
    
    try:
        year1, month1, day1 = getdatefield(date1)
        year2, month2, day2 = getdatefield(date2)
        tmp_diff = datetime.date(year2, month2, day2) - datetime.date(year1, month1, day1)
    except ValueError:
        message('An event data is corrupted: invalid date format')
        return 0

    return tmp_diff.days


def formatDate(year, month, day):
    # returns like: '20051004'
    return u'%4d%02d%02d' % (year, month, day)

def cliprgb(r,g,b): # don't use 255!
    if r < 0:   r=0
    if r > 254: r=254
    if b < 0:   b=0
    if b > 254: b=254
    if g < 0:   g=0
    if g > 254: g=254
    return r, g, b


def message(astring):
    Globs.adminmsg += u'%s<br>\r\n' % astring

def yearmonthplusoffset(year, month, offset):
    month = month+offset
    # handle offset and under/overflows - quick and dirty, yes!
    while month < 1:
        month = month + 12
        year = year - 1
    while month > 12:
        month = month - 12
        year = year + 1
    return year, month

def getPages(request, filter_regex=None):
    """ Return a (filtered) list of pages names.
    """
    filter = None
    if filter_regex:
        filter = re.compile(filter_regex).match
    pages = request.rootpage.getPageList(filter=filter)
    return pages
    
    
def cutstring(strcut, intlen):
    if len(strcut) > intlen:
        newlen = intlen - 3
        strtemp = strcut[:newlen] + '...'
    else:
        strtemp = strcut
        
    return strtemp