/*
** 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 Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
** 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.
**
** 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.cgiOutput = 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){
@