# # TWiki WikiClone ($wikiversion has version info) # # Copyright (C) 2002 Peter Thoeny, Peter@Thoeny.com # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details, published at # http://www.gnu.org/copyleft/gpl.html # # ========================= # # This is the EditTablePlugin used to edit tables in place. # # Each plugin is a package that contains the subs: # # initPlugin ( $topic, $web, $user, $installWeb ) # commonTagsHandler ( $text, $topic, $web ) # startRenderingHandler( $text, $web ) # outsidePREHandler ( $text ) # insidePREHandler ( $text ) # endRenderingHandler ( $text ) # # initPlugin is required, all other are optional. # For increased performance, DISABLE handlers you don't need. # # NOTE: To interact with TWiki use the official TWiki functions # in the &TWiki::Func module. Do not reference any functions or # variables elsewhere in TWiki!! # FIXME: The following TWiki calls used will likely break in a # future TWiki release: # TWiki::Store::readTopic(), TWiki::Store::saveTopic() # TWiki::Store::lockTopic(), TWiki::Store::topicIsLockedBy() # ========================= package TWiki::Plugins::EditTablePlugin; # ========================= use vars qw( $web $topic $user $installWeb $VERSION $debug %labels $query $renderingWeb $preSp $header $footer @format $changeRows $helpTopic $cgiCols $nbCols $encodeStart $encodeEnd $table ); $encodeStart = "--EditTableEncodeStart--"; $encodeEnd = "--EditTableEncodeEnd--"; undef $table; # ========================= sub initPlugin { ( $topic, $web, $user, $installWeb ) = @_; $VERSION = '1.001'; # check for Plugins.pm versions if( $TWiki::Plugins::VERSION < 1 ) { &TWiki::Func::writeWarning( "Version mismatch between EditTablePlugin and Plugins.pm" ); return 0; } $query = &TWiki::Func::getCgiQuery(); if( ! $query ) { return 0; } # Get plugin debug flag $debug = &TWiki::Func::getPreferencesFlag( "EDITTABLEPLUGIN_DEBUG" ); # Get plugin button labels my $ltext = &TWiki::Func::getPreferencesValue( "EDITTABLEPLUGIN_LABELS" ); %labels = (); foreach( split( /\s*,\s*/, $ltext ) ) { my @button = split( /\s*=>\s*/, $_ ); $labels->{$button[0]} = $button[1]; } $renderingWeb = $web; # Plugin correctly initialized &TWiki::Func::writeDebug( "- EditTablePlugin:initPlugin( $web.$topic ) is OK" ) if $debug; # Initialize $table such that the code will correctly detect when to # read in a topic. undef $table; return 1; } # ========================= sub extractParameters { my( $theArgs, $theHeader, $theFooter, $theFormat, $theChangeRows, $theHelpTopic ) = @_; my $tmp = &TWiki::Func::extractNameValuePair( $theArgs, "header" ); $theHeader = $tmp if( $tmp ); $tmp = &TWiki::Func::extractNameValuePair( $theArgs, "footer" ); $theFooter = $tmp if( $tmp ); $tmp = &TWiki::Func::extractNameValuePair( $theArgs, "format" ); $tmp =~ s/^\s*\|*\s*//o; $tmp =~ s/\s*\|*\s*$//o; $theFormat = $tmp if( $tmp ); $tmp = &TWiki::Func::extractNameValuePair( $theArgs, "changerows" ); $theChangeRows = $tmp if( $tmp ); $tmp = &TWiki::Func::extractNameValuePair( $theArgs, "helptopic" ); $theHelpTopic = $tmp if( $tmp ); return ( $theHeader, $theFooter, $theFormat, $theChangeRows, $theHelpTopic ); } # ========================= sub commonTagsHandler { ### my ( $text, $topic, $web ) = @_; # do not uncomment, use $_[0], $_[1]... instead &TWiki::Func::writeDebug( "- EditTablePlugin::commonTagsHandler( $_[2].$_[1] )" ) if $debug; # Test presence of EditTable tags return unless $_[0] =~ /%EDITTABLE{(.*)}%/os; # Initialization of variables my $theWeb = $_[2]; my $theTopic = $_[1]; my $result = ""; my $tableNr = 0; my $rowNr = 0; my $doEdit = 0; my $insideTable = 0; my @cgiCells ; my $getRows = $query->param( 'etrows' ) || -1; my $cgiTableNr = $query->param( 'ettablenr' ) || 0; my $row=0; my $tag=0; $cgiCols = 0; $nbCols = 0; # Parse TWiki page foreach( split( /\n/, $_[0] ) ) { &TWiki::Func::writeDebug( "- EditTablePlugin::debug debut parse" ) if $debug; # Handle our EDITTABLE tags if(s/(\s*)%EDITTABLE{(.*)}%/&handleEditTableTag($theWeb,$1,$2)/geo){ $insideTable = 1; $doEdit=0; $cgiRows=-1; $tableNr += 1; $tag=1; $row=0; # Execute a requiried action on the current edited table if( $cgiTableNr == $tableNr ) { $cgiRows=$getRows; # Dump CGI representation of the TWiki table into perl array if ( !$query->param( 'etedit' ) ) { my $nbRow=0; my $oneSelected=0; my @swap=(); for(my $row=1;$row<=$cgiRows;$row++){ my $srow=$query->param("SEL${row}"); my $thisSelected=(defined $srow)?($row==$srow):0; if($thisSelected){ $oneSelected=1; last; } } for(my $row=1;$row<=$cgiRows;$row++){ my $col=1; my $nrow=$row+1; my @cells; my $srow=$query->param("SEL${row}"); my $snrow=$query->param("SEL${nrow}"); my $thisSelected=(defined $srow)?($row==$srow):0; my $nextSelected=(defined $snrow)?($row==$snrow):0; if ( $query->param( 'etdelrows' ) && $thisSelected ) { next; } while(1){ $value=$query->param("etcell${row}x${col}"); if(!defined $value){ last; } $cells[$col++]=$value; } if ($query->param( 'etinsrows' ) && ($thisSelected || (!$oneSelected && ($row==2)))){ push @cgiCells,[@cells]; $nbRow++; } $nbRow++; if ( ( $query->param( 'etdown' ) && $thisSelected && ( $row<$cgiRows ) ) || ( $query->param( 'etup' ) && $nextSelected && ( $row>1 ) ) ){ push @swap,[@cells]; } else{ push @cgiCells,[@cells]; my $elem = pop(@swap); if(defined $elem){ push @cgiCells,$elem; } } if ($query->param( 'etaddrows' ) && ($thisSelected || (!$oneSelected && ($row==$cgiRows)))){ push @cgiCells,[@cells]; $nbRow++; } if($col>$nbCols){ $nbCols=$col; } } $cgiRows=$nbRow if ($nbRow > 0); } # [Save table] button pressed if( $query->param( 'etsave' ) ) { # FIXME modifier doSaveTable (never return in case browser does # not redirect) doSaveTable( $theWeb, $theTopic, $tableNr ,@cgiCells); return; } # [Cancel] button pressed elsif( $query->param( 'etcancel' ) ) { # FIXME modifier doSaveTable (never return in case browser does # not redirect) doCancelEdit( $theWeb, $theTopic ); return; } # [Add or Delete or Up or Down selected rows] button pressed elsif( $query->param( 'etinsrows' ) || $query->param( 'etaddrows' ) || $query->param( 'etup' ) || $query->param( 'etdown' ) || $query->param( 'etdelrows' ) ) { $doEdit = doEnableEdit( $theWeb, $theTopic, 0 ); return unless( $doEdit ); } # [Edit table] button pressed elsif( $query->param( 'etedit' ) ) { $doEdit = doEnableEdit( $theWeb, $theTopic, 1 ); # return if locked or no permission return unless( $doEdit ); } } $result .= handleTableStart($theWeb,$theTopic,$tableNr,$cgiRows,$doEdit); } else { $tag=0; } # Display the table if($insideTable){ if(!$tag){ # The table must be displayed as a HTML form if(/^(\s*)\|.*\|\s*$/){ if($cgiRows<0 || $query->param( 'etedit' ) || $doEdit==0 ){ $row++; $result .= handleTableRow($preSp,$_,$tableNr,$row,$doEdit,""); $result .= "\n"; } else{ next; } } else{ while($row<$cgiRows){ $result .= handleTableRow($preSp,"",$tableNr,$row,$doEdit,@cgiCells); $result .= "\n"; $row++; } $result .= handleTableEnd($theWeb,$row,$doEdit); $insideTable = 0; } } } else{ $result .= "$_\n"; } } # Return page with edition HTML forms included $_[0] = $result; } # ========================= sub DISABLE_startRenderingHandler { ### my ( $text, $web ) = @_; # do not uncomment, use $_[0], $_[1] instead &TWiki::Func::writeDebug( "- EditTablePlugin::startRenderingHandler( $_[1] )" ) if $debug; # This handler is called by getRenderedVersion just before the line loop $renderingWeb = $_[1]; } # ========================= sub DISABLE_outsidePREHandler { ### my ( $text ) = @_; # do not uncomment, use $_[0] instead &TWiki::Func::writeDebug( "- EditTablePlugin::outsidePREHandler( $renderingWeb.$topic )" ) if $debug; # This handler is called by getRenderedVersion, in loop outside of
tag
# This is the place to define customized rendering rules
# do custom extension rule, like for example:
# $_[0] =~ s/old/new/go;
}
# =========================
sub DISABLE_insidePREHandler
{
### my ( $text ) = @_; # do not uncomment, use $_[0] instead
&TWiki::Func::writeDebug( "- EditTablePlugin::insidePREHandler( $web.$topic )" ) if $debug;
# This handler is called by getRenderedVersion, in loop inside of tag
# This is the place to define customized rendering rules
# do custom extension rule, like for example:
# $_[0] =~ s/old/new/go;
}
# =========================
sub endRenderingHandler
{
### my ( $text ) = @_; # do not uncomment, use $_[0] instead
&TWiki::Func::writeDebug( "- EditTablePlugin::endRenderingHandler( $web.$topic )" ) if $debug;
# This handler is called by getRenderedVersion just after the line loop
return unless $_[0] =~ /$encodeStart/os;
$_[0] =~ s/$encodeStart(.*?)$encodeEnd/&decodeValue($1)/geos;
}
# =========================
sub encodeValue
{
my( $theText ) = @_;
# WindRiver specific hack to remove SprPlugin rendering
$theText =~ s/ value)
if( /^\s*(.*?)\s*=>\s*(.*?)\s*$/ ) {
my ( $web, $topic, $field ) = ( "", "", "" );
my $twikiwd = "($webNameRegex)[.]($wikiWordRegex)";
my ( $key, $option) = ( $1, $2 ) ;
my $caseok = 0;
# The 4 cases where value is a reference to a TWiKi topic
if( $option =~ /^\s*($wikiWordRegex)\s*$/ ){
$web = $theWeb; $topic = $1; $field = ""; }
if( $option =~ /^\s*$twikiwd\s*$/ ){
$web = $1; $topic = $2; $field = ""; }
if( $option =~ /^\s*($wikiWordRegex):($mixedAlphaNumRegex)\s*/ ){
$web = $theWeb; $topic = $1; $field = $2; }
if( $option =~ /^\s*$twikiwd:($mixedAlphaNumRegex)\s*/ ){
$web = $1; $topic = $2; $field = $3; }
if( $web && $topic ){
my( $meta , $text ) = &TWiki::Func::readTopic( $web, $topic );
# The real values are in the text of the topic
if( !$field && $text ) {
foreach( split( /\n/, $text ) ) {
$_ =~ s/,/\$comma/go;
$new .= ",$key => $_";
}
$caseok = 1;
}
# The real values are in a field form of the topic
if( $field && $meta ) {
%ftab = $meta->findOne( "FIELD", $field );
$fval = $ftab{"value"};
if( $fval ){
foreach $subopt ( split( /\n/, $fval ) ){
$subopt =~ s/,/\$comma/go;
$new .= ",$key => $subopt"; }
$caseok = 1;
}
}
}
if( !$topic && !$caseok ){ $new .= ",$_"; }
}
else{ $new .= ",$_"; }
}
}
$format[$i++]=$new;
}
}
# =========================
sub handleEditTableTag
{
my( $theWeb, $thePreSpace, $theArgs ) = @_;
$preSp = $thePreSpace || "";
$header = "";
$footer = "";
my $tFormat = "";
$changeRows = "";
my $iTopic = &TWiki::Func::extractNameValuePair( $theArgs, "include" );
if( $iTopic ) {
# include topic to read definitions
if( $iTopic =~ /^([^\.]+)\.(.*)$/o ) {
$theWeb = $1;
$iTopic = $2;
}
my( $meta, $text ) = &TWiki::Func::readTopic( $theWeb, $iTopic );
$text =~ /%EDITTABLE{(.*)}%/os;
if( $1 ) {
my $args = $1;
if( "$theWeb.$iTopic" ne "$web.$topic" ) {
# expand common vars, unless oneself to prevent recursion
$args = &TWiki::Func::expandCommonVariables($1,$iTopic,$theWeb );
}
( $header, $footer, $tFormat, $changeRows, $helpTopic ) =
extractParameters( $args, $header, $footer, $tFormat,
$changeRows, $helpTopic );
}
}
( $header, $footer, $tFormat, $changeRows, $helpTopic ) =
extractParameters( $theArgs, $header, $footer, $tFormat,
$changeRows, $helpTopic );
$header = "" if( $header =~ /^off$/oi );
$header =~ s/^\s*\|//o;
$header =~ s/\|\s*$//o;
$footer = "" if( $footer =~ /^off$/oi );
$footer =~ s/^\s*\|//o;
$footer =~ s/\|\s*$//o;
$changeRows = "" if( $changeRows =~ /^off$/oi );
$tFormat =~ s/\$nop(\(\))?//gos; # remove filler
$tFormat =~ s/\$quot(\(\))?/\"/gos; # expand double quote
$tFormat =~ s/\$percnt(\(\))?/\%/gos; # expand percent
$tFormat =~ s/\$dollar(\(\))?/\$/gos; # expand dollar
@format = split( /\s*\|\s*/, $tFormat );
$format[0] = "text,16" unless @format;
handleFormatIncludes( $theWeb );
$cgiCols = @format;
# FIXME: No handling yet of footer
return "$preSp";
}
# =========================
sub generateJavascript
{
my( $formName, $nbRows, $cellName ) = @_;
my @select=();
my @dynsel=();
my $nocol=0;
foreach (@format){
if(/^\s*select\s*\(/){ push @dynsel,$nocol; }
if(/^\s*select/){ push @select,$nocol; }
$nocol++;
}
# Javascript header
my $text = "\n";
return $text;
}
# =========================
sub handleTableStart
{
my( $theWeb, $theTopic, $theTableNr, $nbRows, $doEdit ) = @_;
my $viewUrl = &TWiki::Func::getScriptUrl( $theWeb, $theTopic, "viewauth" ) . "\#edittable$theTableNr";
my $formName="edittable$theTableNr";
my $text = "";
$text .= generateJavascript( $formName, $nbRows, "etcell" ) if $doEdit;
$text .= "$preSp\n" if $doEdit;
$text .= "$preSp\n";
$text .= "$preSp\n";
$text .= "$preSp \n" if $doEdit;
return $text;
}
# =========================
sub inputElement
{
my ( $theTableNr, $theRowNr, $theCol, $theName, $theValue, $islabel ) = @_;
$theValue = "" if( !defined $theValue || $theValue eq " " );
my $striped = $theValue;
$striped =~ s/\s*$//o;
$striped =~ s/^\s*//o;
my $text = "";
my $i = @format - 1;
$i = $theCol if( $theCol < $i );
my @bits = split( /,\s*/, $format[$i] );
my $type = "text";
if(@bits > 0){
$type = $bits[0];
$type =~ s/\s*\(.*\)\s*$//o;
}
my $size = 0;
$size = $bits[1] if @bits > 1;
my $val = "";
my $sel = "";
if( $type eq "label" || $islabel) {
# show label text as is, and add a hidden field with value
$text = " $striped" ;
$theValue = $encodeStart . encodeValue( $striped ) . $encodeEnd;
$text .= " ";
} elsif( $type eq "select" ) {
my $colNo=$theCol+1;
my $jsfct = "updateRowOfSelect";
my $jstext = " onchange=$jsfct($theRowNr,$colNo)";
my $sizetext = "";
my $oneSelect = 0;
if($size>0){ $sizetext = " size=\"$size\""; }
$text = "";
} elsif( $type eq "row" ) {
$size = $size + $theRowNr;
$text = "$size";
} else { # if( $type eq "text" )
$size = 16 if $size < 1;
$theValue = $encodeStart . encodeValue( $theValue ) . $encodeEnd if $theValue;
$text = "";
}
return $text;
}
# =========================
sub handleTableRow
{
my ($thePre,$theRow,$theTableNr,$theRowNr,$doForm,@cgiTable) = @_;
my @cells;
my $text = "$thePre\|";
if($theRow){
$theRow =~ s/\|\s*$//o;
@cells = split( /\|/, $theRow );
my $tmp = @cells;
$cgiCols = $tmp if( $tmp > $cgiCols ); # expand number of cols
}
else{
for(my $i=0;$i<$nbCols;$i++){ $cells[$i]=$cgiTable[$theRowNr][$i]; }
$cgiCols=$nbCols;
$theRowNr++;
}
if($doForm){
if($theRowNr>1){
$text .= "\|";
}
else { $text .="\|"; }
}
my $col = 1;
while( $col < $cgiCols ) {
my $cell=$cells[$col];
my $name="etcell${theRowNr}x$col";
if(defined $cell){ $cell =~ s/[\n\r]/ /gos; }
if( ( $theRowNr <= 1 ) && ( $header ) ) {
if( ! $cell ) {
if( $header =~ /^on$/i ) {
if( ( @format-1 >= $col ) && ( $format[$col] =~ /(.*?)\,/ ) ) {
$cell = $1;
}
$cell = "text" unless $cell;
$cell = "*$cell*";
} else {
my @hCells = split( /\|/, $header );
$cell = $hCells[$col-1] if( @hCells >= $col );
$cell = "*text*" unless $cell;
}
}
if (!$doForm) { $text .= $cell . "\|"; }
else{ $text .= inputElement($theTableNr,$theRowNr,$col-1,$name,$cell,1).
"\|";
}
}
elsif( !$doForm ) {
if(!defined $cell || $cell eq ""){ $cell = " "; }
$text .= $cell . "\|";
}
else {
if(!defined $cell){ $cell = " "; }
if ( ( $cell =~ /^\s*$/ ) && ( @format >= $col ) &&
( $format[$col-1] =~ /^\s*(.*?)\,\s*(.*?)\,\s*(.*?)\s*$/ ) ) {
# default value of "| text, 20, a, b,c |" cell is "a, b, c"
# default value of "| select, 1, a, b, c |" cell is "a"
$cell = $3 || "";
$cell =~ s/\,.*$//o if( $1 eq "select" );
}
$text .= inputElement( $theTableNr,$theRowNr,$col-1,$name,$cell,0 ) .
"\|";
}
$col++;
}
return $text;
}
# =========================
sub doSaveTable
{
my ( $theWeb, $theTopic, $theTableNr ,@cgiCells) = @_;
&TWiki::Func::writeDebug( "- EditTablePlugin::doSaveTable( $theWeb, $theTopic, $theTableNr )" ) if $debug;
my( $meta, $text ) = &TWiki::Store::readTopic( $theWeb, $theTopic );
my $cgiRows = $query->param( 'etrows' ) || 1;
my $tableNr = 0;
my $rowNr = 0;
my $insideTable = 0;
my $doSave = 0;
my $result = "";
foreach( split( /\n/, $text ) ) {
if( /%EDITTABLE{(.*)}%/o ) {
$tableNr += 1;
if( $tableNr == $theTableNr ) {
$doSave = 1;
$result .= "$_\n";
}
}
if( $doSave ) {
if( /^(\s*)\|.*\|\s*$/ ) {
$insideTable = 1;
} elsif( $insideTable ) {
$insideTable = 0;
$row=0;
while($row<$cgiRows){
$result .=
handleTableRow($preSp,"",$tableNr,$row,0,@cgiCells);
$result .= "\n";
$row++;
}
$result .= "$_\n";
$doSave = 0;
}
if( /^\s*$/ ) { # empty line
$doSave = 0;
}
}
else
{
$result .= "$_\n";
}
}
&TWiki::Func::writeDebug(
"- EditTablePlugin:debug dosave \n $result ") if $debug;
my $error = &TWiki::Store::saveTopic( $theWeb, $theTopic, $result, $meta );
&TWiki::Store::lockTopic( $theTopic, "on" );
my $url = &TWiki::Func::getViewUrl( $theWeb, $theTopic );
if( $error ) {
$url = &TWiki::Func::getOopsUrl(
$theWeb, $theTopic, "oopssaveerr", $error );
}
&TWiki::Func::redirectCgiQuery( $query, $url );
}
# =========================
sub doCancelEdit
{
my ( $theWeb, $theTopic ) = @_;
&TWiki::Func::writeDebug( "- EditTablePlugin::doCancelEdit( $theWeb, $theTopic )" ) if $debug;
&TWiki::Store::lockTopic( $theTopic, "on" );
&TWiki::Func::redirectCgiQuery( $query, &TWiki::Func::getViewUrl( $theWeb, $theTopic ) );
}
# =========================
sub doEnableEdit
{
my ( $theWeb, $theTopic, $doCheckIfLocked ) = @_;
&TWiki::Func::writeDebug(
"- EditTablePlugin::doEnableEdit( $theWeb, $theTopic )" ) if $debug;
my $wikiUserName = &TWiki::Func::getWikiUserName();
if( ! &TWiki::Func::checkAccessPermission(
"change", $wikiUserName, "", $theTopic, $theWeb ) ) {
# user has not permission to change the topic
my $url = &TWiki::Func::getOopsUrl( $theWeb, $theTopic, "oopsaccesschange" );
&TWiki::Func::redirectCgiQuery( $query, $url );
return 0;
}
my( $lockUser, $lockTime ) = &TWiki::Store::topicIsLockedBy( $theWeb, $theTopic );
if( ( $doCheckIfLocked ) && ( $lockUser ) ) {
# warn user that other person is editing this topic
$lockUser = &TWiki::Func::userToWikiName( $lockUser );
use integer;
$lockTime = ( $lockTime / 60 ) + 1; # convert to minutes
my $editLock = $TWiki::editLockTime / 60;
my $url = &TWiki::Func::getOopsUrl( $theWeb, $theTopic, "oopslocked",
$lockUser, $editLock, $lockTime );
&TWiki::Func::redirectCgiQuery( $query, $url );
return 0;
}
&TWiki::Store::lockTopic( $theTopic );
return 1;
}
# =========================
# The following code is copied from the ChartPlugin Table object.
package TWiki::Plugins::Table;
sub new
{
my ($class, $topicContents) = @_;
my $this = {};
bless $this, $class;
$this->_parseOutTables($topicContents);
return $this;
}
# The guts of this routine was initially copied from SpreadSheetPlugin.pm
# and were used in the ChartPlugin Table object which this was copied from,
# but this has been modified to support the functionality needed by the
# EditTablePlugin. One major change is to only count and save tables
# following an %EDITTABLE{.*}% tag.
#
# This routine basically returns an array of hashes where each hash
# contains the information for a single table. Thus the first hash in the
# array represents the first table found on the topic page, the second hash
# in the array represents the second table found on the topic page, etc.
sub _parseOutTables
{
my ($this, $topic) = @_;
my $tableNum = 1; # Table number (only count tables with EDITTABLE tag)
my @tableMatrix; # Currently parsed table.
my $inEditTable = 0; # Flag to keep track if in an EDITTABLE table
my $result = "";
my $insidePRE = 0;
my $insideTABLE = 0;
my $line = "";
my @row = ();
$topic =~ s/\r//go;
$topic =~ s/\\\n//go; # Join lines ending in "\"
foreach( split( /\n/, $topic ) ) {
# change state:
m||i && ( $insidePRE = 1 );
m||i && ( $insidePRE = 1 );
m| |i && ( $insidePRE = 0 );
m||i && ( $insidePRE = 0 );
if( ! $insidePRE ) {
$inEditTable = 1 if (/%EDITTABLE{(.*)}%/);
if ($inEditTable) {
if( /^\s*\|.*\|\s*$/ ) {
# inside | table |
$insideTABLE = 1;
$line = $_;
$line =~ s/^(\s*\|)(.*)\|\s*$/$2/o; # Remove starting '|'
@row = split( /\|/o, $line, -1 );
_trim(\@row);
push (@tableMatrix, [ @row ]);
} else {
# outside | table |
if( $insideTABLE ) {
# We were inside a table and are now outside of it so
# save the table info into the Table object.
$insideTABLE = 0;
$inEditTable = 0;
if (@tableMatrix != 0) {
# Save the table via its table number
$$this{"TABLE_$tableNum"} = [@tableMatrix];
$tableNum++;
}
undef @tableMatrix; # reset table matrix
}
}
}
}
$result .= "$_\n";
}
$$this{NUM_TABLES} = $tableNum;
}
# Trim any leading and trailing white space and/or '*'.
sub _trim
{
my ($totrim) = @_;
for my $element (@$totrim) {
$element =~ s/^[\s\*]+//; # Strip of leading white/*
$element =~ s/[\s\*]+$//; # Strip of trailing white/*
}
}
# Return the contents of the specified cell
sub getCell
{
my ( $this, $tableNum, $row, $column ) = @_;
my @selectedTable = $this->getTable( $tableNum );
my $value = $selectedTable[$row][$column];
return $value;
}
sub getTable
{
my ($this, $tableNumber) = @_;
my $table = $$this{"TABLE_$tableNumber"};
return @$table if defined( $table );
return ();
}
1;