<?
########## Confixx(R) 3.0 Professional ############
####### Copyright SWsoft, Inc. 2004-2005 ##########
#### http://www.sw-soft.com - info@sw-soft.com ####

/*
  -------------------- Name conventions --------------------
  Function names (except methods):

  ff_DescriptionOfFunction


  Constant names:

  cc_DescriptionOfConstant


  Variable names:

  $ST_DescriptionOfVariable

  where S is a scope, T is a type.

  The following scopes should be used:
  g - global
  s - static
  l - local
  m - member of class
  p - parameter

  The following types should be used:
  s - scalar
  a - array
  r - resource
  o - object
  m - mixed

  -------------------- end Name conventions --------------------
*/





include_once (  dirname(__FILE__) . DIRECTORY_SEPARATOR . "template" . DIRECTORY_SEPARATOR . "csmarty.php" );
include_once (  dirname(__FILE__) . DIRECTORY_SEPARATOR . "class.ValuesSource.php" );
include_once ( dirname(__FILE__) . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "functions.inc.php" );
include_once ( dirname(__FILE__) . DIRECTORY_SEPARATOR . "class.PostValuesSource.php" );





class Pager extends CSmarty
{
    /* -------------------- Members -------------------- */
	var $ma_AddColumns; // array of columns for add form
	var $ms_AddIndex; // current column for add form

	var $ma_EditColumns; // array of columns for edit form
	var $ms_EditIndex; // current column for edit form

	var $ma_ErrorColumns; // array of columns for error form
	var $ms_ErrorIndex; // current column for error form

	var $mo_Source; // source of values
	var $ms_OpeningTag; // if 1 - this is for opening tag (rows loop)
	var $ms_ColumnOpening; // if 1 - this is for opening tag (columns loop)
	var $ms_OpeningPage; // if 1 - this is for opening tag (pages loop)
	var $ms_PerPageOpening; // if 1 - this is for opening tag (items per page loop)

	var $ma_SearchColumns; // array of columns for search form
	var $ms_SearchIndex; // current column for search form
	
	var $ma_BrowseColumns; // array of columns for search/browse form
	var $ms_BrowseIndex; // current column for search/browse form

	var $ms_CurrentID; // current ID

	var $ma_HiddenFields; // hidden fields, will be added to every form

	var $ms_CurrentPage; // current page number, starting from 0
	var $ms_LastPage; // last page, starting from 0
	
	var $ma_ItemsPerPage; // array of values for items per page
	var $ms_ItemsPerPage; // index in $ma_ItemsPerPage
	/* -------------------- end Members -------------------- */





	/* -------------------- Constructor -------------------- */
	function Pager ( &$po_Source )
	{
		$this->CSmarty();
		$this->Initialize ( $po_Source );
	}
    /* -------------------- end Constructor -------------------- */





    /* -------------------- Initialize -------------------- */
	function Initialize ( &$po_Source )
	{
		$po_Source->SetItemsPerPage ( get_class(&$this) );
		$po_Source->SetSort ( get_class(&$this) );
		$this->ma_ItemsPerPage = array( 5, 10, 20, 50, 100 );
		$this->mo_Source =& $po_Source;

		$this->register_block ( "list_show_add_table", array( &$this, "ShowAddTable" ) );
		$this->register_block ( "list_show_summary", array( &$this, "ShowSummary" ) );
		$this->register_block ( "list_show_add_form", array( &$this, "ShowAddForm" ) );
		$this->register_function ( "list_summary", array( &$this, "Summary" ) );
		$this->ma_ErrorColumns = $this->ma_AddColumns = $this->GetAddColumns ();
		if ( array_key_exists( "ListAdd", $_POST ) && $_POST["ListAdd"]=="Y" )
	    ValuesSource::UpdateFromQuery ( $this->ma_ErrorColumns );
		$this->ms_AddIndex = -1;
		$this->register_function ( "list_addcolumns", array( &$this, "AddColumns" ) );
		$this->register_block ( "list_add_columns_loop", array( &$this, "AddColumnsLoop" ) );
		$this->register_function ( "list_add_column_width", array( &$this, "AddColumnWidth" ) );
		$this->register_function ( "list_add_column_label", array( &$this, "AddColumnLabel" ) );
		$this->register_function ( "list_add_column", array( &$this, "AddColumn" ) );
		$this->setText ( "add", ltext("ll_add") );
		$this->setText ( "cancel", ltext("ll_cancel") );
		$this->setText ( "confirm", ltext("ll_confirm") );
		$this->setText ( "save", ltext("ll_save") );
		$this->assign ( "listURL", $this->GetListURL() );

		$this->ma_EditColumns = $this->GetEditColumns();

		if ( $this->IsEditPage() ) {
			if ( array_key_exists( "ListEdit", $_POST ) && $_POST["ListEdit"]=="Y" ){
				$lo_Source = $this->GetPostSource ( $this->ma_EditColumns );
				$lo_Source->Start( $la_Temporary = array() );
				$lo_Source->UpdateColumns ( $this->ma_EditColumns, $lo_Source->NextElement() );

			} else
				$po_Source->UpdateColumns ( $this->ma_EditColumns, $po_Source->GetElement() );
		}

		$this->ms_EditIndex = -1;
		$this->register_block ( "list_edit_columns_loop", array( &$this, "EditColumnsLoop" ) );
		$this->register_function ( "list_edit_column_label", array( &$this, "EditColumnLabel" ) );
		$this->register_function ( "list_edit_column", array( &$this, "EditColumn" ) );

		$this->ms_ErrorIndex = -1;
		$this->register_function ( "list_errorcolumns", array( &$this, "ErrorColumns" ) );
		$this->register_block ( "list_error_columns_loop", array( &$this, "ErrorColumnsLoop" ) );
		$this->register_function ( "list_error_column_width", array( &$this, "ErrorColumnWidth" ) );
		$this->register_function ( "list_error_column_label", array( &$this, "ErrorColumnLabel" ) );
		$this->register_function ( "list_error_column", array( &$this, "ErrorColumn" ) );

		$this->ma_SearchColumns = $this->GetSearchColumns ();
		ValuesSource::UpdateFromQuery ( $this->ma_SearchColumns );
		$this->ms_SearchIndex = -1;
		$this->register_function ( "list_searchcolumns", array( &$this, "SearchColumns" ) );
		$this->register_block ( "list_search_columns_loop", array( &$this, "SearchColumnsLoop" ) );
		$this->register_block ( "list_show_search_form", array( &$this, "ShowSearchForm" ) );
		$this->register_block ( "list_search_noresults", array( &$this, "NoSearchResults" ) );
		$this->register_function ( "list_search_column_width", array( &$this, "SearchColumnWidth" ) );
		$this->register_function ( "list_search_column_align", array( &$this, "SearchColumnAlign" ) );
		$this->register_function ( "list_search_column", array( &$this, "SearchColumn" ) );
		$this->setText ( "search", ltext("ll_search") );
		$this->setText ( "emptysearch", ltext("ll_empty_search") );

		$this->ma_BrowseColumns = $this->GetBrowseColumns ();
		$this->ms_BrowseIndex = -1;
		$this->register_block ( "list_show_browse_table", array( &$this, "ShowBrowseTable" ) );
		$this->register_block ( "list_no_browse_table", array( &$this, "NoBrowseTable" ) );
		$this->register_block ( "list_browse_columns_loop", array( &$this, "BrowseColumnsLoop" ) );
		$this->register_function ( "list_browse_column_width", array( &$this, "BrowseColumnWidth" ) );
		$this->register_function ( "list_browse_column_label", array( &$this, "BrowseColumnLabel" ) );
		$this->register_function ( "list_browse_column_label_nosort", array( &$this, "BrowseColumnLabelNoSort" ) );
		$this->register_function ( "list_browse_column_align", array( &$this, "BrowseColumnAlign" ) );
		$this->register_function ( "list_browse_column", array( &$this, "BrowseColumn" ) );
		$this->register_block ( "list_browse_rows_loop", array( &$this, "BrowseRowsLoop" ) );
		$this->register_function ( "list_item_id", array( &$this, "ItemID" ) );
		$this->setText ( "delquest", ltext("ll_delquest") );
		$this->ms_OpeningTag = 1;

		$this->register_block ( "list_previous_next_page", array( &$this, "PreviousOrNextPage" ) );
		$this->register_block ( "list_previous_page", array( &$this, "PreviousPage" ) );
		$this->register_block ( "list_next_page", array( &$this, "NextPage" ) );
		$this->register_block ( "list_pages_loop", array( &$this, "PagesLoop" ) );
		$this->register_block ( "list_perpage_loop", array( &$this, "PerPageLoop" ) );
		$this->register_function ( "list_start_dots", array( &$this, "StartDots" ) );
		$this->register_function ( "list_end_dots", array( &$this, "EndDots" ) );
		$this->register_function ( "list_perpage_url", array( &$this, "PerPageURL" ) );
		$this->register_function ( "list_page_url", array( &$this, "PageURL" ) );
		$this->register_function ( "list_browsecolumns", array( &$this, "BrowseColumns" ) );
		$this->register_function ( "list_previous_url", array( &$this, "PreviousURL" ) );
		$this->register_function ( "list_next_url", array( &$this, "NextURL" ) );
		$this->register_function ( "list_current_url", array( &$this, "CurrentURL" ) );
		$this->setText ( "next", ltext("ll_next") );
		$this->setText ( "prev", ltext("ll_prev") );
		
		$this->setText ( "delete", ltext("ll_delete") );
		$this->setText ( "apply", ltext("ll_apply") );
		$this->setText ( "perpage", ltext("ll_perpage") );
		
		$this->ma_HiddenFields = $this->GetHiddenFields();
		$this->register_function ( "list_hidden_fields", array( &$this, "HiddenFields" ) );

		$this->setText ( "pages", ltext("ll_pages") );
		$this->SetTotalText ();
	}
    /* -------------------- end Initialize -------------------- */





    /* -------------------- simple methods -------------------- */
	function ShouldShowAddTable()
	{
		return $this->ShouldShowSummary() || $this->ShouldShowAddForm();
	}

	function MaybeShow ( $ps_Content, &$po_Smarty, &$ps_Repeat, $ps_Function )
	{
		if ( is_null($ps_Content) )
			$ps_Repeat = $po_Smarty->$ps_Function();
		else
			echo ( $ps_Content );
	}

	function ColumnsLoop ( $ps_Content, &$po_Smarty, &$ps_Repeat, &$pa_Data, &$ps_Index )
	{
	// NOTE: nested loops will not work with this code
		if ( is_null($ps_Content) )
	    $this->ms_ColumnOpening = 1;
		if ( $this->ms_ColumnOpening )
	    $ps_Repeat = ++$ps_Index < count( $pa_Data );
		else {
	    echo ( $ps_Content );
	    if ( $ps_Index == count($pa_Data)-1 ) {
				$ps_Repeat = FALSE;
				$ps_Index = -1;
	    } else
				$ps_Repeat = TRUE;
		}
		$this->ms_ColumnOpening ^= 1;
	}

	function ColumnFunction ( &$pa_Data, $ps_Index, $ps_Function )
	{
		$lo_Column =& $pa_Data[$ps_Index];
		return $lo_Column->$ps_Function ();
	}

	function URLToPage ( $ps_PageNumber )
	{
		$ls_URL = $_SERVER["REQUEST_URI"];
		if ( ( $ls_Index = strpos( $ls_URL, "?" ) ) !== FALSE )
	    $ls_URL = substr( $ls_URL, 0, $ls_Index );
		if ( $this->mo_Source->IsSearch( $this->ma_SearchColumns ) ) {
	    $la_Query = array();
	    for ( $i=0; $i<count($this->ma_SearchColumns); $i++ )
				$la_Query[] = $this->ma_SearchColumns[$i]->GetURLQuery();
	    for ( $i=0; $i<count($this->ma_HiddenFields); $i++ )
				$la_Query[] = $this->ma_HiddenFields[$i]->GetURLQuery();
	    return $ls_URL."?page=".intval($ps_PageNumber)."&".implode( "&", $la_Query );
		}	else	{
	    $la_Query = array();
	    for ( $i=0; $i<count($this->ma_HiddenFields); $i++ )
				$la_Query[] = $this->ma_HiddenFields[$i]->GetURLQuery();
	    return $ls_URL."?page=".intval($ps_PageNumber). ( count($la_Query) ? "&".implode( "&", $la_Query ) : "" );
		}
	}

	function HiddenFields ()
	{
		$ls_Result = "";
		for ( $i=0; $i < count($this->ma_HiddenFields); $i++ )
	    $ls_Result .= $this->ma_HiddenFields[$i]->GetHTML();
		return $ls_Result;
	}

	function IsEditPage()
	{
		if ( ! strlen($this->GetEditURL()) )
	    return FALSE;
		$ls_URL = $_SERVER["REQUEST_URI"];
		if ( ( $ls_Index = strpos( $ls_URL, "?" ) ) !== FALSE )
	    $ls_URL = substr( $ls_URL, 0, $ls_Index );
		$ls_URL = basename ($ls_URL);
		return $ls_URL == $this->GetEditURL();
	}

	function GetPostSource ( $pa_Columns )
	{
		return new PostValuesSource ( $pa_Columns, array(), $this->mo_Source->GetIDName(), NULL,
																	$this->mo_Source->GetItemsPerPage() );
	}

	function SetTotalText()
	{
		$this->setText ( "total", ltext( "ll_total",
																		 array( $this->mo_Source->GetFirstItem(), $this->mo_Source->GetLastItem( $this->ma_SearchColumns ),
																						$this->mo_Source->TotalElements( $this->ma_SearchColumns ) ) ) );
	}
    /* -------------------- end simple methods -------------------- */





    /* -------------------- "abstract" methods -------------------- */
	function ShouldShowSummary()
	{
		echo ( "method ShouldShowSummary should return TRUE if summary should be shown" );
	}

	function ShouldShowAddForm()
	{
		echo ( "method ShouldShowAddForm should return TRUE if add form should be shown" );
	}

	function GetSummary()
	{
		echo ( "method GetSummary should return summary text" );
	}

	function GetAddColumns()
	{
		echo ( "method GetAddColumns should return array of columns for add table" );
	}

	function GetBrowseColumns()
	{
		echo ( "method GetBrowseColumns should return array of columns for search table" );
	}

	function GetSearchColumns()
	{
		echo ( "method GetSearchColumns should return array of columns for search table" );
	}

	function GetHiddenFields()
	{
		echo ( "method GetHiddenFields should return array of hidden fields" );
	}

	function GetEditColumns()
	{
		return array();
	}

	function GetListURL()
	{
		return "";
	}

	function GetEditURL()
	{
		return "";
	}
    /* -------------------- end "abstract" methods -------------------- */





    /* -------------------- elements manipulation -------------------- */
	function AddElement()
	{

		$this->mo_Source->LockAdd();
		$lm_Error = $this->mo_Source->ValidateAdd();
		if ( is_null($lm_Error) )	{
	    $lm_Error = $this->mo_Source->AddElement();
	    $this->mo_Source->UnLock();
	    $this->SetTotalText();
		}


		if ( is_array($lm_Error) ) {

	    $this->addMessage ( array_key_exists("type",$lm_Error)?$lm_Error["type"]:ERROR, $lm_Error["message"] );
			//	    $this->ShowAddError();
				//				    exit;

		}	elseif ( is_object($lm_Error) )	{
	    $lm_Error->AddErrors ( &$this );
			//	    $this->ShowAddError();
	    exit;
		}
	}

	function EditElements ( $ps_UseLock = TRUE )
	{

		if ( $ps_UseLock )
	    $this->mo_Source->LockEdit();
		$lm_Error = $this->mo_Source->ValidateEdit();

		if ( is_null($lm_Error) )	{
	    $lm_Error = $this->mo_Source->EditElements();
	    $this->mo_Source->UnLock();
		}

		if ( is_array($lm_Error) )	{
	    $this->addMessage ( array_key_exists("type",$lm_Error)?$lm_Error["type"]:ERROR, $lm_Error["message"] );
	    // todo: need better processing
			//	    $this->ShowEditError();


		}	elseif ( is_object($lm_Error) )	{
	    $lm_Error->AddErrors ( &$this );
	    // todo: need better processing
			//	    $this->ShowEditError();

		}	elseif ( $this->IsEditPage() ) {
	    global $HTTP_SERVER_VARS;
	    $ls_Directory = dirname($HTTP_SERVER_VARS['PHP_SELF']);
	    while ( substr( $ls_Directory, 0, 1 ) == "/" )
				$ls_Directory = substr ( $ls_Directory, 1 );
	    $ls_Directory = "/" . $ls_Directory;
	    if ( substr( $ls_Directory, -1 ) != "/" )
				$ls_Directory .= "/";
	    header ( "Location: http://" . $HTTP_SERVER_VARS['HTTP_HOST'] . $ls_Directory . $this->GetListURL() );
	    exit;
		}
	}

	function DeleteElements ( &$pa_IDs )
	{

		$this->mo_Source->LockDelete();
		$lm_Error = $this->mo_Source->DeleteElements ($pa_IDs);
		$this->mo_Source->UnLock();

		if ( is_array($lm_Error) )	{
	    $this->addMessage ( array_key_exists("type",$lm_Error)?$lm_Error["type"]:ERROR, $lm_Error["message"] );
	    // todo: need better processing
			//	    $this->ShowDeleteError();

		}	elseif ( is_object($lm_Error) )	{
	    $lm_Error->AddErrors ( &$this );
	    // todo: need better processing
			//	    $this->ShowDeleteError();
		}

		$this->SetTotalText();
	}
    /* -------------------- end elements manipulation -------------------- */





    /* -------------------- Add Table smarty functions -------------------- */
	function ShowAddTable ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->MaybeShow ( $ps_Content, $po_Smarty, $ps_Repeat, "ShouldShowAddTable" );
	}

	function ShowSummary ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->MaybeShow ( $ps_Content, $po_Smarty, $ps_Repeat, "ShouldShowSummary" );
	}
	
	function ShowAddForm ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->MaybeShow ( $ps_Content, $po_Smarty, $ps_Repeat, "ShouldShowAddForm" );
	}

	function Summary ( $pa_Parameters )
	{
		return $this->GetSummary();
	}
	
	function AddColumns ( $pa_Parameters )
	{
		return count( $this->ma_AddColumns ) + 1;
	}

	function AddColumnsLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->ColumnsLoop ( $ps_Content, $po_Smarty, $ps_Repeat, $this->ma_AddColumns, $this->ms_AddIndex );
	}

	function AddColumnWidth ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_AddColumns, $this->ms_AddIndex, "GetWidth" );
	}

	function AddColumnLabel ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_AddColumns, $this->ms_AddIndex, "GetLabel" );
	}

	function AddColumn ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_AddColumns, $this->ms_AddIndex, "GetHTML" );
	}
    /* -------------------- end Add Table smarty functions -------------------- */





    /* -------------------- Edit Table smarty functions -------------------- */
	function EditColumnsLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->ColumnsLoop ( $ps_Content, $po_Smarty, $ps_Repeat, $this->ma_EditColumns, $this->ms_EditIndex );
	}

	function EditColumnLabel ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_EditColumns, $this->ms_EditIndex, "GetLabel" );
	}

	function EditColumn ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_EditColumns, $this->ms_EditIndex, "GetHTML" );
	}
    /* -------------------- end Edit Table smarty functions -------------------- */





    /* -------------------- Error Table smarty functions -------------------- */
	function ErrorColumns ( $pa_Parameters )
	{
		return count( $this->ma_ErrorColumns ) + 1;
	}

	function ErrorColumnsLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->ColumnsLoop ( $ps_Content, $po_Smarty, $ps_Repeat, $this->ma_ErrorColumns, $this->ms_ErrorIndex );
	}

	function ErrorColumnWidth ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_ErrorColumns, $this->ms_ErrorIndex, "GetWidth" );
	}

	function ErrorColumnLabel ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_ErrorColumns, $this->ms_ErrorIndex, "GetLabel" );
	}

	function ErrorColumn ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_ErrorColumns, $this->ms_ErrorIndex, "GetHTML" );
	}
    /* -------------------- end Error Table smarty functions -------------------- */





    /* -------------------- Search Table smarty functions -------------------- */
	function ShowSearchForm ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->MaybeShow ( $ps_Content, $po_Smarty, $ps_Repeat, "ShouldShowSearchForm" );
	}

	function SearchColumnsLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->ColumnsLoop ( $ps_Content, $po_Smarty, $ps_Repeat, $this->ma_SearchColumns, $this->ms_SearchIndex );
	}

	function SearchColumns ( $pa_Parameters )
	{
		return count ($this->ma_SearchColumns);
	}
	
	function SearchColumnWidth ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_SearchColumns, $this->ms_SearchIndex, "GetWidth" );
	}
	
	function SearchColumnAlign ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_SearchColumns, $this->ms_SearchIndex, "GetAlign" );
	}

	function SearchColumn ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_SearchColumns, $this->ms_SearchIndex, "GetHTML" );
	}
	
	function ShouldShowSearchForm ()
	{
		return count ( $this->ma_SearchColumns ) > 0 && $this->mo_Source->TotalElements( array() ) != 0;
	}

	function NoSearchResults ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		if ( is_null($ps_Content) )
	    $ps_Repeat = $this->mo_Source->TotalElements ( $this->ma_SearchColumns ) == 0;
		else
	    echo ( $ps_Content );
	}
    /* -------------------- end Search Table smarty functions -------------------- */





    /* -------------------- Search/Browse Table smarty functions -------------------- */
	function ShowBrowseTable ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		if ( is_null($ps_Content) )
	    $ps_Repeat = $this->mo_Source->TotalElements ( $this->ma_SearchColumns ) != 0;
		else
	    echo ( $ps_Content );
	}

	function NoBrowseTable ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		if ( is_null($ps_Content) )
	    $ps_Repeat = $this->mo_Source->TotalElements ( array() ) == 0;
		else
	    echo ( $ps_Content );
	}

	function BrowseColumnsLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		$this->ColumnsLoop ( $ps_Content, $po_Smarty, $ps_Repeat, $this->ma_BrowseColumns, $this->ms_BrowseIndex );
	}

	function ItemID ( $pa_Parameters )
	{
		return $this->ms_CurrentID;
	}

	function BrowseColumnWidth ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_BrowseColumns, $this->ms_BrowseIndex, "GetWidth" );
	}

	function BrowseColumnLabel ( $pa_Parameters )
	{
		$ls_Result = "";
		$la_Column =& $this->ma_BrowseColumns[$this->ms_BrowseIndex];
		if ( $la_Column->GetSortable() ) {
	    if ( $this->mo_Source->GetSortColumn() == $la_Column->GetPureName() )
				$ls_Order = $this->mo_Source->GetSortReverse() ? "&SortReverse=N" : "&SortReverse=Y";
	    else
				$ls_Order = "&SortReverse=N";
	    $ls_Result .= "<a href=\"" . $this->URLToPage(0) . "&SortColumn=" . urlencode($la_Column->GetPureName()) .
		    "$ls_Order\" class=\"titel\">";
		}
		$ls_Result .= $this->ColumnFunction ( $this->ma_BrowseColumns, $this->ms_BrowseIndex, "GetLabel" );
		if ( $la_Column->GetSortable() ) {
	    $ls_Result .= "</a>";
	    global $strSkinName;
	    if ( $this->mo_Source->GetSortColumn() == $la_Column->GetPureName() )
				$ls_Result .= "&nbsp;&nbsp;&nbsp;<img src=\"" . ( $this->mo_Source->GetSortReverse() ?
																													"$strSkinName/pics/arrow_down.gif" : "$strSkinName/pics/arrow_up.gif" ) .
					"\" align=middle vspace=0 hspace=0>";
		}
		return $ls_Result;
	}

	function BrowseColumnLabelNoSort ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_BrowseColumns, $this->ms_BrowseIndex, "GetLabel" );
	}

	function BrowseColumnAlign ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_BrowseColumns, $this->ms_BrowseIndex, "GetAlign" );
	}

	function BrowseColumn ( $pa_Parameters )
	{
		return $this->ColumnFunction ( $this->ma_BrowseColumns, $this->ms_BrowseIndex, "GetHTML" );
	}

	function PageURL ( $pa_Parameters )
	{
		$ls_Result = "";
		$ls_Current = $this->mo_Source->GetPageNumber();
		if ( $this->ms_CurrentPage != $ls_Current )
	    $ls_Result .= "<a href=\"" . $this->URLToPage ( $this->ms_CurrentPage ) . "\" title=\"" .
		    ( $this->ms_CurrentPage+1 ) . "\">";
		$ls_Result .= $this->ms_CurrentPage+1;
		if ( $this->ms_CurrentPage != $ls_Current )
	    $ls_Result .= "</a>";
		return $ls_Result;
	}

	function PerPageLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
	// NOTE: nested loops will not work with this code
		if ( is_null($ps_Content) )	{
	    $this->ms_PerPageOpening = 1;
	    $this->ms_ItemsPerPage = 0;
		}
		if ( $this->ms_PerPageOpening )
	    $ps_Repeat = $this->ms_ItemsPerPage < count( $this->ma_ItemsPerPage );
		else	{
	    echo ( $ps_Content );
	    $ps_Repeat = $this->ms_ItemsPerPage++ < count( $this->ma_ItemsPerPage );
		}
		$this->ms_PerPageOpening ^= 1;
	}

	function PerPageURL ( $pa_Parameters )
	{
		$ls_Result = "";
		$ls_Current = $this->mo_Source->GetItemsPerPage();
		$ls_InLoop = $this->ma_ItemsPerPage[$this->ms_ItemsPerPage];
		if ( $ls_InLoop != $ls_Current )
	    $ls_Result .= "<a href=\"" . $this->URLToPage (0) . "&ItemsPerPage=$ls_InLoop\">";
		$ls_Result .= $ls_InLoop;
		if ( $ls_InLoop != $ls_Current )
	    $ls_Result .= "</a>";
		return $ls_Result;
	}

	function CalculatePages ( &$ps_Start, &$ps_End )
	{
		$ls_Last = $this->mo_Source->GetTotalPages ( $this->ma_SearchColumns ) - 1;
		$ls_Current = $this->mo_Source->GetPageNumber();
		if ( $ls_Last - $ls_Current < 2 )	{
	    $ps_End = $ls_Last;
	    $ps_Start = $ps_End-4 > 0 ? $ps_End-4 : 0;

		}	else {
	    $ps_Start = $ls_Current-2 < 0 ? 0 : $ls_Current-2;
	    $ps_End = $ps_Start+4 > $ls_Last ? $ls_Last : $ps_Start+4;
		}
		return $ls_Last;
	}

	function StartDots ( $pa_Parameters )
	{
		$this->CalculatePages ( $ls_Start, $ls_End );
		return $ls_Start==0 ? "" : "...";
	}

	function EndDots ( $pa_Parameters )
	{
		$ls_Last = $this->CalculatePages ( $ls_Start, $ls_End );
		return $ls_End < $ls_Last ? "..." : "";
	}

	function PagesLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
	// NOTE: nested loops will not work with this code
		if ( is_null($ps_Content) )	{
	    $this->ms_OpeningPage = 1;
	    $this->CalculatePages ( $this->ms_CurrentPage, $this->ms_LastPage );
		}
		if ( $this->ms_OpeningPage )
	    $ps_Repeat = $this->ms_CurrentPage <= $this->ms_LastPage;
		else {
	    echo ( $ps_Content );
	    $ps_Repeat = $this->ms_CurrentPage++ <= $this->ms_LastPage;
		}
		$this->ms_OpeningPage ^= 1;
	}

	function BrowseRowsLoop ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
	// NOTE: nested loops will not work with this code
		if ( is_null($ps_Content) || $this->ms_OpeningTag )	{
	    $lo_Source =& $this->mo_Source;
	    if ( ! $lo_Source->InIteration() )
				$lo_Source->Start ( $this->ma_SearchColumns );
	    $ps_Repeat = (bool) ( $la_Element = $lo_Source->NextElement() );
	    if ( $ps_Repeat ) {
				$lo_Source->UpdateColumns ( $this->ma_BrowseColumns, $la_Element );
				$this->ms_CurrentID = $la_Element[ $lo_Source->GetIDName() ];
	    }

		}	else	{
	    echo ( $ps_Content );
	    $ps_Repeat = (bool)$this->mo_Source->InIteration();
		}
		$this->ms_OpeningTag ^= 1;
	}

	function PreviousOrNextPage ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		if ( is_null($ps_Content) )
	    $ps_Repeat = $this->mo_Source->GetPageNumber() > 0 ||
		    $this->mo_Source->GetPageNumber() < $this->mo_Source->GetTotalPages ( $this->ma_SearchColumns ) - 1;
		else
	    echo ( $ps_Content );
	}

	function PreviousPage ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		if ( is_null($ps_Content) )
	    $ps_Repeat = $this->mo_Source->GetPageNumber() > 0;
		else
	    echo ( $ps_Content );
	}

	function NextPage ( $pa_Parameters, $ps_Content, &$po_Smarty, &$ps_Repeat )
	{
		if ( is_null($ps_Content) )
	    $ps_Repeat = $this->mo_Source->GetPageNumber() < $this->mo_Source->GetTotalPages( $this->ma_SearchColumns ) - 1;
		else
	    echo ( $ps_Content );
	}

	function BrowseColumns ( $pa_Parameters )
	{
		return count( $this->ma_BrowseColumns ) + 1;
	}

	function PreviousURL ( $pa_Parameters )
	{
		return $this->URLToPage ( $this->mo_Source->GetPageNumber()-1 );
	}

	function NextURL ( $pa_Parameters )
	{
		return $this->URLToPage ( $this->mo_Source->GetPageNumber()+1 );
	}

	function CurrentURL ( $pa_Parameters )
	{
		return $this->URLToPage ( $this->mo_Source->GetPageNumber() );
	}
    /* -------------------- end Search/Browse Table smarty functions -------------------- */





    /* -------------------- MaybePerformAction & related ------------------ */
	function MaybePerformAction ()
	{
		if ( $_SERVER["REQUEST_METHOD"] == "POST" )	{
	    if ( array_key_exists( "ListAdd", $_POST ) && $_POST["ListAdd"]=="Y" )
				$this->AddElement();
	    if ( array_key_exists( "ListEdit", $_POST ) && $_POST["ListEdit"]=="Y" ) {
				$this->EditElements();
				if ( array_key_exists( $this->DeleteFieldName(), $_POST ) && count($_POST[$this->DeleteFieldName()]) )
					$this->DeleteElements ( $_POST[$this->DeleteFieldName()] );
	    }
		}
	}

	function DeleteFieldName()
	{
		return "IDToDelete";
	}
    /* -------------------- end MaybePerformAction & related -------------------- */





    /* -------------------- error processing -------------------- */
	function ShowAddError()
	{
	// change this method in child class if you'd like
		echo "Pager.ShowAddError: start<br>\n";

		$this->show ( "list", "", "add_error" );
	}

	function ShowEditError()
	{
	// change this method in child class if you'd like
		echo "Pager.ShowEditError: start<br>\n";

		$this->show ( "list", "", "edit_error" );
	}

	function ShowDeleteError()
	{
	// change this method in child class if you'd like
		echo "Pager.ShowDeleteError: start<br>\n";

		$this->show ( "list", "", "delete_error" );
	}
    /* -------------------- end error processing -------------------- */

}
?>
