<?php
//============================================================+
// File name   : tce_functions_tcecode.php
// Begin       : 2002-01-09
// Last Update : 2006-11-20
// 
// Description : Functions to translate TCExam proprietary code 
//               into XHTML.
//
// Author: Nicola Asuni
//
// (c) Copyright:
//               Tecnick.com S.r.l.
//               Via Ugo Foscolo n.19
//               09045 Quartu Sant'Elena (CA)
//               ITALY
//               www.tecnick.com
//               info@tecnick.com
//
// License: GNU GENERAL PUBLIC LICENSE v.2
//          http://www.gnu.org/copyleft/gpl.html
//============================================================+

/**
 * Functions to translate TCExam proprietary code into XHTML.
 * @package com.tecnick.tcexam.shared
 * @author Nicola Asuni
 * @copyright Copyright &copy; 2004-2006, Tecnick.com S.r.l. - Via Ugo Foscolo n.19 - 09045 Quartu Sant'Elena (CA) - ITALY - www.tecnick.com - info@tecnick.com
 * @link www.tecnick.com
 * @since 2002-01-09
 */

/**
 * Returns XHTML code from text marked-up with TCExam Code Tags
 * @param string $text_to_decode text to convert
 * @return string XHTML code
 */
function F_decode_tcecode($text_to_decode) {
		require_once('../config/tce_config.php');
	global $l, $db;
	
	// Patterns and replacements for URL and email tags..
	$pattern = array();
	$replacement = array();
	$i=0;
	
	$newtext = htmlspecialchars($text_to_decode, ENT_NOQUOTES, $l['a_meta_charset']); // escape some special HTML characters
	
	// replace newline chars on [code] tag
	//$newtext = preg_replace("'\r\n'si", "\n",  $newtext);
	//$newtext = preg_replace("'\n\r'si", "\n",  $newtext);
	while (preg_match("'\[code\](.*?) (.*?)\[/code\]'si", $newtext)) {
		$newtext = preg_replace("'\[code\](.*?) (.*?)\[/code\]'si", "[code]\\1&nbsp;\\2[/code]",  $newtext);
	}
	/*
	while (preg_match("'\[code\](.*?)\n(.*?)\[/code\]'si", $newtext)) {
		$newtext = preg_replace("'\[code\](.*?)\n(.*?)\[/code\]'si", "[code]\\1@n@\\2[/code]",  $newtext);
	}*/
	
	// [url]http://www.domain.com[/url]
	$pattern[++$i] = "#\[url\](.*?)\[/url\]#si";
	$replacement[++$i] = '<a class="tcecode" href="\1">\1</a>';
	
	// [url=http://www.domain.com]linkname[/url]
	$pattern[++$i] = "#\[url=(.*?)\](.*?)\[/url\]#si";
	$replacement[++$i] = '<a class="tcecode" href="\1">\2</a>';
	
	// [code] and [/code] display text as source code
	$pattern[++$i] = "#\[code\](.*?)\[/code\]#si";
	$replacement[++$i] = '<div class="tcecodepre">\1</div>';
	
	// [small] and [/small] for small text
	$pattern[++$i] = "#\[small\](.*?)\[/small\]#si";
	$replacement[++$i] = '<small class="tcecode">\1</small>';
	
	// [b] and [/b] for bolding text.
	$pattern[++$i] = "#\[b\](.*?)\[/b\]#si";
	$replacement[++$i] = '<strong class="tcecode">\1</strong>';
	
	// [i] and [/i] for italicizing text.
	$pattern[++$i] = "#\[i\](.*?)\[/i\]#si";
	$replacement[++$i] = '<em class="tcecode">\1</em>';
	
	// [sub] and [/sub] for subscript text.
	$pattern[++$i] = "#\[sub\](.*?)\[/sub\]#si";
	$replacement[++$i] = '<sub class="tcecode">\1</sub>';
	
	// [sup] and [/sup] for superscript text.
	$pattern[++$i] = "#\[sup\](.*?)\[/sup\]#si";
	$replacement[++$i] = '<sup class="tcecode">\1</sup>';
	
	// [ulist] and [/ulist] unordered list
	$pattern[++$i] = "#\[ulist\](.*?)\[/ulist\]#si";
	$replacement[++$i] = '<ul class="tcecode">\1</ul>';
	
	// [olist] and [/olist] ordered list.
	$pattern[++$i] = "#\[olist\](.*?)\[/olist\]#si";
	$replacement[++$i] = '<ol class="tcecode">\1</ol>';
	
	// [li] list items [/li]
	$pattern[++$i] = "#\[li\](.*?)\[/li\]#si";
	$replacement[++$i] = '<li class="tcecode">\1</li>';
	
	$newtext = preg_replace($pattern, $replacement, $newtext);
	
	// line breaks
	$newtext = ereg_replace("(\r\n|\n|\r)", "<br />", $newtext);
	$newtext = str_replace("<br /><li", "<li", $newtext);
	$newtext = str_replace("</li><br />", "</li>", $newtext);
	
	// [object]object_url[/object:width:height:alt]
	$newtext = preg_replace_callback("#\[object\](.*?)\.(.*?)\[/object\:(.*?)\:(.*?)\:(.*?)\]#si", 'F_objects_callback', $newtext);
	// [object]object_url[/object:width:height]
	$newtext = preg_replace_callback("#\[object\](.*?)\.(.*?)\[/object\:(.*?)\:(.*?)\]#si", 'F_objects_callback', $newtext);
	// [object]object_url[/object]
	$newtext = preg_replace_callback("#\[object\](.*?)\.(.*?)\[/object\]#si", 'F_objects_callback', $newtext);
	
	// restore newline chars on [code] tag
	//$newtext = preg_replace("'@n@'si", "\n",  $newtext);
	
	return ($newtext);
}

/**
 * Callback function for preg_replace_callback.
 * Returns replacement code by MIME type.
 * @param string $matches array containing matches: $matches[0] is the complete match, $matches[1] the match for the first subpattern enclosed in '(...)' and so on
 * @return string replacement string by file extension
 */
function F_objects_callback($matches) {
	$width = 0;
	$height = 0;
	$alt = "";
	if(isset($matches[3]) AND ($matches[3] > 0)) {
		$width = $matches[3];
	}
	if(isset($matches[4]) AND ($matches[4] > 0)) {
		$height = $matches[4];
	}
	if(isset($matches[5]) AND (!empty($matches[5]))) {
		$alt = F_tcecodeToTitle($matches[5]);
	}
	return F_objects_replacement($matches[1], $matches[2], $width, $height, $alt);
}

/**
 * Returns the xhtml code needed to display the object by MIME type.
 * @param string $name object path excluded extension
 * @param string $extension object extension (e.g.: gif, jpg, swf, ...)
 * @param int $width object width
 * @param int $height object height
 * @param string $alt alternative content
 * @return string replacement string
 */
function F_objects_replacement($name, $extension, $width=0, $height=0, $alt="") {
	require_once('../config/tce_config.php');
	global $l, $db;
	
	$filename = $name.".".$extension;
	$extension = strtolower($extension);
	$htmlcode = "";
	
	switch($extension) {
		case "gif": 
		case "jpg":
		case "jpeg":
		case "png": { // images
			$htmlcode = "<img src=\"".K_PATH_URL_CACHE.$filename."\"";
			if (!empty($alt)) {
				$htmlcode .= " alt=\"".$alt."\"";
			} else {
				$htmlcode .= " alt=\"image:".$filename."\"";
			}
			if ($width > 0) {
				$htmlcode .= " width=\"".$width."\"";
			}
			if ($height > 0) {
				$htmlcode .= " height=\"".$height."\"";
			}
			$htmlcode .= " class=\"tcecode\" />";
			break;
		}
		default: {
			include('../../shared/config/tce_mime.php');
			if (isset($mime[$extension])) {
				$htmlcode = "<object type=\"".$mime[$extension]."\"
				data=\"".$filename."\"";
				if ($width >0) {
					$htmlcode .= " width=\"".$width."\"";
				}
				if ($height >0) {
					$htmlcode .= " height=\"".$height."\"";
				}
				$htmlcode .= ">";
				$htmlcode .= "\n<param name=\"type\" value=\"".$mime[$extension]."\" />";
				$htmlcode .= "\n<param name=\"src\" value=\"".K_PATH_URL_CACHE.$filename."\" />";
				$htmlcode .= "\n<param name=\"filename\" value=\"".K_PATH_URL_CACHE.$filename."\" />";
				if ($width > 0) {
					$htmlcode .= "\n<param name=\"width\" value=\"".$width."\" />";
				}
				if ($height > 0) {
					$htmlcode .= "\n<param name=\"height\" value=\"".$height."\" />";
				}
				if (!empty($alt)) {
					$htmlcode .= "\n".$alt."";
				} else {
					$htmlcode .= "\n[".$mime[$extension]."]:".$filename."";
				}
				$htmlcode .= "\n</object>";
			}
			else {
				$htmlcode = "[ERROR - UNKNOW MIME TYPE FOR: ".$extension."]";
			}
			break;
		}
	}
	return $htmlcode;
}

/**
 * Returns specified string without tcecode mark-up tags
 * @param string $str text to process
 * @return string without tcecode markup tags
 */
function F_remove_tcecode($str) {
	$str = preg_replace("'\[object\](.*?)\[/object([^\]]*?)\]'si", "[IMG]",  $str);
	$str = preg_replace("'\[code\](.*?)\[/code\]'si", "\1",  $str);
	$str = preg_replace("'\[b\](.*?)\[/b\]'si", "\1",  $str);
	$str = preg_replace("'\[i\](.*?)\[/i\]'si", "\1",  $str);
	$str = preg_replace("'\[small\](.*?)\[/small\]'si", "\1",  $str);
	$str = preg_replace("'\[sub\](.*?)\[/sub\]'si", "\1",  $str);
	$str = preg_replace("'\[sup\](.*?)\[/sup\]'si", "\1",  $str);
	$str = preg_replace("'\[url\](.*?)\[/url\]'si", "\1",  $str);
	$str = preg_replace("'\[li\](.*?)\[/li\]'si", "\1",  $str);
	$str = preg_replace("'\[ulist\](.*?)\[/ulist\]'si", "\1",  $str);
	$str = preg_replace("'\[olist\](.*?)\[/olist\]'si", "\1",  $str);
	return $str;
}

/**
 * Converts tcecode text to a single XHTML string removing some eobjects.
 * @param string $str text to process
 * return string
 */
function F_tcecodeToLine($str) {
	$str = preg_replace("'\[object\](.*?)\[/object([^\]]*)\]'si", "[IMG]",  $str);
	$str = preg_replace("'\[li\](.*?)\[/li\]'si", "\\1",  $str);
	$str = preg_replace("'\[ulist\](.*?)\[/ulist\]'si", "\\1",  $str);
	$str = preg_replace("'\[olist\](.*?)\[/olist\]'si", "\\1",  $str);
	$str = preg_replace("'\[code\](.*?)\[/code\]'si", "\\1",  $str);
	$str = preg_replace("'\[url\](.*?)\[/url\]'si", "\\1",  $str);
	$str = F_compact_string($str);
	$str = F_decode_tcecode($str);
	$str = F_compact_string($str);
	
	if (strlen($str) > K_QUESTION_LINE_MAX_LENGTH) {
		$str = F_substrHTML($str, K_QUESTION_LINE_MAX_LENGTH, 20)." ...";
	}
	return $str;
}

/**
 * Converts tcecode text to simple string for XHTML title attribute.
 * @param string $str text to process
 * return string
 */
function F_tcecodeToTitle($str) {
		require_once('../config/tce_config.php');
	global $l;
	
	$str = F_remove_tcecode($str);
	$str = F_compact_string($str);
	$str = htmlspecialchars($str, ENT_COMPAT, $l['a_meta_charset']);
	return $str;
}

/**
 * Return a substring of XHTML code while making sure no html tags are chopped. 
 * It also prevents chopping while a tag is still open.
 * this function is based on a public-domain script posted on www.php.net by fox@conskript.server and mr@bbp.biz
 * @param string $htmltext
 * @param int $min_length (default=100) the approximate length you want the concatenated text to be
 * @param int $offset_length (default=20) the max variation in how long the text can be
 */
function F_substrHTML($htmltext, $min_length=100, $offset_length=20) {
	// Reset tag counter and quote checker
	$tag_counter = 0;
	$quotes_on = FALSE;
	// Check if the text is too long
	if (strlen($htmltext) > $min_length) {
		// Reset the tag_counter and pass through (part of) the entire text
		$c = 0;
		for ($i = 0; $i < strlen($htmltext); $i++) {
			// Load the current character and the next one if the string has not arrived at the last character
			$current_char = substr($htmltext, $i, 1);
			if ($i < strlen($htmltext) - 1) {
				$next_char = substr($htmltext, $i + 1, 1);
			} else {
				$next_char = "";
			}
			// First check if quotes are on
			if (!$quotes_on) {
				// Check if it's a tag On a "<" add 3 if it's an opening tag (like <a href...) or add only 1 if it's an ending tag (like </a>)
				if ($current_char == '<') {
					if ($next_char == '/') {
						$tag_counter += 1;
					} else {
						$tag_counter += 3;
					}
				}
				// Slash signifies an ending (like </a> or ... />) substract 2
				if (($current_char == '/') AND ($tag_counter != 0)) {
					$tag_counter -= 2;
				}
				// On a ">" substract 1
				if ($current_char == '>') {
					$tag_counter -= 1;
				}
				// If quotes are encountered, start ignoring the tags (for directory slashes)
				if ($current_char == '"') {
					$quotes_on = true;
				}
			} else {
				// IF quotes are encountered again, turn it back off
				if ($current_char == '"') {
					$quotes_on = false;
				}
			}
			// Count only the chars outside html tags
			if(($tag_counter == 2) OR ($tag_counter == 0)){
				$c++;
			}
			// Check if the counter has reached the minimum length yet,
			// then wait for the tag_counter to become 0, and chop the string there
			if (($c > $min_length - $offset_length) AND ($tag_counter == 0) AND ($next_char == ' ')) {
				$htmltext = substr($htmltext,0,$i + 1);
				return $htmltext;
			}
		}
	}
	return $htmltext;
}

//============================================================+
// END OF FILE                                                 
//============================================================+
?>
