<?php if (!defined('PmWiki')) exit();

/*	=== Tabulate ===
 *	Copyright 2008 Eemeli Aro <eemeli@gmail.com>
 *
 *	Handles tab-delimited tables so you can cut and paste to and
 *	from spreadsheet applications
 *
 *	Developed and tested using the PmWiki 2.2.0-beta series.
 *
 *	To install, add the following line to your configuration file :
		include_once("$FarmD/cookbook/casecorrect.php");
 *	and add the directive (:case-correction:) to your 404 page, by
 *	default located at Site.PageNotFound
 *
 *	For more information, please see the online documentation at
 *		http://www.pmwiki.org/wiki/Cookbook/CaseCorrection
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License,
 *	Version 2, as published by the Free Software Foundation.
 *	http://www.gnu.org/copyleft/gpl.html
 */

$RecipeInfo['Tabulate']['Version'] = '2008-09-08';

Markup('tabulate-set', '>if', '/\\(:tab-table(.*?):\\)/ei', "TabulateSetup( \$pagename, PSS('$1') )");
Markup('tabulate-tabs', '>tabulate-set', '/^(?:.*\\t.*\n)+/me', "Tabulate( \$pagename, PSS('$0') )");

function TabulateParseArgs($x) {
	global $TabZeroIndexing;

	$z = array();
	preg_match_all("/\s+(all|col|row|tgt)(\d*)[:=](\"[^\"]*\"|\\S+)/", $x, $terms, PREG_SET_ORDER);
	foreach( $terms as $t ) {
		if ( $t[2] === '' ) $t[2] = $t[3];
		$z[$t[1]][$t[2]] = preg_replace('/^"(.*)"$/', '$1', $t[3] );
		$x = preg_replace( '/'.preg_quote($t[0],'/').'/', '', $x );
	}

	if ( !IsEnabled( $TabZeroIndexing, FALSE ) ) {
		foreach ( $z as $n => $va )
		if ( is_array($va) ) foreach( $va as $p => $v ) {
			if ( --$p < 0 ) $p = 0;
			$nz[$n][$p] = $v;
		} else $nz[$n] = $va;
		$z = $nz;
	}

	$z['tail'] = trim($x);
	return $z;
}

function TabulateSetup( $pagename, $attr  ) {
	global $TabSet;

	$set = TabulateParseArgs($attr);
	if ( isset($set['tgt']) ) {
		$i = key($set['tgt']);
		unset($set['tgt']);
		$TabSet[$i] = $set;
	} else
		$TabSet[] = $set;

	return '';
}

function Tabulate( $pagename, $text ) {
	global $TabMinRows, $TabMinCols, $TabSet, $TabCall;

	SDV( $TabMinRows, 2 );
	SDV( $TabMinCols, 2 );
	SDV( $TabCall, 0 );

	$text = trim(str_replace( array('||','\\\\'), array('&#124;&#124;',"<br />"), $text ));
	foreach( explode("\n",$text) as $n ) $table[] = explode("\t",$n);

	if ( count($table) < $TabMinRows ) return $text;
	for ( $i = 0; $i < $TabMinRows; ++$i ) if ( count($table[$i]) < $TabMinCols ) return $text;

	$ts = "(:table {$TabSet[$TabCall]['tail']}:)\n";
	unset($TabSet[$TabCall]['tail']);

	$tp = array();
	foreach( (array)$TabSet[$TabCall] as $dir => $a ) if ( is_array($a) ) foreach( $a as $i => $s ) {
		if ( !preg_match( '/^\s*([^a-z\d]*)\s*([a-z\d%# ]*?)\s*([^a-z\d]*)\s*$/', $s, $m ) ) continue;
		if (!$m[3]) {
			if ( !$m[1] && !$m[2] ) continue;
			$m[3] = $m[1];
		} else if (!$m[1]) $m[1] = $m[3];
		if ($m[2]) {
			$m[2] = preg_replace(
				array( '/\d+(?:%|px)/i', '/#[a-f\d]{6}/i', '/\b(?:left|center|right|justify)\b/i', '/\b(?:top|middle|bottom|baseline)\b/i' ),
				array( 'width=$0',       'bgcolor=$0',     'align=$0',                             'valign=$0' ),
				$m[2] );
		}
		switch($dir) {
			case 'all':
				foreach( $table as $ri => $r ) foreach( $r as $ci => $tc ) {
					if ($m[1]) $table[$ri][$ci] = $m[1].$tc.$m[3];
					if ($m[2]) $tp[$ri][$ci] .= ' '.$m[2];
				}
				break;
			case 'row':
				if ( $i < count($table) ) {
					foreach( $table[$i] as $j => $tc ) {
						if ($m[1]) $table[$i][$j] = $m[1].$tc.$m[3];
						if ($m[2]) $tp[$i][$j] .= ' '.$m[2];
					}
				}
				break;
			case 'col':
				foreach( $table as $j => $r ) {
					if ( $i < count($r) ) {
						if ($m[1]) $table[$j][$i] = $m[1].$r[$i].$m[3];
						if ($m[2]) $tp[$j][$i] .= ' '.$m[2];
					}
			} break;
		}
	}

	foreach( $table as $i => $r ) foreach( $r as $j => $tc ) {
		$ts .= ($j?'(:cell ':'(:cellnr ') . "{$tp[$i][$j]}:)$tc\n";
	}
	$ts .= "(:tableend:)\n";

	++$TabCall;
	return $ts;
}