layerinfo "type" = "layout";
layerinfo "name" = "Quite Lickable";
layerinfo "author_name" = "Martin Atkins";
layerinfo "redist_uniq" = "lickable/layout";
layerinfo "previews" = "lickable/preview1.jpg,lickable/preview2.jpg";
layerinfo "des" = "A fixed-width layout with drop shadows, various header styles and the possibility for introducing your own background images.";

## Customization Props

propgroup colors {
    property Color clr_margins {
        des = "Page Background Color";
    }
    property Color clr_page_bg {
        des = "Main Content Background Color";
    }
    property Color clr_page_fg {
        des = "Main Content Foreground Color";
    }
    property Color clr_title_bg {
        des = "Title Background Color";
    }
    property Color clr_title_fg {
        des = "Title Text Color";
    }
    property Color clr_title_pattern {
        des = "Color of Title Background Effects";
        note = "The application of this color depends on your selection of heading style.";
    }
    property Color clr_title_separator {
        des = "Color of Line Under Title";
        note = "You must also enable the line in the Appearance section.";
    }
    property Color clr_side_borders {
        des = "Color of Side Borders";
        note = "You must also enable the borders in the Appearance section.";
    }
    property Color clr_link_normal {
        des = "Normal Link Color";
    }
    property Color clr_link_visited {
        des = "Visited Link Color";
    }

    set clr_page_fg = "#000000";
    set clr_margins = "#0183fd";
    set clr_link_visited = "#0063c0";
    set clr_link_normal = "#0183fd";
    set clr_title_pattern = "#faf49a";
    set clr_side_borders = "#000000";
    set clr_page_bg = "#e3f1ff";
    set clr_title_bg = "#0063c0";
    set clr_title_fg = "#ffffff";
    set clr_title_separator = "#000000";
}
propgroup colors = "Colors";

propgroup appearance {

    property int content_width {
        des = "Content area width in pixels";
    }
    set content_width = 750;

    property string content_bg_img {
        des = "Content area background image";
        note = "Since you've chosen how big the sidebar will be in pixels, you could use this to add a sidebar background.";
    }
    set content_bg_img = "";

    property int sidebar_width {
        des = "Sidebar width in pixels";
    }
    set sidebar_width = 230;

    property bool side_borders {
        des = "Show borders at the sides of the content area";
    }
    set side_borders = true;

    property string shadow_img_left {
        des = "Style of drop-shadow for the left of the page";
        values = "|None|shadow-l.png|Normal|shadow-l-small.png|Small";
    }
    set shadow_img_left = "shadow-l.png";

    property string shadow_img_right {
        des = "Style of drop-shadow for the right of the page";
        values = "|None|shadow-r.png|Normal|shadow-r-small.png|Small";
    }
    set shadow_img_right = "shadow-r.png";

    property string title_style {
        des = "Top heading style";
        note = "You can choose the colors to be used from the colors section.";
        values = "topglow|Top Glow|letters|Letters|explosion|Explosion|nature|Nature|camouflage|Camouflage|ramblings|Ramblings|clouds|Clouds|futuristic|Futuristic|bubbles|Circles|bubblewrap|Bubble Wrap|wires|Wires|urban|Urban|__custom|(Custom)||(None)";
    }
    set title_style = "wires";

    property string{}{} title_styles {
        des = "A bunch of top heading style settings";
        noui = 1;
    }
    set title_styles = {
        "topglow" => { "type" => "tilex", "url" => "lickable/topgrad.png" },
        "letters" => { "type" => "deardiary" },
        "explosion" => { "type" => "deardiary" },
        "nature" => { "type" => "deardiary" },
        "camouflage" => { "type" => "deardiary" },
        "ramblings" => { "type" => "deardiary" },
        "clouds" => { "type" => "deardiary" },
        "futuristic" => { "type" => "deardiary" },
        "bubbles" => { "type" => "deardiary" },
        "bubblewrap" => { "type" => "deardiary" },
        "wires" => { "type" => "deardiary" },
        "urban" => { "type" => "deardiary" },
    };

    property string title_style_custom_url {
        des = "Top heading custom background image";
        note = "If you selected 'Custom' as your heading style, you can enter a background image URL here.";
    }
    set title_style_custom_url = "";

    property int title_style_custom_height {
        des = "Top heading custom height";
        note = "If you selected 'Custom' as your heading style, you can enter here how tall you wish the heading to be, in pixels.";
    }
    set title_style_custom_height = 75;

    property bool title_notext {
        des = "Hide top heading text";
        note = "You might want to hide the system-supplied title text if you've used an image with its own text in it.";
    }
    set title_notext = false;

    property bool title_separator {
        des = "Show line under title bar";
    }
    set title_separator = true;
}
propgroup appearance = "Appearance";

propgroup fonts {

    property string{}{} font_sizes {
        des = "A bunch of font size settings";
        noui = 1;
    }
    set font_sizes = {
        "tiny" => {
            "body" => "10px",
            "pagetitle" => "25px",
            "pagesubtitle" => "14px",
            "dayhead" => "14px",
            "entryhead" => "12px",
        },
        "small" => {
            "body" => "12px",
            "pagetitle" => "25px",
            "pagesubtitle" => "14px",
            "dayhead" => "16px",
            "entryhead" => "14px",
        },
        "medium" => {
            "body" => "14px",
            "pagetitle" => "25px",
            "pagesubtitle" => "14px",
            "dayhead" => "18px",
            "entryhead" => "16px",
        },
        "large" => {
            "body" => "16px",
            "pagetitle" => "25px",
            "pagesubtitle" => "14px",
            "dayhead" => "20px",
            "entryhead" => "18px",
        },
        "huge" => {
            "body" => "18px",
            "pagetitle" => "25px",
            "pagesubtitle" => "14px",
            "dayhead" => "22px",
            "entryhead" => "20px",
        },
    };

    property string font_body {
        des = "Font Family For Normal Text";
        note = "Specify a list of acceptable fonts in order of preference, most preferred first.";
    }
    set font_body = "\"Tahoma\", \"Georgia\", \"Helvetica\", \"Arial\", sans-serif";

    property string font_sidebar {
        des = "Font Family For Sidebar";
        note = "Specify a list of acceptable fonts in order of preference, most preferred first.";
    }
    set font_sidebar = "\"Tahoma\", \"Georgia\", \"Helvetica\", \"Arial\", sans-serif";

    property string font_title {
        des = "Font Family For Title";
        note = "Specify a list of acceptable fonts in order of preference, most preferred first.";
    }
    set font_title = "\"Tahoma\", \"Georgia\", \"Helvetica\", \"Arial\", sans-serif";

    property string font_headings {
        des = "Font Family For Headings";
        note = "Specify a list of acceptable fonts in order of preference, most preferred first.";
    }
    set font_headings = "\"Tahoma\", \"Georgia\", \"Helvetica\", \"Arial\", sans-serif";

    property string font_size_keyword {
        des = "Text Size";
        values = "tiny|Tiny|small|Small|medium|Medium|large|Large|huge|Huge";
    }
    set font_size_keyword = "tiny";

}
propgroup fonts = "Fonts";

propgroup options {
    property bool opt_use_friendcolors {
        des = "Use friend colors on friends page";
        noui = 1; # The support for this isn't brilliant
    }
    set opt_use_friendcolors = false;

    property bool opt_hide_userpics {
        des = "Hide user picture icons on entries";
        note = "The pictures will still be shown on the Friends view";
    }
    set opt_hide_userpics = true;

    property use lang_fmt_date_short;
    property use lang_fmt_date_long;
    property use lang_fmt_time_short;

    property use page_recent_items;
    property use page_friends_items;

    property use use_shared_pic;
    property use view_entry_disabled;

    # This layout has quite a hefty stylesheet, so let's
    # make it external to avoid loading it over and over.
    set external_stylesheet = true;

    set tags_aware = true;
    set text_tags = "#";
}
propgroup options = "Options";

## I18n Props

propgroup text {
    property use text_view_recent;
    property use text_view_archive;
    property use text_view_friends;
    property use text_view_userinfo;

    property string i18n_paraphernalia_journalinfo {
        des = "Journal Info Heading";
        note = "If you leave this blank, your configured name will be used.";
    }
    property string i18n_paraphernalia_journalinfo_blurb {
        des = "Journal Info Blurb";
        note = "You can write whatever you want in here; it'll get displayed next to your userpic.";
        rows = 10;
        cols = 25;
    }
    property string i18n_paraphernalia_viewsel {
        des = "View Selection Heading";
        noui = 1;
    }
    property string i18n_paraphernalia_links {
        des = "Link List Heading";
        noui = 1;
    }
    property string i18n_paraphernalia_recent_navigation {
        des = "RecentPage Navigation Heading";
        noui = 1;
    }
    property string i18n_paraphernalia_year_navigation {
        des = "YearPage Navigation Heading";
        noui = 1;
    }
    property string i18n_paraphernalia_entry_navigation {
        des = "EntryPage Navigation Heading";
        noui = 1;
    }
    property string i18n_paraphernalia_day_navigation {
        des = "DayPage Navigation Heading";
        noui = 1;
    }
    set i18n_paraphernalia_journalinfo = "";
    set i18n_paraphernalia_journalinfo_blurb = "";
    set i18n_paraphernalia_viewsel = "View";
    set i18n_paraphernalia_links = "Links";
    set i18n_paraphernalia_recent_navigation = "Navigation";
    set i18n_paraphernalia_year_navigation = "Year";
    set i18n_paraphernalia_entry_navigation = "Entry";
    set i18n_paraphernalia_day_navigation = "Navigation";

    property string i18n_journalinfo_name {
        des = "Journal Name Caption";
        noui = 1;
    }
    property string i18n_journalinfo_website {
        des = "Journal Name Caption";
        noui = 1;
    }
    set i18n_journalinfo_name = "Name";
    set i18n_journalinfo_website = "Website";

    property use text_post_comment;
    property use text_read_comments;
    property use text_post_comment_friends;
    property use text_read_comments_friends;
    property use text_website_default_name;
}
propgroup text = "Text";

function prop_init() {
    # A vague attempt at sanity-checking the font properties. Not
    # foolproof, of course, but this is about as good as it gets in S2.
    if ($*font_body->contains(";")) { $*font_body = "serif"; }
    if ($*font_sidebar->contains(";")) { $*font_sidebar = "sans-serif"; }
    if ($*font_title->contains(";")) { $*font_title = "sans-serif"; }
    if ($*font_headings->contains(";")) { $*font_headings = "serif"; }
}

function heading_styles_deardiary() "Creates a deardiary-style heading" {
"""
#title {
    color: $*clr_title_fg;
    background-color: $*clr_title_bg;
    background-image: url("""+palimg_tint("deardiary/titleimages/${*title_style}.png", $*clr_title_bg, $*clr_title_pattern)+""");
    background-repeat: no-repeat;
    background-position: top right;
    height: 75px;
}
""";
}

function heading_styles_tile() "Creates a heading with a tinted image" {
    var string{} style = $*title_styles{$*title_style};
    var string type = $style{"type"};
    var string url = $style{"url"};
    if ($url == "") {
        $url = "lickable/${*title_style}.png";
    }

"""
#title {
    color: $*clr_title_fg;
    background-color: $*clr_title_bg;
    background-image: url("""+palimg_tint($url, $*clr_title_pattern, $*clr_title_bg)+""");
""";

    if ($type == "tilex") {
        println "background-repeat: repeat-x;";
    }
    elseif ($type == "tiley") {
        println "background-repeat: repeat-y;";
    }
    elseif ($type == "tile") {
        println "background-repeat: repeat;";
    }
    elseif ($type == "notile") {
        println "background-repeat: no-repeat;";
    }

"""
}
""";
}

function heading_styles_custom() "Creates a heading with a custom image and height" {
"""
#title {
    color: $*clr_title_fg;
    background-color: $*clr_title_bg;
""";
if ($*title_style_custom_url != "") {
    println "background-image: url($*title_style_custom_url);";
}
if ($*title_style_custom_height != 0) {
    println "height: ${*title_style_custom_height}px;";
}
"""
    background-position: top left;
}
""";
}

function heading_styles() "Styles for the top heading/title bar" {
    var string{} style = $*title_styles{$*title_style};

    if ($style{"type"} == "deardiary") {
        heading_styles_deardiary();
    }
    elseif ($style{"type"} == "tilex" or $style{"type"} == "tiley" or $style{"type"} == "tile" or  $style{"type"} == "notile") {
        heading_styles_tile();
    }
    elseif ($*title_style == "__custom") {
        heading_styles_custom();
    }
    else {
        $*title_style_custom_url = "";
        $*title_style_custom_height = 75;
        heading_styles_custom();
    }
}

function pretty_styles() "Pretty stuff that's completely dispensible" {

    var int top = ($*title_separator ? 79 : 75);
    var string{} size = $*font_sizes{$*font_size_keyword};

    var int cwid = $*content_width;
    var int sbwid = $*sidebar_width;
    var int mcwid = $*content_width - $*sidebar_width - 25;
    var int shadowwid = 32;
    var int shackwid = $cwid + ($shadowwid * 2);
    if ($*side_borders) {
        $shackwid = $shackwid + 2;
    }

    var Color darker_bg = $*clr_page_bg->darker(20);

"""

body {
    background: $*clr_margins url("""+palimg_tint("solid.png", $*clr_margins)+""");
    color: $*clr_page_fg;
    margin: 0;
    padding: 0;
    border: 0;
    font-family: $*font_body;
    width: 100%;
    height: 100%;
}
body, td, table, th, tr {
    font-size: $size{"body"};
}

#shadowhack1 {
    margin-left: auto;
    margin-right: auto;
    margin-top: 0;
    margin-bottom: 0;
    width: ${shackwid}px;
    background-image: url("""+palimg_tint("lickable/$*shadow_img_left", $*clr_margins)+""");
    background-position: top left;
    background-repeat: repeat-y;
    min-height: 150%;
}

#shadowhack2 {
    margin: 0;
    background-image: url("""+palimg_tint("lickable/$*shadow_img_right", $*clr_margins)+""");
    background-position: top right;
    background-repeat: repeat-y;
    min-height: 100%;
}

#pagecontainer {
    background-color: $*clr_page_bg;
""";
if ($*content_bg_img != "") {
    println "background-image: url($*content_bg_img);";
}
"""
    color: $*clr_page_fg;
    margin-left: ${shadowwid}px;
    margin-right: ${shadowwid}px;
""";
if ($*side_borders) {
"""
    border-left: 1px solid $*clr_side_borders;
    border-right: 1px solid $*clr_side_borders;
""";
}
"""
}

a:link {
    color: $*clr_link_normal;
}
a:visited {
    color: $*clr_link_visited;
}


#title {
    color: $*clr_title_fg;
    background-color: $*clr_title_bg;
""";
if ($*title_separator) {
"""
    border-bottom: 4px solid $*clr_title_separator;
""";
}
"""
    font-family: $*font_title;
    overflow: hidden;
}
#title h1 {
    font-size: $size{"pagetitle"};
    font-weight: bold;
    margin: 0;
    padding-top: 20px;
    padding-left: 8px;
    white-space: no-wrap;
}
#title #journal_subtitle {
    font-size: $size{"pagesubtitle"};
    font-weight: bold;
    margin: 0;
    padding-left: 8px;
    white-space: no-wrap;
    margin-bottom: 5px;
}
""";

heading_styles();

if ($*title_notext) {
"""
#title h1, #title #journal_subtitle {
    display: none;
}
""";
}


"""

#paraphernalia {
    float: right;
    width: ${sbwid}px;
    font-family: $*font_sidebar;
}
#paraphernalia h2 {
    font-size: $size{"dayhead"};
    font-weight: bold;
    text-align: left;
    margin-top: 16px;
    margin-bottom: 8px;
}
#paraphernalia .pbox {
    margin-left: 8px;
    margin-right: 8px;
    clear: both;
}
#journalinfouserpic {
""";

if ($*i18n_paraphernalia_journalinfo_blurb != "") {
"""
    float: left;
    margin-right: 6px;
    margin-bottom: 6px;
""";
}
else {
"""
    text-align: center;
""";
}

"""
}
.pboxcontent {
    margin-left: 8px;
    margin-right: 8px;
}
.pbox dt {
    font-weight: normal;
    margin-top: 4px;
}
.pbox dd {
    padding: 0;
    margin-left: 24px;
}
.pbox ul {
    margin: 0;
    padding: 0;
    list-style: none;
}
.pbox ul ul {
    margin-left: 24px;
}
.pbox li {
    margin: 0;
    padding: 0;
}
.pbox li.current {
    font-weight: bold;
}
.pbox p {
    margin: 8px 0;
}

#main {
    margin: 0;
    min-height: 1024px;
    padding: 0 10px 0 0;
    width: ${mcwid}px;
    float: left;
}
* html #main {
    height: 1024px; // IE-only hack
}

.day h2 {
    font-size: $size{"dayhead"};
    font-weight: bold;
    font-family: $*font_headings;
    margin: 10px;
}

.entry {
    margin: 16px 16px 16px 10px;
}
.entryheader {
    font-size: $size{"entryhead"};
}
.entryheader .entrytimestampdate {
    display: none;
}

.comments .entry {
    margin-left: 0;
    margin-bottom: 8px;
}
.comments .entry .entryheader {
    background: $darker_bg;
}

.calendarmonth {
    width: 60%;
    margin-right: auto;
    margin-left: auto;
    border-collapse: collapse;
    margin-bottom: 2em;
}
.calendarmonth td, .calendarmonth th {
    padding: 0.5em;
    margin: 0;
}
.calendarmonthlink {
    text-align: center;
}
.calendarmonthheader h2 {
    font-size: $size{"entryhead"};
    margin: 0;
}

.page_month #main form, .page_month #main dl {
    margin: 8px;
}

#server_sig {
    font-size: 0.75em;
    text-align: center;
    clear: both;
    width: ${mcwid}px;
}

div.ljtags { display: inline; }

input, textarea {
    font-family: $*font_body;
    font-size: $size{"body"};
}

""";
}

function necessary_styles() "Styles which are likely to be needed whatever stylesheet is in use" {
"""
.entry {
margin-bottom: 2em;
/*clear: both;*/
}

.entry .entryheader {
font-weight: bold;
text-align: left;
}

.entry .entryheader h3 {
font-size: 1em;
margin: 0;
padding: 0;
}

.entryheader .entryicon {
float: right;
margin-right: 1em;
}

.entryheader .entryuserpic {
float: right;
margin-top: 2em;
clear: right;
display: block;
padding: 3px;
""";
if ($*opt_hide_userpics) {
"""
display: none;
}
.page_friends .entryheader .entryuserpic {
display: block;
""";
}

"""
}

.entryheader .entryposter {
display: inline;
float:left;
margin-right: 1em;
}
.entryheader .entryposter:after {
content: ": ";
}
.entryposter img, .collapsed_entry img {
height: 12px;
width: 10px;
}

.entryheader .entrytimestamp {
display: inline;
}

.entrylinkbarpre, .entrylinkbarpost {
display: none;
}
.page_entry .entrylinkbarpre, .page_reply .entrylinkbarpre {
display: block;
float: right;
}

.entry .entrycontent {
margin: 8px;
}

.entrymeta {
list-style: none;
padding: 0;
margin: 0 0 0.5em 0;
display: block;
}
.entrymeta .entrymetacaption {
font-weight: bold;
}
.entrymeta li {
white-space: no-wrap;
}

.entry .entryfooter {
clear: both;
margin: 0;
}

.entryfooter .entrycmdlinks {
list-style: none;
vertical-align: middle;
margin: 0; padding: 0em;
white-space: no-wrap;
text-align: right;
}
.entryfooter .entrycmdlinks:before {
content: "(";
}
.entryfooter .entrycmdlinks:after {
content: ")";
}

.entrycmdlinks li {
display: inline;
}
* html .entrycmdlinks li {
margin-left: 1em;
}
.entrycmdlinks li:before {
content: " - ";
}
.entrycmdlinks li:first-child:before {
content: "";
}

.comments {
    list-style: none;
    padding: 0;
    margin-left: 50px;
}
.comments .comments {
    margin-left: 25px;
}
.comments > li {
    margin: 0;
    padding: 0;
}
.calendardaynum { text-align: right; }
.calendardaycount { text-align: center; }
.calendarday {
width: 14%;
}
.itemrange {
    list-style: none;
    padding: 0;
    margin: 0.5em;
    text-align: center;
}
.itemrange li {
    display: inline;
    margin: 0 0.25em;
}
.itemrange li a:before, .itemrange li.current:before {
    content: "[";
}
.itemrange li a:after, .itemrange li.current:after {
    content: "]";
}
""";
}
function custom_styles() "User layers can override this to add extra CSS to the stylesheet" {}

## Everything after this point should be common to all Cascadadelic layouts

function UserLite::lay_as_string() : string {
    var Image uiimg = userinfoicon($this);
    var string dir = $.journal_type == "C" ? "community" : "users";
    return "<span class='ljuser_$.username' style='white-space:nowrap;'><a href='$*SITEROOT/userinfo.bml?user=$.username'><img src='$uiimg.url' alt='[info]' width='$uiimg.width' height='$uiimg.height' style='vertical-align:bottom;border:0;' /></a><a href='$*SITEROOT/$dir/$.username/'><b>$.username</b></a></span>";
}

function print_stylesheet() {
    necessary_styles();
    pretty_styles();
    custom_styles();
}

function paraphernalia_box_open(string id, string title) "Open a paraphenalia box" {
    "<div class=\"pbox\"";
    if ($id != "") {
        " id=\"$id\"";
    }
    ">";
    if ($title != "") {
        """<h2>$title</h2>""";
    }
    """<div class="pboxcontent">\n""";
}
function paraphernalia_box_close(string id, string title) "Close a paraphenalia box" {
    """</div></div>\n""";
}

function Page::lay_print_heading() {
    print "<h1>$.global_title</h1>";
    if ($.view == "recent" and $.global_subtitle != "") {
        print """<div id="journal_subtitle">$.global_subtitle</div>""";
    }
    else {
        print """<div id="journal_subtitle">"""+$this->view_title()+"""</div>""";
    }
}
function Page::lay_print_journalinfo() {
    paraphernalia_box_open("journalinfo",
        ($*i18n_paraphernalia_journalinfo != "" ? $*i18n_paraphernalia_journalinfo : $.journal.name)
    );
    if (defined $.journal.default_pic) {
        println """<div id="journalinfouserpic">$.journal.default_pic</div>""";
    }
    if ($*i18n_paraphernalia_journalinfo_blurb != "") {
        println "<p>$*i18n_paraphernalia_journalinfo_blurb</p>";
    }
    paraphernalia_box_close("journalinfo",$*i18n_paraphernalia_journalinfo);
}
function Page::lay_print_viewsel() {
    paraphernalia_box_open("viewsel",$*i18n_paraphernalia_viewsel);
    "<ul>\n";
    foreach var string vl ($.views_order) {
        if ($vl == $.view) {
            print "<li class=\"current\">"+lang_viewname($vl)+"</li>\n";
        } else {
            print "<li><a href=\""+ehtml($.view_url{$vl})+"\">"+lang_viewname($vl)+"</a></li>\n";
        }
    }
    "</ul>\n";
    paraphernalia_box_close("viewsel",$*i18n_paraphernalia_viewsel);
}
function Page::lay_print_userlinks() {
    if (size $.linklist <= 0) {
        return;
    }
    paraphernalia_box_open("userlinks",$*i18n_paraphernalia_links);
    $this->print_linklist();
    paraphernalia_box_close("userlinks",$*i18n_paraphernalia_links);
}
function Page::lay_print_viewspec() {}
function Page::lay_print_viewspec_after() {}
function Page::lay_print_custom_paraphernalia() "User layers can override this to add extra paraphernalia" {}

function Page::lay_print_paraphernalia() "User layers can override this to change what appears in the paraphernalia section" {
    $this->lay_print_journalinfo();
    $this->lay_print_viewsel();
    $this->lay_print_viewspec();
    $this->lay_print_custom_paraphernalia();
    $this->lay_print_userlinks();
}

function lang_posting_in(UserLite poster, UserLite journal) : string "Return the string 'poster posting in journal'; I18n layers should override this." {
    return $poster->lay_as_string()+" posting in "+$journal->lay_as_string();
}

function EntryLite::lay_print_icon() {}
function EntryLite::lay_print_metadata() {}
function EntryLite::lay_print_cmdlinks() {}
function EntryLite::lay_print_poster() {
    if (defined $.poster) {
        print """<div class="entryposter">$.poster</div>""";
    }
    else {
        print """<div class="entryposter">$*text_poster_anonymous</div>""";
    }
}
function Entry::lay_print_poster() {
    var Page p = get_page();
    if ($p.view == "recent" and $.poster->equals($.journal)) {
        return;
    }
    if ($p.view == "friends") {
        print """<div class="entryposter">""";
        if (not $.poster->equals($.journal)) {
            print lang_posting_in($.poster, $.journal);
        }
        else {
            print $.poster->lay_as_string();
        }
        print """</div>""";
    }
    else {
        print """<div class="entryposter">"""+$.poster->lay_as_string()+"""</div>""";
    }
}

function Entry::lay_print_icon() {
    if ($.security != "") {
        """<div class="entryicon">""";
        print $.security_icon->as_string("[$.security]");
        "</div>";
    }
}
function Comment::lay_print_icon() {
    if (defined $.subject_icon) {
        """<div class="entryicon">""";
        print $.subject_icon->as_string("");
        "</div>";
    }
}

function Entry::lay_print_metadata() {
    if ($.metadata{"music"} == "" and $.metadata{"mood"} == "" and (size $.tags) < 1) {return;}
    println """<ul class="entrymeta">""";
    if ($.metadata{"mood"} != "") {
        print """<li><span class="entrymetacaption">$*text_meta_mood:</span> """;
        if (defined $.mood_icon) {
            print $.mood_icon->as_string() + " ";
        }
        println """$.metadata{"mood"}</li>""";
    }
    if ($.metadata{"music"} != "") {
        println """<li><span class="entrymetacaption">$*text_meta_music:</span> $.metadata{"music"}</li>""";
    }
    if ((size $.tags) > 0) {
        println """<li><span class="entrymetacaption">Tags:</span> """+$this->get_tags_text()+"""</li>""";
    }
    println """</ul>""";
}
function Comment::lay_print_metadata() {
    if ($.metadata{"poster_ip"} != "") {
        println """<ul class="entrymeta">""";
        println """<li><b>Poster IP Address:</b> $.metadata{"poster_ip"}</li>""";
        println """</ul>""";
    }
}

function Entry::lay_print_cmdlinks() {
    println """<ul class="entrycmdlinks">""";
    if ($.comments.enabled) {
        if ($.comments.count != 0) {
            println "<li>"; $.comments->print_readlink(); "</li>";
        }
        println "<li>"; $.comments->print_postlink(); "</li>";
    }
    println """</ul>""";
}

function Comment::lay_print_cmdlinks() {
    println """<ul class="entrycmdlinks">""";
    if ($.reply_url != "") {
        println """<li><a href="$.reply_url">$*text_comment_reply</a></li>""";
    }
    if ($.parent_url != "") {
        println """<li><a href="$.parent_url">$*text_comment_parent</a></li>""";
    }
    if ($.thread_url != "") {
        println """<li><a href="$.thread_url">$*text_comment_thread</a></li>""";
    }
    println """</ul>""";
}

function Page::lay_print_entrylite(EntryLite e) {
"""<div class="entry">
<div class="entryheader">
<h3 class="entrysubject">$e.subject</h3>""";
    $e->lay_print_poster();
"""<div class="entrytimestamp">
<span class="entrytimestampdate">"""+$e.time->date_format("short")+"""</span>
<span class="entrytimestamptime">"""+$e.time->time_format()+"""</span>
</div>""";

$e->lay_print_icon();
"""<div class="entrylinkbarpre">"""; $e->print_linkbar(); """</div>
""";
    if (defined $e.userpic) {
        """<div class="entryuserpic">$e.userpic</div>""";
    }
"""</div>

<div class="entrycontent">
$e.text
</div>

<div class="entryfooter">

"""; $e->lay_print_metadata(); """
<div class="entrylinkbarpost">"""; $e->print_linkbar(); """</div>
"""; $e->lay_print_cmdlinks(); """

</div>

</div>""";
}
function Page::print_entry(Entry e) {
    $this->lay_print_entrylite($e);
}
function EntryPage::print_comment(Comment c) {
    if ($c.full) {
        $this->lay_print_entrylite($c);
    }
    else {
        var string subject = ($c.subject ? $c.subject : "<i>(no subject)</i>");
        """<div class="collapsed_entry"><a href="$c.permalink_url">$subject</a> - $c.poster</div>""";
    }
}

function Page::lay_print_viewspec_head() {}
function FriendsPage::lay_print_viewspec_head() {
    if (not $*opt_use_friendcolors) { return; }
    println """<style type="text/css">""";
    foreach var string f ($.friends) {
        println ".ljuser_$f { background: $.friends{$f}.bgcolor none; color: $.friends{$f}.fgcolor; padding: 0 0.25em;}";
    }
    println """</style>""";
}

function Page::print() {
   """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<title>"""+$this->title()+"""</title>
""";
    if ($*external_stylesheet) {
        println """<link rel="stylesheet" href="$.stylesheet_url" type="text/css" />""";
    }
    else {
        println """<style type="text/css">""";
        print_stylesheet();
        println """</style>""";
    }
    $this->print_head();
    $this->lay_print_viewspec_head();
"""
</head>

<body class="page_$.view">

<div id="shadowhack1">
<div id="shadowhack2">

<div id="pagecontainer">

<div id="title">
"""; $this->lay_print_heading(); """
</div>

<div id="paraphernalia">
"""; $this->lay_print_paraphernalia(); """
</div>

<div id="main">
"""; $this->print_body(); """
</div>

"""; $this->lay_print_viewspec_after(); """

<div id="server_sig">"""; server_sig(); """</div>

</div>

</div>
</div>

</body>
</html>""";

}

## Some general page stuff

function Page::print_linklist() {
    if (size $.linklist <= 0) {
        return;
    }

    var bool section_open = false;

    println "<ul>";
    foreach var UserLink l ($.linklist) {
        if ($l.title) {
            if ($l.is_heading) {
                if ($section_open) {
                    println "</ul></li>";
                }
                println """<li><span style="font-weight: bold;">$l.title</span>\n<ul>""";
                $section_open = true;
            } else {
                println """<li><a href="$l.url">$l.title</a></li>""";
            }
        }
    }
    if ($section_open) {
        println "</ul></li>";
    }
    println "</ul>";
}


## RecentPage Stuff
function lang_skipped_back(RecentNav nav) : string
"Return short text saying how many entries have been skipped back. i18n layers should override this."
{
    return "Skipped Back $nav.skip";
}

function lang_adjacent_skip(RecentNav nav, bool next) : string
"Return either 'Previous N' or 'Next N' depending on the value of the 'next' parameter"
{
    if ($next) {
        return "Next $nav.forward_count";
    }
    else {
        return "Previous $nav.backward_count";
    }
}

function RecentPage::lay_print_viewspec() {
    if ($.nav.backward_url != "" or $.nav.forward_url != "") {
        paraphernalia_box_open("recentnav",$*i18n_paraphernalia_recent_navigation);
        if ($.nav.skip > 0) {
            println "<p>"+lang_skipped_back($.nav)+"</p>";
        }
        println """<ul>""";
        if ($.nav.backward_url) {
            println """<li><a href="$.nav.backward_url">"""+lang_adjacent_skip($.nav,false)+"""</a></li>""";
        }
        if ($.nav.forward_url) {
            println """<li><a href="$.nav.forward_url">"""+lang_adjacent_skip($.nav,true)+"""</a></li>""";
        }
        println "</ul>";
        paraphernalia_box_close("recentnav",$*i18n_paraphernalia_recent_navigation);
    }
}

function RecentPage::print_body() {
    foreach var Entry e ($.entries) {
        if ($e.new_day) {
            """<div class="day" id="day"""+$e.time->date_format("%%yyyy%%%%mm%%%%dd%%")+"\">\n";
            println "<h2>"+$e.time->date_format("long")+"</h2>";
        }
        # Print the entry
        $this->print_entry($e);
        if ($e.end_day) {
            "</div>";
        }
    }
}


## YearPage Stuff
function YearPage::lay_print_viewspec() {
    paraphernalia_box_open("yearnav",$*i18n_paraphernalia_year_navigation);
    $this->print_year_links();
    paraphernalia_box_close("yearnav",$*i18n_paraphernalia_year_navigation);
}
function YearPage::print_body {
    println """<div id="calendarmonthcontainer">""";
    foreach var YearMonth m ($.months) {
        $this->print_month($m);
    }
    println "</div>";
}
function YearPage::print_year_links() {
    """<ul class="viewspecnavbar">\n""";
    foreach var YearYear y ($.years) {
        if ($y.displayed) {
            """<li class="current">$y.year</li>\n""";
        } else {
            """<li><a href="$y.url">$y.year</a></li>\n""";
        }
    }
    """</ul>\n""";
}
function YearPage::print_month(YearMonth m) {
    if (not $m.has_entries) { return; }
    """<table class="calendarmonth">\n
       <tr><th colspan="7" class="calendarmonthheader">""";
    print "<h2>"+$m->month_format()+"</h2>\n";
    """</th></tr><tr>\n""";
    foreach var int d (weekdays()) {
        "<th>"+$*lang_dayname_short[$d]+"</th>\n";
    }
    "</tr>\n";
    foreach var YearWeek w ($m.weeks) {
        $w->print();
    }
    """<tr><td colspan="7" class="calendarmonthlink">
        <a href="$m.url">$*text_view_month</a></td></tr>\n""";
    "</table>";
}
function YearWeek::print() {
   """<tr valign="top" style="height: 3em;">\n""";
   if ($.pre_empty > 0) {
      """<td class="emptyday" colspan="$.pre_empty">&nbsp;</td>\n""";
   }
   foreach var YearDay d ($.days) {
       """<td class="calendarday">\n""";
       """<div class="calendardaynum">$d.day</div>\n""";
       if ($d.num_entries > 0) {
           """<div class="calendardaycount"><a href="$d.url">$d.num_entries</a></div>\n""";
       }
       """</td>\n""";
   }
   if ($.post_empty > 0) {
      """<td colspan="$.post_empty">&nbsp;</td>\n""";
   }
   "</tr>";
}

# EntryPage and ReplyPage stuff
function EntryPage::lay_print_pager() {
    if ($.comment_pages.all_subitems_displayed) { return; }
    print "<ul class=\"itemrange\">";
    foreach var int i (1 .. $.comment_pages.total) {
        if ($i == $.comment_pages.current) {
            print "<li class=\"current\">$i</li>";
        }
        else {
            print "<li><a href=\""+$.comment_pages->url_of($i)+"\">$i</a></li>";
        }
    }
    print "</ul>";
}
function EntryPage::print_body() {
    $this->lay_print_entrylite($.entry);
    $this->lay_print_pager();
    $this->print_comments($.comments);
    $this->lay_print_pager();
}
function ReplyPage::print_body() {
    $this->lay_print_entrylite($.replyto);
    """<div id="commentform">""";
    $.form->print();
    """</div>""";
}

function EntryPage::print_comments (Comment[] cs) {
    if (size $cs == 0) { return; }
    """<ul class="comments">\n""";
    foreach var Comment c ($cs) {
        var int indent = ($c.depth - 1) * 25;
        print "<li>";
        $this->print_comment($c);
        $this->print_comments($c.replies);
        println "</li>";
    }
    """</ul>""";
}

# DayPage stuff

function DayPage::lay_print_viewspec() {
    paraphernalia_box_open("daynav",$*i18n_paraphernalia_day_navigation);
    println """<ul>""";
    if ($.prev_url) {
        println """<li><a href="$.prev_url">"""+$.prev_date->date_format()+"""</a></li>""";
    }
    if ($.next_url) {
        println """<li><a href="$.next_url">"""+$.next_date->date_format()+"""</a></li>""";
    }
    println "</ul>";
    paraphernalia_box_close("daynav",$*i18n_paraphernalia_day_navigation);
}
function DayPage::print_body() {
    "<div class=\"day\" id=\""+$.date->date_format("%%yyyy%%%%mm%%%%dd%%")+"\">\n<h2>";
    print $.date->date_format("long");
    "</h2>\n";
    if ($.has_entries) {

        foreach var Entry e ($.entries) {
            $this->print_entry($e);
        }

        "</div>";
    } else {
        """<div class="entry"><div class="entryheader">&nbsp;</div>\n""";
        """<div class="entrycontent"><p>$*text_noentries_day</p></div>\n""";
        """<div class="entryfooter">&nbsp;</div></div>\n""";
    }

}

function print_theme_preview() {
}