<?php if (!defined('PmWiki')) exit();
/*
 * SourceBlock - Yet another source code syntax highlighter for PmWiki 2.0
 * Copyright 2005-2006 by D.Faure (dfaure@cpan.org)
 * Geshi module written by and (C) Nigel McNie (oracle.shinoda@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * See http://www.pmwiki.org/wiki/Cookbook/SourceBlock for info.
 */
$RecipeInfo['SourceBlock']['Version'] = '20061025';
 
SDV($SourceBlockAction, 'sourceblock');
if ($action == $SourceBlockAction)
  $HandleActions[$SourceBlockAction] = 'HandleSourceBlock';

Markup('sourceblock', '>markupend',
  "/\\(:source(\\s+.*?)?\\s*:\\)[^\\S\n]*\\[([=@])(.*?)\\2\\]/sei",
  "SourceBlock(\$pagename, PSS('$1'), PSS('$3'))");
Markup('sourceblockend', '>sourceblock',
  "/\\(:source(\\s+.*?)?\\s*:\\)[^\\S\n]*\n(.*?)\\(:sourcee?nd:\\)/sei",
  "SourceBlock(\$pagename, PSS('$1'), PSS('$2'))");

Markup('codeblock', '>markupend',
  "/\\(:code(\\s+.*?)?\\s*:\\)[^\\S\n]*\\[([=@])(.*?)\\2\\]/sei",
  "CodeBlock(\$pagename, PSS('$1'), PSS('$3'))");
Markup('codeblockend', '>codeblock',
  "/\\(:code(\\s+.*?)?\\s*:\\)[^\\S\n]*\n(.*?)\\(:codee?nd:\\)/sei",
  "CodeBlock(\$pagename, PSS('$1'), PSS('$2'))");

function HandleSourceBlock($pagename) {
  global $HandleBrowseFmt;
  $HandleBrowseFmt = '';
  HandleBrowse($pagename);
  return;
}

function ManageSourceBlockHandling($pagename, &$opt, &$block) {
  global $PCache, $action, $SourceBlockAction, $SourceBlockLinkUrl,
         $SourceBlockLinkText;
  SDV($PCache[$pagename]['sourceblock'], 0);
  $ref = ++$PCache[$pagename]['sourceblock'];

  if ($action == $SourceBlockAction && ($ref == $_REQUEST['ref'] || ( isset($opt['filename']) && $opt['filename']== $_REQUEST['ref'])) ) {
    # undo PmWiki's htmlspecialchars conversion
	if (isset($opt['load'])) {
		$block = @file_get_contents($opt['load']);
		if ($block===false) {
			$block = "PmWiki ERROR: file $opt[load] was not found";
		}
	} else {
    $block = str_replace(array('<:vspace>', '&lt;', '&gt;', '&amp;'),
                          array('', '<', '>', '&'), $block);	
	}	
    $filename = isset($opt['filename']) ?
                $opt['filename'] : "sourceblock_{$ref}.txt";
    $type = 'text/plain';
    $disp = @in_array('attach', $opt['-']) ? 'attachment' : 'inline';
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
      $type = 'application/octet-stream';
      $disp = 'attachment';
    }
    header("Content-type: $type");
    header("Content-disposition: $disp; filename=$filename");
    header('Content-Length: ' . strlen($block));
    echo $block;
    exit(0);
  }
  SDV($SourceBlockLinkUrl, "<a href='\$LinkUrl' type='text/plain'>\$LinkText</a>");
  SDV($SourceBlockLinkText, "[$[Get Code]]");
  return MakeLink($pagename,
                  "{$pagename}?action={$SourceBlockAction}&ref={$ref}",
                  $SourceBlockLinkText, NULL, $SourceBlockLinkUrl);
}

function CodeBlock($pagename, $args, $block) {
  global $CodeBlockHeaderFmt, $CodeBlockFooterFmt, $HTMLStylesFmt;
  $opt = ParseArgs($args);
  $Url = ManageSourceBlockHandling($pagename, $opt, $block);
  $txt = isset($opt['wrap']) ? wordwrap($block, $opt['wrap']) : $block;
  SDV($CodeBlockHeaderFmt, "<div class='codeblock'>
<div class='codeblocklink'>\$Url</div><div class='codeblocktext'><pre>");
  SDV($CodeBlockFooterFmt, "</pre></div></div>");
  SDV($HTMLStylesFmt['codeblock'], "
.codeblocklink {
  text-align: right;
  font-size: smaller;
}
.codeblocktext {
  text-align: left;
  padding: 0.5em;
  border: 1px solid #808080;
  background-color: #f1f0ed;
}
.codeblocktext pre {
  font-family: monospace;
  font-size: small;
  line-height: 1;
}\n");
  return '<:block>'.Keep(eval("return (\"$CodeBlockHeaderFmt\");") . $txt .
                         eval("return (\"$CodeBlockFooterFmt\");"));
}

function SourceBlock($pagename, $args, $block) {
  global $SourceBlockParams, $GESHI_PATH, $HTMLStylesFmt, $GeshiStyles,
         $SourceBlockHeaderFmt, $SourceBlockFooterFmt;
  SDVA($SourceBlockParams, array(
  'header' => '',
  'footer' => '',
  ));
  $opt = array_merge((array)$SourceBlockParams, ParseArgs($args));
  $Url = ManageSourceBlockHandling($pagename, $opt, $block);
  if(!@in_array('trim', $opt['-'])) $block = trim($block);
  if($opt['lang']) {
    SDV($GESHI_PATH, dirname(__FILE__) . "/geshi");
    include_once($GESHI_PATH . "/geshi.php");
    # undo PmWiki's htmlspecialchars conversion
	if (isset($opt['load'])) {
		$block = @file_get_contents($opt['load']);
		if ($block===false) {
			$block = "PmWiki ERROR: file $opt[load] was not found";
		}
	} else {
    $block = str_replace(array('<:vspace>', '&lt;', '&gt;', '&amp;'),
                          array('', '<', '>', '&'), $block);	
	}
    $geshi =& new GeSHi($block, $opt['lang'], $GESHI_PATH . "/geshi");
    $geshi->enable_classes();
    SDVA($GeshiStyles, array(
    'code'  => 'font-family: monospace; font-weight: normal;',
    'line1' => 'font-family: monospace; color: black; font-weight: normal;',
    'line2' => 'font-weight: bold;',
    ));
    $geshi->set_code_style($GeshiStyles['code']);
    $geshi->set_line_style($GeshiStyles['line1'], $GeshiStyles['line2']);
    $geshi->set_header_type(GESHI_HEADER_DIV);
    if ($opt['tabwidth']) $geshi->set_tab_width($opt['tabwidth']);
    if (@in_array('linenum', $opt['']))
      $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
    if ($opt['linenum']) {
      $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
      $geshi->start_line_numbers_at($opt['linenum']);
    }
    if($opt['highlight']) {
      $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
      $geshi->highlight_lines_extra(preg_split("/[\s,]+/", $opt['highlight']));
    }
    $geshi->set_header_content($opt['header']);
    $geshi->set_footer_content($opt['footer']);
    if ($opt['id']) $geshi->set_overall_id($opt['id']);
    $HTMLStylesFmt['geshi_'.$opt['lang']] = $geshi->get_stylesheet();
    $txt = $geshi->parse_code();
    if($geshi->error()) $txt = $geshi->error();
  } else {
    $lines = explode("\n", $block);
    $count = count($lines);
    if(@in_array('linenum', $opt[''])) $linenum = "<ol>";
    elseif ($opt['linenum']) $linenum = "<ol start=" . $opt['linenum'] . ">";
    for ($i = 0; $i < $count; $i++)
      $txt .= ($linenum ? "<li>" : "") . $lines[$i] . ($linenum ? "</li>" : "<br/>");
    $txt = "<div>{$linenum}{$txt}" . ($linenum ? "</ol>" : "") . "</div>";
  }
  SDV($HTMLStylesFmt['sourceblock'], "
.sourceblocklink {
  text-align: right;
  font-size: smaller;
}
.sourceblocktext {
  padding: 0.5em;
  border: 1px solid #808080;
  background-color: #f1f0ed;
}
.sourceblocktext div {
  font-family: monospace;
  font-size: small;
  line-height: 1;
  height: 1%;
}
.sourceblocktext div.head,
.sourceblocktext div.foot {
  font: italic medium serif;
  padding: 0.5em;
}\n");
  SDV($SourceBlockHeaderFmt, "<div class='sourceblock'>
<div class='sourceblocklink'>\$Url</div><div class='sourceblocktext'>");
  SDV($SourceBlockFooterFmt, "</div></div>");
  return '<:block>'.Keep(eval("return (\"$SourceBlockHeaderFmt\");") . $txt .
                         eval("return (\"$SourceBlockFooterFmt\");"));
}