CVS update: /cowiki/includes/cowiki/class/parse/
[email protected] 9 Apr 2005 23:34:08 -0000
| Newsgroups | gmane.comp.php.cowiki.cvs |
|---|---|
| Message-ID | <[email protected]> |
User: dgorski Date: 05/04/09 16:34:08 Modified: /cowiki/includes/cowiki/class/parse/ class.WikiReverseParser.php, class.WikiParser.php Log: Revert to the state that has worked for Boron release and plus a small fix after Boron, that is mentioned in the ChangeLog (bug #202). Until there is no other fully tested parser, there shouldn't be any half-hearted changes. File Changes: Directory: /cowiki/includes/cowiki/class/parse/ =============================================== File [changed]: class.WikiReverseParser.php Url: http://cowiki.tigris.org/source/browse/cowiki/includes/cowiki/class/parse/class.WikiReverseParser.php?r1=1.16&r2=1.17 Delta lines: +14 -63 --------------------- --- class.WikiReverseParser.php 21 Mar 2005 16:45:50 -0000 1.16 +++ class.WikiReverseParser.php 9 Apr 2005 23:34:07 -0000 1.17 @@ -2,7 +2,7 @@ /** * - * $Id: class.WikiReverseParser.php,v 1.16 2005/03/21 16:45:50 cmarble Exp $ + * $Id: class.WikiReverseParser.php,v 1.17 2005/04/09 23:34:07 dgorski Exp $ * * This file is part of coWiki. coWiki is free software under the terms of * the GNU General Public License (GPL). Read the LICENSE file. If you did @@ -17,7 +17,7 @@ * @author Daniel T. Gorski, <[email protected]> * @copyright (C) Daniel T. Gorski, {@link http://www.develnet.org} * @license http://www.gnu.org/licenses/gpl.html - * @version $Revision: 1.16 $ + * @version $Revision: 1.17 $ * */ @@ -135,6 +135,7 @@ $sStr = $this->processPosting($sStr); $sStr = $this->processParagraph($sStr); $sStr = $this->processHeading($sStr); + $sStr = $this->processEmphasis($sStr); $sStr = $this->processHorizontalRule($sStr); $sStr = $this->processVariable($sStr); $sStr = $this->processPlugin($sStr); @@ -143,10 +144,8 @@ $sStr = $this->processBreak($sStr); $sStr = $this->processSup($sStr); $sStr = $this->processSub($sStr); - $sStr = $this->processJustification($sStr); - $sStr = $this->processEmphasis($sStr); - $sStr = $this->processTable($sStr); $sStr = $this->processList($sStr); + $sStr = $this->processTable($sStr); $sStr = $this->processQuote($sStr); // last one! return trim(unescape($sStr)); @@ -434,38 +433,23 @@ * @todo [D11N] Check description */ protected function processEmphasis(&$sStr) { - - //italic $sStr = preg_replace( - '=<(em|i)>(.*)</\1>=Ums', - '/\2/', + '=<em>(.*)</em>=Ums', + '/\1/', $sStr ); - //bold + $sStr = preg_replace( - '=<(strong|b)>(.*)</\1>=Ums', - '*\2*', + '=<strong>(.*)</strong>=Ums', + '*\1*', $sStr ); - //monospaced + $sStr = preg_replace( '=<tt>(.*)</tt>=Ums', '=\1=', $sStr ); - //strikethrough - $sStr = preg_replace( - '=<strike>(.*)</strike>=Ums', - '--\1--', - $sStr - ); - //underlined - $sStr = preg_replace( - '=<u>(.*)</u>=Ums', - '_\1_', - $sStr - ); - return $sStr; } @@ -797,49 +781,27 @@ protected function buildTable(&$aMatches) { $sStr = "\n<table".$aMatches[1].">\n"; - // Caption before first tr - if(preg_match( - '=<caption>(.*)</caption>=Uis', - $aMatches[2], - $aCaption - )) { - $sStr .= "|+ " . $aCaption[1][0] . "\n"; - } - // Isolate rows preg_match_all( - '=<tr ?([^>]*)>(.+)</tr>=Uis', + '=<tr[^>]*>(.+)</tr>=USs', $aMatches[2], $aRows ); // Treat cells for ($i=0, $n=sizeof($aRows[1]); $i<$n; $i++) { - $sStr .= "|-" . trim($aRows[1][$i]) . "\n"; - preg_match_all( - '=<t(d|h) ?([^>]*)>(.*)</t\1>=Uis', - $aRows[2][$i], + '=<td colspan\="([0-9]+)">(.*)</td>=USs', + $aRows[1][$i], $aCells ); for ($j=0, $m=sizeof($aCells[1]); $j<$m; $j++) { - switch($aCells[1][$j]){ - case "d": - $sSep = '|'; - break; - case "h": - $sSep = "!"; - break; - } - if( strlen($aCells[2][$j]) ) { - $sStr .= $sSep . trim($aCells[2][$j]) . "|\n" . $aCells[3][$j] ."\n"; - } else { - $sStr .= $sSep . "\n" . $aCells[3][$j] ."\n"; - } + $sStr .= str_repeat('|', $aCells[1][$j]); + $sStr .= $aCells[2][$j]; } - $sStr; + $sStr .= "\n"; } return $sStr . "</table>\n"; @@ -886,17 +848,6 @@ $sStr = preg_replace( '=<sub>(.*)</sub>=Ums', "<sub>\\1</sub>", - $sStr - ); - return $sStr; - } - - // -------------------------------------------------------------------- - - protected function processJustification(&$sStr) { - $sStr = preg_replace( - '=<(left|center|right)>(.*)</\\1>=Usi', - "<\\1>\\2</\\1>", $sStr ); return $sStr; File [changed]: class.WikiParser.php Url: http://cowiki.tigris.org/source/browse/cowiki/includes/cowiki/class/parse/class.WikiParser.php?r1=1.48&r2=1.49 Delta lines: +139 -398 ----------------------- --- class.WikiParser.php 29 Mar 2005 13:40:52 -0000 1.48 +++ class.WikiParser.php 9 Apr 2005 23:34:07 -0000 1.49 @@ -2,7 +2,7 @@ /** * - * $Id: class.WikiParser.php,v 1.48 2005/03/29 13:40:52 cmarble Exp $ + * $Id: class.WikiParser.php,v 1.49 2005/04/09 23:34:07 dgorski Exp $ * * This file is part of coWiki. coWiki is free software under the terms of * the GNU General Public License (GPL). Read the LICENSE file. If you did @@ -21,7 +21,7 @@ * @author Daniel T. Gorski, <[email protected]> * @copyright (C) Daniel T. Gorski, {@link http://www.develnet.org} * @license http://www.gnu.org/licenses/gpl.html - * @version $Revision: 1.48 $ + * @version $Revision: 1.49 $ * */ @@ -31,115 +31,27 @@ // On the other hand, the coWiki syntax is quite loose and is not easy // to express by a BNF parser, IMO. -/** - * coWiki token "no operation" - */ -define('WIKI_TOKEN_NOOP', 1); - -/** - * coWiki token "preformated" - */ -define('WIKI_TOKEN_PRE', 2); - -/** - * coWiki token "source code" - */ -define('WIKI_TOKEN_CODE', 3); - -/** - * coWiki token "posting" - */ -define('WIKI_TOKEN_POSTING', 4); - -/** - * coWiki token "hyperlink" - */ -define('WIKI_TOKEN_LINK', 5); - -/** - * coWiki token "Uniform Ressource Identifier (URI)" - */ -define('WIKI_TOKEN_URI', 6); - -/** - * coWiki token "Table of Contents (ToC)" - */ -define('WIKI_TOKEN_TOC', 7); - -/** - * coWiki token "plugin with parameter(s)" - */ -define('WIKI_TOKEN_PARAM_PLUGIN', 8); - -/** - * coWiki token "plugin without parameter(s)" - */ -define('WIKI_TOKEN_SIMPLE_PLUGIN', 9); -/** - * coWiki token "heading" - */ -define('WIKI_TOKEN_HEADING', 10); - -/** - * coWiki token "horicontal ruler" - */ -define('WIKI_TOKEN_HR', 11); - -/** - * coWiki token "list" - */ -define('WIKI_TOKEN_LIST', 12); - -/** - * coWiki token "quotation" - */ -define('WIKI_TOKEN_QUOTE', 13); - -/** - * coWiki token "system variable" - */ -define('WIKI_TOKEN_VAR', 14); - -/** - * coWiki token "line break" - */ -define('WIKI_TOKEN_BREAK', 15); - -/** - * coWiki token "table with parameter(s)" - */ -define('WIKI_TOKEN_PARAM_TABLE', 16); - -/** - * coWiki token "table without parameter(s)" - */ -define('WIKI_TOKEN_SIMPLE_TABLE', 17); - -/** - * coWiki token "remark" - */ -define('WIKI_TOKEN_REM', 18); - -/** - * coWiki token "subscript" - */ -define('WIKI_TOKEN_SUB', 19); - -/** - * coWiki token "superscript" - */ -define('WIKI_TOKEN_SUP', 20); - -/** - * coWiki token "justification" - */ -define('WIKI_TOKEN_JUSTIFICATION', 21); - -/** - * coWiki token "emphasis" - */ -define('WIKI_TOKEN_EMPHASIS', 22); + define('WIKI_TOKEN_NOOP', 1); + define('WIKI_TOKEN_PRE', 2); + define('WIKI_TOKEN_CODE', 3); + define('WIKI_TOKEN_POSTING', 4); + define('WIKI_TOKEN_LINK', 5); + define('WIKI_TOKEN_URI', 6); + define('WIKI_TOKEN_TOC', 7); + define('WIKI_TOKEN_PARAM_PLUGIN', 8); + define('WIKI_TOKEN_SIMPLE_PLUGIN', 9); + define('WIKI_TOKEN_HEADING', 10); + define('WIKI_TOKEN_HR', 11); + define('WIKI_TOKEN_LIST', 12); + define('WIKI_TOKEN_QUOTE', 13); + define('WIKI_TOKEN_VAR', 14); + define('WIKI_TOKEN_BREAK', 15); + define('WIKI_TOKEN_PARAM_TABLE', 16); + define('WIKI_TOKEN_SIMPLE_TABLE', 17); + define('WIKI_TOKEN_REM', 18); + define('WIKI_TOKEN_SUB', 19); + define('WIKI_TOKEN_SUP', 20); /** * coWiki - Wiki parser class @@ -181,8 +93,7 @@ WIKI_TOKEN_PARAM_TABLE, WIKI_TOKEN_SIMPLE_TABLE, WIKI_TOKEN_SUB, - WIKI_TOKEN_SUP, - WIKI_TOKEN_JUSTIFICATION + WIKI_TOKEN_SUP ); // Helper @@ -409,7 +320,7 @@ break; case WIKI_TOKEN_LIST: - $sStr = $this->createList($sStr, $mMeta); + $sStr = $this->createList($sStr); break; case WIKI_TOKEN_SIMPLE_TABLE: @@ -443,14 +354,6 @@ case WIKI_TOKEN_SUP: $sStr = $this->createSupElement($sStr); break; - - case WIKI_TOKEN_JUSTIFICATION: - $sStr = $this->createJustificationElement($sStr, $mMeta); - break; - - case WIKI_TOKEN_EMPHASIS: - $sStr = $this->createEmphasisElement($sStr, $mMeta); - break; } return $sStr; @@ -487,7 +390,7 @@ // -------------------------------------------------------------------- /** - * Create a <<pre>>-element + * Create a <pre>-element * * @access protected * @@ -501,7 +404,7 @@ // -------------------------------------------------------------------- /** - * Create a <<code>>-element + * Create a <code>-element * * @access protected * @@ -756,45 +659,6 @@ return '<sup>'.$sStr.'</sup>'; } - // -------------------------------------------------------------------- - - protected function createJustificationElement(&$sStr, &$mMeta) { - return '<'.$mMeta.'>'.$this->invokeParagraphs($sStr).'</'.$mMeta.'>'; - } - - protected function createEmphasisElement(&$sStr, &$mMeta) { - - $sOpen = $sClose = ''; - for ($i=0 ; $i < strlen($mMeta) ; $i++ ){ - switch(substr($mMeta,$i,1)){ - case '_': - $sOpen .= "<u>"; - $sClose = "</u>".$sClose; - break; - case '-': - if(!strcmp(substr($mMeta,$i+1,1),'-')){ - $sOpen .= "<strike>"; - $sClose = "</strike>".$sClose; - $i++; - } - break; - case '=': - $sOpen .= "<tt>"; - $sClose = "</tt>".$sClose; - break; - case '*': - $sOpen .= "<b>"; - $sClose = "</b>".$sClose; - break; - case '/': - $sOpen .= "<i>"; - $sClose = "</i>".$sClose; - break; - } - } - return $sOpen . $sStr . $sClose; - } - // --- Element creator helpers ---------------------------------------- /** @@ -986,6 +850,10 @@ // processing. $sStr = $this->processToc($sStr); + // After this step all emphasis markups (bold, italic, ...) are + // converted. These markups are not tokenized. + $sStr = $this->processEmphasis($sStr); + // After this step all headings (+, ++, +++ -> H1, H2, H3 etc.) are // tokenized for further processing. $sStr = $this->processHeading($sStr); @@ -1009,14 +877,6 @@ // After this step lists are tokenized for further processing. $sStr = $this->processList($sStr); - // After this step all emphasis markups (bold, italic, ...) are - // tokenized for further processing. - $sStr = $this->processEmphasis($sStr); - - // After this step all <left>,<right> & <centre> are tokenized - // for further processing. - $sStr = $this->processJustification($sStr); - // After this step all parameterized <table></table> are tokenized // for further processing. $sStr = $this->processParamTable($sStr); @@ -1486,79 +1346,59 @@ */ protected function processEmphasis(&$sStr) { - /* - this ought to work, halfway between Boron and proper fixing - - /x/ - italics - *x* - bold - --x-- - strikethrough - _x_ - underlined - =x= - monospaced - */ - - $sEmph= '(-{2}|[_=\*/]+)'; - $sCont= '([^\n_=*/]*)'; - $sWord= '([^ \n/](\S?|.*(\S|\t)))'; - - $sStr = $this->collapseEmphasis( $sStr ); - - $sStr = preg_replace_callback( - '~ ((-{2}|[_=*/])+) - (([^\n_=*/])+) - ((-{2}|[_=*/])+) - ~mix', - array(&$this,'tokenizeEmphasis'), - $sStr - ); - - return $sStr; - } - - protected function collapseEmphasis(&$sStr) { + // These are the possible start delimiters for bold, italic + // and monospace emphasis markups + $sStart = '(\[\''; + + // These are the possible end delimiters for bold, italic + // and monospace emphasis markups + $sEnd = '\s,.;:!?()\[\]_-'; - //italic + // Italic first, because we do not want to match "</foo>/bar" $sStr = preg_replace( - '=<(em|i)>(.*)</\1>=ms', - '/\2/', + '~ ([^<])? + (\s|=|\*|<br>|"|['.$sStart.']) + (/) + ([^ \n/](\S?|.*(\S|\t))) + \3 + (?=['.$sEnd.']|\*|<br>|"|=) # do not eat up + # trailing chars + ~Umix', + '\1\2<em>\4</em>\7', $sStr ); - //bold - $sStr = preg_replace( - '=<(strong|b)>(.*)</\1>=ms', - '*\2*', - $sStr - ); - //monospaced - $sStr = preg_replace( - '=<tt>(.*)</tt>=ms', - '=\1=', - $sStr - ); - //strikethrough + + // Bold $sStr = preg_replace( - '=<strike>(.*)</strike>=ms', - '--\1--', + '~ (\s|=|<em>|<br>|"|['.$sStart.']) + (\*) + ([^ \n\*](\S?|.*(\S|\t))) + \2 + (?=['.$sEnd.']|=|<br>|"|</em>) # do not eat up + # trailing chars + ~Umix', + '\1<strong>\3</strong>\6', $sStr ); - //underlined + + // Mono $sStr = preg_replace( - '=<u>(.*)</u>=ms', - '_\1_', + '~ (\s|<em>|<strong>|"|<br>|['.$sStart.']) + (=) + ([^ \n=](\S?|.*(\S|\t))) + \2 + (?=['.$sEnd.']|<br>|"|</em>|</strong>) # do not + # eat up + # trailing + # chars + ~Umix', + '\1<tt>\3</tt>\6', $sStr ); return $sStr; } - protected function tokenizeEmphasis(&$aMatches) { - //proper emphatic nesting - if ($aMatches[1]==strrev($aMatches[5])) { - return $this->tokenize($aMatches[3],WIKI_TOKEN_EMPHASIS, $aMatches[1]); - } else { - return $aMatches[0]; - } - } - // -------------------------------------------------------------------- /** @@ -1784,23 +1624,6 @@ // -------------------------------------------------------------------- - protected function processJustification(&$sStr) { - $sStr = preg_replace_callback( - '=<(left|center|right)>(.*)</\1>=Usi', - array(&$this, 'tokenizeJustification'), - $sStr ); - - return $sStr; - } - - // -------------------------------------------------------------------- - - protected function tokenizeJustification(&$aMatches) { - return $this->tokenize($aMatches[2], WIKI_TOKEN_JUSTIFICATION, $aMatches[1]); - } - - // -------------------------------------------------------------------- - /** * Ordered and unordered bullet lists (Asterisk *, Hash #) * @@ -1813,8 +1636,7 @@ // Treat lists $sStr = preg_replace_callback( - /* '=\n(( {0,})(\*|#)+ (.*))$=Us',*/ - '=\n((\*|#) (.*)\n)(?! {0,}(\*|#))=Us', + '=\n((\*|#) .*\n)(?! {0,}(\*|#))=Us', array(&$this, 'tokenizeList'), $sStr ); @@ -1833,11 +1655,7 @@ * @since coWiki 0.3.0 */ protected function tokenizeList(&$aMatches) { - return "\n".$this->tokenize( - $aMatches[1], - WIKI_TOKEN_LIST, - $this->processEmphasis($aMatches[4]) - )."\n"; + return "\n".$this->tokenize($aMatches[1], WIKI_TOKEN_LIST)."\n"; } // -------------------------------------------------------------------- @@ -1850,7 +1668,7 @@ * @author Daniel T. Gorski, <[email protected]> * @since coWiki 0.3.0 */ - protected function createList(&$sStr, &$mMeta) { + protected function createList(&$sStr) { // Fix multiple bullets at the beginning of the line. // E.g. fix sick things like this to make it intuitive: @@ -1883,10 +1701,7 @@ $this->aList = array(); for ($i=0; $i<sizeof($aList[1]); $i++) { - //$this->aList[$i]['TEXT'] = $this->restoreTokens($mMeta); - //$this->aList[$i]['TEXT'] = $aList[3][$i]; - $sEmp = $this->restoreTokens($this->processEmphasis($aList[3][$i])); - $this->aList[$i]['TEXT'] = $sEmp; + $this->aList[$i]['TEXT'] = $aList[3][$i]; $this->aList[$i]['DEPTH'] = strspn($aList[1][$i], ' '); $this->aList[$i]['TYPE'] = $aList[2][$i]; } @@ -2055,149 +1870,75 @@ $aRows = explode("\n", $sStr); $aTable = array(); - $nHeads = 0; - $sRet = ''; - $sContent = ''; - $sTable = ''; - $sRow = ''; - $bPriorRow = false; - //$i = -1; - //$n = sizeof($aRows); for ($i=0, $n=sizeof($aRows); $i<$n; $i++) { - //while( ++$i < $n ) { - if (!strlen(trim($aRows[$i]))) { + // Row MUST start with pipe + if (strlen(trim($aRows[$i])) == 0 || $aRows[$i]{0} != '|') { return '<tr valign="top"><td colspan="1">'.$sStr.'</td></tr>'; } - //rows expected to hold table syntax (pipes), may instead - //make room for ongoing content (tables, lists, etc) - $sRow = $aRows[$i]."\n"; - - //find table syntax within a (long?) row - while( strlen($sRow) && preg_match( - '=^([\|!][-+]?)( {0,1}[^\|!\n]*)?=', - $sRow, - $aMatches) ) { - - //found exploded row begins with pipe syntax, poss params - $sRow = substr( $sRow, strlen($aMatches[0]) ); - - $nType = 0; - //tables made of cells, headers, rows, caption - if ($aMatches[1]=="|") { - $sRet .= '<td'; - $nType = 1; - }else if ($aMatches[1]=="!") { - $sRet .= '<th'; - $nType = 2; - }else if ($aMatches[1]=="|-") { - if ($bPriorRow) { - $sRet .= "</tr>\n<tr"; - } else { - $sRet .= '<tr'; - } - $nType = 3; - $bPriorRow = true; - }else if ($aMatches[1]=="|+") { - $sRet .= '<caption>'.$aMatches[2]."</caption>\n"; - continue 1; - } - - //content can be large, room for it here - $sContent = ''; - - if ($aMatches[2]{0}==' ') { - //left a space to denote no params - $sRet .= '>'; - $sContent .= substr($aMatches[2],1); - //expect double pipe, bang or newline - } elseif (strlen($aMatches[2])) { - //got params. look for pipe syntax that blocked last preg - $sRet .= ' '.unescape($aMatches[2]).'>'; - if (preg_match('=^\|([^\|!\n]*)=',$sRow,$aMatches)) { - //got rest of pipe syntax (...|text) - $sContent .= $aMatches[1]; - $sRow = substr( $sRow, strlen($aMatches[0]) ); - } - } else { - $sRet .= '>'; - } - - //look ahead now. - if ($sRow == "\n") { - //look ahead to close our content - while( ++$i<$n ){ - $sRow = $aRows[$i]; - //pipe syntax (will force $sContent) to continue - if ($sRow{0} == '|' || $sRow{0} == '!') { - $sRet .= $sContent; - switch($nType){ - case 1: - $sRet .= "</td>\n"; - break; - case 2: - $sRet .= "</th>\n"; - break; - } - --$i; - continue 3; - /* - } else if (preg_match("=^<nest=i", $sRow)) { - $sTable = $sRow."\n"; - while( ++$i < $n ){ - $sRow = $aRows[$i]; - if(preg_match("=^</nest>=i", $sRow)) { - $sTable .= $sRow."\n"; - $sTable = preg_replace("=^<nest=i","<table",$sTable); - $sTable = preg_replace("=</nest=i","</table",$sTable); - $sTable = $this->processSimpleTable( $sTable ); - $sTable = $this->processParamTable( $sTable ); - $sContent .= $this->restoreTokens( $sTable ); - continue 2; - } else { - $sTable .= $sRow."\n"; - } - } - */ - } else { - //non-pipe (ever-increasing) content - $sContent .= $sRow; - } - } - $i = $n; - $sRet .= $sContent; - switch($nType){ - case 1: - $sRet .= "</td>\n"; - break; - case 2: - $sRet .= "</th>\n"; - break; - } - continue 2; - } elseif ( ( $sRow{0} == "|" || $sRow{0} == "!") && - ($sRow{1} == "|" || $sRow{1} == "!") ) { - $sRow = substr($sRow, 1); - $sRet .= $sContent; - switch($nType){ - case 1: - $sRet .= "</td>\n"; - break; - case 2: - $sRet .= "</th>\n"; - break; - } - continue 1; - } - } - } - if( $bPriorRow ) { - return $sRet."</tr>"; - } else { - return $sRet; + $aRows[$i] = substr($aRows[$i], 1); + + // Row MAY have one (or more) trailing pipes + if (substr($aRows[$i], -1) == '|') { + $aRows[$i] = substr($aRows[$i], 0, -1); } + + // Mark and remember all <noop>s in table row + $this->aTblRowNoop = array(); + $aRows[$i] = preg_replace_callback( + '#(<noop>.*</noop>)#U', + array(&$this, 'extractTableRowNoops'), + $aRows[$i] + ); + + // Exchange column delemiter + $aRows[$i] = str_replace('|', "\x02", $aRows[$i]); + + // Restore <noop>s in table row + for ($j=0, $m=sizeof($this->aTblRowNoop); $j<$m; $j++) { + $aRows[$i] = preg_replace( + "#\x01#", + $this->aTblRowNoop[$j], + $aRows[$i], + 1 + ); + } + + // Divide columns + $aCols = explode("\x02", $aRows[$i]); + + $nSpan = 0; + $sRow = ''; + + for ($j=0, $m=sizeof($aCols); $j<$m; $j++) { + + if (strlen($aCols[$j]) == 0) { + $nSpan++; + if ($j < $m-1) { + continue; + } + } + + if ($nSpan) { + $sRow .= '<td colspan="'.($nSpan+1).'">'; + $sRow .= $aCols[$j]; + $sRow .= '</td>'; + $nSpan = 0; + continue; + } + + $sRow .= '<td colspan="1">'.$aCols[$j].'</td>'; + } + + $aTable[] = '<tr valign="top">' + .$sRow + .'</tr>'; + } + + $sTable = join('', $aTable); + return $sTable; } // --------------------------------------------------------------------