{"id":788,"date":"2010-09-01T12:27:04","date_gmt":"2010-09-01T10:27:04","guid":{"rendered":"http:\/\/blog.benny-baumann.de\/?p=788"},"modified":"2010-09-01T17:28:23","modified_gmt":"2010-09-01T15:28:23","slug":"possible-rework-on-the-geshi-parser-waiting-for-review","status":"publish","type":"post","link":"https:\/\/blog.benny-baumann.de\/?p=788","title":{"rendered":"Possible rework on the GeSHi parser waiting for review"},"content":{"rendered":"<p>As announced earlier here&#8217;s some external work by Simon G\u00e1bor that might get into the GeSHi core IF I can get enough confidence in those changes to work properly and don&#8217;t cause any major regressions &#8211; which I currently lack nor can confirm by reviewing this patch.<!--more--><\/p>\n<p>To give you an overview: Here&#8217;s what this change is about:<\/p>\n<blockquote><p>If you remember, the problem was that if there were more than one regexes that matched a certain line, the first one inserted the marker tags into the text, and so the text had changed and the second regex couldn&#8217;t match it.<\/p>\n<p>Since the presence of the marker tags spoiled the regex matching, the tags may be inserted only when all regex matching\/replacements are done, but then we have to store the information about which regex matched which portion of the text.<\/p>\n<p>As this cannot be stored in the text itself, I added an array ($keys[]) that is exactly as long as the text, and its elements contain the indices of the regexes that matched the characters of the text. However, it introduced another issue, namely that the text itself can (legally) change during the replacements, so this $keys array shall be changed along with it:<\/p>\n<ul>\n<li>if a backreference (\\1..\\9) is used in the &#8218;before&#8216; or &#8218;after&#8216; blocks, not only the given portions of the text shall be copied, but the portions of the $keys as well<\/li>\n<li>all the text generated by the &#8218;replace&#8216; block of a regex shall generate elements in the keys array with the index of the regex<\/li>\n<\/ul>\n<\/blockquote>\n<p>The patch Simon sent me tries to address this issue, BUT I don&#8217;t get the hang of it and thus decided (fow now) not including it. In addition this patch has some bad implications that I feared AND which Simon confirms:<\/p>\n<blockquote><p>Unfortunately, this means that neither &#8218;preg_replace()&#8216;, nor even &#8218;preg_replace_callback()&#8216; can be used for managing the (text, keys) buffer pair, so I had to use &#8218;preg_match()&#8216; and do the regex replacements manually, modifying the text and the keys buffers in parallel.<\/p>\n<p>When all the regex processing is done, finally this $keys buffer must be iterated through, and the proper marker tags must be inserted into the text.<\/p><\/blockquote>\n<p>To sum the problems up:<\/p>\n<ul>\n<li>Complex patch<\/li>\n<li>Might need MUCH memory and thus conflicts with the aim for a reasonably low memory footprint<\/li>\n<li>Will slow down processing even if not needed, since the housekeeping has to be done (if opting for a way to enabe it by language duplicate source WILL result, which is bad too)<\/li>\n<li>Only few language files actually use it (The only one apart from Simon&#8217;s one that might benefit is LaTeX AFAIK)<\/li>\n<\/ul>\n<p>As I trust the masses to come up with a solution I&#8217;m releasing this patch including some more details on its history so people get a chance working on it. Thus if anyone has an idea that might help with getting this feature integrated in a swifter way, while not affecting languages that don&#8217;t require this processing, I&#8217;d be really glad to hear about it.<\/p>\n<p>As an example on what can be done with this patch &#8211; or well, let&#8217;s more say: for what he needed it &#8211; he mentioned highlighting of changelog files that look simular to this:<\/p>\n<pre lang=\"text\" escaped=\"true\">2010-06-14 Author Name <author @somewhere.com>\r\nOne-line summary about the changes\r\n\r\n        * file1.c: some changes\r\n\r\n        * file2.c, file2.h: some other changes whose\r\n        description wraps to a second line\r\n\r\n        * file3.c: yet again some changes<\/author><\/pre>\n<p>But as this is neither the format that Debian uses nor the one that GeSHi uses there is little chance for directly applying this language file as is. But there is one standing issue that affects parts of LaTeX highlighting thus even though the Changelog file itsel is no convincing reason, having this fix for LaTeX might be a benefit. Additionally this works around a long-standing problem with Regexp breaking highlighting for some language files which requires you to take care in what you&#8217;re doing with Regexp.<\/p>\n<p>But enough said for now: Here&#8217;s the patch for the mentioned feature. It should apply cleanly to GeSHi releases 1.0.8.8 and 1.0.8.9 as well as GeSHi trunk.<\/p>\n<pre lang=\"diff\" escaped=\"true\">diff -Naur SyntaxHighlight_GeSHi.orig\/geshi\/geshi\/changelog.php SyntaxHighlight_GeSHi\/geshi\/geshi\/changelog.php\r\n--- SyntaxHighlight_GeSHi.orig\/geshi\/geshi\/changelog.php\u00a0\u00a0 \u00a01970-01-01 01:00:00.000000000 +0100\r\n+++ SyntaxHighlight_GeSHi\/geshi\/geshi\/changelog.php\u00a0\u00a0 \u00a02010-07-05 10:48:17.000000000 +0200\r\n@@ -0,0 +1,151 @@\r\n+&lt;?php\r\n+\/*************************************************************************************\r\n+ * changelog.php\r\n+ * --------\r\n+ * Author: Gabor Simon (gabor.simon2@it-services.hu)\r\n+ * Copyright: (c) 2010 Gabor Simon\r\n+ * Release Version: 1.0.8.X\r\n+ * Date Started: 06\/10\/2010\r\n+ *\r\n+ * Changelog language file for GeSHi.\r\n+ *\r\n+ * CHANGES\r\n+ * -------\r\n+ * 07\/05\/1010 (0.0.1)\r\n+ * - Pattern marking now uses the before-replace-after scheme\r\n+ * 06\/10\/2010 (0.0.0)\r\n+ * - Syntax File Created\r\n+ *\r\n+ *\r\n+ *************************************************************************************\r\n+ *\r\n+ *\u00a0\u00a0\u00a0\u00a0 This file is part of GeSHi.\r\n+ *\r\n+ *\u00a0\u00a0 GeSHi is free software; you can redistribute it and\/or modify\r\n+ *\u00a0\u00a0 it under the terms of the GNU General Public License as published by\r\n+ *\u00a0\u00a0 the Free Software Foundation; either version 2 of the License, or\r\n+ *\u00a0\u00a0 (at your option) any later version.\r\n+ *\r\n+ *\u00a0\u00a0 GeSHi is distributed in the hope that it will be useful,\r\n+ *\u00a0\u00a0 but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n+ *\u00a0\u00a0 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\u00a0 See the\r\n+ *\u00a0\u00a0 GNU General Public License for more details.\r\n+ *\r\n+ *\u00a0\u00a0 You should have received a copy of the GNU General Public License\r\n+ *\u00a0\u00a0 along with GeSHi; if not, write to the Free Software\r\n+ *\u00a0\u00a0 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\u00a0 02111-1307\u00a0 USA\r\n+ *\r\n+ ************************************************************************************\/\r\n+\r\n+$language_data = array (\r\n+\u00a0\u00a0\u00a0 'LANG_NAME' =&gt; 'changelog',\r\n+\u00a0\u00a0\u00a0 'CASE_KEYWORDS' =&gt; 0,\r\n+\u00a0\u00a0\u00a0 'CASE_SENSITIVE' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'OBJECT_SPLITTERS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'SCRIPT_DELIMITERS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'HIGHLIGHT_STRICT_BLOCK' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'COMMENT_SINGLE' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'COMMENT_MULTI' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'CASE_KEYWORD' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'QUOTEMARKS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'ESCAPE_CHAR' =&gt; '',\r\n+\u00a0\u00a0\u00a0 'KEYWORDS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'SYMBOLS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'SCRIPT' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'URLS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'OOLANG' =&gt; false,\r\n+\u00a0\u00a0\u00a0 'STRICT_MODE_APPLIES' =&gt; GESHI_NEVER,\r\n+\u00a0\u00a0\u00a0 'NUMBERS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0 'REGEXPS' =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # header: \"yyyy-mm-dd Author Name &lt;author@email&gt;\"\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^([0-9]{4}-[0-9]{2}-[0-9]{2})(.*?)(\\&amp;lt;.*?\\&amp;gt;)',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\1',\u00a0\u00a0 \u00a0# date\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; '\\\\2\\\\3'\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^([0-9]{4}-[0-9]{2}-[0-9]{2})(.*?)(\\&amp;lt;.*?\\&amp;gt;)',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '\\\\1',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\2',\u00a0\u00a0 \u00a0# author name\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; '\\\\3'\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^([0-9]{4}-[0-9]{2}-[0-9]{2})(.*?)(\\&amp;lt;.*?\\&amp;gt;)',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '\\\\1\\\\2',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\3',\u00a0\u00a0 \u00a0# author email\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; ''\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # summary: \"One line that starts with non-space and non-date\"\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 3 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^((?![0-9]{4}-[0-9]{2}-[0-9]{2})[^\\s].*)$',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\1',\u00a0\u00a0 \u00a0# the summary line\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; ''\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # filehdr: \"\u00a0\u00a0\u00a0\u00a0\u00a0 * filename: comments\"\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 4 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^(\\s+\\*\\s*)([^:]*)(:\\s*)(.*)$',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\1',\u00a0\u00a0 \u00a0# the '*' sign\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; '\\\\2\\\\3\\\\4'\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 5 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^(\\s+\\*\\s*)([^:]*)(:\\s*)(.*)$',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '\\\\1',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\2',\u00a0\u00a0 \u00a0# filename\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; '\\\\3\\\\4'\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 6 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^(\\s+\\*\\s*)([^:]*)(:\\s*)(.*)$',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '\\\\1\\\\2',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\3',\u00a0\u00a0 \u00a0# the ':' sign\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; '\\\\4'\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 7 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^(\\s+\\*\\s*)([^:]*)(:\\s*)(.*)$',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '\\\\1\\\\2\\\\3',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\4',\u00a0\u00a0 \u00a0# comments\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; ''\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # comment cont: \"\u00a0\u00a0\u00a0\u00a0 [^*]comments\"\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 8 =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_SEARCH =&gt; '^(\\s{2,}[^*\\s].*)$',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_MODIFIERS =&gt; 'm',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_BEFORE =&gt; '',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_REPLACE =&gt; '\\\\1',\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GESHI_AFTER =&gt; ''\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 )\r\n+\u00a0\u00a0\u00a0 ),\r\n+\u00a0\u00a0\u00a0 'STYLES' =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'KEYWORDS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'COMMENTS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'ESCAPE_CHAR' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'BRACKETS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'SYMBOLS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'STRINGS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'NUMBERS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'METHODS' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'SCRIPT' =&gt; array(),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'REGEXPS' =&gt; array(\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0 =&gt; 'color: #7f0000;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # date\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1 =&gt; 'color: #bfbf00;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # author\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2 =&gt; 'color: #bf00bf;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # email\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 3 =&gt; 'color: #00bf7f;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # summary\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 4 =&gt; 'color: #00bf00;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # *\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 5 =&gt; 'color: #0000ff;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # filenames\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 6 =&gt; 'color: #00bf00;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # :\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 7 =&gt; 'color: #000000;',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # comment\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 8 =&gt; 'color: #000000;'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # comment cont.\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 )\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 )\r\n+);\r\n+\r\n+?&gt;\r\ndiff -Naur SyntaxHighlight_GeSHi.orig\/geshi\/geshi.php SyntaxHighlight_GeSHi\/geshi\/geshi.php\r\n--- SyntaxHighlight_GeSHi.orig\/geshi\/geshi.php\u00a0\u00a0 \u00a02010-06-29 20:18:53.000000000 +0200\r\n+++ SyntaxHighlight_GeSHi\/geshi\/geshi.php\u00a0\u00a0 \u00a02010-07-05 18:51:12.000000000 +0200\r\n@@ -3229,6 +3229,48 @@\r\n\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0 \/**\r\n+\u00a0 \u00a0\u00a0 * appends a backreference-resolved string to a (string,regex-index) buffer pair\r\n+\u00a0 \u00a0\u00a0 *\r\n+\u00a0 \u00a0\u00a0 * @param string the string buffer\r\n+\u00a0 \u00a0\u00a0 * @param array the index buffer\r\n+\u00a0 \u00a0\u00a0 * @param string the string to append\r\n+\u00a0 \u00a0\u00a0 * @param array the matches for the backref resolution\r\n+\u00a0 \u00a0\u00a0 *\r\n+\u00a0 \u00a0\u00a0 * @note the matches array must be of the extended form:\r\n+\u00a0 \u00a0\u00a0 * @note matches[][0] is the matched string\r\n+\u00a0 \u00a0\u00a0 * @note matches[][1] is the match offset\r\n+\u00a0 \u00a0\u00a0 * @note matches[][2] is the index array of the match\r\n+\u00a0 \u00a0\u00a0 * @return none\r\n+\u00a0 \u00a0\u00a0 * @access private\r\n+\u00a0 \u00a0\u00a0 *\/\r\n+\u00a0\u00a0\u00a0 function rgx_resolve_append(&amp;$newstuff, &amp;$newkeys, $src, $matches) {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $srclen = strlen($src);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for ($i = 0; $i &lt; $srclen; $i++) {\r\n+\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 \/\/ check if it is an escaped char\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($src[$i] == '\\\\') {\r\n+\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ escaped char, skip backslash anyway\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $i++;\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (($i &lt; $srclen) and ('0' &lt;= $src[$i]) and ($src[$i] &lt;= '9')) {\r\n+\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 \/\/ backreference, parse which submatch is referenced\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $m = $src[$i] - '0';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newstuff .= $matches[$m][0]; # append the text\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newkeys = array_merge($newkeys, $matches[$m][2]); # append the indices\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n+\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 \/\/ not a backreference, but an backslash-escaped char\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newstuff .= '\\\\';\u00a0 \/\/ append the backslash\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array_push($newkeys, -1); \/\/ new text, doesn't belong to any regex\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newstuff .= $src[$i]; \/\/ append the char\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array_push($newkeys, -1);\u00a0 \/\/ new text again\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n+\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # normal char\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newstuff .= $src[$i]; \/\/ append the char\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array_push($newkeys, -1); \/\/ new text again\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0 }\r\n+\r\n+\u00a0\u00a0\u00a0 \/**\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 * Takes a string that has no strings or comments in it, and highlights\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 * stuff like keywords, numbers and methods.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 *\r\n@@ -3308,41 +3350,127 @@\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Regular expressions\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ NOTE: for some reason, there is a space is at the start of the content\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ and that spoils matching '^' on the 1st line, so I replace it by an EOL\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ and restore it at the end\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_firstchar = $stuff_to_parse[0];\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($stuff_firstchar == ' ')\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse[0] = \"\\n\";\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $keys = array_fill(0, strlen($stuff_to_parse), -1);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach ($this-&gt;language_data['REGEXPS'] as $key =&gt; $regexp) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($this-&gt;lexic_permissions['REGEXPS'][$key]) {\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_key = $key;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (is_array($regexp)) {\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($this-&gt;line_numbers != GESHI_NO_LINE_NUMBERS) {\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ produce valid HTML when we match multiple lines\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_replace = $regexp[GESHI_REPLACE];\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_before = $regexp[GESHI_BEFORE];\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_key = $key;\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_after = $regexp[GESHI_AFTER];\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = preg_replace_callback(\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"\/\" . $regexp[GESHI_SEARCH] . \"\/{$regexp[GESHI_MODIFIERS]}\",\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array($this, 'handle_multiline_regexps'),\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse);\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_replace = false;\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_before = '';\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_after = '';\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = preg_replace(\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '\/' . $regexp[GESHI_SEARCH] . '\/' . $regexp[GESHI_MODIFIERS],\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $regexp[GESHI_BEFORE] . '&lt;|!REG3XP'. $key .'!&gt;' . $regexp[GESHI_REPLACE] . '|&gt;' . $regexp[GESHI_AFTER],\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse);\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $pattern = \"\/\" . $regexp[GESHI_SEARCH] . \"\/{$regexp[GESHI_MODIFIERS]}\";\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_before = $regexp[GESHI_BEFORE];\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_replace = $regexp[GESHI_REPLACE];\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_after = $regexp[GESHI_AFTER];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($this-&gt;line_numbers != GESHI_NO_LINE_NUMBERS) {\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ produce valid HTML when we match multiple lines\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_key = $key;\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = preg_replace_callback( \"\/(\" . $regexp . \")\/\",\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array($this, 'handle_multiline_regexps'), $stuff_to_parse);\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_key = '';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $pattern = \"\/(\" . $regexp . \")\/\";\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_before = '';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_replace = '\\\\1';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_after = '';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ NOTE: GESHI_NO_LINE_NUMBERS is handled when inserting the tags at the end\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ NOTE: the matched (and hence marked) strings may be required for other\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ regexes, so we may actually insert the marker tags only after all regex\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ matching and replacement.\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Because of this, for each character we store the number of the regex\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ that matched it (==key) in a separate array, and only do the tag insertion\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ at the end.\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ This means that whenever the string is modified (eg. at replacements),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ this key array must be modified as well, so we cannot use preg_replace\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ but have to do it manually.\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $offs = 0;\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ offset from whence to try matching\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while (preg_match($pattern, $stuff_to_parse, $matches, PREG_OFFSET_CAPTURE, $offs) == 1) {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ NOTE: PREG_OFFSET_CAPTURE generates a detailed $matches:\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/\u00a0\u00a0 $matches[$i][0] is the matched string\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/\u00a0\u00a0 $matches[$i][1] is the position of the match\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ and we extend this by\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/\u00a0\u00a0 $matches[$i][2] is the array of keys for the matched string\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for ($i = 0; $i &lt; count($matches); $i++)\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $matches[$i][2] = array_slice($keys, $matches[$i][1], strlen($matches[$i][0]));\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ NOTE: as we don't want to spoil the offsets in $matches[][1], we cannot\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ modify $stuff_to_parse and $keys in-place, but temporary working copies\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ ($newstuff, $newkeys) are needed\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ copy the text that precedes the match\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newstuff = substr($stuff_to_parse, 0, $matches[0][1]);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newkeys = array_slice($keys, 0, $matches[0][1]);\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ append the 'before' part\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;rgx_resolve_append($newstuff, $newkeys, $this-&gt;_hmr_before, $matches);\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ append the 'replace' and mark its part in $newkeys as $key\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $kpos = count($newkeys);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;rgx_resolve_append($newstuff, $newkeys, $this-&gt;_hmr_replace, $matches);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $offs = count($newkeys);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ this is where we start looking for a match next time\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($offs &gt; $kpos) {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array_splice($newkeys, $kpos, $offs - $kpos, array_fill(0, $offs - $kpos, $key));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = preg_replace( \"\/(\" . $regexp . \")\/\", \"&lt;|!REG3XP$key!&gt;\\\\1|&gt;\", $stuff_to_parse);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 error_log(\"Infinite loop caught;\");\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ append the 'after'\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;rgx_resolve_append($newstuff, $newkeys, $this-&gt;_hmr_after, $matches);\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ append the text after the match\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $i = $matches[0][1] + strlen($matches[0][0]);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newstuff .= substr($stuff_to_parse, $i);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $newkeys = array_merge($newkeys, array_slice($keys, $i));\r\n+\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ replace the original $stuff and $keys with the temporary ones\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = $newstuff;\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $keys = $newkeys;\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_key = '';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_before = '';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_replace = false;\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $this-&gt;_hmr_after = '';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ process $keys and insert the appropriate tags into $stuff_to_parse\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ NOTE: if $keys is all -1s (when the formatting was done by preg_replace),\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ this part leaves $stuff_to_parse intact\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 array_push($keys, -1); \/\/ trailing 'normal' marker to ensure closing of the last range\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $k = -1; \/\/ currently used key\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for ($kpos = $spos = 0; $kpos &lt; count($keys); $kpos++, $spos++)\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (($this-&gt;line_numbers != GESHI_NO_LINE_NUMBERS) and\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ($stuff_to_parse[$spos] == '\\\\n')) {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $keys[$kpos] = -1;\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # treat '\\n'-s as normal (key==-1), so a closing tag will be inserted\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # before and an opening after them if they are part of a coloured\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # range -&gt; the line numbering won't affect the colouring\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($keys[$kpos] != $k)\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($k != -1)\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ insert closing tag\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = substr_replace($stuff_to_parse, '|&gt;', $spos, 0);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $spos += 2;\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $k = $keys[$kpos];\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($k != -1)\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ insert opening tag\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $repl = '&lt;|!REG3XP'. $k .'!&gt;';\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse = substr_replace($stuff_to_parse, $repl, $spos, 0);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $spos += strlen($repl);\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 \u00a0 }\r\n-\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Restore the leading ' ' that was replace by an EOL\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ($stuff_to_parse[0] == \"\\n\")\r\n+\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $stuff_to_parse[0] = $stuff_firstchar;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Highlight numbers. As of 1.0.8 we support different types of numbers\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $numbers_found = false;<\/pre>\n<p>If anyone has an idea, let me know!<\/p>\n<p class=\"wp-flattr-button\"><a href=\"https:\/\/blog.benny-baumann.de\/?flattrss_redirect&amp;id=788&amp;md5=6ce84d9efe0a833b060e52f4602a8c5e\" title=\"Flattr\" target=\"_blank\"><img src=\"http:\/\/blog.benny-baumann.de\/wp-content\/plugins\/flattr\/img\/flattr-badge-large.png\" srcset=\"http:\/\/blog.benny-baumann.de\/wp-content\/plugins\/flattr\/img\/flattr-badge-large.png\" alt=\"Flattr this!\"\/><\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>As announced earlier here&#8217;s some external work by Simon G\u00e1bor that might get into the GeSHi core IF I can get enough confidence in those changes to work properly and don&#8217;t cause any major regressions &#8211; which I currently lack nor can confirm by reviewing this patch.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[3],"tags":[98,345,13,21],"class_list":["post-788","post","type-post","status-publish","format-standard","hentry","category-geshi","tag-developement","tag-geshi","tag-patch","tag-php"],"_links":{"self":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/788","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=788"}],"version-history":[{"count":6,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/788\/revisions"}],"predecessor-version":[{"id":790,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/788\/revisions\/790"}],"wp:attachment":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=788"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=788"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=788"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}