/*
** Copyright (c) 2006,2007 D. Richard Hipp
**
** 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.
**
** 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.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code to implement the basic web page look and feel.
**
*/
#include "config.h"
#include "style.h"
/*
** Elements of the submenu are collected into the following
** structure and displayed below the main menu by style_header().
**
** Populate this structure with calls to style_submenu_element()
** prior to calling style_header().
*/
static struct Submenu {
const char *zLabel;
const char *zTitle;
const char *zLink;
} aSubmenu[30];
static int nSubmenu = 0;
/*
** Remember that the header has been generated. The footer is omitted
** if an error occurs before the header.
*/
static int headerHasBeenGenerated = 0;
/*
** Add a new element to the submenu
*/
void style_submenu_element(
const char *zLabel,
const char *zTitle,
const char *zLink,
...
){
va_list ap;
assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) );
aSubmenu[nSubmenu].zLabel = zLabel;
aSubmenu[nSubmenu].zTitle = zTitle;
va_start(ap, zLink);
aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap);
va_end(ap);
nSubmenu++;
}
/*
** Compare two submenu items for sorting purposes
*/
static int submenuCompare(const void *a, const void *b){
const struct Submenu *A = (const struct Submenu*)a;
const struct Submenu *B = (const struct Submenu*)b;
return strcmp(A->zLabel, B->zLabel);
}
/*
** Draw the header.
*/
void style_header(const char *zTitleFormat, ...){
va_list ap;
char *zTitle;
const char *zHeader = db_get("header", (char*)zDefaultHeader);
login_check_credentials();
va_start(ap, zTitleFormat);
zTitle = vmprintf(zTitleFormat, ap);
va_end(ap);
cgi_destination(CGI_HEADER);
cgi_printf("%s",
"");
if( g.thTrace ) Th_Trace("BEGIN_HEADER \n", -1);
/* Generate the header up through the main menu */
Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
Th_Store("title", zTitle);
Th_Store("baseurl", g.zBaseURL);
Th_Store("index_page", db_get("index-page","/home"));
Th_Store("current_page", g.zPath);
Th_Store("manifest_version", MANIFEST_VERSION);
Th_Store("manifest_date", MANIFEST_DATE);
if( g.zLogin ){
Th_Store("login", g.zLogin);
}
if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT \n", -1);
Th_Render(zHeader);
if( g.thTrace ) Th_Trace("END_HEADER \n", -1);
Th_Unstore("title"); /* Avoid collisions with ticket field names */
cgi_destination(CGI_BODY);
g.cgiPanic = 1;
headerHasBeenGenerated = 1;
}
/*
** Draw the footer at the bottom of the page.
*/
void style_footer(void){
const char *zFooter;
if( !headerHasBeenGenerated ) return;
/* Go back and put the submenu at the top of the page. We delay the
** creation of the submenu until the end so that we can add elements
** to the submenu while generating page text.
*/
cgi_destination(CGI_HEADER);
if( nSubmenu>0 ){
int i;
@
cgi_destination(CGI_BODY);
/* Put the footer at the bottom of the page.
*/
@
zFooter = db_get("footer", (char*)zDefaultFooter);
if( g.thTrace ) Th_Trace("BEGIN_FOOTER \n", -1);
Th_Render(zFooter);
if( g.thTrace ) Th_Trace("END_FOOTER \n", -1);
/* Render trace log if TH1 tracing is enabled. */
if( g.thTrace ){
cgi_append_content("\n", -1);
cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
cgi_append_content("\n", -1);
}
}
/*
** Begin a side-box on the right-hand side of a page. The title and
** the width of the box are given as arguments. The width is usually
** a percentage of total screen width.
*/
void style_sidebox_begin(const char *zTitle, const char *zWidth){
@
@
@ %h(zTitle)
}
/* End the side-box
*/
void style_sidebox_end(void){
@