##############################################################
##
## MOD Title:   bbGeSHi - a better syntax highlighter
## MOD Author:  DarrenSW <darren@phpportalen.net> (Darren J) http://www.phpportalen.net
## MOD Description:
##   Replaces phpBB's own highlighter with GeSHi syntax highlighter.
##
##   Use it like this
##       [code=SYNTAX_NAME]...[/code]
##   Or
##       [SYNTAX_NAME]...[/SYNTAX_NAME]
##
##   This MOD uses a modified version of the latest stable* GeSHi release 1.0.7.20.
##   GeSHi and information about it can be found at http://qbnz.com/highlighter/
##
##   * as of 14 July 2007
##
## MOD Version: 0.7.5
##
## Installation Level: Easy
## Installation Time:  ~15 Minutes
##
## Files To Edit:
##   includes/bbcode.php
##   includes/functions.php
##   includes/message_parser.php
##   language/en/common.php
##   styles/prosilver/template/bbcode.html
##   styles/prosilver/template/forum_fn.js
##   styles/prosilver/theme/colours.css
##   styles/prosilver/theme/stylesheet.css
##
## Included Files:
##   page_code.gif
##      - just a simple icon file
##   bbGeSHi.css
##      - bbGeSHi css classes
##   geshi.php
##      - modified version of GeSHi 1.0.7.20
##   geshi/*.* 
##      - all language files
##
##############################################################
##
## Author Notes:
##
##  As always, be sure to make backup for the files that will be modified.
##
##############################################################
##
## MOD History:
##   2007-07-29 - Version 0.7.5
##      - Expand/Contract codebox function added
##      - Couple of bug fixes
##   2007-07-14 - Version 0.7.0
##      - Added possibility to use [syntax-name] tags instead of [code=syntax_name]
##      - New language added Extensible Stylesheet Language (XSL)
##      - A couple of minor fixes
##   2007-07-11 - Version 0.5.2
##      - First public release
##
##############################################################
## Before Adding This MOD To Your Forum, You Should Back Up All Files Related To This MOD
##############################################################
#
#-----[ COPY ]------------------------------------------
#
COPY geshi.php           TO  phpbb_root_path/includes
COPY geshi/*.*           TO  phpbb_root_path/includes/geshi/*.*
COPY page_code.gif       TO  phpbb_root_path/styles/prosilver/theme/images/page_code.gif
COPY bbGeSHi.css         TO  phpbb_root_path/styles/prosilver/theme/bbGeSHi.css
#
#-----[ OPEN ]------------------------------------------
#
includes/bbcode.php
#
#-----[ FIND ]------------------------------------------
#
							'#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise'	=> "\$this->bbcode_second_pass_code('\$1', '\$2')",
#
#-----[ REPLACE WITH ]------------------------------------------
# 
							'#\[code(?:=([a-z0-9_]+))?:$uid\](.*?)\[/code:$uid\]#ise'	=> "\$this->bbcode_second_pass_code('\$1', '\$2')",
#
#-----[ FIND ]------------------------------------------
#
				case 12:
					$this->bbcode_cache[$bbcode_id] = array(
						'str'	=> array(
							'[/attachment:$uid]'	=> $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
						),
						'preg'	=> array(
							'#\[attachment=([0-9]+):$uid\]#'	=> $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
						)
					);
				break;
#
#-----[ AFTER, ADD ]------------------------------------------
#
				case 99:
					$this->bbcode_cache[$bbcode_id] = array(
						'preg' => array(
							'#\[(abap|actionscript|ada|apache|applescript|asm|asp|autoit|bash|blitzbasic|bnf|c|caddcl|cadlisp|cfdg|cfm|cpp-qt|cpp|csharp|css|c_mac|d|delphi|diff|div|dos|dot|eiffel|fortran|freebasic|genero|gml|groovy|haskell|html|html4strict|idl|ini|inno|io|java|java5|javascript|js|latex|lisp|lua|m68k|matlab|mirc|mpasm|mysql|nsis|objc|ocaml-brief|ocaml|oobas|oracle8|pascal|per|perl|php-brief|php|plsql|python|qbasic|rails|reg|robots|ruby|sas|scheme|sdlbasic|smalltalk|smarty|sql|tcl|text|thinbasic|tsql|vb|vbnet|vhdl|visualfoxpro|winbatch|xml|xpp|xsl|z80)(?:=([a-z0-9_]+))?:$uid\](.*?)\[/(abap|actionscript|ada|apache|applescript|asm|asp|autoit|bash|blitzbasic|bnf|c|caddcl|cadlisp|cfdg|cfm|cpp-qt|cpp|csharp|css|c_mac|d|delphi|diff|div|dos|dot|eiffel|fortran|freebasic|genero|gml|groovy|haskell|html|html4strict|idl|ini|inno|io|java|java5|javascript|js|latex|lisp|lua|m68k|matlab|mirc|mpasm|mysql|nsis|objc|ocaml-brief|ocaml|oobas|oracle8|pascal|per|perl|php-brief|php|plsql|python|qbasic|rails|reg|robots|ruby|sas|scheme|sdlbasic|smalltalk|smarty|sql|tcl|text|thinbasic|tsql|vb|vbnet|vhdl|visualfoxpro|winbatch|xml|xpp|xsl|z80):$uid\]#ise'	=> "\$this->bbcode_second_pass_code('\$2', '\$3')",
						)
					);
				break;
#
#-----[ FIND ]------------------------------------------
#
		$code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close');
#
#-----[ AFTER, ADD ]------------------------------------------
#
		$random_id = rand(0,99999);
		$code = str_replace('{CB}', 'cb' . $random_id, $code);
		$code = str_replace("\'", "'", $code);
#-----[ OPEN ]------------------------------------------
#
includes/functions.php
#
#-----[ FIND ]------------------------------------------
# 
		$match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid");
		$replace = array("\n", '', '', '', '');
#
#-----[ REPLACE WITH ]------------------------------------------
#
		$match = array('</li></ol>', '</li>', '<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid");
		$replace = array("", "\n", "\n", '', '', '', '');
#
#-----[ FIND ]------------------------------------------
# 
		$match = array('<br />');
		$replace = array("\n");
#
#-----[ REPLACE WITH ]------------------------------------------
#
		$match = array('</li></ol>', '</li>', '<br />');
		$replace = array("", "\n", "\n");
#
#-----[ OPEN ]------------------------------------------
#
includes/message_parser.php
#
#-----[ FIND ]------------------------------------------
#
if (!class_exists('bbcode'))
{
	include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
}
#
#-----[ AFTER, ADD ]------------------------------------------
# 
/* bbGeSHi */
if (!class_exists('GeSHi'))
{
	include($phpbb_root_path . 'includes/geshi.' . $phpEx);
}
#
#-----[ FIND ]-------------------------------------------------
#
		// This array holds all bbcode data. BBCodes will be processed in this
		// order, so it is important to keep [code] in first position and
		// [quote] in second position.
		$this->bbcodes = array(
#
#-----[ REPLACE WITH ]------------------------------------------
#
		// This array holds all bbcode data. BBCodes will be processed in this
		// order, so it is important to keep [code] in first position and
		// [quote] in second position.
		$this->bbcodes = array(
			'geshi'			=> array('bbcode_id' => 99,	'regexp' => array('#\[(abap|actionscript|ada|apache|applescript|asm|asp|autoit|bash|blitzbasic|bnf|c|caddcl|cadlisp|cfdg|cfm|cpp-qt|cpp|csharp|css|c_mac|d|delphi|diff|div|dos|dot|eiffel|fortran|freebasic|genero|gml|groovy|haskell|html|html4strict|idl|ini|inno|io|java|java5|js|latex|lisp|lua|m68k|matlab|mirc|mpasm|mysql|nsis|objc|ocaml-brief|ocaml|oobas|oracle8|pascal|per|perl|php-brief|php|plsql|python|qbasic|rails|reg|robots|ruby|sas|scheme|sdlbasic|smalltalk|smarty|sql|tcl|text|thinbasic|tsql|vb|vbnet|vhdl|visualfoxpro|winbatch|xml|xpp|xsl|z80)\](.+\[/(abap|actionscript|ada|apache|applescript|asm|asp|autoit|bash|blitzbasic|bnf|c|caddcl|cadlisp|cfdg|cfm|cpp-qt|cpp|csharp|css|c_mac|d|delphi|diff|div|dos|dot|eiffel|fortran|freebasic|genero|gml|groovy|haskell|html|html4strict|idl|ini|inno|io|java|java5|js|latex|lisp|lua|m68k|matlab|mirc|mpasm|mysql|nsis|objc|ocaml-brief|ocaml|oobas|oracle8|pascal|per|perl|php-brief|php|plsql|python|qbasic|rails|reg|robots|ruby|sas|scheme|sdlbasic|smalltalk|smarty|sql|tcl|text|thinbasic|tsql|vb|vbnet|vhdl|visualfoxpro|winbatch|xml|xpp|xsl|z80)\])#ise' => "\$this->bbcode_geshi('[\$1]', '\$2')")),
#
#-----[ FIND ]-------------------------------------------------
#
			'code'			=> array('bbcode_id' => 8,	'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#ise' => "\$this->bbcode_code('\$1', '\$2')")),
#
#-----[ REPLACE WITH ]------------------------------------------
#
			'code'			=> array('bbcode_id' => 8,	'regexp' => array('#\[code(?:=([a-z0-9_]+))?\](.+\[/code\])#ise' => "\$this->bbcode_code('\$1', '\$2')")),
#
#-----[ FIND ]---------------------------------------------------
#
	function bbcode_parse_code($stx, &$code)
	{
		switch (strtolower($stx))
		{
			case 'php':

				$remove_tags = false;
				$code = str_replace(array('&lt;', '&gt;'), array('<', '>'), $code);

				if (!preg_match('/\<\?.*?\?\>/is', $code))
				{
					$remove_tags = true;
					$code = "<?php $code ?>";
				}

				$conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string');
				foreach ($conf as $ini_var)
				{
					@ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var));
				}

				// Because highlight_string is specialcharing the text (but we already did this before), we have to reverse this in order to get correct results
				$code = htmlspecialchars_decode($code);
				$code = highlight_string($code, true);

				$str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
				$str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');

				if ($remove_tags)
				{
					$str_from[] = '<span class="syntaxdefault">&lt;?php </span>';
					$str_to[] = '';
					$str_from[] = '<span class="syntaxdefault">&lt;?php&nbsp;';
					$str_to[] = '<span class="syntaxdefault">';
				}

				$code = str_replace($str_from, $str_to, $code);
				$code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#is', '$1$2$3', $code);

				if ($remove_tags)
				{
					$code = preg_replace('#(<span class="[a-z]+">)?\?&gt;(</span>)#', '$1&nbsp;$2', $code);
				}

				$code = preg_replace('#^<span class="[a-z]+"><span class="([a-z]+)">(.*)</span></span>#s', '<span class="$1">$2</span>', $code);
				$code = preg_replace('#(?:[\n\r\s\t]|&nbsp;)*</span>$#u', '</span>', $code);

				// remove newline at the end
				if (!empty($code) && $code[strlen($code) - 1] == "\n")
				{
					$code = substr($code, 0, -1);
				}

				return "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']';
			break;

			default:
				return '[code:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($code) . '[/code:' . $this->bbcode_uid . ']';
			break;
		}
	}
#
#-----[ REPLACE WITH ]------------------------------------------
#
	function bbcode_parse_code($stx, &$code)
	{
		if ($stx == '')
		{
			$stx = 'text';
		}

		$code = $this->bbcode_highlight($code, $stx);
		return "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']';
	}

	function bbcode_parse_geshi($stx, &$code){
		$code = $this->bbcode_highlight($code, $stx);
		$code = str_replace('[code', '&#91;code', $code);
		return "[$stx:" . $this->bbcode_uid . ']' . $code . '[/' . $stx . ':' . $this->bbcode_uid . ']';
	}

	/**
	* Highlight code
	*/
	function bbcode_highlight($code, $stx)
	{
		$code = str_replace(array('&lt;', '&gt;'), array('<', '>'), $code);
		$code = htmlspecialchars_decode($code);

		$geshi = new GeSHi($code, $stx);

		$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 2);
		$geshi->set_header_type(GESHI_HEADER_DIV);
		$geshi->set_tab_width(4);
		$geshi->set_overall_id("{CB}");

		$result = $geshi->parse_code();
		return $result;
	}

	function bbcode_geshi($stx, $in){
		$text = $stx . $in;

		$syntaxes = array('abap', 'actionscript', 'ada', 'apache', 'applescript', 'asm', 'asp', 'autoit', 'bash', 'blitzbasic', 'bnf', 'c', 'caddcl', 'cadlisp', 'cfdg', 'cfm', 'cpp-qt', 'cpp', 'csharp', 'css', 'c_mac', 'd', 'delphi', 'diff', 'div', 'dos', 'dot', 'eiffel', 'fortran', 'freebasic', 'genero', 'gml', 'groovy', 'haskell', 'html', 'html4strict', 'idl', 'ini', 'inno', 'io', 'java', 'java5', 'js', 'latex', 'lisp', 'lua', 'm68k', 'matlab', 'mirc', 'mpasm', 'mysql', 'nsis', 'objc', 'ocaml-brief', 'ocaml', 'oobas', 'oracle8', 'pascal', 'per', 'perl', 'php-brief', 'php', 'plsql', 'python', 'qbasic', 'rails', 'reg', 'robots', 'ruby', 'sas', 'scheme', 'sdlbasic', 'smalltalk', 'smarty', 'sql', 'tcl', 'text', 'thinbasic', 'tsql', 'vb', 'vbnet', 'vhdl', 'visualfoxpro', 'winbatch', 'xml', 'xpp', 'xsl', 'z80');

		foreach($syntaxes as $syntax => $value){
			$tag_count = preg_match_all('#\[' . $value . '\](.*?)\[/' . $value . '\]#is', $text, $matches);

			for ($i = 0; $i < $tag_count; $i++){
				$text = str_replace($matches[0][$i], $this->bbcode_parse_geshi($value, $matches[1][$i]), $text);
			}

			$matches = array();
		}

		unset($syntaxes);
		unset($matches);

		return $text;
	}
#
#-----[ FIND ]---------------------------------------------------
#
			// Determine position and tag length of next code block
			preg_match('#(.*?)(\[code(?:=([a-z]+))?\])(.+)#is', $in, $buffer);
#
#-----[ REPLACE WITH ]------------------------------------------
#
			// Determine position and tag length of next code block
			preg_match('#(.*?)(\[code(?:=([a-z0-9_]+))?\])(.+)#is', $in, $buffer);
#
#-----[ OPEN ]--------------------------------------------------
#
language/en/common.php
#
#-----[ FIND ]---------------------------------------------------
#
	'SUBMIT'					=> 'Submit',
#
#-----[ AFTER, ADD ]------------------------------------------
#
	'LINE_NUMBERS'				=> 'Line number On/Off',
	'EXPAND_CODE'				=> 'Expand/Contract',

#
#-----[ OPEN ]--------------------------------------------------
#
language/es/common.php
#
#-----[ FIND ]---------------------------------------------------
# Linea parcial...
	'SUBMIT'					=>
#
#-----[ AFTER, ADD ]------------------------------------------
#
	'LINE_NUMBERS'				=> 'Nmero de lnes On/Off',
	'EXPAND_CODE'				=> 'Expandir/Contraer',
#
#-----[ OPEN ]--------------------------------------------------
#
styles/prosilver/template/bbcode.html
#
#-----[ FIND ]---------------------------------------------------
#
<!-- BEGIN code_open --><dl class="codebox"><dt>{L_CODE}: <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></dt><dd><code><!-- END code_open -->
<!-- BEGIN code_close --></code></dd></dl><!-- END code_close -->
#
#-----[ REPLACE WITH ]------------------------------------------
#
<!-- BEGIN code_open --><div class="codebox"><div class="codeheader"><a href="#" onclick="linenumberOnOff('{CB}'); return false;">{L_LINE_NUMBERS}</a> | <a href="#" onclick="expandCode('{CB}'); return false;">{L_EXPAND_CODE}</a> | <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></div><!-- we need this dummy div to fix a firefox bug when selecting code lines --><div class="codeholder"><!-- END code_open -->
<!-- BEGIN code_close --></div></div><!-- END code_close -->
#
#-----[ OPEN ]--------------------------------------------------
#
styles/prosilver/template/forum_fn.js
#
#-----[ FIND ]---------------------------------------------------
#
	// Get ID of code block
	var e = a.parentNode.parentNode.getElementsByTagName('CODE')[0];
#
#-----[ REPLACE WITH ]------------------------------------------
#
	// Get ID of code block
	var e = a.parentNode.parentNode.getElementsByTagName('DIV')[1];
#
#-----[ FIND ]---------------------------------------------------
#
	obj.width = width;
	obj.height = height + 16;

	obj.SetControllerVisible(true);
	obj.Play();
}
#
#-----[ AFTER, ADD ]------------------------------------------
#
function linenumberOnOff(id){
	var parent = document.getElementById(id);
	var holder = parent.parentNode;

	if (parent.firstChild.nodeName == "OL"){
		var show = 'hide';
	} else if (parent.firstChild.nodeName == "DIV"){
		var show = 'show';
	}

	if (show == 'hide'){
		var child = parent.getElementsByTagName("ol");

		var children = child[0].childNodes;

		var replacement = document.createElement("div");
		replacement.setAttribute("id", id);
		replacement.setAttribute("class", parent.getAttribute("class"));
		replacement.setAttribute("className", parent.getAttribute("className"));
		replacement.setAttribute("style", parent.getAttribute("style"));
		
		for (var b = 0; b <= children.length - 1; b++){
			if (children[b].nodeType == 1){
				var row = document.createElement("div");

				row.setAttribute("class", children[b].getAttribute("class"));
				row.setAttribute("className", children[b].getAttribute("className"));
				row.setAttribute("style", children[b].getAttribute("style") + "; border-left: none;");
				row.style.cssText = 'border-left: none;';

				var rowdata = children[b].childNodes;

				for (var c = 0; c <= rowdata.length - 1; c++){
					row.appendChild(rowdata[c].cloneNode(true));
				}

				replacement.appendChild(row);
			}
		}
		
		holder.replaceChild(replacement, parent);
	} else {
		var replacement = document.createElement("div");
		replacement.setAttribute("id", id);
		replacement.setAttribute("class", parent.getAttribute("class"));
		replacement.setAttribute("className", parent.getAttribute("className"));
		replacement.setAttribute("style", parent.getAttribute("style"));

		var list = document.createElement("ol");

		var dds = parent.getElementsByTagName("div");

		for (var b = 0; b <= dds.length -1; b++){
			var row = document.createElement("li");
			row.setAttribute("class", dds[b].getAttribute("class"));
			row.setAttribute("className", dds[b].getAttribute("className"));
			row.setAttribute("style", dds[b].getAttribute('style') + "; border-left: 1px solid #999;");

			var rowdata = dds[b].childNodes;

			for (var c = 0; c <= rowdata.length - 1; c++){
				row.appendChild(rowdata[c].cloneNode(true));
			}

			list.appendChild(row);
		}

		replacement.appendChild(list);
		holder.replaceChild(replacement, parent);
	}
}

function expandCode(id){
	var parent = document.getElementById(id);

	if (parent.style.display === 'block' || parent.style.display === ''){
		parent.style.display = 'none';
	} else {
		parent.style.display = 'block';
	}
}
#
#-----[ OPEN ]--------------------------------------------------
#
styles/prosilver/theme/colours.css
#
#-----[ FIND ]---------------------------------------------------
#
input.search {
	background-image: url("{T_THEME_PATH}/images/icon_textbox_search.gif");
}
#
#-----[ AFTER, ADD ]---------------------------------------------------
#
div.codeheader {
	background: url("{T_THEME_PATH}/images/page_code.gif") no-repeat 0px 0px;
}
#
#-----[ OPEN ]--------------------------------------------------
#
styles/prosilver/theme/stylesheet.css
#
#-----[ FIND ]---------------------------------------------------
#
@import url("colours.css");
#
#-----[ AFTER, ADD ]---------------------------------------------------
#
@import url("bbGeSHi.css");
#
#-----[ SAVE/CLOSE ALL FILES ]------------------------------------------
#
Be sure to purge the cache from the admin area and clear the cache of your browser to.
# EoM