00001 <?php
00036
00037
00038
00039
00040
00041
00042
00044 define('GESHI_VERSION', '1.0.7.20');
00045
00046
00047 if (!defined('GESHI_ROOT')) {
00049 define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
00050 }
00053 define('GESHI_LANG_ROOT', GESHI_ROOT . 'geshi' . DIRECTORY_SEPARATOR);
00054
00055
00056
00058 define('GESHI_NO_LINE_NUMBERS', 0);
00060 define('GESHI_NORMAL_LINE_NUMBERS', 1);
00062 define('GESHI_FANCY_LINE_NUMBERS', 2);
00063
00064
00066 define('GESHI_HEADER_NONE', 0);
00068 define('GESHI_HEADER_DIV', 1);
00070 define('GESHI_HEADER_PRE', 2);
00071
00072
00074 define('GESHI_CAPS_NO_CHANGE', 0);
00076 define('GESHI_CAPS_UPPER', 1);
00078 define('GESHI_CAPS_LOWER', 2);
00079
00080
00082 define('GESHI_LINK', 0);
00084 define('GESHI_HOVER', 1);
00086 define('GESHI_ACTIVE', 2);
00088 define('GESHI_VISITED', 3);
00089
00090
00091
00092
00094 define('GESHI_START_IMPORTANT', '<BEGIN GeSHi>');
00096 define('GESHI_END_IMPORTANT', '<END GeSHi>');
00097
00101
00103 define('GESHI_NEVER', 0);
00106 define('GESHI_MAYBE', 1);
00108 define('GESHI_ALWAYS', 2);
00109
00110
00112 define('GESHI_SEARCH', 0);
00115 define('GESHI_REPLACE', 1);
00117 define('GESHI_MODIFIERS', 2);
00120 define('GESHI_BEFORE', 3);
00123 define('GESHI_AFTER', 4);
00126 define('GESHI_CLASS', 5);
00127
00129 define('GESHI_COMMENTS', 0);
00130
00131
00135 define('GESHI_ERROR_NO_INPUT', 1);
00137 define('GESHI_ERROR_NO_SUCH_LANG', 2);
00139 define('GESHI_ERROR_FILE_NOT_READABLE', 3);
00141 define('GESHI_ERROR_INVALID_HEADER_TYPE', 4);
00143 define('GESHI_ERROR_INVALID_LINE_NUMBER_TYPE', 5);
00158 class GeSHi {
00166 var $source = '';
00167
00172 var $language = '';
00173
00178 var $language_data = array();
00179
00184 var $language_path = GESHI_LANG_ROOT;
00185
00191 var $error = false;
00192
00197 var $error_messages = array(
00198 GESHI_ERROR_NO_SUCH_LANG => 'GeSHi could not find the language {LANGUAGE} (using path {PATH})',
00199 GESHI_ERROR_FILE_NOT_READABLE => 'The file specified for load_from_file was not readable',
00200 GESHI_ERROR_INVALID_HEADER_TYPE => 'The header type specified is invalid',
00201 GESHI_ERROR_INVALID_LINE_NUMBER_TYPE => 'The line number type specified is invalid'
00202 );
00203
00208 var $strict_mode = false;
00209
00214 var $use_classes = false;
00215
00226 var $header_type = GESHI_HEADER_PRE;
00227
00232 var $lexic_permissions = array(
00233 'KEYWORDS' => array(),
00234 'COMMENTS' => array('MULTI' => true),
00235 'REGEXPS' => array(),
00236 'ESCAPE_CHAR' => true,
00237 'BRACKETS' => true,
00238 'SYMBOLS' => true,
00239 'STRINGS' => true,
00240 'NUMBERS' => true,
00241 'METHODS' => true,
00242 'SCRIPT' => true
00243 );
00244
00249 var $time = 0;
00250
00255 var $header_content = '';
00256
00261 var $footer_content = '';
00262
00267 var $header_content_style = '';
00268
00273 var $footer_content_style = '';
00274
00280 var $force_code_block = false;
00281
00286 var $link_styles = array();
00287
00294 var $enable_important_blocks = false;
00295
00303 var $important_styles = 'font-weight: bold; color: red;';
00304
00309 var $add_ids = false;
00310
00315 var $highlight_extra_lines = array();
00316
00321 var $highlight_extra_lines_style = 'color: #cc0; background-color: #ffc;';
00322
00329 var $line_ending = null;
00330
00335 var $line_numbers_start = 1;
00336
00341 var $overall_style = '';
00342
00347 var $code_style = 'font-family: \'Courier New\', Courier, monospace; font-weight: normal;';
00348
00353 var $overall_class = '';
00354
00359 var $overall_id = '';
00360
00365 var $line_style1 = 'font-family: \'Courier New\', Courier, monospace; color: black; font-weight: normal; font-style: normal;';
00366
00371 var $line_style2 = 'font-weight: bold;';
00372
00377 var $line_numbers = GESHI_NO_LINE_NUMBERS;
00378
00383 var $line_nth_row = 0;
00384
00389 var $tab_width = 8;
00390
00395 var $use_language_tab_width = false;
00396
00401 var $link_target = '';
00402
00408 var $encoding = 'ISO-8859-1';
00409
00414 var $keyword_links = true;
00415
00432 function GeSHi($source, $language, $path = '') {
00433 $this->set_source($source);
00434 $this->set_language_path($path);
00435 $this->set_language($language);
00436 }
00437
00445 function error() {
00446 if ($this->error) {
00447 $msg = $this->error_messages[$this->error];
00448 $debug_tpl_vars = array(
00449 '{LANGUAGE}' => $this->language,
00450 '{PATH}' => $this->language_path
00451 );
00452 foreach ($debug_tpl_vars as $tpl => $var) {
00453 $msg = str_replace($tpl, $var, $msg);
00454 }
00455 return "<br /><strong>GeSHi Error:</strong> $msg (code $this->error)<br />";
00456 }
00457 return false;
00458 }
00459
00467 function get_language_name() {
00468 if (GESHI_ERROR_NO_SUCH_LANG == $this->error) {
00469 return $this->language_data['LANG_NAME'] . ' (Unknown Language)';
00470 }
00471 return $this->language_data['LANG_NAME'];
00472 }
00473
00480 function set_source($source) {
00481 $this->source = $source;
00482 $this->highlight_extra_lines = array();
00483 }
00484
00491 function set_language($language) {
00492 $this->error = false;
00493 $this->strict_mode = GESHI_NEVER;
00494
00495 $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language);
00496 $this->language = strtolower($language);
00497
00498 $file_name = $this->language_path . $this->language . '.php';
00499 if (!is_readable($file_name)) {
00500 $this->error = GESHI_ERROR_NO_SUCH_LANG;
00501 return;
00502 }
00503
00504 $this->load_language($file_name);
00505 }
00506
00519 function set_language_path($path) {
00520 if ($path) {
00521 $this->language_path = ('/' == substr($path, strlen($path) - 1, 1)) ? $path : $path . '/';
00522 $this->set_language($this->language);
00523 }
00524 }
00525
00540 function set_header_type($type) {
00541 if (GESHI_HEADER_DIV != $type && GESHI_HEADER_PRE != $type && GESHI_HEADER_NONE != $type) {
00542 $this->error = GESHI_ERROR_INVALID_HEADER_TYPE;
00543 return;
00544 }
00545 $this->header_type = $type;
00546
00547 if (GESHI_HEADER_DIV == $type && !$this->overall_style) {
00548 $this->overall_style = 'font-family: monospace;';
00549 }
00550 }
00551
00561 function set_overall_style($style, $preserve_defaults = false) {
00562 if (!$preserve_defaults) {
00563 $this->overall_style = $style;
00564 }
00565 else {
00566 $this->overall_style .= $style;
00567 }
00568 }
00569
00578 function set_overall_class($class) {
00579 $this->overall_class = $class;
00580 }
00581
00589 function set_overall_id($id) {
00590 $this->overall_id = $id;
00591 }
00592
00600 function enable_classes($flag = true) {
00601 $this->use_classes = ($flag) ? true : false;
00602 }
00603
00618 function set_code_style($style, $preserve_defaults = false) {
00619 if (!$preserve_defaults) {
00620 $this->code_style = $style;
00621 }
00622 else {
00623 $this->code_style .= $style;
00624 }
00625 }
00626
00639 function set_line_style($style1, $style2 = '', $preserve_defaults = false) {
00640 if (is_bool($style2)) {
00641 $preserve_defaults = $style2;
00642 $style2 = '';
00643 }
00644 if (!$preserve_defaults) {
00645 $this->line_style1 = $style1;
00646 $this->line_style2 = $style2;
00647 }
00648 else {
00649 $this->line_style1 .= $style1;
00650 $this->line_style2 .= $style2;
00651 }
00652 }
00653
00671 function enable_line_numbers($flag, $nth_row = 5) {
00672 if (GESHI_NO_LINE_NUMBERS != $flag && GESHI_NORMAL_LINE_NUMBERS != $flag
00673 && GESHI_FANCY_LINE_NUMBERS != $flag) {
00674 $this->error = GESHI_ERROR_INVALID_LINE_NUMBER_TYPE;
00675 }
00676 $this->line_numbers = $flag;
00677 $this->line_nth_row = $nth_row;
00678 }
00679
00691 function set_keyword_group_style($key, $style, $preserve_defaults = false) {
00692 if (!$preserve_defaults) {
00693 $this->language_data['STYLES']['KEYWORDS'][$key] = $style;
00694 }
00695 else {
00696 $this->language_data['STYLES']['KEYWORDS'][$key] .= $style;
00697 }
00698 }
00699
00707 function set_keyword_group_highlighting($key, $flag = true) {
00708 $this->lexic_permissions['KEYWORDS'][$key] = ($flag) ? true : false;
00709 }
00710
00722 function set_comments_style($key, $style, $preserve_defaults = false) {
00723 if (!$preserve_defaults) {
00724 $this->language_data['STYLES']['COMMENTS'][$key] = $style;
00725 }
00726 else {
00727 $this->language_data['STYLES']['COMMENTS'][$key] .= $style;
00728 }
00729 }
00730
00738 function set_comments_highlighting($key, $flag = true) {
00739 $this->lexic_permissions['COMMENTS'][$key] = ($flag) ? true : false;
00740 }
00741
00752 function set_escape_characters_style($style, $preserve_defaults = false) {
00753 if (!$preserve_defaults) {
00754 $this->language_data['STYLES']['ESCAPE_CHAR'][0] = $style;
00755 }
00756 else {
00757 $this->language_data['STYLES']['ESCAPE_CHAR'][0] .= $style;
00758 }
00759 }
00760
00767 function set_escape_characters_highlighting($flag = true) {
00768 $this->lexic_permissions['ESCAPE_CHAR'] = ($flag) ? true : false;
00769 }
00770
00785 function set_brackets_style($style, $preserve_defaults = false) {
00786 if (!$preserve_defaults) {
00787 $this->language_data['STYLES']['BRACKETS'][0] = $style;
00788 }
00789 else {
00790 $this->language_data['STYLES']['BRACKETS'][0] .= $style;
00791 }
00792 }
00793
00804 function set_brackets_highlighting($flag) {
00805 $this->lexic_permissions['BRACKETS'] = ($flag) ? true : false;
00806 }
00807
00818 function set_symbols_style($style, $preserve_defaults = false) {
00819 if (!$preserve_defaults) {
00820 $this->language_data['STYLES']['SYMBOLS'][0] = $style;
00821 }
00822 else {
00823 $this->language_data['STYLES']['SYMBOLS'][0] .= $style;
00824 }
00825
00826 $this->set_brackets_style ($style, $preserve_defaults);
00827 }
00828
00835 function set_symbols_highlighting($flag) {
00836 $this->lexic_permissions['SYMBOLS'] = ($flag) ? true : false;
00837
00838 $this->set_brackets_highlighting ($flag);
00839 }
00840
00851 function set_strings_style($style, $preserve_defaults = false) {
00852 if (!$preserve_defaults) {
00853 $this->language_data['STYLES']['STRINGS'][0] = $style;
00854 }
00855 else {
00856 $this->language_data['STYLES']['STRINGS'][0] .= $style;
00857 }
00858 }
00859
00866 function set_strings_highlighting($flag) {
00867 $this->lexic_permissions['STRINGS'] = ($flag) ? true : false;
00868 }
00869
00880 function set_numbers_style($style, $preserve_defaults = false) {
00881 if (!$preserve_defaults) {
00882 $this->language_data['STYLES']['NUMBERS'][0] = $style;
00883 }
00884 else {
00885 $this->language_data['STYLES']['NUMBERS'][0] .= $style;
00886 }
00887 }
00888
00895 function set_numbers_highlighting($flag) {
00896 $this->lexic_permissions['NUMBERS'] = ($flag) ? true : false;
00897 }
00898
00912 function set_methods_style($key, $style, $preserve_defaults = false) {
00913 if (!$preserve_defaults) {
00914 $this->language_data['STYLES']['METHODS'][$key] = $style;
00915 }
00916 else {
00917 $this->language_data['STYLES']['METHODS'][$key] .= $style;
00918 }
00919 }
00920
00927 function set_methods_highlighting($flag) {
00928 $this->lexic_permissions['METHODS'] = ($flag) ? true : false;
00929 }
00930
00941 function set_regexps_style($key, $style, $preserve_defaults = false) {
00942 if (!$preserve_defaults) {
00943 $this->language_data['STYLES']['REGEXPS'][$key] = $style;
00944 }
00945 else {
00946 $this->language_data['STYLES']['REGEXPS'][$key] .= $style;
00947 }
00948 }
00949
00957 function set_regexps_highlighting($key, $flag) {
00958 $this->lexic_permissions['REGEXPS'][$key] = ($flag) ? true : false;
00959 }
00960
00968 function set_case_sensitivity($key, $case) {
00969 $this->language_data['CASE_SENSITIVE'][$key] = ($case) ? true : false;
00970 }
00971
00983 function set_case_keywords($case) {
00984 $this->language_data['CASE_KEYWORDS'] = $case;
00985 }
00986
00995 function set_tab_width($width) {
00996 $this->tab_width = intval($width);
00997
00998 if($this->tab_width < 1) {
00999
01000 $this->tab_width = 8;
01001 }
01002 }
01003
01009 function set_use_language_tab_width($use) {
01010 $this->use_language_tab_width = (bool) $use;
01011 }
01012
01019 function get_real_tab_width() {
01020 if (!$this->use_language_tab_width || !isset($this->language_data['TAB_WIDTH'])) {
01021 return $this->tab_width;
01022 } else {
01023 return $this->language_data['TAB_WIDTH'];
01024 }
01025 }
01026
01035 function enable_strict_mode($mode = true) {
01036 if (GESHI_MAYBE == $this->language_data['STRICT_MODE_APPLIES']) {
01037 $this->strict_mode = ($mode) ? true : false;
01038 }
01039 }
01040
01047 function disable_highlighting() {
01048 foreach ($this->lexic_permissions as $key => $value) {
01049 if (is_array($value)) {
01050 foreach ($value as $k => $v) {
01051 $this->lexic_permissions[$key][$k] = false;
01052 }
01053 }
01054 else {
01055 $this->lexic_permissions[$key] = false;
01056 }
01057 }
01058
01059 $this->enable_important_blocks = false;
01060 }
01061
01068 function enable_highlighting() {
01069 foreach ($this->lexic_permissions as $key => $value) {
01070 if (is_array($value)) {
01071 foreach ($value as $k => $v) {
01072 $this->lexic_permissions[$key][$k] = true;
01073 }
01074 }
01075 else {
01076 $this->lexic_permissions[$key] = true;
01077 }
01078 }
01079
01080 $this->enable_important_blocks = true;
01081 }
01082
01094 function get_language_name_from_extension( $extension, $lookup = array() ) {
01095 if ( !$lookup ) {
01096 $lookup = array(
01097 'actionscript' => array('as'),
01098 'ada' => array('a', 'ada', 'adb', 'ads'),
01099 'apache' => array('conf'),
01100 'asm' => array('ash', 'asm'),
01101 'asp' => array('asp'),
01102 'bash' => array('sh'),
01103 'c' => array('c', 'h'),
01104 'c_mac' => array('c', 'h'),
01105 'caddcl' => array(),
01106 'cadlisp' => array(),
01107 'cdfg' => array('cdfg'),
01108 'cpp' => array('cpp', 'h', 'hpp'),
01109 'csharp' => array(),
01110 'css' => array('css'),
01111 'delphi' => array('dpk', 'dpr'),
01112 'html4strict' => array('html', 'htm'),
01113 'java' => array('java'),
01114 'javascript' => array('js'),
01115 'lisp' => array('lisp'),
01116 'lua' => array('lua'),
01117 'mpasm' => array(),
01118 'nsis' => array(),
01119 'objc' => array(),
01120 'oobas' => array(),
01121 'oracle8' => array(),
01122 'pascal' => array('pas'),
01123 'perl' => array('pl', 'pm'),
01124 'php' => array('php', 'php5', 'phtml', 'phps'),
01125 'python' => array('py'),
01126 'qbasic' => array('bi'),
01127 'sas' => array('sas'),
01128 'smarty' => array(),
01129 'vb' => array('bas'),
01130 'vbnet' => array(),
01131 'visualfoxpro' => array(),
01132 'xml' => array('xml')
01133 );
01134 }
01135
01136 foreach ($lookup as $lang => $extensions) {
01137 foreach ($extensions as $ext) {
01138 if ($ext == $extension) {
01139 return $lang;
01140 }
01141 }
01142 }
01143 return '';
01144 }
01145
01161 function load_from_file($file_name, $lookup = array()) {
01162 if (is_readable($file_name)) {
01163 $this->set_source(implode('', file($file_name)));
01164 $this->set_language($this->get_language_name_from_extension(substr(strrchr($file_name, '.'), 1), $lookup));
01165 }
01166 else {
01167 $this->error = GESHI_ERROR_FILE_NOT_READABLE;
01168 }
01169 }
01170
01178 function add_keyword($key, $word) {
01179 $this->language_data['KEYWORDS'][$key][] = $word;
01180 }
01181
01189 function remove_keyword($key, $word) {
01190 $this->language_data['KEYWORDS'][$key] =
01191 array_diff($this->language_data['KEYWORDS'][$key], array($word));
01192 }
01193
01203 function add_keyword_group($key, $styles, $case_sensitive = true, $words = array()) {
01204 $words = (array) $words;
01205 $this->language_data['KEYWORDS'][$key] = $words;
01206 $this->lexic_permissions['KEYWORDS'][$key] = true;
01207 $this->language_data['CASE_SENSITIVE'][$key] = $case_sensitive;
01208 $this->language_data['STYLES']['KEYWORDS'][$key] = $styles;
01209 }
01210
01217 function remove_keyword_group ($key) {
01218 unset($this->language_data['KEYWORDS'][$key]);
01219 unset($this->lexic_permissions['KEYWORDS'][$key]);
01220 unset($this->language_data['CASE_SENSITIVE'][$key]);
01221 unset($this->language_data['STYLES']['KEYWORDS'][$key]);
01222 }
01223
01230 function set_header_content($content) {
01231 $this->header_content = $content;
01232 }
01233
01240 function set_footer_content($content) {
01241 $this->footer_content = $content;
01242 }
01243
01250 function set_header_content_style($style) {
01251 $this->header_content_style = $style;
01252 }
01253
01260 function set_footer_content_style($style) {
01261 $this->footer_content_style = $style;
01262 }
01263
01271 function enable_inner_code_block($flag) {
01272 $this->force_code_block = (bool)$flag;
01273 }
01274
01284 function set_url_for_keyword_group($group, $url) {
01285 $this->language_data['URLS'][$group] = $url;
01286 }
01287
01296 function set_link_styles($type, $styles) {
01297 $this->link_styles[$type] = $styles;
01298 }
01299
01306 function set_link_target($target) {
01307 if (!$target) {
01308 $this->link_target = '';
01309 }
01310 else {
01311 $this->link_target = ' target="' . $target . '" ';
01312 }
01313 }
01314
01321 function set_important_styles($styles) {
01322 $this->important_styles = $styles;
01323 }
01324
01331 function enable_important_blocks($flag) {
01332 $this->enable_important_blocks = ( $flag ) ? true : false;
01333 }
01334
01341 function enable_ids($flag = true) {
01342 $this->add_ids = ($flag) ? true : false;
01343 }
01344
01353 function highlight_lines_extra($lines) {
01354 if (is_array($lines)) {
01355 foreach ($lines as $line) {
01356 $this->highlight_extra_lines[intval($line)] = intval($line);
01357 }
01358 }
01359 else {
01360 $this->highlight_extra_lines[intval($lines)] = intval($lines);
01361 }
01362 }
01363
01370 function set_highlight_lines_extra_style($styles) {
01371 $this->highlight_extra_lines_style = $styles;
01372 }
01373
01379 function set_line_ending($line_ending) {
01380 $this->line_ending = (string)$line_ending;
01381 }
01382
01398 function start_line_numbers_at($number) {
01399 $this->line_numbers_start = abs(intval($number));
01400 }
01401
01414 function set_encoding($encoding) {
01415 if ($encoding) {
01416 $this->encoding = $encoding;
01417 }
01418 }
01419
01425 function enable_keyword_links($enable = true) {
01426 $this->keyword_links = ($enable) ? true : false;
01427 }
01428
01439 function parse_code () {
01440
01441 $start_time = microtime();
01442
01443
01444 if ($this->error) {
01445 $result = GeSHi::hsc($this->source);
01446
01447 $this->set_time($start_time, $start_time);
01448 return $this->finalise($result);
01449 }
01450
01451
01452 $code = str_replace("\r\n", "\n", $this->source);
01453 $code = str_replace("\r", "\n", $code);
01454
01455 $code = "\n" . $code . "\n";
01456
01457
01458 $length = strlen($code);
01459 $STRING_OPEN = '';
01460 $CLOSE_STRING = false;
01461 $ESCAPE_CHAR_OPEN = false;
01462 $COMMENT_MATCHED = false;
01463
01464 $HIGHLIGHTING_ON = ( !$this->strict_mode ) ? true : '';
01465
01466 $HIGHLIGHT_INSIDE_STRICT = false;
01467 $HARDQUOTE_OPEN = false;
01468 $STRICTATTRS = '';
01469 $stuff_to_parse = '';
01470 $result = '';
01471
01472
01473
01474 if ($this->enable_important_blocks) {
01475 $this->language_data['COMMENT_MULTI'][GESHI_START_IMPORTANT] = GESHI_END_IMPORTANT;
01476 }
01477
01478 if ($this->strict_mode) {
01479
01480
01481 $parts = array(0 => array(0 => ''));
01482 $k = 0;
01483 for ($i = 0; $i < $length; $i++) {
01484 $char = substr($code, $i, 1);
01485 if (!$HIGHLIGHTING_ON) {
01486 foreach ($this->language_data['SCRIPT_DELIMITERS'] as $key => $delimiters) {
01487 foreach ($delimiters as $open => $close) {
01488
01489 $check = substr($code, $i, strlen($open));
01490
01491 if ($check == $open) {
01492
01493
01494 $HIGHLIGHTING_ON = $open;
01495 $i += strlen($open) - 1;
01496 $char = $open;
01497 $parts[++$k][0] = $char;
01498
01499
01500 break(2);
01501 }
01502 }
01503 }
01504 }
01505 else {
01506 foreach ($this->language_data['SCRIPT_DELIMITERS'] as $key => $delimiters) {
01507 foreach ($delimiters as $open => $close) {
01508 if ($open == $HIGHLIGHTING_ON) {
01509
01510 break(2);
01511 }
01512 }
01513 }
01514
01515
01516 $check = substr($code, $i - strlen($close) + 1, strlen($close));
01517 if ($check == $close) {
01518 $HIGHLIGHTING_ON = '';
01519
01520 $parts[$k][1] = ( isset($parts[$k][1]) ) ? $parts[$k][1] . $char : $char;
01521 $parts[++$k][0] = '';
01522 $char = '';
01523 }
01524 }
01525 $parts[$k][1] = ( isset($parts[$k][1]) ) ? $parts[$k][1] . $char : $char;
01526 }
01527 $HIGHLIGHTING_ON = '';
01528 }
01529 else {
01530
01531
01532 $parts = array(
01533 1 => array(
01534 0 => '',
01535 1 => $code
01536 )
01537 );
01538 }
01539
01540
01541
01542
01543 foreach ($parts as $key => $data) {
01544 $part = $data[1];
01545
01546 if ($key % 2) {
01547 if ($this->strict_mode) {
01548
01549 foreach ($this->language_data['SCRIPT_DELIMITERS'] as $script_key => $script_data) {
01550 foreach ($script_data as $open => $close) {
01551 if ($data[0] == $open) {
01552 break(2);
01553 }
01554 }
01555 }
01556
01557 if ($this->language_data['STYLES']['SCRIPT'][$script_key] != '' &&
01558 $this->lexic_permissions['SCRIPT']) {
01559
01560
01561 if (!$this->use_classes &&
01562 $this->language_data['STYLES']['SCRIPT'][$script_key] != '') {
01563 $attributes = ' style="' . $this->language_data['STYLES']['SCRIPT'][$script_key] . '"';
01564 }
01565 else {
01566 $attributes = ' class="sc' . $script_key . '"';
01567 }
01568 $result .= "<span$attributes>";
01569 $STRICTATTRS = $attributes;
01570 }
01571 }
01572
01573 if (!$this->strict_mode || $this->language_data['HIGHLIGHT_STRICT_BLOCK'][$script_key]) {
01574
01575
01576
01577 $length = strlen($part);
01578 for ($i = 0; $i < $length; $i++) {
01579
01580 $char = substr($part, $i, 1);
01581 $hq = isset($this->language_data['HARDQUOTE']) ? $this->language_data['HARDQUOTE'][0] : false;
01582
01583 if (($this->line_numbers != GESHI_NO_LINE_NUMBERS
01584 || count($this->highlight_extra_lines) > 0)
01585 && $char == "\n") {
01586
01587
01588
01589
01590
01591 if ($STRING_OPEN) {
01592 if (!$this->use_classes) {
01593 $attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][0] . '"';
01594 }
01595 else {
01596 $attributes = ' class="st0"';
01597 }
01598 $char = '</span>' . $char . "<span$attributes>";
01599 }
01600 }
01601 else if ($char == $STRING_OPEN) {
01602
01603 if (($this->lexic_permissions['ESCAPE_CHAR'] && $ESCAPE_CHAR_OPEN) ||
01604 ($this->lexic_permissions['STRINGS'] && !$ESCAPE_CHAR_OPEN)) {
01605 $char = GeSHi::hsc($char) . '</span>';
01606 }
01607 $escape_me = false;
01608 if ($HARDQUOTE_OPEN) {
01609 if ($ESCAPE_CHAR_OPEN) {
01610 $escape_me = true;
01611 }
01612 else {
01613 foreach ($this->language_data['HARDESCAPE'] as $hardesc) {
01614 if (substr($part, $i, strlen($hardesc)) == $hardesc) {
01615 $escape_me = true;
01616 break;
01617 }
01618 }
01619 }
01620 }
01621
01622 if (!$ESCAPE_CHAR_OPEN) {
01623 $STRING_OPEN = '';
01624 $CLOSE_STRING = true;
01625 }
01626 if (!$escape_me) {
01627 $HARDQUOTE_OPEN = false;
01628 }
01629 $ESCAPE_CHAR_OPEN = false;
01630 }
01631 else if (in_array($char, $this->language_data['QUOTEMARKS']) &&
01632 ($STRING_OPEN == '') && $this->lexic_permissions['STRINGS']) {
01633
01634 $STRING_OPEN = $char;
01635 if (!$this->use_classes) {
01636 $attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][0] . '"';
01637 }
01638 else {
01639 $attributes = ' class="st0"';
01640 }
01641 $char = "<span$attributes>" . GeSHi::hsc($char);
01642
01643 $result .= $this->parse_non_string_part( $stuff_to_parse );
01644 $stuff_to_parse = '';
01645 }
01646 else if ($hq && substr($part, $i, strlen($hq)) == $hq &&
01647 ($STRING_OPEN == '') && $this->lexic_permissions['STRINGS']) {
01648
01649 $STRING_OPEN = $this->language_data['HARDQUOTE'][1];
01650 if (!$this->use_classes) {
01651 $attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][0] . '"';
01652 }
01653 else {
01654 $attributes = ' class="st0"';
01655 }
01656 $char = "<span$attributes>" . $hq;
01657 $i += strlen($hq) - 1;
01658 $HARDQUOTE_OPEN = true;
01659 $result .= $this->parse_non_string_part($stuff_to_parse);
01660 $stuff_to_parse = '';
01661 }
01662 else if ($char == $this->language_data['ESCAPE_CHAR'] && $STRING_OPEN != '') {
01663
01664 if (!$ESCAPE_CHAR_OPEN) {
01665 $ESCAPE_CHAR_OPEN = !$HARDQUOTE_OPEN;
01666 if ($HARDQUOTE_OPEN) {
01667 foreach ($this->language_data['HARDESCAPE'] as $hard) {
01668 if (substr($part, $i, strlen($hard)) == $hard) {
01669 $ESCAPE_CHAR_OPEN = true;
01670 break;
01671 }
01672 }
01673 }
01674 if ($ESCAPE_CHAR_OPEN && $this->lexic_permissions['ESCAPE_CHAR']) {
01675 if (!$this->use_classes) {
01676 $attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][0] . '"';
01677 }
01678 else {
01679 $attributes = ' class="es0"';
01680 }
01681 $char = "<span$attributes>" . $char;
01682 if (substr($code, $i + 1, 1) == "\n") {
01683
01684
01685 $char .= '</span>';
01686 $ESCAPE_CHAR_OPEN = false;
01687 }
01688 }
01689 }
01690 else {
01691 $ESCAPE_CHAR_OPEN = false;
01692 if ($this->lexic_permissions['ESCAPE_CHAR']) {
01693 $char .= '</span>';
01694 }
01695 }
01696 }
01697 else if ($ESCAPE_CHAR_OPEN) {
01698 if ($this->lexic_permissions['ESCAPE_CHAR']) {
01699 $char .= '</span>';
01700 }
01701 $ESCAPE_CHAR_OPEN = false;
01702 $test_str = $char;
01703 }
01704 else if ($STRING_OPEN == '') {
01705
01706 foreach ($this->language_data['COMMENT_MULTI'] as $open => $close) {
01707 $com_len = strlen($open);
01708 $test_str = substr( $part, $i, $com_len );
01709 $test_str_match = $test_str;
01710 if ($open == $test_str) {
01711 $COMMENT_MATCHED = true;
01712
01713 if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
01714 $test_str == GESHI_START_IMPORTANT) {
01715 if ($test_str != GESHI_START_IMPORTANT) {
01716 if (!$this->use_classes) {
01717 $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS']['MULTI'] . '"';
01718 }
01719 else {
01720 $attributes = ' class="coMULTI"';
01721 }
01722 $test_str = "<span$attributes>" . GeSHi::hsc($test_str);
01723 }
01724 else {
01725 if (!$this->use_classes) {
01726 $attributes = ' style="' . $this->important_styles . '"';
01727 }
01728 else {
01729 $attributes = ' class="imp"';
01730 }
01731
01732
01733 $test_str = "<span$attributes>";
01734 }
01735 }
01736 else {
01737 $test_str = GeSHi::hsc($test_str);
01738 }
01739
01740 $close_pos = strpos( $part, $close, $i + strlen($close) );
01741
01742 $oops = false;
01743 if ($close_pos === false) {
01744 $close_pos = strlen($part);
01745 $oops = true;
01746 }
01747 else {
01748 $close_pos -= ($com_len - strlen($close));
01749 }
01750
01751
01752 $rest_of_comment = GeSHi::hsc(substr($part, $i + $com_len, $close_pos - $i));
01753 if (($this->lexic_permissions['COMMENTS']['MULTI'] ||
01754 $test_str_match == GESHI_START_IMPORTANT) &&
01755 ($this->line_numbers != GESHI_NO_LINE_NUMBERS ||
01756 count($this->highlight_extra_lines) > 0)) {
01757
01758 $test_str .= str_replace(
01759 "\n", "</span>\n<span$attributes>",
01760 str_replace("\n ", "\n ", $rest_of_comment)
01761 );
01762 }
01763 else {
01764 $test_str .= $rest_of_comment;
01765 }
01766
01767 if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
01768 $test_str_match == GESHI_START_IMPORTANT) {
01769 $test_str .= '</span>';
01770 if ($oops) {
01771 $test_str .= "\n";
01772 }
01773 }
01774 $i = $close_pos + $com_len - 1;
01775
01776 $result .= $this->parse_non_string_part($stuff_to_parse);
01777 $stuff_to_parse = '';
01778 break;
01779 }
01780 }
01781
01782 if (!$COMMENT_MATCHED) {
01783 foreach ($this->language_data['COMMENT_SINGLE'] as $comment_key => $comment_mark) {
01784 $com_len = strlen($comment_mark);
01785 $test_str = substr($part, $i, $com_len);
01786 if ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS]) {
01787 $match = ($comment_mark == $test_str);
01788 }
01789 else {
01790 $match = (strtolower($comment_mark) == strtolower($test_str));
01791 }
01792 if ($match) {
01793 $COMMENT_MATCHED = true;
01794 if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
01795 if (!$this->use_classes) {
01796 $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment_key] . '"';
01797 }
01798 else {
01799 $attributes = ' class="co' . $comment_key . '"';
01800 }
01801 $test_str = "<span$attributes>" . GeSHi::hsc($this->change_case($test_str));
01802 }
01803 else {
01804 $test_str = GeSHi::hsc($test_str);
01805 }
01806 $close_pos = strpos($part, "\n", $i);
01807 $oops = false;
01808 if ($close_pos === false) {
01809 $close_pos = strlen($part);
01810 $oops = true;
01811 }
01812 $test_str .= GeSHi::hsc(substr($part, $i + $com_len, $close_pos - $i - $com_len));
01813 if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
01814 $test_str .= "</span>";
01815 }
01816
01817 if (!$oops) {
01818 $test_str .= "\n";
01819 }
01820 $i = $close_pos;
01821
01822 $result .= $this->parse_non_string_part($stuff_to_parse);
01823 $stuff_to_parse = '';
01824 break;
01825 }
01826 }
01827 }
01828 }
01829 else if ($STRING_OPEN != '') {
01830
01831 if (strtolower($this->encoding) == 'utf-8') {
01832
01833 if (ord($char) < 128) {
01834 $char = GeSHi::hsc($char);
01835 }
01836 }
01837 else {
01838
01839 $char = GeSHi::hsc($char);
01840 }
01841 }
01842
01843 if (!$COMMENT_MATCHED) {
01844 if (($STRING_OPEN == '') && !$CLOSE_STRING) {
01845 $stuff_to_parse .= $char;
01846 }
01847 else {
01848 $result .= $char;
01849 $CLOSE_STRING = false;
01850 }
01851 }
01852 else {
01853 $result .= $test_str;
01854 $COMMENT_MATCHED = false;
01855 }
01856 }
01857
01858 $result .= $this->parse_non_string_part($stuff_to_parse);
01859 $stuff_to_parse = '';
01860 }
01861 else {
01862 if ($STRICTATTRS != '') {
01863 $part = str_replace("\n", "</span>\n<span$STRICTATTRS>", GeSHi::hsc($part));
01864 $STRICTATTRS = '';
01865 }
01866 $result .= $part;
01867 }
01868
01869 if ($this->strict_mode && $this->language_data['STYLES']['SCRIPT'][$script_key] != '' &&
01870 $this->lexic_permissions['SCRIPT']) {
01871 $result .= '</span>';
01872 }
01873 }
01874 else {
01875
01876 $result .= GeSHi::hsc($part);
01877 }
01878 }
01879
01880
01881 $result .= $this->parse_non_string_part($stuff_to_parse);
01882
01883
01884 $result = substr($result, 1, -1);
01885
01886
01887 if ($STRING_OPEN) {
01888 $result .= '</span>';
01889 }
01890
01891
01892 $this->set_time($start_time, microtime());
01893
01894 return $this->finalise($result);
01895 }
01896
01906 function indent($result) {
01908 if (false !== strpos($result, "\t")) {
01909 $lines = explode("\n", $result);
01910 $tab_width = $this->get_real_tab_width();
01911 foreach ($lines as $key => $line) {
01912 if (false === strpos($line, "\t")) {
01913 $lines[$key] = $line;
01914 continue;
01915 }
01916
01917 $pos = 0;
01918 $length = strlen($line);
01919 $result_line = '';
01920
01921 $IN_TAG = false;
01922 for ($i = 0; $i < $length; $i++) {
01923 $char = substr($line, $i, 1);
01924
01925
01926
01927
01928
01929
01930
01931 if ($IN_TAG && '>' == $char) {
01932 $IN_TAG = false;
01933 $result_line .= '>';
01934 ++$pos;
01935 }
01936 else if (!$IN_TAG && '<' == $char) {
01937 $IN_TAG = true;
01938 $result_line .= '<';
01939 ++$pos;
01940 }
01941 else if (!$IN_TAG && '&' == $char) {
01942 $substr = substr($line, $i + 3, 4);
01943
01944 $posi = strpos($substr, ';');
01945 if (false !== $posi) {
01946 $pos += $posi + 3;
01947 }
01948 $result_line .= '&';
01949 }
01950 else if (!$IN_TAG && "\t" == $char) {
01951 $str = '';
01952
01953
01954
01955
01956
01957
01958 $strs = array(0 => ' ', 1 => ' ');
01959 for ($k = 0; $k < ($tab_width - (($i - $pos) % $tab_width)); $k++) $str .= $strs[$k % 2];
01960 $result_line .= $str;
01961 $pos += ($i - $pos) % $tab_width + 1;
01962
01963 if (false === strpos($line, "\t", $i + 1)) {
01964 $result_line .= substr($line, $i + 1);
01965 break;
01966 }
01967 }
01968 else if ($IN_TAG) {
01969 ++$pos;
01970 $result_line .= $char;
01971 }
01972 else {
01973 $result_line .= $char;
01974
01975 }
01976 }
01977 $lines[$key] = $result_line;
01978 }
01979 $result = implode("\n", $lines);
01980 }
01981
01982
01983 $result = str_replace("\n ", "\n ", $result);
01984 $result = str_replace(' ', ' ', $result);
01985
01986 if ($this->line_numbers == GESHI_NO_LINE_NUMBERS) {
01987 if ($this->line_ending === null) {
01988 $result = nl2br($result);
01989 } else {
01990 $result = str_replace("\n", $this->line_ending, $result);
01991 }
01992 }
01993 return $result;
01994 }
01995
02004 function change_case($instr) {
02005 if ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_UPPER) {
02006 return strtoupper($instr);
02007 }
02008 else if ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_LOWER) {
02009 return strtolower($instr);
02010 }
02011 return $instr;
02012 }
02013
02025 function add_url_to_keyword($keyword, $group, $start_or_end) {
02026 if (!$this->keyword_links) {
02027
02028 return;
02029 }
02030
02031 if (isset($this->language_data['URLS'][$group]) &&
02032 $this->language_data['URLS'][$group] != '' &&
02033 substr($keyword, 0, 5) != '</') {
02034
02035 if ($start_or_end == 'BEGIN') {
02036
02037 if ($keyword != '') {
02038
02039
02040
02041 foreach ($this->language_data['KEYWORDS'][$group] as $word) {
02042 if (strtolower($word) == strtolower($keyword)) {
02043 break;
02044 }
02045 }
02046 $word = ( substr($word, 0, 4) == '<' ) ? substr($word, 4) : $word;
02047 $word = ( substr($word, -4) == '>' ) ? substr($word, 0, strlen($word) - 4) : $word;
02048 if (!$word) return '';
02049
02050 return '<|UR1|"' .
02051 str_replace(
02052 array('{FNAME}', '.'),
02053 array(GeSHi::hsc($word), '<DOT>'),
02054 $this->language_data['URLS'][$group]
02055 ) . '">';
02056 }
02057 return '';
02058
02059 }
02060 else if (!($this->language == 'html4strict' && ('>' == $keyword || '<' == $keyword))) {
02061 return '</a>';
02062 }
02063 }
02064 }
02065
02075 function parse_non_string_part(&$stuff_to_parse) {
02076 $stuff_to_parse = ' ' . GeSHi::hsc($stuff_to_parse);
02077 $stuff_to_parse_pregquote = preg_quote($stuff_to_parse, '/');
02078 $func = '$this->change_case';
02079 $func2 = '$this->add_url_to_keyword';
02080
02081
02082
02083
02084 foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
02085 if ($this->lexic_permissions['REGEXPS'][$key]) {
02086 if (is_array($regexp)) {
02087 $stuff_to_parse = preg_replace(
02088 "/" .
02089 str_replace('/', '\/', $regexp[GESHI_SEARCH]) .
02090 "/{$regexp[GESHI_MODIFIERS]}",
02091 "{$regexp[GESHI_BEFORE]}<|!REG3XP$key!>{$regexp[GESHI_REPLACE]}|>{$regexp[GESHI_AFTER]}",
02092 $stuff_to_parse
02093 );
02094 }
02095 else {
02096 $stuff_to_parse = preg_replace( "/(" . str_replace('/', '\/', $regexp) . ")/", "<|!REG3XP$key!>\\1|>", $stuff_to_parse);
02097 }
02098 }
02099 }
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 if ($this->lexic_permissions['NUMBERS'] && preg_match('#[0-9]#', $stuff_to_parse )) {
02111 $stuff_to_parse = preg_replace('/([-+]?\\b(?:[0-9]*\\.)?[0-9]+\\b)/', '<|/NUM!/>\\1|>', $stuff_to_parse);
02112 }
02113
02114
02115
02116 if (preg_match('#[a-zA-Z]{2,}#', $stuff_to_parse)) {
02117 foreach ($this->language_data['KEYWORDS'] as $k => $keywordset) {
02118 if ($this->lexic_permissions['KEYWORDS'][$k]) {
02119 foreach ($keywordset as $keyword) {
02120 $keyword = preg_quote($keyword, '/');
02121
02122
02123
02124
02125
02126
02127 if (false !== stristr($stuff_to_parse_pregquote, $keyword )) {
02128 $stuff_to_parse .= ' ';
02129
02130
02131
02132 $styles = "/$k/";
02133 if ($this->language_data['CASE_SENSITIVE'][$k]) {
02134 $stuff_to_parse = preg_replace(
02135 "/([^a-zA-Z0-9\$_\|\#;>|^])($keyword)(?=[^a-zA-Z0-9_<\|%\-&])/e",
02136 "'\\1' . $func2('\\2', '$k', 'BEGIN') . '<|$styles>' . $func('\\2') . '|>' . $func2('\\2', '$k', 'END')",
02137 $stuff_to_parse
02138 );
02139 }
02140 else {
02141
02142
02143 if ('smarty' == $this->language) { $hackage = '\/'; } else { $hackage = ''; }
02144 $stuff_to_parse = preg_replace(
02145 "/([^a-zA-Z0-9\$_\|\#;>$hackage|^])($keyword)(?=[^a-zA-Z0-9_<\|%\-&])/ie",
02146 "'\\1' . $func2('\\2', '$k', 'BEGIN') . '<|$styles>' . $func('\\2') . '|>' . $func2('\\2', '$k', 'END')",
02147 $stuff_to_parse
02148 );
02149 }
02150 $stuff_to_parse = substr($stuff_to_parse, 0, strlen($stuff_to_parse) - 1);
02151 }
02152 }
02153 }
02154 }
02155 }
02156
02157
02158
02159
02160 foreach ($this->language_data['KEYWORDS'] as $k => $kws) {
02161 if (!$this->use_classes) {
02162 $attributes = ' style="' . $this->language_data['STYLES']['KEYWORDS'][$k] . '"';
02163 }
02164 else {
02165 $attributes = ' class="kw' . $k . '"';
02166 }
02167 $stuff_to_parse = str_replace("/$k/", $attributes, $stuff_to_parse);
02168 }
02169
02170
02171 if (!$this->use_classes && $this->lexic_permissions['NUMBERS']) {
02172 $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][0] . '"';
02173 }
02174 else {
02175 $attributes = ' class="nu0"';
02176 }
02177 $stuff_to_parse = str_replace('/NUM!/', $attributes, $stuff_to_parse);
02178
02179
02180
02181
02182 if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) {
02183 foreach ($this->language_data['OBJECT_SPLITTERS'] as $key => $splitter) {
02184 if (false !== stristr($stuff_to_parse, $splitter)) {
02185 if (!$this->use_classes) {
02186 $attributes = ' style="' . $this->language_data['STYLES']['METHODS'][$key] . '"';
02187 }
02188 else {
02189 $attributes = ' class="me' . $key . '"';
02190 }
02191 $stuff_to_parse = preg_replace("/(" . preg_quote($this->language_data['OBJECT_SPLITTERS'][$key], 1) . "[\s]*)([a-zA-Z\*\(][a-zA-Z0-9_\*]*)/", "\\1<|$attributes>\\2|>", $stuff_to_parse);
02192 }
02193 }
02194 }
02195
02196
02197
02198
02199
02200
02201
02202 if ($this->lexic_permissions['BRACKETS']) {
02203 $code_entities_match = array('[', ']', '(', ')', '{', '}');
02204 if (!$this->use_classes) {
02205 $code_entities_replace = array(
02206 '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">[|>',
02207 '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">]|>',
02208 '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">(|>',
02209 '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">)|>',
02210 '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">{|>',
02211 '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">}|>',
02212 );
02213 }
02214 else {
02215 $code_entities_replace = array(
02216 '<| class="br0">[|>',
02217 '<| class="br0">]|>',
02218 '<| class="br0">(|>',
02219 '<| class="br0">)|>',
02220 '<| class="br0">{|>',
02221 '<| class="br0">}|>',
02222 );
02223 }
02224 $stuff_to_parse = str_replace( $code_entities_match, $code_entities_replace, $stuff_to_parse );
02225 }
02226
02227
02228
02229
02230 foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
02231 if ($this->lexic_permissions['REGEXPS'][$key]) {
02232 if (!$this->use_classes) {
02233 $attributes = ' style="' . $this->language_data['STYLES']['REGEXPS'][$key] . '"';
02234 }
02235 else {
02236 if(is_array($this->language_data['REGEXPS'][$key]) &&
02237 array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$key])) {
02238 $attributes = ' class="'
02239 . $this->language_data['REGEXPS'][$key][GESHI_CLASS] . '"';
02240 }
02241 else {
02242 $attributes = ' class="re' . $key . '"';
02243 }
02244 }
02245 $stuff_to_parse = str_replace("!REG3XP$key!", "$attributes", $stuff_to_parse);
02246 }
02247 }
02248
02249
02250 $stuff_to_parse = str_replace('<DOT>', '.', $stuff_to_parse);
02251
02252 if (isset($this->link_styles[GESHI_LINK])) {
02253 if ($this->use_classes) {
02254 $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
02255 }
02256 else {
02257 $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' style="' . $this->link_styles[GESHI_LINK] . '" href=', $stuff_to_parse);
02258 }
02259 }
02260 else {
02261 $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
02262 }
02263
02264
02265
02266
02267
02268 $stuff_to_parse = str_replace('<|', '<span', $stuff_to_parse);
02269 $stuff_to_parse = str_replace ( '|>', '</span>', $stuff_to_parse );
02270
02271 return substr($stuff_to_parse, 1);
02272 }
02273
02282 function set_time($start_time, $end_time) {
02283 $start = explode(' ', $start_time);
02284 $end = explode(' ', $end_time);
02285 $this->time = $end[0] + $end[1] - $start[0] - $start[1];
02286 }
02287
02294 function get_time() {
02295 return $this->time;
02296 }
02297
02304 function load_language($file_name) {
02305 $this->enable_highlighting();
02306 $language_data = array();
02307 require $file_name;
02308
02309
02310 $this->language_data = $language_data;
02311
02312 if ($this->language_data['STRICT_MODE_APPLIES'] == GESHI_ALWAYS) {
02313 $this->strict_mode = true;
02314 }
02315
02316
02317 foreach ($this->language_data['KEYWORDS'] as $key => $words) {
02318 $this->lexic_permissions['KEYWORDS'][$key] = true;
02319 }
02320 foreach ($this->language_data['COMMENT_SINGLE'] as $key => $comment) {
02321 $this->lexic_permissions['COMMENTS'][$key] = true;
02322 }
02323 foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
02324 $this->lexic_permissions['REGEXPS'][$key] = true;
02325 }
02326
02327 $this->overall_class = $this->language;
02328 }
02329
02339 function finalise($parsed_code) {
02340
02341
02342
02343 if ($this->enable_important_blocks &&
02344 (strstr($parsed_code, GeSHi::hsc(GESHI_START_IMPORTANT)) === false)) {
02345 $parsed_code = str_replace(GeSHi::hsc(GESHI_END_IMPORTANT), '', $parsed_code);
02346 }
02347
02348
02349 if ($this->header_type != GESHI_HEADER_PRE) {
02350 $parsed_code = $this->indent($parsed_code);
02351 }
02352
02353
02354 $parsed_code = preg_replace('#<span[^>]+>(\s*)</span>#', '\\1', $parsed_code);
02355 $parsed_code = preg_replace('#<div[^>]+>(\s*)</div>#', '\\1', $parsed_code);
02356
02357
02358
02359 if ($this->add_ids && !$this->overall_id) {
02360 $this->overall_id = 'geshi-' . substr(md5(microtime()), 0, 4);
02361 }
02362
02363
02364
02365 if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
02366
02367
02368 $ls = ($this->header_type != GESHI_HEADER_PRE) ? "\n" : '';
02369
02370 $code = explode("\n", $parsed_code);
02371
02372 $parsed_code = '';
02373 $i = 0;
02374 $attrs = array();
02375
02376
02377 foreach ($code as $line) {
02378
02379
02380 if ('' == trim($line)) {
02381 $line = ' ';
02382 }
02383
02384 if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
02385 $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
02386
02387 if ($this->use_classes) {
02388
02389 $attrs['class'][] = 'li2';
02390 $def_attr = ' class="de2"';
02391 }
02392 else {
02393
02394 $attrs['style'][] = $this->line_style2;
02395
02396
02397
02398 $def_attr = ' style="' . $this->code_style . '"';
02399 }
02400
02401 $start = "<div$def_attr>";
02402 $end = '</div>';
02403 }
02404 else {
02405 if ($this->use_classes) {
02406
02407 $attrs['class'][] = 'li1';
02408 $def_attr = ' class="de1"';
02409 }
02410 else {
02411
02412 $attrs['style'][] = $this->line_style1;
02413 $def_attr = ' style="' . $this->code_style . '"';
02414 }
02415 $start = "<div$def_attr>";
02416 $end = '</div>';
02417 }
02418
02419 ++$i;
02420
02421 if ($this->add_ids) {
02422 $attrs['id'][] = "$this->overall_id-$i";
02423 }
02424 if ($this->use_classes && in_array($i, $this->highlight_extra_lines)) {
02425 $attrs['class'][] = 'ln-xtra';
02426 }
02427 if (!$this->use_classes && in_array($i, $this->highlight_extra_lines)) {
02428 $attrs['style'][] = $this->highlight_extra_lines_style;
02429 }
02430
02431
02432 $attr_string = ' ';
02433 foreach ($attrs as $key => $attr) {
02434 $attr_string .= $key . '="' . implode(' ', $attr) . '" ';
02435 }
02436 $attr_string = substr($attr_string, 0, -1);
02437 $parsed_code .= "<li$attr_string>$start$line$end</li>$ls";
02438 $attrs = array();
02439 }
02440 }
02441 else {
02442
02443
02444 $code = explode("\n", $parsed_code);
02445 $parsed_code = '';
02446 $i = 0;
02447 foreach ($code as $line) {
02448
02449
02450 if ('' == trim($line)) {
02451 $line = ' ';
02452 }
02453 if (in_array(++$i, $this->highlight_extra_lines)) {
02454 if ($this->use_classes) {
02455 $parsed_code .= '<div class="ln-xtra">';
02456 }
02457 else {
02458 $parsed_code .= "<div style=\"{$this->highlight_extra_lines_style}\">";
02459 }
02460
02461 $parsed_code .= $line . "</div>";
02462 }
02463 else {
02464 $parsed_code .= $line . "\n";
02465 }
02466 }
02467 }
02468
02469 if ($this->header_type == GESHI_HEADER_PRE) {
02470
02471 $parsed_code = str_replace('<li></li>', '<li> </li>', $parsed_code);
02472 }
02473
02474 return $this->header() . chop($parsed_code) . $this->footer();
02475 }
02476
02484 function header() {
02485
02486 $attributes = $this->get_attributes();
02487
02488 $ol_attributes = '';
02489
02490 if ($this->line_numbers_start != 1) {
02491 $ol_attributes .= ' start="' . $this->line_numbers_start . '"';
02492 }
02493
02494
02495 $header = $this->format_header_content();
02496
02497 if (GESHI_HEADER_NONE == $this->header_type) {
02498 if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
02499 return "$header<ol$ol_attributes>";
02500 }
02501 return $header .
02502 ($this->force_code_block ? '<div>' : '');
02503 }
02504
02505
02506 if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
02507 if ($this->header_type == GESHI_HEADER_PRE) {
02508 return "<pre$attributes>$header<ol$ol_attributes>";
02509 }
02510 else if ($this->header_type == GESHI_HEADER_DIV) {
02511 return "<div$attributes>$header<ol$ol_attributes>";
02512 }
02513 }
02514 else {
02515 if ($this->header_type == GESHI_HEADER_PRE) {
02516 return "<pre$attributes>$header" .
02517 ($this->force_code_block ? '<div>' : '');
02518 }
02519 else if ($this->header_type == GESHI_HEADER_DIV) {
02520 return "<div$attributes>$header" .
02521 ($this->force_code_block ? '<div>' : '');
02522 }
02523 }
02524 }
02525
02533 function format_header_content() {
02534 $header = $this->header_content;
02535 if ($header) {
02536 if ($this->header_type == GESHI_HEADER_PRE) {
02537 $header = str_replace("\n", '', $header);
02538 }
02539 $header = $this->replace_keywords($header);
02540
02541 if ($this->use_classes) {
02542 $attr = ' class="head"';
02543 }
02544 else {
02545 $attr = " style=\"{$this->header_content_style}\"";
02546 }
02547 return "<div$attr>$header</div>";
02548 }
02549 }
02550
02558 function footer() {
02559 $footer_content = $this->format_footer_content();
02560
02561 if (GESHI_HEADER_NONE == $this->header_type) {
02562 return ($this->line_numbers != GESHI_NO_LINE_NUMBERS) ? '</ol>' . $footer_content
02563 : $footer_content;
02564 }
02565
02566 if ($this->header_type == GESHI_HEADER_DIV) {
02567 if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
02568 return "</ol>$footer_content</div>";
02569 }
02570 return ($this->force_code_block ? '</div>' : '') .
02571 "$footer_content</div>";
02572 }
02573 else {
02574 if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
02575 return "</ol>$footer_content</pre>";
02576 }
02577 return ($this->force_code_block ? '</div>' : '') .
02578 "$footer_content</pre>";
02579 }
02580 }
02581
02589 function format_footer_content() {
02590 $footer = $this->footer_content;
02591 if ($footer) {
02592 if ($this->header_type == GESHI_HEADER_PRE) {
02593 $footer = str_replace("\n", '', $footer);;
02594 }
02595 $footer = $this->replace_keywords($footer);
02596
02597 if ($this->use_classes) {
02598 $attr = ' class="foot"';
02599 }
02600 else {
02601 $attr = " style=\"{$this->footer_content_style}\"";
02602 }
02603 return "<div$attr>$footer</div>";
02604 }
02605 }
02606
02616 function replace_keywords($instr) {
02617 $keywords = $replacements = array();
02618
02619 $keywords[] = '<TIME>';
02620 $keywords[] = '{TIME}';
02621 $replacements[] = $replacements[] = number_format($this->get_time(), 3);
02622
02623 $keywords[] = '<LANGUAGE>';
02624 $keywords[] = '{LANGUAGE}';
02625 $replacements[] = $replacements[] = $this->language;
02626
02627 $keywords[] = '<VERSION>';
02628 $keywords[] = '{VERSION}';
02629 $replacements[] = $replacements[] = GESHI_VERSION;
02630
02631 return str_replace($keywords, $replacements, $instr);
02632 }
02633
02643 function get_attributes() {
02644 $attributes = '';
02645
02646 if ($this->overall_class != '') {
02647 $attributes .= " class=\"{$this->overall_class}\"";
02648 }
02649 if ($this->overall_id != '') {
02650 $attributes .= " id=\"{$this->overall_id}\"";
02651 }
02652 if ($this->overall_style != '') {
02653 $attributes .= ' style="' . $this->overall_style . '"';
02654 }
02655 return $attributes;
02656 }
02657
02710 function hsc($string, $quote_style=ENT_COMPAT) {
02711
02712 $aTransSpecchar = array(
02713 '&' => '&',
02714 '"' => '"',
02715 '<' => '<',
02716 '>' => '>'
02717 );
02718
02719 if (ENT_NOQUOTES == $quote_style)
02720 {
02721 unset($aTransSpecchar['"']);
02722 }
02723 elseif (ENT_QUOTES == $quote_style)
02724 {
02725 $aTransSpecchar["'"] = ''';
02726 }
02727
02728
02729 return strtr($string,$aTransSpecchar);
02730 }
02731
02741 function get_stylesheet($economy_mode = true) {
02742
02743
02744
02745 if ($this->error) {
02746 return '';
02747 }
02748
02749
02750
02751 $selector = ($this->overall_id != '') ? "#{$this->overall_id} " : '';
02752 $selector = ($selector == '' && $this->overall_class != '') ? ".{$this->overall_class} " : $selector;
02753
02754
02755 if (!$economy_mode) {
02756 $stylesheet = "/**\n * GeSHi Dynamically Generated Stylesheet\n * --------------------------------------\n * Dynamically generated stylesheet for {$this->language}\n * CSS class: {$this->overall_class}, CSS id: {$this->overall_id}\n * GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter)\n */\n";
02757 } else {
02758 $stylesheet = '/* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter) */' . "\n";
02759 }
02760
02761
02762
02763
02764
02765 if (!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
02766
02767 $stylesheet .= "$selector.de1, $selector.de2 {{$this->code_style}}\n";
02768 }
02769
02770
02771 if (!$economy_mode || $this->overall_style != '') {
02772 $stylesheet .= "$selector {{$this->overall_style}}\n";
02773 }
02774
02775
02776 foreach ($this->link_styles as $key => $style) {
02777 if (!$economy_mode || $key == GESHI_LINK && $style != '') {
02778 $stylesheet .= "{$selector}a:link {{$style}}\n";
02779 }
02780 if (!$economy_mode || $key == GESHI_HOVER && $style != '') {
02781 $stylesheet .= "{$selector}a:hover {{$style}}\n";
02782 }
02783 if (!$economy_mode || $key == GESHI_ACTIVE && $style != '') {
02784 $stylesheet .= "{$selector}a:active {{$style}}\n";
02785 }
02786 if (!$economy_mode || $key == GESHI_VISITED && $style != '') {
02787 $stylesheet .= "{$selector}a:visited {{$style}}\n";
02788 }
02789 }
02790
02791
02792 if (!$economy_mode || $this->header_content_style != '') {
02793 $stylesheet .= "$selector.head {{$this->header_content_style}}\n";
02794 }
02795 if (!$economy_mode || $this->footer_content_style != '') {
02796 $stylesheet .= "$selector.foot {{$this->footer_content_style}}\n";
02797 }
02798
02799
02800 if (!$economy_mode || $this->important_styles != '') {
02801 $stylesheet .= "$selector.imp {{$this->important_styles}}\n";
02802 }
02803
02804
02805 if (!$economy_mode || count($this->highlight_extra_lines)) {
02806 $stylesheet .= "$selector.ln-xtra {{$this->highlight_extra_lines_style}}\n";
02807 }
02808
02809
02810 if (!$economy_mode || ($this->line_numbers != GESHI_NO_LINE_NUMBERS && $this->line_style1 != '')) {
02811 $stylesheet .= "{$selector}li {{$this->line_style1}}\n";
02812 }
02813
02814
02815 if (!$economy_mode || ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS && $this->line_style2 != '')) {
02816 $stylesheet .= "{$selector}li.li2 {{$this->line_style2}}\n";
02817 }
02818
02819 foreach ($this->language_data['STYLES']['KEYWORDS'] as $group => $styles) {
02820 if (!$economy_mode || !($economy_mode && (!$this->lexic_permissions['KEYWORDS'][$group] || $styles == ''))) {
02821 $stylesheet .= "$selector.kw$group {{$styles}}\n";
02822 }
02823 }
02824 foreach ($this->language_data['STYLES']['COMMENTS'] as $group => $styles) {
02825 if (!$economy_mode || !($economy_mode && $styles == '') &&
02826 !($economy_mode && !$this->lexic_permissions['COMMENTS'][$group])) {
02827 $stylesheet .= "$selector.co$group {{$styles}}\n";
02828 }
02829 }
02830 foreach ($this->language_data['STYLES']['ESCAPE_CHAR'] as $group => $styles) {
02831 if (!$economy_mode || !($economy_mode && $styles == '') && !($economy_mode &&
02832 !$this->lexic_permissions['ESCAPE_CHAR'])) {
02833 $stylesheet .= "$selector.es$group {{$styles}}\n";
02834 }
02835 }
02836 foreach ($this->language_data['STYLES']['SYMBOLS'] as $group => $styles) {
02837 if (!$economy_mode || !($economy_mode && $styles == '') && !($economy_mode &&
02838 !$this->lexic_permissions['BRACKETS'])) {
02839 $stylesheet .= "$selector.br$group {{$styles}}\n";
02840 }
02841 }
02842 foreach ($this->language_data['STYLES']['STRINGS'] as $group => $styles) {
02843 if (!$economy_mode || !($economy_mode && $styles == '') && !($economy_mode &&
02844 !$this->lexic_permissions['STRINGS'])) {
02845 $stylesheet .= "$selector.st$group {{$styles}}\n";
02846 }
02847 }
02848 foreach ($this->language_data['STYLES']['NUMBERS'] as $group => $styles) {
02849 if (!$economy_mode || !($economy_mode && $styles == '') && !($economy_mode &&
02850 !$this->lexic_permissions['NUMBERS'])) {
02851 $stylesheet .= "$selector.nu$group {{$styles}}\n";
02852 }
02853 }
02854 foreach ($this->language_data['STYLES']['METHODS'] as $group => $styles) {
02855 if (!$economy_mode || !($economy_mode && $styles == '') && !($economy_mode &&
02856 !$this->lexic_permissions['METHODS'])) {
02857 $stylesheet .= "$selector.me$group {{$styles}}\n";
02858 }
02859 }
02860 foreach ($this->language_data['STYLES']['SCRIPT'] as $group => $styles) {
02861 if (!$economy_mode || !($economy_mode && $styles == '')) {
02862 $stylesheet .= "$selector.sc$group {{$styles}}\n";
02863 }
02864 }
02865 foreach ($this->language_data['STYLES']['REGEXPS'] as $group => $styles) {
02866 if (!$economy_mode || !($economy_mode && $styles == '') && !($economy_mode &&
02867 !$this->lexic_permissions['REGEXPS'][$group])) {
02868 if (is_array($this->language_data['REGEXPS'][$group]) &&
02869 array_key_exists(GESHI_CLASS,
02870 $this->language_data['REGEXPS'][$group])) {
02871 $stylesheet .= "$selector.";
02872 $stylesheet .= $this->language_data['REGEXPS'][$group][GESHI_CLASS];
02873 $stylesheet .= " {{$styles}}\n";
02874 }
02875 else {
02876 $stylesheet .= "$selector.re$group {{$styles}}\n";
02877 }
02878 }
02879 }
02880
02881 return $stylesheet;
02882 }
02883
02884 }
02885
02886
02887 if (!function_exists('geshi_highlight')) {
02899 function geshi_highlight($string, $language, $path = null, $return = false) {
02900 $geshi = new GeSHi($string, $language, $path);
02901 $geshi->set_header_type(GESHI_HEADER_NONE);
02902 if ($return) {
02903 return '<code>' . $geshi->parse_code() . '</code>';
02904 }
02905 echo '<code>' . $geshi->parse_code() . '</code>';
02906 if ($geshi->error()) {
02907 return false;
02908 }
02909 return true;
02910 }
02911 }
02912
02913 ?>