plugins/geshi/base.php
changeset 3 f3e2bbbd2155
parent 2 9e3258dfae15
equal deleted inserted replaced
2:9e3258dfae15 3:f3e2bbbd2155
    39 // their values - you never know when a value may change in a future
    39 // their values - you never know when a value may change in a future
    40 // version
    40 // version
    41 //
    41 //
    42 
    42 
    43 /** The version of this GeSHi file */
    43 /** The version of this GeSHi file */
    44 define('GESHI_VERSION', '1.0.8.2');
    44 define('GESHI_VERSION', '1.0.8.4');
    45 
    45 
    46 // Define the root directory for the GeSHi code tree
    46 // Define the root directory for the GeSHi code tree
    47 if (!defined('GESHI_ROOT')) {
    47 if (!defined('GESHI_ROOT')) {
    48     /** The root directory for GeSHi */
    48     /** The root directory for GeSHi */
    49     define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
    49     define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
   981      * @param string  The style to make the escape characters
   981      * @param string  The style to make the escape characters
   982      * @param boolean Whether to merge the new styles with the old or just
   982      * @param boolean Whether to merge the new styles with the old or just
   983      *                to overwrite them
   983      *                to overwrite them
   984      * @since 1.0.0
   984      * @since 1.0.0
   985      */
   985      */
   986     function set_escape_characters_style($style, $preserve_defaults = false) {
   986     function set_escape_characters_style($style, $preserve_defaults = false, $group = 0) {
   987         if (!$preserve_defaults) {
   987         if (!$preserve_defaults) {
   988             $this->language_data['STYLES']['ESCAPE_CHAR'][0] = $style;
   988             $this->language_data['STYLES']['ESCAPE_CHAR'][$group] = $style;
   989         } else {
   989         } else {
   990             $this->language_data['STYLES']['ESCAPE_CHAR'][0] .= $style;
   990             $this->language_data['STYLES']['ESCAPE_CHAR'][$group] .= $style;
   991         }
   991         }
   992     }
   992     }
   993 
   993 
   994     /**
   994     /**
   995      * Turns highlighting on/off for escaped characters
   995      * Turns highlighting on/off for escaped characters
  1103     function set_strings_highlighting($flag) {
  1103     function set_strings_highlighting($flag) {
  1104         $this->lexic_permissions['STRINGS'] = ($flag) ? true : false;
  1104         $this->lexic_permissions['STRINGS'] = ($flag) ? true : false;
  1105     }
  1105     }
  1106 
  1106 
  1107     /**
  1107     /**
       
  1108      * Sets the styles for strict code blocks. If $preserve_defaults is
       
  1109      * true, then styles are merged with the default styles, with the
       
  1110      * user defined styles having priority
       
  1111      *
       
  1112      * @param string  The style to make the script blocks
       
  1113      * @param boolean Whether to merge the new styles with the old or just
       
  1114      *                to overwrite them
       
  1115      * @param int     Tells the group of script blocks for which style should be set.
       
  1116      * @since 1.0.8.4
       
  1117      */
       
  1118     function set_script_style($style, $preserve_defaults = false, $group = 0) {
       
  1119         // Update the style of symbols
       
  1120         if (!$preserve_defaults) {
       
  1121             $this->language_data['STYLES']['SCRIPT'][$group] = $style;
       
  1122         } else {
       
  1123             $this->language_data['STYLES']['SCRIPT'][$group] .= $style;
       
  1124         }
       
  1125     }
       
  1126 
       
  1127     /**
  1108      * Sets the styles for numbers. If $preserve_defaults is
  1128      * Sets the styles for numbers. If $preserve_defaults is
  1109      * true, then styles are merged with the default styles, with the
  1129      * true, then styles are merged with the default styles, with the
  1110      * user defined styles having priority
  1130      * user defined styles having priority
  1111      *
  1131      *
  1112      * @param string  The style to make the numbers
  1132      * @param string  The style to make the numbers
  1327      * @todo static?
  1347      * @todo static?
  1328      */
  1348      */
  1329     function get_language_name_from_extension( $extension, $lookup = array() ) {
  1349     function get_language_name_from_extension( $extension, $lookup = array() ) {
  1330         if ( !is_array($lookup) || empty($lookup)) {
  1350         if ( !is_array($lookup) || empty($lookup)) {
  1331             $lookup = array(
  1351             $lookup = array(
       
  1352                 'abap' => array('abap'),
  1332                 'actionscript' => array('as'),
  1353                 'actionscript' => array('as'),
  1333                 'ada' => array('a', 'ada', 'adb', 'ads'),
  1354                 'ada' => array('a', 'ada', 'adb', 'ads'),
  1334                 'apache' => array('conf'),
  1355                 'apache' => array('conf'),
  1335                 'asm' => array('ash', 'asm', 'inc'),
  1356                 'asm' => array('ash', 'asm', 'inc'),
  1336                 'asp' => array('asp'),
  1357                 'asp' => array('asp'),
  1390                 'tcl' => array('tcl'),
  1411                 'tcl' => array('tcl'),
  1391                 'vb' => array('bas'),
  1412                 'vb' => array('bas'),
  1392                 'vbnet' => array(),
  1413                 'vbnet' => array(),
  1393                 'visualfoxpro' => array(),
  1414                 'visualfoxpro' => array(),
  1394                 'whitespace' => array('ws'),
  1415                 'whitespace' => array('ws'),
  1395                 'xml' => array('xml', 'svg'),
  1416                 'xml' => array('xml', 'svg', 'xrc'),
  1396                 'z80' => array('z80', 'asm', 'inc')
  1417                 'z80' => array('z80', 'asm', 'inc')
  1397             );
  1418             );
  1398         }
  1419         }
  1399 
  1420 
  1400         foreach ($lookup as $lang => $extensions) {
  1421         foreach ($lookup as $lang => $extensions) {
  1527      * @since 1.0.8
  1548      * @since 1.0.8
  1528      */
  1549      */
  1529     function optimize_keyword_group($key) {
  1550     function optimize_keyword_group($key) {
  1530         $this->language_data['CACHED_KEYWORD_LISTS'][$key] =
  1551         $this->language_data['CACHED_KEYWORD_LISTS'][$key] =
  1531             $this->optimize_regexp_list($this->language_data['KEYWORDS'][$key]);
  1552             $this->optimize_regexp_list($this->language_data['KEYWORDS'][$key]);
       
  1553         $space_as_whitespace = false;
       
  1554         if(isset($this->language_data['PARSER_CONTROL'])) {
       
  1555             if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
       
  1556                 if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'])) {
       
  1557                     $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'];
       
  1558                 }
       
  1559                 if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
       
  1560                     if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
       
  1561                         $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'];
       
  1562                     }
       
  1563                 }
       
  1564             }
       
  1565         }
       
  1566         if($space_as_whitespace) {
       
  1567             foreach($this->language_data['CACHED_KEYWORD_LISTS'][$key] as $rxk => $rxv) {
       
  1568                 $this->language_data['CACHED_KEYWORD_LISTS'][$key][$rxk] =
       
  1569                     str_replace(" ", "\\s+", $rxv);
       
  1570             }
       
  1571         }
  1532     }
  1572     }
  1533 
  1573 
  1534     /**
  1574     /**
  1535      * Sets the content of the header block
  1575      * Sets the content of the header block
  1536      *
  1576      *
  1924 
  1964 
  1925             //Number format specification
  1965             //Number format specification
  1926             //All this formats are matched case-insensitively!
  1966             //All this formats are matched case-insensitively!
  1927             static $numbers_format = array(
  1967             static $numbers_format = array(
  1928                 GESHI_NUMBER_INT_BASIC =>
  1968                 GESHI_NUMBER_INT_BASIC =>
  1929                     '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z\.])',
  1969                     '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z]|\.(?!(?m:$)))',
  1930                 GESHI_NUMBER_INT_CSTYLE =>
  1970                 GESHI_NUMBER_INT_CSTYLE =>
  1931                     '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)l(?![0-9a-z\.])',
  1971                     '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)l(?![0-9a-z\.])',
  1932                 GESHI_NUMBER_BIN_SUFFIX =>
  1972                 GESHI_NUMBER_BIN_SUFFIX =>
  1933                     '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[01]+?b(?![0-9a-z\.])',
  1973                     '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[01]+?b(?![0-9a-z\.])',
  1934                 GESHI_NUMBER_BIN_PREFIX_PERCENT =>
  1974                 GESHI_NUMBER_BIN_PREFIX_PERCENT =>
  1970                     }
  2010                     }
  1971                     $regexp = implode("|", $rxuse);
  2011                     $regexp = implode("|", $rxuse);
  1972                 }
  2012                 }
  1973 
  2013 
  1974                 $this->language_data['NUMBERS_RXCACHE'][$key] =
  2014                 $this->language_data['NUMBERS_RXCACHE'][$key] =
  1975                     "/(?<!<\|\/NUM!)(?<!\d\/>)($regexp)(?!\|>)/i";
  2015                     "/(?<!<\|\/)(?<!<\|!REG3XP)(?<!<\|\/NUM!)(?<!\d\/>)($regexp)(?!\|>)(?![^\"\|\>\<]+<)/i";
  1976             }
  2016             }
  1977         }
  2017         }
  1978 
  2018 
  1979         $this->parse_cache_built = true;
  2019         $this->parse_cache_built = true;
  1980     }
  2020     }
  2089                          *  - Group 2 is the closer
  2129                          *  - Group 2 is the closer
  2090                          */
  2130                          */
  2091                         if(!GESHI_PHP_PRE_433 && //Needs proper rewrite to work with PHP >=4.3.0; 4.3.3 is guaranteed to work.
  2131                         if(!GESHI_PHP_PRE_433 && //Needs proper rewrite to work with PHP >=4.3.0; 4.3.3 is guaranteed to work.
  2092                             preg_match($delimiters, $code, $matches_rx, PREG_OFFSET_CAPTURE, $i)) {
  2132                             preg_match($delimiters, $code, $matches_rx, PREG_OFFSET_CAPTURE, $i)) {
  2093                             //We got a match ...
  2133                             //We got a match ...
  2094                             $matches[$dk] = array(
  2134                             if(isset($matches_rx['start']) && isset($matches_rx['end']))
  2095                                 'next_match' => $matches_rx[1][1],
  2135                             {
  2096                                 'dk' => $dk,
  2136                                 $matches[$dk] = array(
  2097 
  2137                                     'next_match' => $matches_rx['start'][1],
  2098                                 'close_strlen' => strlen($matches_rx[2][0]),
  2138                                     'dk' => $dk,
  2099                                 'close_pos' => $matches_rx[2][1],
  2139 
  2100                                 );
  2140                                     'close_strlen' => strlen($matches_rx['end'][0]),
       
  2141                                     'close_pos' => $matches_rx['end'][1],
       
  2142                                     );
       
  2143                             } else {
       
  2144                                 $matches[$dk] = array(
       
  2145                                     'next_match' => $matches_rx[1][1],
       
  2146                                     'dk' => $dk,
       
  2147 
       
  2148                                     'close_strlen' => strlen($matches_rx[2][0]),
       
  2149                                     'close_pos' => $matches_rx[2][1],
       
  2150                                     );
       
  2151                             }
  2101                         } else {
  2152                         } else {
  2102                             // no match for this delimiter ever
  2153                             // no match for this delimiter ever
  2103                             unset($delim_copy[$dk]);
  2154                             unset($delim_copy[$dk]);
  2104                             continue;
  2155                             continue;
  2105                         }
  2156                         }
  2108                             $next_match_pointer =& $matches[$dk];
  2159                             $next_match_pointer =& $matches[$dk];
  2109                             $next_match_pos = $matches[$dk]['next_match'];
  2160                             $next_match_pos = $matches[$dk]['next_match'];
  2110                         }
  2161                         }
  2111                     }
  2162                     }
  2112                 }
  2163                 }
       
  2164 
  2113                 // non-highlightable text
  2165                 // non-highlightable text
  2114                 $parts[$k] = array(
  2166                 $parts[$k] = array(
  2115                     1 => substr($code, $i, $next_match_pos - $i)
  2167                     1 => substr($code, $i, $next_match_pos - $i)
  2116                 );
  2168                 );
  2117                 ++$k;
  2169                 ++$k;
  2381                             }
  2433                             }
  2382                         }
  2434                         }
  2383                         $char_len = strlen($char);
  2435                         $char_len = strlen($char);
  2384                     }
  2436                     }
  2385 
  2437 
  2386                     if ($string_started && $i != $next_comment_regexp_pos) {
  2438                     if ($string_started && ($i != $next_comment_regexp_pos)) {
  2387                         // Hand out the correct style information for this string
  2439                         // Hand out the correct style information for this string
  2388                         $string_key = array_search($char, $this->language_data['QUOTEMARKS']);
  2440                         $string_key = array_search($char, $this->language_data['QUOTEMARKS']);
  2389                         if (!isset($this->language_data['STYLES']['STRINGS'][$string_key]) ||
  2441                         if (!isset($this->language_data['STYLES']['STRINGS'][$string_key]) ||
  2390                             !isset($this->language_data['STYLES']['ESCAPE_CHAR'][$string_key])) {
  2442                             !isset($this->language_data['STYLES']['ESCAPE_CHAR'][$string_key])) {
  2391                             $string_key = 0;
  2443                             $string_key = 0;
  2573                         $result .= $string;
  2625                         $result .= $string;
  2574                         $string = '';
  2626                         $string = '';
  2575                         $i = $start - 1;
  2627                         $i = $start - 1;
  2576                         continue;
  2628                         continue;
  2577                     } else if ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char &&
  2629                     } else if ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char &&
  2578                         substr($part, $i, $hq_strlen) == $hq) {
  2630                         substr($part, $i, $hq_strlen) == $hq && ($i != $next_comment_regexp_pos)) {
  2579                         // The start of a hard quoted string
  2631                         // The start of a hard quoted string
  2580                         if (!$this->use_classes) {
  2632                         if (!$this->use_classes) {
  2581                             $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS']['HARD'] . '"';
  2633                             $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS']['HARD'] . '"';
  2582                             $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR']['HARD'] . '"';
  2634                             $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR']['HARD'] . '"';
  2583                         } else {
  2635                         } else {
  2593 
  2645 
  2594                         // look for closing quote
  2646                         // look for closing quote
  2595                         $start = $i + $hq_strlen;
  2647                         $start = $i + $hq_strlen;
  2596                         while ($close_pos = strpos($part, $this->language_data['HARDQUOTE'][1], $start)) {
  2648                         while ($close_pos = strpos($part, $this->language_data['HARDQUOTE'][1], $start)) {
  2597                             $start = $close_pos + 1;
  2649                             $start = $close_pos + 1;
  2598                             if ($this->lexic_permissions['ESCAPE_CHAR'] && $part[$close_pos - 1] == $this->language_data['ESCAPE_CHAR']) {
  2650                             if ($this->lexic_permissions['ESCAPE_CHAR'] && $part[$close_pos - 1] == $this->language_data['HARDCHAR']) {
  2599                                 // make sure this quote is not escaped
  2651                                 // make sure this quote is not escaped
  2600                                 foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
  2652                                 foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
  2601                                     if (substr($part, $close_pos - 1, strlen($hardescape)) == $hardescape) {
  2653                                     if (substr($part, $close_pos - 1, strlen($hardescape)) == $hardescape) {
  2602                                         // check wether this quote is escaped or if it is something like '\\'
  2654                                         // check wether this quote is escaped or if it is something like '\\'
  2603                                         $escape_char_pos = $close_pos - 1;
  2655                                         $escape_char_pos = $close_pos - 1;
  2604                                         while ($escape_char_pos > 0
  2656                                         while ($escape_char_pos > 0
  2605                                                 && $part[$escape_char_pos - 1] == $this->language_data['ESCAPE_CHAR']) {
  2657                                                 && $part[$escape_char_pos - 1] == $this->language_data['HARDCHAR']) {
  2606                                             --$escape_char_pos;
  2658                                             --$escape_char_pos;
  2607                                         }
  2659                                         }
  2608                                         if (($close_pos - $escape_char_pos) & 1) {
  2660                                         if (($close_pos - $escape_char_pos) & 1) {
  2609                                             // uneven number of escape chars => this quote is escaped
  2661                                             // uneven number of escape chars => this quote is escaped
  2610                                             continue 2;
  2662                                             continue 2;
  3181      * @todo BUGGY! Why? Why not build string and return?
  3233      * @todo BUGGY! Why? Why not build string and return?
  3182      */
  3234      */
  3183     function parse_non_string_part($stuff_to_parse) {
  3235     function parse_non_string_part($stuff_to_parse) {
  3184         $stuff_to_parse = ' ' . $this->hsc($stuff_to_parse);
  3236         $stuff_to_parse = ' ' . $this->hsc($stuff_to_parse);
  3185 
  3237 
       
  3238         // Highlight keywords
       
  3239         $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
       
  3240         $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
       
  3241         if ($this->lexic_permissions['STRINGS']) {
       
  3242             $quotemarks = preg_quote(implode($this->language_data['QUOTEMARKS']), '/');
       
  3243             $disallowed_before .= $quotemarks;
       
  3244             $disallowed_after .= $quotemarks;
       
  3245         }
       
  3246         $disallowed_before .= "])";
       
  3247         $disallowed_after .= "])";
       
  3248 
       
  3249         $parser_control_pergroup = false;
       
  3250         if (isset($this->language_data['PARSER_CONTROL'])) {
       
  3251             if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
       
  3252                 $x = 0; // check wether per-keyword-group parser_control is enabled
       
  3253                 if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
       
  3254                     $disallowed_before = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
       
  3255                     ++$x;
       
  3256                 }
       
  3257                 if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
       
  3258                     $disallowed_after = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
       
  3259                     ++$x;
       
  3260                 }
       
  3261                 $parser_control_pergroup = (count($this->language_data['PARSER_CONTROL']['KEYWORDS']) - $x) > 0;
       
  3262             }
       
  3263         }
       
  3264 
       
  3265         foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
       
  3266             if (!isset($this->lexic_permissions['KEYWORDS'][$k]) ||
       
  3267             $this->lexic_permissions['KEYWORDS'][$k]) {
       
  3268 
       
  3269                 $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k];
       
  3270                 $modifiers = $case_sensitive ? '' : 'i';
       
  3271 
       
  3272                 // NEW in 1.0.8 - per-keyword-group parser control
       
  3273                 $disallowed_before_local = $disallowed_before;
       
  3274                 $disallowed_after_local = $disallowed_after;
       
  3275                 if ($parser_control_pergroup && isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k])) {
       
  3276                     if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'])) {
       
  3277                         $disallowed_before_local =
       
  3278                             $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'];
       
  3279                     }
       
  3280 
       
  3281                     if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'])) {
       
  3282                         $disallowed_after_local =
       
  3283                             $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'];
       
  3284                     }
       
  3285                 }
       
  3286 
       
  3287                 $this->_kw_replace_group = $k;
       
  3288 
       
  3289                 //NEW in 1.0.8, the cached regexp list
       
  3290                 // since we don't want PHP / PCRE to crash due to too large patterns we split them into smaller chunks
       
  3291                 for ($set = 0, $set_length = count($this->language_data['CACHED_KEYWORD_LISTS'][$k]); $set <  $set_length; ++$set) {
       
  3292                     $keywordset =& $this->language_data['CACHED_KEYWORD_LISTS'][$k][$set];
       
  3293                     // Might make a more unique string for putting the number in soon
       
  3294                     // Basically, we don't put the styles in yet because then the styles themselves will
       
  3295                     // get highlighted if the language has a CSS keyword in it (like CSS, for example ;))
       
  3296                     $stuff_to_parse = preg_replace_callback(
       
  3297                         "/$disallowed_before_local({$keywordset})(?!\<DOT\>(?:htm|php))$disallowed_after_local/$modifiers",
       
  3298                         array($this, 'handle_keyword_replace'),
       
  3299                         $stuff_to_parse
       
  3300                         );
       
  3301                 }
       
  3302             }
       
  3303         }
       
  3304 
  3186         // Regular expressions
  3305         // Regular expressions
  3187         foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
  3306         foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
  3188             if ($this->lexic_permissions['REGEXPS'][$key]) {
  3307             if ($this->lexic_permissions['REGEXPS'][$key]) {
  3189                 if (is_array($regexp)) {
  3308                 if (is_array($regexp)) {
  3190                     if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
  3309                     if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
  3218                     }
  3337                     }
  3219                 }
  3338                 }
  3220             }
  3339             }
  3221         }
  3340         }
  3222 
  3341 
  3223         // Highlight numbers. As of 1.0.8 we support diffent types of numbers
  3342         // Highlight numbers. As of 1.0.8 we support different types of numbers
  3224         $numbers_found = false;
  3343         $numbers_found = false;
  3225         if ($this->lexic_permissions['NUMBERS'] && preg_match('#\d#', $stuff_to_parse )) {
  3344         if ($this->lexic_permissions['NUMBERS'] && preg_match('#\d#', $stuff_to_parse )) {
  3226             $numbers_found = true;
  3345             $numbers_found = true;
  3227 
  3346 
  3228             //For each of the formats ...
  3347             //For each of the formats ...
  3229             foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
  3348             foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
  3230                 //Check if it should be highlighted ...
  3349                 //Check if it should be highlighted ...
  3231                 $stuff_to_parse = preg_replace($regexp, "<|/NUM!$id/>\\1|>", $stuff_to_parse);
  3350                 $stuff_to_parse = preg_replace($regexp, "<|/NUM!$id/>\\1|>", $stuff_to_parse);
  3232             }
       
  3233         }
       
  3234 
       
  3235         // Highlight keywords
       
  3236         $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
       
  3237         $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
       
  3238         if ($this->lexic_permissions['STRINGS']) {
       
  3239             $quotemarks = preg_quote(implode($this->language_data['QUOTEMARKS']), '/');
       
  3240             $disallowed_before .= $quotemarks;
       
  3241             $disallowed_after .= $quotemarks;
       
  3242         }
       
  3243         $disallowed_before .= "])";
       
  3244         $disallowed_after .= "])";
       
  3245 
       
  3246         $parser_control_pergroup = false;
       
  3247         if (isset($this->language_data['PARSER_CONTROL'])) {
       
  3248             if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
       
  3249                 $x = 0; // check wether per-keyword-group parser_control is enabled
       
  3250                 if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
       
  3251                     $disallowed_before = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
       
  3252                     ++$x;
       
  3253                 }
       
  3254                 if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
       
  3255                     $disallowed_after = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
       
  3256                     ++$x;
       
  3257                 }
       
  3258                 $parser_control_pergroup = (count($this->language_data['PARSER_CONTROL']['KEYWORDS']) - $x) > 0;
       
  3259             }
       
  3260         }
       
  3261 
       
  3262         // if this is changed, don't forget to change it below
       
  3263 //        if (!empty($disallowed_before)) {
       
  3264 //            $disallowed_before = "(?<![$disallowed_before])";
       
  3265 //        }
       
  3266 //        if (!empty($disallowed_after)) {
       
  3267 //            $disallowed_after = "(?![$disallowed_after])";
       
  3268 //        }
       
  3269 
       
  3270         foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
       
  3271             if (!isset($this->lexic_permissions['KEYWORDS'][$k]) ||
       
  3272                 $this->lexic_permissions['KEYWORDS'][$k]) {
       
  3273 
       
  3274                 $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k];
       
  3275                 $modifiers = $case_sensitive ? '' : 'i';
       
  3276 
       
  3277                 // NEW in 1.0.8 - per-keyword-group parser control
       
  3278                 $disallowed_before_local = $disallowed_before;
       
  3279                 $disallowed_after_local = $disallowed_after;
       
  3280                 if ($parser_control_pergroup && isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k])) {
       
  3281                     if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'])) {
       
  3282                         $disallowed_before_local =
       
  3283                             $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'];
       
  3284                     }
       
  3285 
       
  3286                     if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'])) {
       
  3287                         $disallowed_after_local =
       
  3288                             $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'];
       
  3289                     }
       
  3290                 }
       
  3291 
       
  3292                 $this->_kw_replace_group = $k;
       
  3293 
       
  3294                 //NEW in 1.0.8, the cached regexp list
       
  3295                 // since we don't want PHP / PCRE to crash due to too large patterns we split them into smaller chunks
       
  3296                 for ($set = 0, $set_length = count($this->language_data['CACHED_KEYWORD_LISTS'][$k]); $set <  $set_length; ++$set) {
       
  3297                     $keywordset =& $this->language_data['CACHED_KEYWORD_LISTS'][$k][$set];
       
  3298                     // Might make a more unique string for putting the number in soon
       
  3299                     // Basically, we don't put the styles in yet because then the styles themselves will
       
  3300                     // get highlighted if the language has a CSS keyword in it (like CSS, for example ;))
       
  3301                     $stuff_to_parse = preg_replace_callback(
       
  3302                         "/$disallowed_before_local({$keywordset})(?!\<DOT\>(?:htm|php))$disallowed_after_local/$modifiers",
       
  3303                         array($this, 'handle_keyword_replace'),
       
  3304                         $stuff_to_parse
       
  3305                         );
       
  3306                 }
       
  3307             }
  3351             }
  3308         }
  3352         }
  3309 
  3353 
  3310         //
  3354         //
  3311         // Now that's all done, replace /[number]/ with the correct styles
  3355         // Now that's all done, replace /[number]/ with the correct styles
  3322         }
  3366         }
  3323 
  3367 
  3324         if ($numbers_found) {
  3368         if ($numbers_found) {
  3325             // Put number styles in
  3369             // Put number styles in
  3326             foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
  3370             foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
  3327 //Commented out for now, as this needs some review ...
  3371                 //Commented out for now, as this needs some review ...
  3328 //                if ($numbers_permissions & $id) {
  3372                 //                if ($numbers_permissions & $id) {
  3329                     //Get the appropriate style ...
  3373                 //Get the appropriate style ...
  3330                         //Checking for unset styles is done by the style cache builder ...
  3374                 //Checking for unset styles is done by the style cache builder ...
  3331                     if (!$this->use_classes) {
  3375                 if (!$this->use_classes) {
  3332                         $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][$id] . '"';
  3376                     $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][$id] . '"';
  3333                     } else {
  3377                 } else {
  3334                         $attributes = ' class="nu'.$id.'"';
  3378                     $attributes = ' class="nu'.$id.'"';
  3335                     }
  3379                 }
  3336 
  3380 
  3337                     //Set in the correct styles ...
  3381                 //Set in the correct styles ...
  3338                     $stuff_to_parse = str_replace("/NUM!$id/", $attributes, $stuff_to_parse);
  3382                 $stuff_to_parse = str_replace("/NUM!$id/", $attributes, $stuff_to_parse);
  3339 //                }
  3383                 //                }
  3340             }
  3384             }
  3341         }
  3385         }
  3342 
  3386 
  3343         // Highlight methods and fields in objects
  3387         // Highlight methods and fields in objects
  3344         if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) {
  3388         if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) {
  3634                 } else {
  3678                 } else {
  3635                     $this->lexic_permissions[$flag] = $perm;
  3679                     $this->lexic_permissions[$flag] = $perm;
  3636                 }
  3680                 }
  3637             }
  3681             }
  3638             unset($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS']);
  3682             unset($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS']);
       
  3683         }
       
  3684 
       
  3685         //Fix: Problem where hardescapes weren't handled if no ESCAPE_CHAR was given
       
  3686         //You need to set one for HARDESCAPES only in this case.
       
  3687         if(!isset($this->language_data['HARDCHAR'])) {
       
  3688             $this->language_data['HARDCHAR'] = $this->language_data['ESCAPE_CHAR'];
  3639         }
  3689         }
  3640 
  3690 
  3641         //NEW in 1.0.8: Allow styles to be loaded from a separate file to override defaults
  3691         //NEW in 1.0.8: Allow styles to be loaded from a separate file to override defaults
  3642         $style_filename = substr($file_name, 0, -4) . '.style.php';
  3692         $style_filename = substr($file_name, 0, -4) . '.style.php';
  3643         if (is_readable($style_filename)) {
  3693         if (is_readable($style_filename)) {
  4004             if ($this->use_classes) {
  4054             if ($this->use_classes) {
  4005                 $attr = ' class="foot"';
  4055                 $attr = ' class="foot"';
  4006             } else {
  4056             } else {
  4007                 $attr = " style=\"{$this->footer_content_style}\"";
  4057                 $attr = " style=\"{$this->footer_content_style}\"";
  4008             }
  4058             }
  4009             if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->linenumbers != GESHI_NO_LINE_NUMBERS) {
  4059             if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
  4010                 $footer = "<tfoot><tr><td colspan=\"2\">$footer</td></tr></tfoot>";
  4060                 $footer = "<tfoot><tr><td colspan=\"2\">$footer</td></tr></tfoot>";
  4011             } else {
  4061             } else {
  4012                 $footer = "<div$attr>$footer</div>";
  4062                 $footer = "<div$attr>$footer</div>";
  4013             }
  4063             }
  4014         }
  4064         }