Fossil with Commonmark

Check-in [befd44c747]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge latest trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | svn-import
Files: files | file ages | folders
SHA1:befd44c747405c1abb9264a14fe796cc648ffb40
User & Date: baruch 2015-01-25 09:54:04
Context
2015-01-28
11:07
Deleting a branch closes it check-in: 86ab1f468b user: baruch tags: svn-import
2015-01-25
09:54
Merge latest trunk check-in: befd44c747 user: baruch tags: svn-import
2015-01-24
22:13
Enhance the "fossil sync" command to retry all of the returned values from getaddrinfo() until it finds one that actually works. That way, it will find the IPv4 version on machines that do not have an IPv6 gateway. check-in: ae3ef4d3d9 user: drh tags: trunk
2015-01-18
21:12
Merge trunk check-in: 0746fbe416 user: baruch tags: svn-import
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added .dockerignore.

            1  +_FOSSIL_
            2  +.fslckout
            3  +ajax
            4  +art
            5  +autosetup
            6  +bld
            7  +compat
            8  +debian
            9  +fossil
           10  +fossil.exe
           11  +setup
           12  +src
           13  +test
           14  +tools
           15  +win
           16  +wbld
           17  +win
           18  +www
           19  +*.a
           20  +*.lib
           21  +*.log
           22  +*.manifest
           23  +*.o
           24  +*.obj
           25  +*.pdb
           26  +*.res

Changes to Dockerfile.

     1      1   ###
     2      2   #   Dockerfile for Fossil
     3      3   ###
     4      4   FROM fedora:21
     5      5   
     6      6   ### Now install some additional parts we will need for the build
     7         -RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl-devel tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
            7  +RUN yum update -y && yum install -y gcc make zlib-devel openssl-devel tcl tar && yum clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil
     8      8   
     9         -### If you want to build "trunk", change the next line accordingly.
    10         -ENV FOSSIL_INSTALL_VERSION release
            9  +### If you want to build "release", change the next line accordingly.
           10  +ENV FOSSIL_INSTALL_VERSION trunk
    11     11   
    12     12   RUN curl "http://www.fossil-scm.org/index.html/tarball/fossil-src.tar.gz?name=fossil-src&uuid=${FOSSIL_INSTALL_VERSION}" | tar zx
    13     13   RUN cd fossil-src && ./configure --disable-lineedit --disable-fusefs --json --with-th1-docs --with-th1-hooks --with-tcl --with-tcl-stubs --with-tcl-private-stubs && make;
    14     14   RUN cp fossil-src/fossil /usr/bin && rm -rf fossil-src && chmod a+rx /usr/bin/fossil && mkdir -p /opt/fossil && chown fossil:fossil /opt/fossil
    15     15   
    16     16   ### Build is done, remove modules no longer needed
    17         -RUN yum remove -y gcc make zlib-devel openssl-devel tcl-devel tar && yum clean all
           17  +RUN yum remove -y gcc make zlib-devel openssl-devel tar && yum clean all
    18     18   
    19     19   USER fossil
    20     20   
    21     21   ENV HOME /opt/fossil
    22     22   
    23     23   RUN fossil new --docker -A admin /opt/fossil/repository.fossil && fossil user password -R /opt/fossil/repository.fossil admin admin && fossil cache init -R /opt/fossil/repository.fossil
    24     24   
    25     25   EXPOSE 8080
    26     26   
    27     27   CMD ["/usr/bin/fossil", "server", "/opt/fossil/repository.fossil"]

Added skins/README.md.

            1  +Built-in Skins
            2  +==============
            3  +
            4  +Each subdirectory under this folder describes a built-in "skin".
            5  +There are three files in each subdirectory for the CSS, the header,
            6  +and the footer for the skin.
            7  +
            8  +To improve an existing built-in skin, simply edit the appropriate
            9  +files and recompile.
           10  +
           11  +To add a new skin:
           12  +
           13  +   1.   Create a new subdirectory under skins/.  (The new directory is
           14  +        called "skins/newskin" below but you should use a new original
           15  +        name, of course.)
           16  +
           17  +   2.   Add files skins/newskin/css.txt, skins/newskin/header.txt,
           18  +        and skins/newskin/footer.txt.  Be sure to "fossil add" these files.
           19  +
           20  +   3.   Go to the src/ directory and rerun "tclsh makemake.tcl".  This
           21  +        step rebuilds the various makefiles so that they have dependencies
           22  +        on the skin files you just installed.
           23  +
           24  +   4.   Edit the BuiltinSkin[] array near the top of the src/skins.c source
           25  +        file so that it describes and references the "newskin" skin.
           26  +
           27  +   5.   Type "make" to rebuild.

Added skins/black_and_white/css.txt.

            1  +/* General settings for the entire page */
            2  +body {
            3  +    margin:0px 0px 0px 0px;
            4  +    padding:0px;
            5  +    font-family:verdana, arial, helvetica, "sans serif";
            6  +    color:#333;
            7  +    background-color:white;
            8  +}
            9  +
           10  +/* consistent colours */
           11  +h2 {
           12  +  color: #333;
           13  +}
           14  +h3 {
           15  +  color: #333;
           16  +}
           17  +
           18  +/* The project logo in the upper left-hand corner of each page */
           19  +div.logo {
           20  +  display: table-cell;
           21  +  text-align: left;
           22  +  vertical-align: bottom;
           23  +  font-weight: bold;
           24  +  color: #333;
           25  +  white-space: nowrap;
           26  +}
           27  +
           28  +/* The page title centered at the top of each page */
           29  +div.title {
           30  +  display: table-cell;
           31  +  font-size: 2em;
           32  +  font-weight: bold;
           33  +  text-align: center;
           34  +  color: #333;
           35  +  vertical-align: bottom;
           36  +  width: 100%;
           37  +}
           38  +
           39  +/* The login status message in the top right-hand corner */
           40  +div.status {
           41  +  display: table-cell;
           42  +  padding-right: 10px;
           43  +  text-align: right;
           44  +  vertical-align: bottom;
           45  +  padding-bottom: 5px;
           46  +  color: #333;
           47  +  font-size: 0.8em;
           48  +  font-weight: bold;
           49  +  white-space: nowrap;
           50  +}
           51  +
           52  +/* The header across the top of the page */
           53  +div.header {
           54  +    margin:10px 0px 10px 0px;
           55  +    padding:1px 0px 0px 20px;
           56  +    border-style:solid;
           57  +    border-color:black;
           58  +    border-width:1px 0px;
           59  +    background-color:#eee;
           60  +}
           61  +
           62  +/* The main menu bar that appears at the top left of the page beneath
           63  +** the header. Width must be co-ordinated with the container below */
           64  +div.mainmenu {
           65  +  float: left;
           66  +  margin-left: 10px;
           67  +  margin-right: 10px;
           68  +  font-size: 0.9em;
           69  +  font-weight: bold;
           70  +  padding:5px;
           71  +  background-color:#eee;
           72  +  border:1px solid #999;
           73  +  width:8em;
           74  +}
           75  +
           76  +/* Main menu is now a list */
           77  +div.mainmenu ul {
           78  +  padding: 0;
           79  +  list-style:none;
           80  +}
           81  +div.mainmenu a, div.mainmenu a:visited{
           82  +  padding: 1px 10px 1px 10px;
           83  +  color: #333;
           84  +  text-decoration: none;
           85  +}
           86  +div.mainmenu a:hover {
           87  +  color: #eee;
           88  +  background-color: #333;
           89  +}
           90  +
           91  +/* Container for the sub-menu and content so they don't spread
           92  +** out underneath the main menu */
           93  +#container {
           94  +  padding-left: 9em;
           95  +}
           96  +
           97  +/* The submenu bar that *sometimes* appears below the main menu */
           98  +div.submenu, div.sectionmenu {
           99  +  padding: 3px 10px 3px 10px;
          100  +  font-size: 0.9em;
          101  +  text-align: center;
          102  +  border:1px solid #999;
          103  +  border-width:1px 0px;
          104  +  background-color: #eee;
          105  +  color: #333;
          106  +}
          107  +div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link,
          108  +div.sectionmenu>a.button:visited {
          109  +  padding: 3px 10px 3px 10px;
          110  +  color: #333;
          111  +  text-decoration: none;
          112  +}
          113  +div.submenu a:hover, div.sectionmenu>a.button:hover {
          114  +  color: #eee;
          115  +  background-color: #333;
          116  +}
          117  +
          118  +/* All page content from the bottom of the menu or submenu down to
          119  +** the footer */
          120  +div.content {
          121  +  padding: 2ex 1ex 0ex 2ex;
          122  +}
          123  +
          124  +/* Some pages have section dividers */
          125  +div.section {
          126  +  margin-bottom: 0px;
          127  +  margin-top: 1em;
          128  +  padding: 1px 1px 1px 1px;
          129  +  font-size: 1.2em;
          130  +  font-weight: bold;
          131  +  border-style:solid;
          132  +  border-color:#999;
          133  +  border-width:1px 0px;
          134  +  background-color: #eee;
          135  +  color: #333;
          136  +  white-space: nowrap;
          137  +}
          138  +
          139  +/* The "Date" that occurs on the left hand side of timelines */
          140  +div.divider {
          141  +  background: #eee;
          142  +  border: 2px #999 solid;
          143  +  font-size: 1em; font-weight: normal;
          144  +  padding: .25em;
          145  +  margin: .2em 0 .2em 0;
          146  +  float: left;
          147  +  clear: left;
          148  +  color: #333;
          149  +  white-space: nowrap;
          150  +}
          151  +
          152  +/* The footer at the very bottom of the page */
          153  +div.footer {
          154  +  font-size: 0.8em;
          155  +  margin-top: 12px;
          156  +  padding: 5px 10px 5px 10px;
          157  +  text-align: right;
          158  +  background-color: #eee;
          159  +  color: #555;
          160  +}
          161  +
          162  +/* <verbatim> blocks */
          163  +pre.verbatim {
          164  +  background-color: #f5f5f5;
          165  +  padding: 0.5em;
          166  +  white-space: pre-wrap;
          167  +}
          168  +
          169  +/* The label/value pairs on (for example) the ci page */
          170  +table.label-value th {
          171  +  vertical-align: top;
          172  +  text-align: right;
          173  +  padding: 0.2ex 2ex;
          174  +}

Added skins/black_and_white/footer.txt.

            1  +<div class="footer">
            2  +Fossil version $manifest_version $manifest_date
            3  +</div>
            4  +</body></html>

Added skins/black_and_white/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss">
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen">
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="logo">
           13  +    <img src="$logo_image_url" alt="logo">
           14  +    <br />$<project_name>
           15  +  </div>
           16  +  <div class="title">$<title></div>
           17  +  <div class="status"><th1>
           18  +     if {[info exists login]} {
           19  +       puts "Logged in as $login"
           20  +     } else {
           21  +       puts "Not logged in"
           22  +     }
           23  +  </th1></div>
           24  +</div>
           25  +<div class="mainmenu">
           26  +<th1>
           27  +html "<a href='$home$index_page'>Home</a>\n"
           28  +if {[anycap jor]} {
           29  +  html "<a href='$home/timeline'>Timeline</a>\n"
           30  +}
           31  +if {[hascap oh]} {
           32  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
           33  +}
           34  +if {[hascap o]} {
           35  +  html "<a href='$home/brlist'>Branches</a>\n"
           36  +  html "<a href='$home/taglist'>Tags</a>\n"
           37  +}
           38  +if {[hascap r]} {
           39  +  html "<a href='$home/reportlist'>Tickets</a>\n"
           40  +}
           41  +if {[hascap j]} {
           42  +  html "<a href='$home/wiki'>Wiki</a>\n"
           43  +}
           44  +if {[hascap s]} {
           45  +  html "<a href='$home/setup'>Admin</a>\n"
           46  +} elseif {[hascap a]} {
           47  +  html "<a href='$home/setup_ulist'>Users</a>\n"
           48  +}
           49  +if {[info exists login]} {
           50  +  html "<a href='$home/login'>Logout</a>\n"
           51  +} else {
           52  +  html "<a href='$home/login'>Login</a>\n"
           53  +}
           54  +</th1></ul></div>

Added skins/default/css.txt.

            1  +/* General settings for the entire page */
            2  +body {
            3  +  margin: 0ex 1ex;
            4  +  padding: 0px;
            5  +  background-color: white;
            6  +  font-family: sans-serif;
            7  +}
            8  +
            9  +/* The project logo in the upper left-hand corner of each page */
           10  +div.logo {
           11  +  display: table-cell;
           12  +  text-align: center;
           13  +  vertical-align: bottom;
           14  +  font-weight: bold;
           15  +  color: #558195;
           16  +  min-width: 200px;
           17  +  white-space: nowrap;
           18  +}
           19  +
           20  +/* The page title centered at the top of each page */
           21  +div.title {
           22  +  display: table-cell;
           23  +  font-size: 2em;
           24  +  font-weight: bold;
           25  +  text-align: center;
           26  +  padding: 0 0 0 1em;
           27  +  color: #558195;
           28  +  vertical-align: bottom;
           29  +  width: 100%;
           30  +}
           31  +
           32  +/* The login status message in the top right-hand corner */
           33  +div.status {
           34  +  display: table-cell;
           35  +  text-align: right;
           36  +  vertical-align: bottom;
           37  +  color: #558195;
           38  +  font-size: 0.8em;
           39  +  font-weight: bold;
           40  +  min-width: 200px;
           41  +  white-space: nowrap;
           42  +}
           43  +
           44  +/* The header across the top of the page */
           45  +div.header {
           46  +  display: table;
           47  +  width: 100%;
           48  +}
           49  +
           50  +/* The main menu bar that appears at the top of the page beneath
           51  +** the header */
           52  +div.mainmenu {
           53  +  padding: 5px 10px 5px 10px;
           54  +  font-size: 0.9em;
           55  +  font-weight: bold;
           56  +  text-align: center;
           57  +  letter-spacing: 1px;
           58  +  background-color: #558195;
           59  +  border-top-left-radius: 8px;
           60  +  border-top-right-radius: 8px;
           61  +  color: white;
           62  +}
           63  +
           64  +/* The submenu bar that *sometimes* appears below the main menu */
           65  +div.submenu, div.sectionmenu {
           66  +  padding: 3px 10px 3px 0px;
           67  +  font-size: 0.9em;
           68  +  text-align: center;
           69  +  background-color: #456878;
           70  +  color: white;
           71  +}
           72  +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
           73  +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
           74  +  padding: 3px 10px 3px 10px;
           75  +  color: white;
           76  +  text-decoration: none;
           77  +}
           78  +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
           79  +  color: #558195;
           80  +  background-color: white;
           81  +}
           82  +
           83  +/* All page content from the bottom of the menu or submenu down to
           84  +** the footer */
           85  +div.content {
           86  +  padding: 0ex 1ex 1ex 1ex;
           87  +  border: solid #aaa;
           88  +  border-width: 1px;
           89  +}
           90  +
           91  +/* Some pages have section dividers */
           92  +div.section {
           93  +  margin-bottom: 0px;
           94  +  margin-top: 1em;
           95  +  padding: 1px 1px 1px 1px;
           96  +  font-size: 1.2em;
           97  +  font-weight: bold;
           98  +  background-color: #558195;
           99  +  color: white;
          100  +  white-space: nowrap;
          101  +}
          102  +
          103  +/* The "Date" that occurs on the left hand side of timelines */
          104  +div.divider {
          105  +  background: #a1c4d4;
          106  +  border: 2px #558195 solid;
          107  +  font-size: 1em; font-weight: normal;
          108  +  padding: .25em;
          109  +  margin: .2em 0 .2em 0;
          110  +  float: left;
          111  +  clear: left;
          112  +  white-space: nowrap;
          113  +}
          114  +
          115  +/* The footer at the very bottom of the page */
          116  +div.footer {
          117  +  clear: both;
          118  +  font-size: 0.8em;
          119  +  padding: 5px 10px 5px 10px;
          120  +  text-align: right;
          121  +  background-color: #558195;
          122  +  border-bottom-left-radius: 8px;
          123  +  border-bottom-right-radius: 8px;
          124  +  color: white;
          125  +}
          126  +
          127  +/* Hyperlink colors in the footer */
          128  +div.footer a { color: white; }
          129  +div.footer a:link { color: white; }
          130  +div.footer a:visited { color: white; }
          131  +div.footer a:hover { background-color: white; color: #558195; }
          132  +
          133  +/* verbatim blocks */
          134  +pre.verbatim {
          135  +  background-color: #f5f5f5;
          136  +  padding: 0.5em;
          137  +  white-space: pre-wrap;
          138  +}
          139  +
          140  +/* The label/value pairs on (for example) the ci page */
          141  +table.label-value th {
          142  +  vertical-align: top;
          143  +  text-align: right;
          144  +  padding: 0.2ex 2ex;
          145  +}

Added skins/default/footer.txt.

            1  +<div class="footer">
            2  +This page was generated in about
            3  +<th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
            4  +Fossil version $manifest_version $manifest_date
            5  +</div>
            6  +</body></html>

Added skins/default/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss" />
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen" />
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="logo">
           13  +    <img src="$logo_image_url" alt="logo" />
           14  +  </div>
           15  +  <div class="title"><small>$<project_name></small><br />$<title></div>
           16  +  <div class="status"><th1>
           17  +     if {[info exists login]} {
           18  +       puts "Logged in as $login"
           19  +     } else {
           20  +       puts "Not logged in"
           21  +     }
           22  +  </th1></div>
           23  +</div>
           24  +<div class="mainmenu">
           25  +<th1>
           26  +html "<a href='$home$index_page'>Home</a>\n"
           27  +if {[anycap jor]} {
           28  +  html "<a href='$home/timeline'>Timeline</a>\n"
           29  +}
           30  +if {[hascap oh]} {
           31  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
           32  +}
           33  +if {[hascap o]} {
           34  +  html "<a href='$home/brlist'>Branches</a>\n"
           35  +  html "<a href='$home/taglist'>Tags</a>\n"
           36  +}
           37  +if {[hascap r]} {
           38  +  html "<a href='$home/reportlist'>Tickets</a>\n"
           39  +}
           40  +if {[hascap j]} {
           41  +  html "<a href='$home/wiki'>Wiki</a>\n"
           42  +}
           43  +if {[hascap s]} {
           44  +  html "<a href='$home/setup'>Admin</a>\n"
           45  +} elseif {[hascap a]} {
           46  +  html "<a href='$home/setup_ulist'>Users</a>\n"
           47  +}
           48  +if {[info exists login]} {
           49  +  html "<a href='$home/login'>Logout</a>\n"
           50  +} else {
           51  +  html "<a href='$home/login'>Login</a>\n"
           52  +}
           53  +</th1></div>

Added skins/eagle/css.txt.

            1  +/* General settings for the entire page */
            2  +body {
            3  +  margin: 0ex 1ex;
            4  +  padding: 0px;
            5  +  background-color: #485D7B;
            6  +  font-family: sans-serif;
            7  +  color: white;
            8  +}
            9  +
           10  +/* The project logo in the upper left-hand corner of each page */
           11  +div.logo {
           12  +  display: table-cell;
           13  +  text-align: center;
           14  +  vertical-align: bottom;
           15  +  font-weight: bold;
           16  +  color: white;
           17  +  padding: 5 0 5 0em;
           18  +  white-space: nowrap;
           19  +}
           20  +
           21  +/* The page title centered at the top of each page */
           22  +div.title {
           23  +  display: table-cell;
           24  +  font-size: 2em;
           25  +  font-weight: bold;
           26  +  text-align: left;
           27  +  padding: 0 0 0 1em;
           28  +  color: white;
           29  +  vertical-align: bottom;
           30  +  width: 100%;
           31  +}
           32  +
           33  +/* The login status message in the top right-hand corner */
           34  +div.status {
           35  +  display: table-cell;
           36  +  text-align: right;
           37  +  vertical-align: bottom;
           38  +  color: white;
           39  +  font-size: 0.8em;
           40  +  font-weight: bold;
           41  +  min-width: 200px;
           42  +  white-space: nowrap;
           43  +}
           44  +
           45  +/* The header across the top of the page */
           46  +div.header {
           47  +  display: table;
           48  +  width: 100%;
           49  +}
           50  +
           51  +/* The main menu bar that appears at the top of the page beneath
           52  +** the header */
           53  +div.mainmenu {
           54  +  padding: 5px 10px 5px 10px;
           55  +  font-size: 0.9em;
           56  +  font-weight: bold;
           57  +  text-align: center;
           58  +  letter-spacing: 1px;
           59  +  background-color: #76869D;
           60  +  border-top-left-radius: 8px;
           61  +  border-top-right-radius: 8px;
           62  +  color: white;
           63  +}
           64  +
           65  +/* The submenu bar that *sometimes* appears below the main menu */
           66  +div.submenu, div.sectionmenu {
           67  +  padding: 3px 10px 3px 0px;
           68  +  font-size: 0.9em;
           69  +  font-weight: bold;
           70  +  text-align: center;
           71  +  background-color: #485D7B;
           72  +  color: white;
           73  +}
           74  +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
           75  +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
           76  +  padding: 3px 10px 3px 10px;
           77  +  color: white;
           78  +  text-decoration: none;
           79  +}
           80  +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
           81  +  text-decoration: underline;
           82  +}
           83  +
           84  +/* All page content from the bottom of the menu or submenu down to
           85  +** the footer */
           86  +div.content {
           87  +  padding: 0ex 1ex 0ex 2ex;
           88  +}
           89  +
           90  +/* Some pages have section dividers */
           91  +div.section {
           92  +  margin-bottom: 0px;
           93  +  margin-top: 1em;
           94  +  padding: 1px 1px 1px 1px;
           95  +  font-size: 1.2em;
           96  +  font-weight: bold;
           97  +  background-color: #485D7B;
           98  +  color: white;
           99  +  white-space: nowrap;
          100  +}
          101  +
          102  +/* The "Date" that occurs on the left hand side of timelines */
          103  +div.divider {
          104  +  background: #9DB0CC;
          105  +  color: white;
          106  +  border: 2px white solid;
          107  +  font-size: 1em; font-weight: normal;
          108  +  padding: .25em;
          109  +  margin: .2em 0 .2em 0;
          110  +  float: left;
          111  +  clear: left;
          112  +  white-space: nowrap;
          113  +}
          114  +
          115  +/* The footer at the very bottom of the page */
          116  +div.footer {
          117  +  clear: both;
          118  +  font-size: 0.8em;
          119  +  margin-top: 12px;
          120  +  padding: 5px 10px 5px 10px;
          121  +  text-align: right;
          122  +  background-color: #485D7B;
          123  +  border-bottom-left-radius: 8px;
          124  +  border-bottom-right-radius: 8px;
          125  +  color: white;
          126  +}
          127  +
          128  +/* Hyperlink colors in the footer */
          129  +a { color: white; }
          130  +a:link { color: white; }
          131  +a:visited { color: white; }
          132  +a:hover { color: #9DB0CC; }
          133  +
          134  +/* verbatim blocks */
          135  +pre.verbatim {
          136  +  background-color: #485D7B;
          137  +  color: white;
          138  +  padding: 0.5em;
          139  +  white-space: pre-wrap;
          140  +}
          141  +
          142  +/* The label/value pairs on (for example) the ci page */
          143  +table.label-value th {
          144  +  vertical-align: top;
          145  +  text-align: right;
          146  +  padding: 0.2ex 2ex;
          147  +}
          148  +
          149  +/* The nomenclature sidebox for branches,.. */
          150  +div.sidebox {
          151  +  float: right;
          152  +  background-color: #485D7B;
          153  +  border-width: medium;
          154  +  border-style: double;
          155  +  margin: 10px;
          156  +}
          157  +
          158  +/* the format for the timeline data table */
          159  +table.timelineTable {
          160  +  cellspacing: 0;
          161  +  border: 0;
          162  +  cellpadding: 0;
          163  +  font-family: "courier new";
          164  +}
          165  +
          166  +/* Side-by-side diff */
          167  +table.sbsdiff {
          168  +  background-color: #485D7B;
          169  +  font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace;
          170  +  font-size: 8pt;
          171  +  border-collapse:collapse;
          172  +  white-space: pre;
          173  +  width: 98%;
          174  +  border: 1px #000 dashed;
          175  +  margin-left: auto;
          176  +  margin-right: auto;
          177  +}
          178  +
          179  +/* format for the layout table, used for the captcha display */
          180  +table.captcha {
          181  +  margin: auto;
          182  +  padding: 10px;
          183  +  border-width: 4px;
          184  +  border-style: double;
          185  +  border-color: white;
          186  +}
          187  +
          188  +/* format for the user list table on the user setup page */
          189  +table.usetupUserList {
          190  +  outline-style: double;
          191  +  outline-width: 1px;
          192  +  border-color: white;
          193  +  padding: 10px;
          194  +}
          195  +
          196  +/* color for capabilities, inherited by reader */
          197  +span.ueditInheritReader {
          198  +  color: white;
          199  +}
          200  +
          201  +/* format for values on ticket display page */
          202  +td.tktDspValue {
          203  +  text-align: left;
          204  +  vertical-align: top;
          205  +  background-color: #485D7B;
          206  +}
          207  +
          208  +/* format for example table cells on the report edit page */
          209  +td.rpteditex {
          210  +  border-width: thin;
          211  +  border-color: white;
          212  +  border-style: solid;
          213  +}
          214  +
          215  +/* List of files in a timeline */
          216  +ul.filelist {
          217  +  margin-top: 3px;
          218  +  line-height: 100%;
          219  +}
          220  +
          221  +/* side-by-side diff display */
          222  +div.sbsdiff {
          223  +  font-family: monospace;
          224  +  font-size: smaller;
          225  +  white-space: pre;
          226  +}
          227  +
          228  +/* context diff display */
          229  +div.udiff {
          230  +  font-family: monospace;
          231  +  white-space: pre;
          232  +}
          233  +
          234  +/* changes in a diff */
          235  +span.diffchng {
          236  +  background-color: rgb(170, 170, 140);
          237  +}
          238  +
          239  +/* added code in a diff */
          240  +span.diffadd {
          241  +  background-color: rgb(100, 200, 100);
          242  +}
          243  +
          244  +/* deleted in a diff */
          245  +span.diffrm {
          246  +  background-color: rgb(230, 110, 110);
          247  +}
          248  +
          249  +/* suppressed lines in a diff */
          250  +span.diffhr {
          251  +  display: inline-block;
          252  +  margin: .5em 0 1em;
          253  +  color: rgb(150, 150, 140);
          254  +}
          255  +
          256  +/* line numbers in a diff */
          257  +span.diffln {
          258  +  color: white;
          259  +}
          260  +
          261  +#canvas {
          262  +  background-color: #485D7B;
          263  +}

Added skins/eagle/footer.txt.

            1  +<div class="footer">
            2  +  <th1>
            3  +  proc getTclVersion {} {
            4  +    if {[catch {tclEval info patchlevel} tclVersion] == 0} {
            5  +      return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion"
            6  +    }
            7  +    return ""
            8  +  }
            9  +  proc getVersion { version } {
           10  +    set length [string length $version]
           11  +    return [string range $version 1 [expr {$length - 2}]]
           12  +  }
           13  +  set version [getVersion $manifest_version]
           14  +  set tclVersion [getTclVersion]
           15  +  set fossilUrl https://www.fossil-scm.org
           16  +  </th1>
           17  +  This page was generated in about
           18  +  <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
           19  +  <a href="$fossilUrl/">Fossil</a>
           20  +  version $release_version $tclVersion
           21  +  <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
           22  +  <a href="$fossilUrl/index.html/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
           23  +</div>
           24  +</body></html>

Added skins/eagle/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss" />
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen" />
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="logo">
           13  +    <th1>
           14  +    ##
           15  +    ## NOTE: The purpose of this procedure is to take the base URL of the
           16  +    ##       Fossil project and return the root of the entire web site using
           17  +    ##       the same URI scheme as the base URL (e.g. http or https).
           18  +    ##
           19  +    proc getLogoUrl { baseurl } {
           20  +      set idx(first) [string first // $baseurl]
           21  +      if {$idx(first) != -1} {
           22  +        ##
           23  +        ## NOTE: Skip second slash.
           24  +        ##
           25  +        set idx(first+1) [expr {$idx(first) + 2}]
           26  +        ##
           27  +        ## NOTE: (part 1) The [string first] command does NOT actually
           28  +        ##       support the optional startIndex argument as specified
           29  +        ##       in the TH1 support manual; therefore, we fake it by
           30  +        ##       using the [string range] command and then adding the
           31  +        ##       necessary offset to the resulting index manually
           32  +        ##       (below).  In Tcl, we could use the following instead:
           33  +        ##
           34  +        ##       set idx(next) [string first / $baseurl $idx(first+1)]
           35  +        ##
           36  +        set idx(nextRange) [string range $baseurl $idx(first+1) end]
           37  +        set idx(next) [string first / $idx(nextRange)]
           38  +        if {$idx(next) != -1} {
           39  +          ##
           40  +          ## NOTE: (part 2) Add the necessary offset to the result of
           41  +          ##       the search for the next slash (i.e. the one after
           42  +          ##       the initial search for the two slashes).
           43  +          ##
           44  +          set idx(next) [expr {$idx(next) + $idx(first+1)}]
           45  +          ##
           46  +          ## NOTE: Back up one character from the next slash.
           47  +          ##
           48  +          set idx(next-1) [expr {$idx(next) - 1}]
           49  +          ##
           50  +          ## NOTE: Extract the URI scheme and host from the base URL.
           51  +          ##
           52  +          set scheme [string range $baseurl 0 $idx(first)]
           53  +          set host [string range $baseurl $idx(first+1) $idx(next-1)]
           54  +          ##
           55  +          ## NOTE: Try to stay in SSL mode if we are there now.
           56  +          ##
           57  +          if {[string compare $scheme http:/] == 0} {
           58  +            set scheme http://
           59  +          } else {
           60  +            set scheme https://
           61  +          }
           62  +          set logourl $scheme$host/
           63  +        } else {
           64  +          set logourl $baseurl
           65  +        }
           66  +      } else {
           67  +        set logourl $baseurl
           68  +      }
           69  +      return $logourl
           70  +    }
           71  +    set logourl [getLogoUrl $baseurl]
           72  +    </th1>
           73  +    <a href="$logourl">
           74  +      <img src="$logo_image_url" border="0" alt="$project_name">
           75  +    </a>
           76  +  </div>
           77  +  <div class="title">$<title></div>
           78  +  <div class="status"><th1>
           79  +     if {[info exists login]} {
           80  +       puts "Logged in as $login"
           81  +     } else {
           82  +       puts "Not logged in"
           83  +     }
           84  +  </th1></nobr><small><div id="clock"></div></small></div>
           85  +</div>
           86  +<script>
           87  +function updateClock(){
           88  +  var e = document.getElementById("clock");
           89  +  if(e){
           90  +    var d = new Date();
           91  +    e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,"");
           92  +    setTimeout("updateClock();",(60-d.getSeconds())*1000);
           93  +  }
           94  +}
           95  +updateClock();
           96  +</script>
           97  +<div class="mainmenu">
           98  +<th1>
           99  +html "<a href='$home$index_page'>Home</a>\n"
          100  +html "<a href='$home/help'>Help</a>\n"
          101  +if {[anycap jor]} {
          102  +  html "<a href='$home/timeline'>Timeline</a>\n"
          103  +}
          104  +if {[hascap oh]} {
          105  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
          106  +}
          107  +if {[hascap o]} {
          108  +  html "<a href='$home/brlist'>Branches</a>\n"
          109  +  html "<a href='$home/taglist'>Tags</a>\n"
          110  +}
          111  +if {[hascap r]} {
          112  +  html "<a href='$home/reportlist'>Tickets</a>\n"
          113  +}
          114  +if {[hascap j]} {
          115  +  html "<a href='$home/wiki'>Wiki</a>\n"
          116  +}
          117  +if {[hascap s]} {
          118  +  html "<a href='$home/setup'>Admin</a>\n"
          119  +} elseif {[hascap a]} {
          120  +  html "<a href='$home/setup_ulist'>Users</a>\n"
          121  +}
          122  +if {[info exists login]} {
          123  +  html "<a href='$home/login'>Logout</a>\n"
          124  +} else {
          125  +  html "<a href='$home/login'>Login</a>\n"
          126  +}
          127  +</th1></div>

Added skins/enhanced1/css.txt.

            1  +/* General settings for the entire page */
            2  +body {
            3  +  margin: 0ex 1ex;
            4  +  padding: 0px;
            5  +  background-color: white;
            6  +  font-family: sans-serif;
            7  +}
            8  +
            9  +/* The project logo in the upper left-hand corner of each page */
           10  +div.logo {
           11  +  display: table-cell;
           12  +  text-align: center;
           13  +  vertical-align: bottom;
           14  +  font-weight: bold;
           15  +  color: #558195;
           16  +  min-width: 200px;
           17  +  white-space: nowrap;
           18  +}
           19  +
           20  +/* The page title centered at the top of each page */
           21  +div.title {
           22  +  display: table-cell;
           23  +  font-size: 2em;
           24  +  font-weight: bold;
           25  +  text-align: center;
           26  +  padding: 0 0 0 1em;
           27  +  color: #558195;
           28  +  vertical-align: bottom;
           29  +  width: 100%;
           30  +}
           31  +
           32  +/* The login status message in the top right-hand corner */
           33  +div.status {
           34  +  display: table-cell;
           35  +  text-align: right;
           36  +  vertical-align: bottom;
           37  +  color: #558195;
           38  +  font-size: 0.8em;
           39  +  font-weight: bold;
           40  +  min-width: 200px;
           41  +  white-space: nowrap;
           42  +}
           43  +
           44  +/* The header across the top of the page */
           45  +div.header {
           46  +  display: table;
           47  +  width: 100%;
           48  +}
           49  +
           50  +/* The main menu bar that appears at the top of the page beneath
           51  +** the header */
           52  +div.mainmenu {
           53  +  padding: 5px 10px 5px 10px;
           54  +  font-size: 0.9em;
           55  +  font-weight: bold;
           56  +  text-align: center;
           57  +  letter-spacing: 1px;
           58  +  background-color: #558195;
           59  +  border-top-left-radius: 8px;
           60  +  border-top-right-radius: 8px;
           61  +  color: white;
           62  +}
           63  +
           64  +/* The submenu bar that *sometimes* appears below the main menu */
           65  +div.submenu, div.sectionmenu {
           66  +  padding: 3px 10px 3px 0px;
           67  +  font-size: 0.9em;
           68  +  text-align: center;
           69  +  background-color: #456878;
           70  +  color: white;
           71  +}
           72  +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
           73  +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
           74  +  padding: 3px 10px 3px 10px;
           75  +  color: white;
           76  +  text-decoration: none;
           77  +}
           78  +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
           79  +  color: #558195;
           80  +  background-color: white;
           81  +}
           82  +
           83  +/* All page content from the bottom of the menu or submenu down to
           84  +** the footer */
           85  +div.content {
           86  +  padding: 0ex 1ex 1ex 1ex;
           87  +  border: solid #aaa;
           88  +  border-width: 1px;
           89  +}
           90  +
           91  +/* Some pages have section dividers */
           92  +div.section {
           93  +  margin-bottom: 0px;
           94  +  margin-top: 1em;
           95  +  padding: 1px 1px 1px 1px;
           96  +  font-size: 1.2em;
           97  +  font-weight: bold;
           98  +  background-color: #558195;
           99  +  color: white;
          100  +  white-space: nowrap;
          101  +}
          102  +
          103  +/* The "Date" that occurs on the left hand side of timelines */
          104  +div.divider {
          105  +  background: #a1c4d4;
          106  +  border: 2px #558195 solid;
          107  +  font-size: 1em; font-weight: normal;
          108  +  padding: .25em;
          109  +  margin: .2em 0 .2em 0;
          110  +  float: left;
          111  +  clear: left;
          112  +  white-space: nowrap;
          113  +}
          114  +
          115  +/* The footer at the very bottom of the page */
          116  +div.footer {
          117  +  clear: both;
          118  +  font-size: 0.8em;
          119  +  padding: 5px 10px 5px 10px;
          120  +  text-align: right;
          121  +  background-color: #558195;
          122  +  border-bottom-left-radius: 8px;
          123  +  border-bottom-right-radius: 8px;
          124  +  color: white;
          125  +}
          126  +
          127  +/* Hyperlink colors in the footer */
          128  +div.footer a { color: white; }
          129  +div.footer a:link { color: white; }
          130  +div.footer a:visited { color: white; }
          131  +div.footer a:hover { background-color: white; color: #558195; }
          132  +
          133  +/* verbatim blocks */
          134  +pre.verbatim {
          135  +  background-color: #f5f5f5;
          136  +  padding: 0.5em;
          137  +  white-space: pre-wrap;
          138  +}
          139  +
          140  +/* The label/value pairs on (for example) the ci page */
          141  +table.label-value th {
          142  +  vertical-align: top;
          143  +  text-align: right;
          144  +  padding: 0.2ex 2ex;
          145  +}

Added skins/enhanced1/footer.txt.

            1  +<div class="footer">
            2  +  <th1>
            3  +  proc getTclVersion {} {
            4  +    if {[catch {tclEval info patchlevel} tclVersion] == 0} {
            5  +      return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion"
            6  +    }
            7  +    return ""
            8  +  }
            9  +  proc getVersion { version } {
           10  +    set length [string length $version]
           11  +    return [string range $version 1 [expr {$length - 2}]]
           12  +  }
           13  +  set version [getVersion $manifest_version]
           14  +  set tclVersion [getTclVersion]
           15  +  set fossilUrl https://www.fossil-scm.org
           16  +  </th1>
           17  +  This page was generated in about
           18  +  <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
           19  +  <a href="$fossilUrl/">Fossil</a>
           20  +  version $release_version $tclVersion
           21  +  <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
           22  +  <a href="$fossilUrl/index.html/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
           23  +</div>
           24  +</body></html>

Added skins/enhanced1/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss" />
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen" />
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="logo">
           13  +    <th1>
           14  +    ##
           15  +    ## NOTE: The purpose of this procedure is to take the base URL of the
           16  +    ##       Fossil project and return the root of the entire web site using
           17  +    ##       the same URI scheme as the base URL (e.g. http or https).
           18  +    ##
           19  +    proc getLogoUrl { baseurl } {
           20  +      set idx(first) [string first // $baseurl]
           21  +      if {$idx(first) != -1} {
           22  +        ##
           23  +        ## NOTE: Skip second slash.
           24  +        ##
           25  +        set idx(first+1) [expr {$idx(first) + 2}]
           26  +        ##
           27  +        ## NOTE: (part 1) The [string first] command does NOT actually
           28  +        ##       support the optional startIndex argument as specified
           29  +        ##       in the TH1 support manual; therefore, we fake it by
           30  +        ##       using the [string range] command and then adding the
           31  +        ##       necessary offset to the resulting index manually
           32  +        ##       (below).  In Tcl, we could use the following instead:
           33  +        ##
           34  +        ##       set idx(next) [string first / $baseurl $idx(first+1)]
           35  +        ##
           36  +        set idx(nextRange) [string range $baseurl $idx(first+1) end]
           37  +        set idx(next) [string first / $idx(nextRange)]
           38  +        if {$idx(next) != -1} {
           39  +          ##
           40  +          ## NOTE: (part 2) Add the necessary offset to the result of
           41  +          ##       the search for the next slash (i.e. the one after
           42  +          ##       the initial search for the two slashes).
           43  +          ##
           44  +          set idx(next) [expr {$idx(next) + $idx(first+1)}]
           45  +          ##
           46  +          ## NOTE: Back up one character from the next slash.
           47  +          ##
           48  +          set idx(next-1) [expr {$idx(next) - 1}]
           49  +          ##
           50  +          ## NOTE: Extract the URI scheme and host from the base URL.
           51  +          ##
           52  +          set scheme [string range $baseurl 0 $idx(first)]
           53  +          set host [string range $baseurl $idx(first+1) $idx(next-1)]
           54  +          ##
           55  +          ## NOTE: Try to stay in SSL mode if we are there now.
           56  +          ##
           57  +          if {[string compare $scheme http:/] == 0} {
           58  +            set scheme http://
           59  +          } else {
           60  +            set scheme https://
           61  +          }
           62  +          set logourl $scheme$host/
           63  +        } else {
           64  +          set logourl $baseurl
           65  +        }
           66  +      } else {
           67  +        set logourl $baseurl
           68  +      }
           69  +      return $logourl
           70  +    }
           71  +    set logourl [getLogoUrl $baseurl]
           72  +    </th1>
           73  +    <a href="$logourl">
           74  +      <img src="$logo_image_url" border="0" alt="$project_name">
           75  +    </a>
           76  +  </div>
           77  +  <div class="title">$<title></div>
           78  +  <div class="status"><th1>
           79  +     if {[info exists login]} {
           80  +       puts "Logged in as $login"
           81  +     } else {
           82  +       puts "Not logged in"
           83  +     }
           84  +  </th1></nobr><small><div id="clock"></div></small></div>
           85  +</div>
           86  +<script>
           87  +function updateClock(){
           88  +  var e = document.getElementById("clock");
           89  +  if(e){
           90  +    var d = new Date();
           91  +    e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,"");
           92  +    setTimeout("updateClock();",(60-d.getSeconds())*1000);
           93  +  }
           94  +}
           95  +updateClock();
           96  +</script>
           97  +<div class="mainmenu">
           98  +<th1>
           99  +html "<a href='$home$index_page'>Home</a>\n"
          100  +html "<a href='$home/help'>Help</a>\n"
          101  +if {[anycap jor]} {
          102  +  html "<a href='$home/timeline'>Timeline</a>\n"
          103  +}
          104  +if {[hascap oh]} {
          105  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
          106  +}
          107  +if {[hascap o]} {
          108  +  html "<a href='$home/brlist'>Branches</a>\n"
          109  +  html "<a href='$home/taglist'>Tags</a>\n"
          110  +}
          111  +if {[hascap r]} {
          112  +  html "<a href='$home/reportlist'>Tickets</a>\n"
          113  +}
          114  +if {[hascap j]} {
          115  +  html "<a href='$home/wiki'>Wiki</a>\n"
          116  +}
          117  +if {[hascap s]} {
          118  +  html "<a href='$home/setup'>Admin</a>\n"
          119  +} elseif {[hascap a]} {
          120  +  html "<a href='$home/setup_ulist'>Users</a>\n"
          121  +}
          122  +if {[info exists login]} {
          123  +  html "<a href='$home/login'>Logout</a>\n"
          124  +} else {
          125  +  html "<a href='$home/login'>Login</a>\n"
          126  +}
          127  +</th1></div>

Added skins/etienne1/README.md.

            1  +This skin was contributed by Étienne Deparis.

Added skins/etienne1/css.txt.

            1  +body {
            2  +    margin: 0 auto;
            3  +    width: 960px;
            4  +    font-family: sans-serif;
            5  +    font-size:14pt;
            6  +}
            7  +
            8  +a {
            9  +    color: #4183C4;
           10  +    text-decoration: none;
           11  +}
           12  +a:hover {
           13  +    color: #4183C4;
           14  +    text-decoration: underline;
           15  +}
           16  +
           17  +hr {
           18  +    border: 0px;
           19  +}
           20  +
           21  +.title {
           22  +    color: #4183C4;
           23  +    float:left;
           24  +    padding-top: 30px;
           25  +    padding-bottom: 10px;
           26  +}
           27  +.title h1 {
           28  +    display:inline;
           29  +}
           30  +.title h1:after {
           31  +    content: " / ";
           32  +    color: #777;
           33  +    font-weight: normal;
           34  +}
           35  +
           36  +.status {
           37  +    float:right;
           38  +    font-size:.7em;
           39  +    padding-top:50px;
           40  +}
           41  +
           42  +.mainmenu {
           43  +    font-size:.8em;
           44  +    clear:both;
           45  +    padding:10px;
           46  +    background:#eaeaea linear-gradient(#fafafa, #eaeaea) repeat-x;
           47  +    border:1px solid #eaeaea;
           48  +    border-radius:5px;
           49  +}
           50  +
           51  +.mainmenu a {
           52  +    padding: 10px 20px;
           53  +    text-decoration:none;
           54  +    color: #777;
           55  +    border-right:1px solid #eaeaea;
           56  +}
           57  +.mainmenu a.active,
           58  +.mainmenu a:hover {
           59  +    color: #000;
           60  +    border-bottom:2px solid #D26911;
           61  +}
           62  +
           63  +.submenu {
           64  +    font-size: .7em;
           65  +    margin-top: 10px;
           66  +    padding: 10px;
           67  +    border-bottom: 1px solid #ccc;
           68  +}
           69  +
           70  +.submenu a {
           71  +    padding: 10px;
           72  +    text-decoration:none;
           73  +    color: #777;
           74  +}
           75  +
           76  +.submenu a:hover {
           77  +    border: 1px solid #ccc;
           78  +    border-bottom: 1px solid #fff;
           79  +    border-top-left-radius: 5px;
           80  +    border-top-right-radius: 5px;
           81  +}
           82  +
           83  +.content {
           84  +    padding-top: 10px;
           85  +    font-size:.9em;
           86  +    color: #444;
           87  +}
           88  +
           89  +.udiff, .sbsdiff,
           90  +.content blockquote {
           91  +    font-size: .85em !important;
           92  +    overflow: auto;
           93  +    border: 1px solid #ccc;
           94  +    border-radius: 5px;
           95  +}
           96  +.content blockquote {
           97  +    padding: 0 15px;
           98  +}
           99  +
          100  +table.report {
          101  +    cursor: auto;
          102  +    border-radius: 5px;
          103  +    border: 1px solid #ccc;
          104  +    margin: 1em 0;
          105  +}
          106  +.report td, .report th {
          107  +   border: 0;
          108  +   font-size: .8em;
          109  +   padding: 10px;
          110  +}
          111  +.report td:first-child {
          112  +    border-top-left-radius: 5px;
          113  +}
          114  +.report tbody tr:last-child td:first-child {
          115  +    border-bottom-left-radius: 5px;
          116  +}
          117  +.report td:last-child {
          118  +    border-top-right-radius: 5px;
          119  +}
          120  +.report tbody tr:last-child {
          121  +    border-bottom-left-radius: 5px;
          122  +    border-bottom-right-radius: 5px;
          123  +}
          124  +.report tbody tr:last-child td:last-child {
          125  +    border-bottom-right-radius: 5px;
          126  +}
          127  +.report th {
          128  +    cursor: pointer;
          129  +}
          130  +.report thead+tbody tr:hover {
          131  +    background-color: #f5f9fc !important;
          132  +}
          133  +
          134  +td.tktDspLabel {
          135  +    max-width: 70px;
          136  +    text-align: right;
          137  +}
          138  +td.tktDspValue {
          139  +    max-width: 800px;
          140  +    text-align: left;
          141  +    vertical-align: top;
          142  +    background-color: #f5f9fc;
          143  +}
          144  +td.tktDspValue pre {
          145  +    white-space: pre-wrap;
          146  +}
          147  +
          148  +.footer {
          149  +    border-top: 1px solid #ccc;
          150  +    padding: 10px;
          151  +    font-size:.7em;
          152  +    margin-top: 10px;
          153  +    color: #ccc;
          154  +}

Added skins/etienne1/footer.txt.

            1  +<div class="footer">
            2  +This page was generated in about
            3  +<th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
            4  +Fossil version $manifest_version $manifest_date
            5  +</div>
            6  +</body></html>

Added skins/etienne1/header.txt.

            1  +<html>
            2  +  <head>
            3  +    <base href="$baseurl/$current_page" />
            4  +    <title>$<project_name>: $<title></title>
            5  +      <link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +            href="$home/timeline.rss" />
            7  +      <link rel="stylesheet" href="$home/style.css?default" type="text/css"
            8  +            media="screen" />
            9  +  </head>
           10  +
           11  +  <body>
           12  +    <div class="header">
           13  +      <div class="title"><h1>$<project_name></h1>$<title></div>
           14  +        <div class="status"><th1>
           15  +     if {[info exists login]} {
           16  +       html "$login — <a href='$home/login'>Logout</a>\n"
           17  +     } else {
           18  +       html "<a href='$home/login'>Login</a>\n"
           19  +     }
           20  +        </th1></div>
           21  +    </div>
           22  +
           23  +    <div class="mainmenu">
           24  +      <th1>
           25  +proc isin {val lst} {
           26  +    set tot [llength $lst]
           27  +    for {set i 0} {$i < $tot} {set i [expr {$i + 1}]} {
           28  +        set cur [lindex $lst $i]
           29  +        if {$val eq $cur} {
           30  +            return 0
           31  +        }
           32  +    }
           33  +    return 1
           34  +}
           35  +
           36  +proc menulink {pagename url name} {
           37  +    upvar current_page current
           38  +    upvar home home
           39  +
           40  +    set compsetup [string compare [string range $current 0 4] setup]
           41  +    set comphome [string compare [string range $current 0 3] home]
           42  +    set comptag [string compare $current tagtimeline]
           43  +    set compbr [string compare $current brtimeline]
           44  +    set compdir [isin $current "artifact ci finfo hexdump"]
           45  +    set comptl [string compare $current info]
           46  +    set comptkt [isin $current "modreq rptedit tktnew rptsql rptview"]
           47  +
           48  +    html "<a href='$home$url'"
           49  +
           50  +    if {$pagename eq $current
           51  +        || ($pagename eq "home" && $comphome == 0)
           52  +        || ($pagename eq "setup" && $compsetup == 0)
           53  +        || ($pagename eq "taglist" && $comptag == 0)
           54  +        || ($pagename eq "dir" && $compdir == 0)
           55  +        || ($pagename eq "timeline" && $comptl == 0)
           56  +        || ($pagename eq "reportlist" && $comptkt == 0)
           57  +        || ($pagename eq "brlist" && $compbr == 0)
           58  +    } {
           59  +        html " class='active' "
           60  +    }
           61  +
           62  +    html ">$name</a>"
           63  +}
           64  +
           65  +menulink "home" $index_page Home
           66  +
           67  +if {[anycap jor]} {
           68  +    menulink "timeline" "/timeline" Timeline
           69  +}
           70  +if {[hascap oh]} {
           71  +    menulink "dir" "/dir?ci=tip" Files
           72  +}
           73  +if {[hascap o]} {
           74  +    menulink "brlist" "/brlist" Branches
           75  +    menulink "taglist" "/taglist" Tags
           76  +}
           77  +if {[hascap r]} {
           78  +    menulink "reportlist" "/reportlist" Tickets
           79  +}
           80  +if {[hascap j]} {
           81  +    menulink "wiki" "/wiki" Wiki
           82  +}
           83  +if {[hascap s]} {
           84  +    menulink "setup" "/setup" Admin
           85  +} elseif {[hascap a]} {
           86  +    menulink "setup_ulist" "/setup_ulist" Users
           87  +}
           88  +</th1></div>

Added skins/khaki/css.txt.

            1  +/* General settings for the entire page */
            2  +body {
            3  +  margin: 0ex 0ex;
            4  +  padding: 0px;
            5  +  background-color: #fef3bc;
            6  +  font-family: sans-serif;
            7  +}
            8  +
            9  +/* The project logo in the upper left-hand corner of each page */
           10  +div.logo {
           11  +  display: inline;
           12  +  text-align: center;
           13  +  vertical-align: bottom;
           14  +  font-weight: bold;
           15  +  font-size: 2.5em;
           16  +  color: #a09048;
           17  +  white-space: nowrap;
           18  +}
           19  +
           20  +/* The page title centered at the top of each page */
           21  +div.title {
           22  +  display: table-cell;
           23  +  font-size: 2em;
           24  +  font-weight: bold;
           25  +  text-align: left;
           26  +  padding: 0 0 0 5px;
           27  +  color: #a09048;
           28  +  vertical-align: bottom;
           29  +  width: 100%;
           30  +}
           31  +
           32  +/* The login status message in the top right-hand corner */
           33  +div.status {
           34  +  display: table-cell;
           35  +  text-align: right;
           36  +  vertical-align: bottom;
           37  +  color: #a09048;
           38  +  padding: 5px 5px 0 0;
           39  +  font-size: 0.8em;
           40  +  font-weight: bold;
           41  +  white-space: nowrap;
           42  +}
           43  +
           44  +/* The header across the top of the page */
           45  +div.header {
           46  +  display: table;
           47  +  width: 100%;
           48  +}
           49  +
           50  +/* The main menu bar that appears at the top of the page beneath
           51  +** the header */
           52  +div.mainmenu {
           53  +  padding: 5px 10px 5px 10px;
           54  +  font-size: 0.9em;
           55  +  font-weight: bold;
           56  +  text-align: center;
           57  +  letter-spacing: 1px;
           58  +  background-color: #a09048;
           59  +  color: black;
           60  +}
           61  +
           62  +/* The submenu bar that *sometimes* appears below the main menu */
           63  +div.submenu, div.sectionmenu {
           64  +  padding: 3px 10px 3px 0px;
           65  +  font-size: 0.9em;
           66  +  text-align: center;
           67  +  background-color: #c0af58;
           68  +  color: white;
           69  +}
           70  +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
           71  +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
           72  +  padding: 3px 10px 3px 10px;
           73  +  color: white;
           74  +  text-decoration: none;
           75  +}
           76  +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
           77  +  color: #a09048;
           78  +  background-color: white;
           79  +}
           80  +
           81  +/* All page content from the bottom of the menu or submenu down to
           82  +** the footer */
           83  +div.content {
           84  +  padding: 1ex 5px;
           85  +}
           86  +div.content a { color: #706532; }
           87  +div.content a:link { color: #706532; }
           88  +div.content a:visited { color: #704032; }
           89  +div.content a:hover { background-color: white; color: #706532; }
           90  +
           91  +/* Some pages have section dividers */
           92  +div.section {
           93  +  margin-bottom: 0px;
           94  +  margin-top: 1em;
           95  +  padding: 3px 3px 0 3px;
           96  +  font-size: 1.2em;
           97  +  font-weight: bold;
           98  +  background-color: #a09048;
           99  +  color: white;
          100  +  white-space: nowrap;
          101  +}
          102  +
          103  +/* The "Date" that occurs on the left hand side of timelines */
          104  +div.divider {
          105  +  background: #e1d498;
          106  +  border: 2px #a09048 solid;
          107  +  font-size: 1em; font-weight: normal;
          108  +  padding: .25em;
          109  +  margin: .2em 0 .2em 0;
          110  +  float: left;
          111  +  clear: left;
          112  +  white-space: nowrap;
          113  +}
          114  +
          115  +/* The footer at the very bottom of the page */
          116  +div.footer {
          117  +  font-size: 0.8em;
          118  +  margin-top: 12px;
          119  +  padding: 5px 10px 5px 10px;
          120  +  text-align: right;
          121  +  background-color: #a09048;
          122  +  color: white;
          123  +}
          124  +
          125  +/* Hyperlink colors */
          126  +div.footer a { color: white; }
          127  +div.footer a:link { color: white; }
          128  +div.footer a:visited { color: white; }
          129  +div.footer a:hover { background-color: white; color: #558195; }
          130  +
          131  +/* <verbatim> blocks */
          132  +pre.verbatim {
          133  +  background-color: #f5f5f5;
          134  +  padding: 0.5em;
          135  +  white-space: pre-wrap;
          136  +}
          137  +
          138  +/* The label/value pairs on (for example) the ci page */
          139  +table.label-value th {
          140  +  vertical-align: top;
          141  +  text-align: right;
          142  +  padding: 0.2ex 2ex;
          143  +}

Added skins/khaki/footer.txt.

            1  +<div class="footer">
            2  +Fossil version $manifest_version $manifest_date
            3  +</div>
            4  +</body></html>

Added skins/khaki/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss">
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen">
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="title">$<title></div>
           13  +  <div class="status">
           14  +    <div class="logo">$<project_name></div><br/>
           15  +    <th1>
           16  +     if {[info exists login]} {
           17  +       puts "Logged in as $login"
           18  +     } else {
           19  +       puts "Not logged in"
           20  +     }
           21  +  </th1></div>
           22  +</div>
           23  +<div class="mainmenu">
           24  +<th1>
           25  +html "<a href='$home$index_page'>Home</a>\n"
           26  +if {[anycap jor]} {
           27  +  html "<a href='$home/timeline'>Timeline</a>\n"
           28  +}
           29  +if {[hascap oh]} {
           30  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
           31  +}
           32  +if {[hascap o]} {
           33  +  html "<a href='$home/brlist'>Branches</a>\n"
           34  +  html "<a href='$home/taglist'>Tags</a>\n"
           35  +}
           36  +if {[hascap r]} {
           37  +  html "<a href='$home/reportlist'>Tickets</a>\n"
           38  +}
           39  +if {[hascap j]} {
           40  +  html "<a href='$home/wiki'>Wiki</a>\n"
           41  +}
           42  +if {[hascap s]} {
           43  +  html "<a href='$home/setup'>Admin</a>\n"
           44  +} elseif {[hascap a]} {
           45  +  html "<a href='$home/setup_ulist'>Users</a>\n"
           46  +}
           47  +if {[info exists login]} {
           48  +  html "<a href='$home/login'>Logout</a>\n"
           49  +} else {
           50  +  html "<a href='$home/login'>Login</a>\n"
           51  +}
           52  +</th1></div>

Added skins/plain_gray/css.txt.

            1  +/* General settings for the entire page */
            2  +body {
            3  +  margin: 0ex 1ex;
            4  +  padding: 0px;
            5  +  background-color: white;
            6  +  font-family: sans-serif;
            7  +}
            8  +
            9  +/* The project logo in the upper left-hand corner of each page */
           10  +div.logo {
           11  +  display: table-row;
           12  +  text-align: center;
           13  +  /* vertical-align: bottom;*/
           14  +  font-size: 2em;
           15  +  font-weight: bold;
           16  +  background-color: #707070;
           17  +  color: #ffffff;
           18  +  min-width: 200px;
           19  +  white-space: nowrap;
           20  +}
           21  +
           22  +/* The page title centered at the top of each page */
           23  +div.title {
           24  +  display: table-cell;
           25  +  font-size: 1.5em;
           26  +  font-weight: bold;
           27  +  text-align: center;
           28  +  padding: 0 0 0 10px;
           29  +  color: #404040;
           30  +  vertical-align: bottom;
           31  +  width: 100%;
           32  +}
           33  +
           34  +/* The login status message in the top right-hand corner */
           35  +div.status {
           36  +  display: table-cell;
           37  +  text-align: right;
           38  +  vertical-align: bottom;
           39  +  color: #404040;
           40  +  font-size: 0.8em;
           41  +  font-weight: bold;
           42  +  min-width: 200px;
           43  +  white-space: nowrap;
           44  +}
           45  +
           46  +/* The header across the top of the page */
           47  +div.header {
           48  +  display: table;
           49  +  width: 100%;
           50  +}
           51  +
           52  +/* The main menu bar that appears at the top of the page beneath
           53  +** the header */
           54  +div.mainmenu {
           55  +  padding: 5px 10px 5px 10px;
           56  +  font-size: 0.9em;
           57  +  font-weight: bold;
           58  +  text-align: center;
           59  +  letter-spacing: 1px;
           60  +  background-color: #404040;
           61  +  color: white;
           62  +}
           63  +
           64  +/* The submenu bar that *sometimes* appears below the main menu */
           65  +div.submenu, div.sectionmenu {
           66  +  padding: 3px 10px 3px 0px;
           67  +  font-size: 0.9em;
           68  +  text-align: center;
           69  +  background-color: #606060;
           70  +  color: white;
           71  +}
           72  +div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
           73  +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
           74  +  padding: 3px 10px 3px 10px;
           75  +  color: white;
           76  +  text-decoration: none;
           77  +}
           78  +div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
           79  +  color: #404040;
           80  +  background-color: white;
           81  +}
           82  +
           83  +/* All page content from the bottom of the menu or submenu down to
           84  +** the footer */
           85  +div.content {
           86  +  padding: 0ex 0ex 0ex 0ex;
           87  +}
           88  +/* Hyperlink colors */
           89  +div.content a { color: #604000; }
           90  +div.content a:link { color: #604000;}
           91  +div.content a:visited { color: #600000; }
           92  +
           93  +/* <verbatim> blocks */
           94  +pre.verbatim {
           95  +  background-color: #ffffff;
           96  +  padding: 0.5em;
           97  +  white-space: pre-wrap;
           98  +}
           99  +
          100  +/* Some pages have section dividers */
          101  +div.section {
          102  +  margin-bottom: 0px;
          103  +  margin-top: 1em;
          104  +  padding: 1px 1px 1px 1px;
          105  +  font-size: 1.2em;
          106  +  font-weight: bold;
          107  +  background-color: #404040;
          108  +  color: white;
          109  +  white-space: nowrap;
          110  +}
          111  +
          112  +/* The "Date" that occurs on the left hand side of timelines */
          113  +div.divider {
          114  +  background: #a0a0a0;
          115  +  border: 2px #505050 solid;
          116  +  font-size: 1em; font-weight: normal;
          117  +  padding: .25em;
          118  +  margin: .2em 0 .2em 0;
          119  +  float: left;
          120  +  clear: left;
          121  +  white-space: nowrap;
          122  +}
          123  +
          124  +/* The footer at the very bottom of the page */
          125  +div.footer {
          126  +  font-size: 0.8em;
          127  +  margin-top: 12px;
          128  +  padding: 5px 10px 5px 10px;
          129  +  text-align: right;
          130  +  background-color: #404040;
          131  +  color: white;
          132  +}
          133  +
          134  +/* The label/value pairs on (for example) the vinfo page */
          135  +table.label-value th {
          136  +  vertical-align: top;
          137  +  text-align: right;
          138  +  padding: 0.2ex 2ex;
          139  +}

Added skins/plain_gray/footer.txt.

            1  +<div class="footer">
            2  +Fossil version $manifest_version $manifest_date
            3  +</div>
            4  +</body></html>

Added skins/plain_gray/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss">
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen">
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="title"><small>$<project_name></small><br />$<title></div>
           13  +  <div class="status"><th1>
           14  +     if {[info exists login]} {
           15  +       puts "Logged in as $login"
           16  +     } else {
           17  +       puts "Not logged in"
           18  +     }
           19  +  </th1></div>
           20  +</div>
           21  +<div class="mainmenu">
           22  +<th1>
           23  +html "<a href='$home$index_page'>Home</a>\n"
           24  +if {[anycap jor]} {
           25  +  html "<a href='$home/timeline'>Timeline</a>\n"
           26  +}
           27  +if {[hascap oh]} {
           28  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
           29  +}
           30  +if {[hascap o]} {
           31  +  html "<a href='$home/brlist'>Branches</a>\n"
           32  +  html "<a href='$home/taglist'>Tags</a>\n"
           33  +}
           34  +if {[hascap r]} {
           35  +  html "<a href='$home/reportlist'>Tickets</a>\n"
           36  +}
           37  +if {[hascap j]} {
           38  +  html "<a href='$home/wiki'>Wiki</a>\n"
           39  +}
           40  +if {[hascap s]} {
           41  +  html "<a href='$home/setup'>Admin</a>\n"
           42  +} elseif {[hascap a]} {
           43  +  html "<a href='$home/setup_ulist'>Users</a>\n"
           44  +}
           45  +if {[info exists login]} {
           46  +  html "<a href='$home/login'>Logout</a>\n"
           47  +} else {
           48  +  html "<a href='$home/login'>Login</a>\n"
           49  +}
           50  +</th1></div>

Added skins/rounded1/css.txt.

            1  +/* General settings for the entire page */
            2  +html {
            3  +  min-height: 100%;
            4  +}
            5  +body {
            6  +  margin: 0ex 1ex;
            7  +  padding: 0px;
            8  +  background-color: white;
            9  +  color: #333;
           10  +  font-family: Verdana, sans-serif;
           11  +  font-size: 0.8em;
           12  +}
           13  +
           14  +/* The project logo in the upper left-hand corner of each page */
           15  +div.logo {
           16  +  display: table-cell;
           17  +  text-align: right;
           18  +  vertical-align: bottom;
           19  +  font-weight: normal;
           20  +  white-space: nowrap;
           21  +}
           22  +
           23  +/* Widths */
           24  +div.header, div.mainmenu, div.submenu, div.content, div.footer {
           25  +  max-width: 900px;
           26  +  margin: auto;
           27  +  padding: 3px 20px 3px 20px;
           28  +  clear: both;
           29  +}
           30  +
           31  +/* The page title at the top of each page */
           32  +div.title {
           33  +  display: table-cell;
           34  +  padding-left: 10px;
           35  +  font-size: 2em;
           36  +  margin: 10px 0 10px -20px;
           37  +  vertical-align: bottom;
           38  +  text-align: left;
           39  +  width: 80%;
           40  +  font-family: Verdana, sans-serif;
           41  +  font-weight: bold;
           42  +  color: #558195;
           43  +  text-shadow: 0px 2px 2px #999999;
           44  +}
           45  +
           46  +/* The login status message in the top right-hand corner */
           47  +div.status {
           48  +  display: table-cell;
           49  +  text-align: right;
           50  +  vertical-align: bottom;
           51  +  color: #333;
           52  +  margin-right: -20px;
           53  +  white-space: nowrap;
           54  +}
           55  +
           56  +/* The main menu bar that appears at the top of the page beneath
           57  + ** the header */
           58  +div.mainmenu {
           59  +  text-align: center;
           60  +  color: white;
           61  +  border-top-left-radius: 5px;
           62  +  border-top-right-radius: 5px;
           63  +  vertical-align: middle;
           64  +  padding-top: 8px;
           65  +  padding-bottom: 8px;
           66  +  background-color: #446979;
           67  +  box-shadow: 0px 3px 4px #333333;
           68  +}
           69  +
           70  +/* The submenu bar that *sometimes* appears below the main menu */
           71  +div.submenu {
           72  +  padding-top:10px;
           73  +  padding-bottom:0;
           74  +  text-align: right;
           75  +  color: #000;
           76  +  background-color: #fff;
           77  +  height: 1.5em;
           78  +  vertical-align:middle;
           79  +  box-shadow: 0px 3px 4px #999;
           80  +}
           81  +div.mainmenu a, div.mainmenu a:visited {
           82  +  padding: 3px 10px 3px 10px;
           83  +  color: white;
           84  +  text-decoration: none;
           85  +}
           86  +div.submenu a, div.submenu a:visited, a.button,
           87  +div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
           88  +  padding: 2px 8px;
           89  +  color: #000;
           90  +  font-family: Arial;
           91  +  text-decoration: none;
           92  +  margin:auto;
           93  +  border-radius: 5px;
           94  +  background-color: #e0e0e0;
           95  +  text-shadow: 0px -1px 0px #eee;
           96  +  border: 1px solid #000;
           97  +}
           98  +
           99  +div.mainmenu a:hover {
          100  +  color: #000;
          101  +  background-color: white;
          102  +}
          103  +
          104  +div.submenu a:hover, div.sectionmenu>a.button:hover {
          105  +  background-color: #c0c0c0;
          106  +}
          107  +
          108  +/* All page content from the bottom of the menu or submenu down to
          109  + ** the footer */
          110  +div.content {
          111  +  background-color: #fff;
          112  +  box-shadow: 0px 3px 4px #999;
          113  +  border-bottom-right-radius: 5px;
          114  +  border-bottom-left-radius: 5px;
          115  +  padding-bottom: 1em;
          116  +  min-height:40%;
          117  +}
          118  +
          119  +
          120  +/* Some pages have section dividers */
          121  +div.section {
          122  +  margin-bottom: 0.5em;
          123  +  margin-top: 1em;
          124  +  margin-right: auto;
          125  +  padding: 1px 1px 1px 1px;
          126  +  font-size: 1.2em;
          127  +  font-weight: bold;
          128  +  text-align: center;
          129  +  color: white;
          130  +  border-radius: 5px;
          131  +  background-color: #446979;
          132  +  box-shadow: 0px 3px 4px #333333;
          133  +  white-space: nowrap;
          134  +}
          135  +
          136  +/* The "Date" that occurs on the left hand side of timelines */
          137  +div.divider {
          138  +  font-size: 1.2em;
          139  +  font-family: Georgia, serif;
          140  +  font-weight: bold;
          141  +  margin-top: 1em;
          142  +  white-space: nowrap;
          143  +}
          144  +
          145  +/* The footer at the very bottom of the page */
          146  +div.footer {
          147  +  font-size: 0.9em;
          148  +  text-align: right;
          149  +  margin-bottom: 1em;
          150  +  color: #666;
          151  +}
          152  +
          153  +/* Hyperlink colors in the footer */
          154  +div.footer a { color: white; }
          155  +div.footer a:link { color: white; }
          156  +div.footer a:visited { color: white; }
          157  +div.footer a:hover { background-color: white; color: #558195; }
          158  +
          159  +/* <verbatim> blocks */
          160  +pre.verbatim, blockquote pre {
          161  +  font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace;
          162  +  background-color: #f3f3f3;
          163  +  padding: 0.5em;
          164  +  white-space: pre-wrap;
          165  +}
          166  +
          167  +blockquote pre {
          168  +  border: 1px #000 dashed;
          169  +}
          170  +
          171  +/* The label/value pairs on (for example) the ci page */
          172  +table.label-value th {
          173  +  vertical-align: top;
          174  +  text-align: right;
          175  +  padding: 0.2ex 2ex;
          176  +}
          177  +
          178  +table.report tr th {
          179  +  padding: 3px 5px;
          180  +  text-transform: capitalize;
          181  +  cursor: pointer;
          182  +}
          183  +
          184  +table.report tr td {
          185  +  padding: 3px 5px;
          186  +  cursor: pointer;
          187  +}
          188  +
          189  +textarea {
          190  +  font-size: 1em;
          191  +}
          192  +
          193  +.fullsize-text {
          194  +  font-size: 1.25em;
          195  +}

Added skins/rounded1/footer.txt.

            1  +<div class="footer">
            2  +Fossil version $manifest_version $manifest_date
            3  +</div>
            4  +</body></html>

Added skins/rounded1/header.txt.

            1  +<html>
            2  +<head>
            3  +<base href="$baseurl/$current_page" />
            4  +<title>$<project_name>: $<title></title>
            5  +<link rel="alternate" type="application/rss+xml" title="RSS Feed"
            6  +      href="$home/timeline.rss">
            7  +<link rel="stylesheet" href="$stylesheet_url" type="text/css"
            8  +      media="screen">
            9  +</head>
           10  +<body>
           11  +<div class="header">
           12  +  <div class="logo">
           13  +    <img src="$logo_image_url" alt="logo">
           14  +    <br />$<project_name>
           15  +  </div>
           16  +  <div class="title">$<title></div>
           17  +  <div class="status"><th1>
           18  +     if {[info exists login]} {
           19  +       puts "Logged in as $login"
           20  +     } else {
           21  +       puts "Not logged in"
           22  +     }
           23  +  </th1></div>
           24  +</div>
           25  +<div class="mainmenu">
           26  +<th1>
           27  +html "<a href='$home$index_page'>Home</a>\n"
           28  +if {[anycap jor]} {
           29  +  html "<a href='$home/timeline'>Timeline</a>\n"
           30  +}
           31  +if {[hascap oh]} {
           32  +  html "<a href='$home/tree?ci=tip'>Files</a>\n"
           33  +}
           34  +if {[hascap o]} {
           35  +  html "<a href='$home/brlist'>Branches</a>\n"
           36  +  html "<a href='$home/taglist'>Tags</a>\n"
           37  +}
           38  +if {[hascap r]} {
           39  +  html "<a href='$home/reportlist'>Tickets</a>\n"
           40  +}
           41  +if {[hascap j]} {
           42  +  html "<a href='$home/wiki'>Wiki</a>\n"
           43  +}
           44  +if {[hascap s]} {
           45  +  html "<a href='$home/setup'>Admin</a>\n"
           46  +} elseif {[hascap a]} {
           47  +  html "<a href='$home/setup_ulist'>Users</a>\n"
           48  +}
           49  +if {[info exists login]} {
           50  +  html "<a href='$home/login'>Logout</a>\n"
           51  +} else {
           52  +  html "<a href='$home/login'>Login</a>\n"
           53  +}
           54  +</th1></div>

Changes to src/attach.c.

    88     88         zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
    89     89       }
    90     90       @ <li><p>
    91     91       @ Attachment %z(href("%R/ainfo/%s",zUuid))%S(zUuid)</a>
    92     92       if( moderation_pending(attachid) ){
    93     93         @ <span class="modpending">*** Awaiting Moderator Approval ***</span>
    94     94       }
    95         -    @ <br><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
    96         -    @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
           95  +    @ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
           96  +    @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
    97     97       if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
    98     98       if( zComment && zComment[0] ){
    99     99         @ %!w(zComment)<br />
   100    100       }
   101    101       if( zPage==0 && zTkt==0 ){
   102    102         if( zSrc==0 || zSrc[0]==0 ){
   103    103           zSrc = "Deleted from";

Changes to src/branch.c.

   339    339   */
   340    340   static void new_brlist_page(void){
   341    341     Stmt q;
   342    342     double rNow;
   343    343     login_check_credentials();
   344    344     if( !g.perm.Read ){ login_needed(); return; }
   345    345     style_header("Branches");
          346  +  style_adunit_config(ADUNIT_RIGHT_OK);
   346    347     login_anonymous_available();
   347    348     
   348    349     db_prepare(&q, brlistQuery/*works-like:""*/);
   349    350     rNow = db_double(0.0, "SELECT julianday('now')");
   350    351     @ <div class="brlist"><table id="branchlisttable">
   351    352     @ <thead><tr>
   352    353     @ <th>Branch Name</th>
................................................................................
   364    365       const char *zLastCkin = db_column_text(&q, 5);
   365    366       char *zAge = human_readable_age(rNow - rMtime);
   366    367       sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
   367    368       if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
   368    369       @ <tr>
   369    370       @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
   370    371       @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
   371         -    @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td>
          372  +    @ <td>%d(nCkin)</td>
   372    373       fossil_free(zAge);
   373    374       @ <td>%s(isClosed?"closed":"")</td>
   374    375       if( zMergeTo ){
   375    376         @ <td>merged into
   376    377         @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td>
   377    378       }else{
   378    379         @ <td></td>
   379    380       }
   380    381       @ </tr>
   381    382     }
   382    383     @ </tbody></table></div>
   383    384     db_finalize(&q);
   384         -  output_table_sorting_javascript("branchlisttable","tkktt",2);
          385  +  output_table_sorting_javascript("branchlisttable","tkNtt",2);
   385    386     style_footer();
   386    387   }
   387    388   
   388    389   /*
   389    390   ** WEBPAGE: brlist
   390    391   ** Show a list of branches
   391    392   ** Query parameters:

Changes to src/browse.c.

   131    131     HQuery sURI;
   132    132   
   133    133     if( strcmp(PD("type",""),"tree")==0 ){ page_tree(); return; }
   134    134     login_check_credentials();
   135    135     if( !g.perm.Read ){ login_needed(); return; }
   136    136     while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
   137    137     style_header("File List");
          138  +  style_adunit_config(ADUNIT_RIGHT_OK);
   138    139     sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
   139    140                             pathelementFunc, 0, 0);
   140    141     url_initialize(&sURI, "dir");
   141    142   
   142    143     /* If the name= parameter is an empty string, make it a NULL pointer */
   143    144     if( zD && strlen(zD)==0 ){ zD = 0; }
   144    145   
................................................................................
   553    554       showDirOnly = 1;
   554    555       url_add_parameter(&sURI, "nofiles", "1");
   555    556       style_header("Folder Hierarchy");
   556    557     }else{
   557    558       showDirOnly = 0;
   558    559       style_header("File Tree");
   559    560     }
          561  +  style_adunit_config(ADUNIT_RIGHT_OK);
   560    562     if( P("expand")!=0 ){
   561    563       startExpanded = 1;
   562    564       url_add_parameter(&sURI, "expand", "1");
   563    565     }else{
   564    566       startExpanded = 0;
   565    567     }
   566    568   
................................................................................
   633    635       style_submenu_element("Trunk", "Trunk", "%s",
   634    636                             url_render(&sURI, "ci", "trunk", 0, 0));
   635    637     }
   636    638     if( linkTip ){
   637    639       style_submenu_element("Tip", "Tip", "%s",
   638    640                             url_render(&sURI, "ci", "tip", 0, 0));
   639    641     }
          642  +  style_submenu_element("Flat-View", "Flat-View", "%s",
          643  +                        url_render(&sURI, "type", "flat", 0, 0));
   640    644   
   641    645     /* Compute the file hierarchy.
   642    646     */
   643    647     if( zCI ){
   644    648       Stmt q;
   645    649       compute_fileage(rid, 0);
   646    650       db_prepare(&q,
................................................................................
   650    654          "   AND blob.rid=fileage.fid\n"
   651    655          " ORDER BY filename.name COLLATE nocase;"
   652    656       );
   653    657       while( db_step(&q)==SQLITE_ROW ){
   654    658         const char *zFile = db_column_text(&q,0);
   655    659         const char *zUuid = db_column_text(&q,1);
   656    660         double mtime = db_column_double(&q,2);
          661  +      if( nD>0 && (fossil_strncmp(zFile, zD, nD-1)!=0 || zFile[nD-1]!='/') ){
          662  +        continue;
          663  +      }
   657    664         if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue;
   658    665         tree_add_node(&sTree, zFile, zUuid, mtime);
   659    666         nFile++;
   660    667       }
   661    668       db_finalize(&q);
   662    669     }else{
   663    670       Stmt q;

Changes to src/builtin.c.

    29     29   */
    30     30   #include "builtin_data.h"
    31     31   
    32     32   /*
    33     33   ** Return a pointer to built-in content
    34     34   */
    35     35   const unsigned char *builtin_file(const char *zFilename, int *piSize){
    36         -  int lwr, upr, i;
           36  +  int lwr, upr, i, c;
    37     37     lwr = 0;
    38     38     upr = sizeof(aBuiltinFiles)/sizeof(aBuiltinFiles[0]) - 1;
    39     39     while( upr>=lwr ){
    40     40       i = (upr+lwr)/2;
    41         -    if( strcmp(aBuiltinFiles[i].zName,zFilename)==0 ){
           41  +    c = strcmp(aBuiltinFiles[i].zName,zFilename);
           42  +    if( c<0 ){
           43  +      lwr = i+1;
           44  +    }else if( c>0 ){
           45  +      upr = i-1;
           46  +    }else{
    42     47         if( piSize ) *piSize = aBuiltinFiles[i].nByte;
    43     48         return aBuiltinFiles[i].pData;
    44     49       }
    45     50     }
    46     51     if( piSize ) *piSize = 0;
    47     52     return 0;
           53  +}
           54  +const char *builtin_text(const char *zFilename){
           55  +  return (char*)builtin_file(zFilename, 0);
    48     56   }
    49     57   
    50     58   /*
    51     59   ** COMMAND: test-builtin-list
    52     60   **
    53     61   ** List the names and sizes of all built-in resources
    54     62   */

Changes to src/cgi.c.

   106    106   /*
   107    107   ** Check to see if the header contains the zNeedle string.  Return true
   108    108   ** if it does and false if it does not.
   109    109   */
   110    110   int cgi_header_contains(const char *zNeedle){
   111    111     return strstr(blob_str(&cgiContent[0]), zNeedle)!=0;
   112    112   }
          113  +int cgi_body_contains(const char *zNeedle){
          114  +  return strstr(blob_str(&cgiContent[1]), zNeedle)!=0;
          115  +}
   113    116   
   114    117   /*
   115    118   ** Append reply content to what already exists.
   116    119   */
   117    120   void cgi_append_content(const char *zData, int nAmt){
   118    121     blob_append(pContent, zData, nAmt);
   119    122   }

Changes to src/codecheck1.c.

   274    274     /* A string literal is safe for use with %s */
   275    275     if( is_string_lit(z) ) return 1;
   276    276   
   277    277     /* Certain functions are guaranteed to return a string that is safe
   278    278     ** for use with %s */
   279    279     z = next_non_whitespace(z, &len, &eType);
   280    280     for(i=0; i<sizeof(azSafeFunc)/sizeof(azSafeFunc[0]); i++){
   281         -    if( eType==TK_ID 
          281  +    if( eType==TK_ID
   282    282        && strncmp(z, azSafeFunc[i], len)==0
   283    283        && strlen(azSafeFunc[i])==len
   284    284       ){
   285    285         return 1;
   286    286       }
   287    287     }
   288    288   
................................................................................
   289    289     /* Expressions of the form:  EXPR ? "..." : "...." can count as
   290    290     ** a string literal. */
   291    291     if( is_string_expr(z) ) return 1;
   292    292   
   293    293     /* If the "safe-for-%s" comment appears in the argument, then
   294    294     ** let it through */
   295    295     if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1;
   296         -    
          296  +
   297    297     return 0;
   298    298   }
   299    299   
   300    300   /*
   301    301   ** Processing flags
   302    302   */
   303    303   #define FMT_NO_S   0x00001     /* Do not allow %s substitutions */
................................................................................
   458    458       if( z[len]==0 ) break;
   459    459       z[len] = 0;
   460    460       for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; }
   461    461       z += len + 1;
   462    462     }
   463    463     acType = (char*)&azArg[nArg];
   464    464     if( fmtArg>nArg ){
   465         -    printf("%s:%d: too few arguments to %.*s()\n", 
          465  +    printf("%s:%d: too few arguments to %.*s()\n",
   466    466              zFilename, lnFCall, szFName, zFCall);
   467    467       nErr++;
   468    468     }else{
   469    469       const char *zFmt = azArg[fmtArg-1];
   470    470       const char *zOverride = strstr(zFmt, "/*works-like:");
   471    471       if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1;
   472    472       if( !is_string_lit(zFmt) ){
................................................................................
   535    535           nCurly++;
   536    536         }else if( z[0]=='}' ){
   537    537           nCurly--;
   538    538         }else if( nCurly>0 && z[0]=='(' && ePrev==TK_ID
   539    539               && (x = isFormatFunc(zPrev,szPrev,&fmtFlags))>0 ){
   540    540           nErr += checkFormatFunc(zName, zPrev, lnPrev, x, fmtFlags);
   541    541         }
   542         -    }    
          542  +    }
   543    543       zPrev = z;
   544    544       ePrev = eToken;
   545    545       szPrev = szToken;
   546    546       lnPrev = ln;
   547    547     }
   548    548     return nErr;
   549    549   }

Changes to src/configure.c.

    95     95     { "index-page",             CONFIGSET_SKIN },
    96     96     { "timeline-block-markup",  CONFIGSET_SKIN },
    97     97     { "timeline-max-comment",   CONFIGSET_SKIN },
    98     98     { "timeline-plaintext",     CONFIGSET_SKIN },
    99     99     { "adunit",                 CONFIGSET_SKIN },
   100    100     { "adunit-omit-if-admin",   CONFIGSET_SKIN },
   101    101     { "adunit-omit-if-user",    CONFIGSET_SKIN },
          102  +  { "white-foreground",       CONFIGSET_SKIN },
   102    103   #ifdef FOSSIL_ENABLE_TH1_DOCS
   103    104     { "th1-docs",               CONFIGSET_TH1 },
   104    105   #endif
   105    106   #ifdef FOSSIL_ENABLE_TH1_HOOKS
   106    107     { "th1-hooks",              CONFIGSET_TH1 },
   107    108   #endif
   108    109     { "th1-setup",              CONFIGSET_TH1 },
................................................................................
   987    988     }else
   988    989     {
   989    990       fossil_fatal("METHOD should be one of:"
   990    991                    " export import merge pull push reset");
   991    992     }
   992    993     configure_rebuild();
   993    994   }
          995  +
          996  +
          997  +/*
          998  +** COMMAND: test-var-list
          999  +**
         1000  +** Usage: %fossil test-var-list ?PATTERN? ?--unset? ?--mtime?
         1001  +**
         1002  +** Show the content of the CONFIG table in a repository.  If PATTERN is
         1003  +** specified, then only show the entries that match that glob pattern.
         1004  +** Last modification time is shown if the --mtime option is present.
         1005  +**
         1006  +** If the --unset option is included, then entries are deleted rather than
         1007  +** being displayed.  WARNING! This cannot be undone.  Be sure you know what
         1008  +** you are doing!  The --unset option only works if there is a PATTERN.
         1009  +** Probably you should run the command once without --unset to make sure
         1010  +** you know exactly what is being deleted.
         1011  +**
         1012  +** If not in an open check-out, use the -R REPO option to specify a
         1013  +** a repository.
         1014  +*/
         1015  +void test_var_list_cmd(void){
         1016  +  Stmt q;
         1017  +  int i, j;
         1018  +  const char *zPattern = 0;
         1019  +  int doUnset;
         1020  +  int showMtime;
         1021  +  Blob sql;
         1022  +  Blob ans;
         1023  +  unsigned char zTrans[1000];
         1024  +
         1025  +  doUnset = find_option("unset",0,0)!=0;
         1026  +  showMtime = find_option("mtime",0,0)!=0;
         1027  +  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
         1028  +  verify_all_options();
         1029  +  if( g.argc>=3 ){
         1030  +    zPattern = g.argv[2];
         1031  +  }
         1032  +  blob_init(&sql,0,0);
         1033  +  blob_appendf(&sql, "SELECT name, value, datetime(mtime,'unixepoch')"
         1034  +                     " FROM config");
         1035  +  if( zPattern ){
         1036  +    blob_appendf(&sql, " WHERE name GLOB %Q", zPattern);
         1037  +  }
         1038  +  if( showMtime ){
         1039  +    blob_appendf(&sql, " ORDER BY mtime, name");
         1040  +  }else{
         1041  +    blob_appendf(&sql, " ORDER BY name");
         1042  +  }
         1043  +  db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/);
         1044  +  blob_reset(&sql);
         1045  +#define MX_VAL 40
         1046  +#define MX_NM  28
         1047  +#define MX_LONGNM 60
         1048  +  while( db_step(&q)==SQLITE_ROW ){
         1049  +    const char *zName = db_column_text(&q,0);
         1050  +    int nName = db_column_bytes(&q,0);
         1051  +    const char *zValue = db_column_text(&q,1);
         1052  +    int szValue = db_column_bytes(&q,1);
         1053  +    const char *zMTime = db_column_text(&q,2);
         1054  +    for(i=j=0; j<MX_VAL && zValue[i]; i++){
         1055  +      unsigned char c = (unsigned char)zValue[i];
         1056  +      if( c>=' ' && c<='~' ){
         1057  +        zTrans[j++] = c;
         1058  +      }else{
         1059  +        zTrans[j++] = '\\';
         1060  +        if( c=='\n' ){
         1061  +          zTrans[j++] = 'n';
         1062  +        }else if( c=='\r' ){
         1063  +          zTrans[j++] = 'r';
         1064  +        }else if( c=='\t' ){
         1065  +          zTrans[j++] = 't';
         1066  +        }else{      
         1067  +          zTrans[j++] = '0' + ((c>>6)&7);
         1068  +          zTrans[j++] = '0' + ((c>>3)&7);
         1069  +          zTrans[j++] = '0' + (c&7);
         1070  +        }
         1071  +      }
         1072  +    }
         1073  +    zTrans[j] = 0;
         1074  +    if( i<szValue ){
         1075  +      sqlite3_snprintf(sizeof(zTrans)-j, (char*)zTrans+j, "...+%d", szValue-i);
         1076  +      j += (int)strlen((char*)zTrans+j);
         1077  +    }
         1078  +    if( showMtime ){
         1079  +      fossil_print("%s:%*s%s\n", zName, 58-nName, "", zMTime);
         1080  +    }else if( nName<MX_NM-2 ){
         1081  +      fossil_print("%s:%*s%s\n", zName, MX_NM-1-nName, "", zTrans);
         1082  +    }else if( nName<MX_LONGNM-2 && j<10 ){
         1083  +      fossil_print("%s:%*s%s\n", zName, MX_LONGNM-1-nName, "", zTrans);
         1084  +    }else{
         1085  +      fossil_print("%s:\n%*s%s\n", zName, MX_NM, "", zTrans);
         1086  +    }
         1087  +  }
         1088  +  db_finalize(&q);
         1089  +  if( zPattern && doUnset ){
         1090  +    prompt_user("Delete all of the above? (y/N)? ", &ans);
         1091  +    if( blob_str(&ans)[0]=='y' || blob_str(&ans)[0]=='Y' ){
         1092  +      db_multi_exec("DELETE FROM config WHERE name GLOB %Q", zPattern);
         1093  +    }
         1094  +    blob_reset(&ans);
         1095  +  }
         1096  +}
         1097  +
         1098  +/*
         1099  +** COMMAND: test-var-get
         1100  +**
         1101  +** Usage: %fossil test-var-get VAR ?FILE?
         1102  +**
         1103  +** Write the text of the VAR variable into FILE.  If FILE is "-" 
         1104  +** or is omitted then output goes to standard output.  VAR can be a
         1105  +** GLOB pattern.
         1106  +**
         1107  +** If not in an open check-out, use the -R REPO option to specify a
         1108  +** a repository.
         1109  +*/
         1110  +void test_var_get_cmd(void){
         1111  +  const char *zVar;
         1112  +  const char *zFile;
         1113  +  int n;
         1114  +  Blob x;
         1115  +  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
         1116  +  verify_all_options();
         1117  +  if( g.argc<3 ){
         1118  +    usage("VAR ?FILE?");
         1119  +  }
         1120  +  zVar = g.argv[2];
         1121  +  zFile = g.argc>=4 ? g.argv[3] : "-";
         1122  +  n = db_int(0, "SELECT count(*) FROM config WHERE name GLOB %Q", zVar);
         1123  +  if( n==0 ){
         1124  +    fossil_fatal("no match for %Q", zVar);
         1125  +  }
         1126  +  if( n>1 ){
         1127  +    fossil_fatal("multiple matches: %s",
         1128  +      db_text(0, "SELECT group_concat(quote(name),', ') FROM ("
         1129  +                 " SELECT name FROM config WHERE name GLOB %Q ORDER BY 1)",
         1130  +                 zVar));
         1131  +  }
         1132  +  blob_init(&x,0,0);
         1133  +  db_blob(&x, "SELECT value FROM config WHERE name GLOB %Q", zVar);
         1134  +  blob_write_to_file(&x, zFile);
         1135  +}
         1136  +
         1137  +/*
         1138  +** COMMAND: test-var-set
         1139  +**
         1140  +** Usage: %fossil test-var-set VAR ?VALUE? ?--file FILE?
         1141  +**
         1142  +** Store VALUE or the content of FILE (exactly one of which must be
         1143  +** supplied) into variable VAR.  Use a FILE of "-" to read from
         1144  +** standard input.
         1145  +**
         1146  +** WARNING: changing the value of a variable can interfere with the
         1147  +** operation of Fossil.  Be sure you know what you are doing.
         1148  +**
         1149  +** Use "--blob FILE" instead of "--file FILE" to load a binary blob
         1150  +** such as a GIF.
         1151  +*/
         1152  +void test_var_set_cmd(void){
         1153  +  const char *zVar;
         1154  +  const char *zFile;
         1155  +  const char *zBlob;
         1156  +  Blob x;
         1157  +  Stmt ins;
         1158  +  zFile = find_option("file",0,1);
         1159  +  zBlob = find_option("blob",0,1);
         1160  +  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
         1161  +  verify_all_options();
         1162  +  if( g.argc<3 || (zFile==0 && zBlob==0 && g.argc<4) ){
         1163  +    usage("VAR ?VALUE? ?--file FILE?");
         1164  +  }
         1165  +  zVar = g.argv[2];
         1166  +  if( zFile ){
         1167  +    if( zBlob ) fossil_fatal("cannot do both --file or --blob");
         1168  +    blob_read_from_file(&x, zFile);
         1169  +  }else if( zBlob ){
         1170  +    blob_read_from_file(&x, zBlob);
         1171  +  }else{
         1172  +    blob_init(&x,g.argv[3],-1);
         1173  +  }
         1174  +  db_prepare(&ins,
         1175  +     "REPLACE INTO config(name,value,mtime)"
         1176  +     "VALUES(%Q,:val,now())", zVar);
         1177  +  if( zBlob ){
         1178  +    db_bind_blob(&ins, ":val", &x);
         1179  +  }else{
         1180  +    db_bind_text(&ins, ":val", blob_str(&x));
         1181  +  }
         1182  +  db_step(&ins);
         1183  +  db_finalize(&ins);
         1184  +  blob_reset(&x);
         1185  +}

Changes to src/db.c.

   803    803   void db_add_aux_functions(sqlite3 *db){
   804    804     sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
   805    805                             db_checkin_mtime_function, 0, 0);
   806    806     sqlite3_create_function(db, "symbolic_name_to_rid", 1, SQLITE_UTF8, 0,
   807    807                             db_sym2rid_function, 0, 0);
   808    808     sqlite3_create_function(db, "symbolic_name_to_rid", 2, SQLITE_UTF8, 0,
   809    809                             db_sym2rid_function, 0, 0);
          810  +  sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0,
          811  +                                 db_now_function, 0, 0);
   810    812   }
   811    813   
   812    814   
   813    815   /*
   814    816   ** Open a database file.  Return a pointer to the new database
   815    817   ** connection.  An error results in process abort.
   816    818   */
................................................................................
   825    827          g.zVfsName
   826    828     );
   827    829     if( rc!=SQLITE_OK ){
   828    830       db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
   829    831     }
   830    832     sqlite3_busy_timeout(db, 5000);
   831    833     sqlite3_wal_autocheckpoint(db, 1);  /* Set to checkpoint frequently */
   832         -  sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0,
   833         -                                 db_now_function, 0, 0);
   834    834     sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
   835    835     sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
   836    836     sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
   837    837     sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
   838    838     sqlite3_create_function(
   839    839       db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
   840    840     );
................................................................................
   925    925   void db_open_config(int useAttach){
   926    926     char *zDbName;
   927    927     char *zHome;
   928    928     if( g.zConfigDbName ){
   929    929       if( useAttach==g.useAttach ) return;
   930    930       db_close_config();
   931    931     }
          932  +  zHome = fossil_getenv("FOSSIL_HOME");
   932    933   #if defined(_WIN32) || defined(__CYGWIN__)
   933         -  zHome = fossil_getenv("LOCALAPPDATA");
   934    934     if( zHome==0 ){
   935         -    zHome = fossil_getenv("APPDATA");
          935  +    zHome = fossil_getenv("LOCALAPPDATA");
   936    936       if( zHome==0 ){
   937         -      char *zDrive = fossil_getenv("HOMEDRIVE");
   938         -      zHome = fossil_getenv("HOMEPATH");
   939         -      if( zDrive && zHome ) zHome = mprintf("%s%s", zDrive, zHome);
          937  +      zHome = fossil_getenv("APPDATA");
          938  +      if( zHome==0 ){
          939  +        char *zDrive = fossil_getenv("HOMEDRIVE");
          940  +        char *zPath = fossil_getenv("HOMEPATH");
          941  +        if( zDrive && zPath ) zHome = mprintf("%s%s", zDrive, zPath);
          942  +      }
   940    943       }
   941    944     }
   942    945     if( zHome==0 ){
   943         -    fossil_fatal("cannot locate home directory - "
   944         -                "please set the LOCALAPPDATA or APPDATA or HOMEPATH "
   945         -                "environment variables");
          946  +    fossil_fatal("cannot locate home directory - please set the "
          947  +                 "FOSSIL_HOME, LOCALAPPDATA, APPDATA, or HOMEPATH "
          948  +                 "environment variables");
   946    949     }
   947    950   #else
   948         -  zHome = fossil_getenv("HOME");
          951  +  if( zHome==0 ){
          952  +    zHome = fossil_getenv("HOME");
          953  +  }
   949    954     if( zHome==0 ){
   950         -    fossil_fatal("cannot locate home directory - "
   951         -                 "please set the HOME environment variable");
          955  +    fossil_fatal("cannot locate home directory - please set the "
          956  +                 "FOSSIL_HOME or HOME environment variables");
   952    957     }
   953    958   #endif
   954    959     if( file_isdir(zHome)!=1 ){
   955    960       fossil_fatal("invalid home directory: %s", zHome);
   956    961     }
   957    962   #if defined(_WIN32) || defined(__CYGWIN__)
   958    963     /* . filenames give some window systems problems and many apps problems */
................................................................................
  1353   1358     pStmt = 0;
  1354   1359     if( reportErrors ){
  1355   1360       while( (pStmt = sqlite3_next_stmt(g.db, pStmt))!=0 ){
  1356   1361         fossil_warning("unfinalized SQL statement: [%s]", sqlite3_sql(pStmt));
  1357   1362       }
  1358   1363     }
  1359   1364     db_close_config();
         1365  +
         1366  +  /* If the localdb (the check-out database) is open and if it has
         1367  +  ** a lot of unused free space, then VACUUM it as we shut down.
         1368  +  */
         1369  +  if( g.localOpen && strcmp(db_name("localdb"),"main")==0 ){
         1370  +    int nFree = db_int(0, "PRAGMA main.freelist_count");
         1371  +    int nTotal = db_int(0, "PRAGMA main.page_count");
         1372  +    if( nFree>nTotal/4 ){
         1373  +      db_multi_exec("VACUUM;");
         1374  +    }
         1375  +  }
         1376  +
  1360   1377     if( g.db ){
  1361   1378       sqlite3_wal_checkpoint(g.db, 0);
  1362   1379       sqlite3_close(g.db);
  1363   1380       g.db = 0;
  1364   1381       g.zMainDbType = 0;
  1365   1382     }
  1366   1383     g.repositoryOpen = 0;
................................................................................
  1420   1437     db_multi_exec(
  1421   1438        "UPDATE user SET cap='s', pw=lower(hex(randomblob(3)))"
  1422   1439        " WHERE login=%Q", zUser
  1423   1440     );
  1424   1441     if( !setupUserOnly ){
  1425   1442       db_multi_exec(
  1426   1443          "INSERT OR IGNORE INTO user(login,pw,cap,info)"
  1427         -       "   VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
         1444  +       "   VALUES('anonymous',hex(randomblob(8)),'hmnc','Anon');"
  1428   1445          "INSERT OR IGNORE INTO user(login,pw,cap,info)"
  1429         -       "   VALUES('nobody','','gjor','Nobody');"
         1446  +       "   VALUES('nobody','','gjorz','Nobody');"
  1430   1447          "INSERT OR IGNORE INTO user(login,pw,cap,info)"
  1431   1448          "   VALUES('developer','','dei','Dev');"
  1432   1449          "INSERT OR IGNORE INTO user(login,pw,cap,info)"
  1433   1450          "   VALUES('reader','','kptw','Reader');"
  1434   1451       );
  1435   1452     }
  1436   1453   }

Changes to src/diff.tcl.

            1  +# The "diff --tk" command outputs prepends a "set fossilcmd {...}" line
            2  +# to this file, then runs this file using "tclsh" in order to display the
            3  +# graphical diff in a separate window.  A typical "set fossilcmd" line
            4  +# looks like this:
            5  +#
            6  +#     set fossilcmd {| "./fossil" diff --html -y -i -v}
            7  +#
            8  +# This header comment is stripped off by the "mkbuiltin.c" program.
            9  +#
     1     10   set prog {
     2     11   package require Tk
     3     12   
     4     13   array set CFG {
     5     14     TITLE      {Fossil Diff}
     6     15     LN_COL_BG  #dddddd
     7     16     LN_COL_FG  #444444

Changes to src/doc.c.

   351    351     for(i=2; i<g.argc; i++){
   352    352       fossil_print("%-20s -> %s\n", g.argv[i], mimetype_from_name(g.argv[i]));
   353    353     }
   354    354   }
   355    355   
   356    356   /*
   357    357   ** WEBPAGE: doc
   358         -** URL: /doc?name=BASELINE/PATH
   359         -** URL: /doc/BASELINE/PATH
          358  +** URL: /doc?name=CHECKIN/FILE
          359  +** URL: /doc/CHECKIN/FILE
          360  +**
          361  +** CHECKIN can be either tag or SHA1 hash or timestamp identifying a
          362  +** particular check, or the name of a branch (meaning the most recent
          363  +** check-in on that branch) or one of various magic words:
          364  +**
          365  +**     "tip"      means the most recent check-in
          366  +**
          367  +**     "ckout"    means the current check-out, if the server is run from
          368  +**                within a check-out, otherwise it is the same as "tip"
          369  +**
          370  +** FILE is the name of a file to delivered up as a webpage.  FILE is relative
          371  +** to the root of the source tree of the repository. The FILE must
          372  +** be a part of CHECKIN, except when CHECKIN=="ckout" when FILE is read
          373  +** directly from disk and need not be a managed file.
   360    374   **
   361         -** BASELINE can be either a baseline uuid prefix or magic words "tip"
   362         -** to mean the most recently checked in baseline or "ckout" to mean the
   363         -** content of the local checkout, if any.  PATH is the relative pathname
   364         -** of some file.  This method returns the file content.
          375  +** The "ckout" CHECKIN is intended for development - to provide a mechanism
          376  +** for looking at what a file will look like using the /doc webpage after
          377  +** it gets checked in.
   365    378   **
   366         -** If PATH matches the patterns *.wiki or *.txt then formatting content
   367         -** is added before returning the file.  For all other names, the content
   368         -** is returned straight without any interpretation or processing.
          379  +** The file extension is used to decide how to render the file.
   369    380   */
   370    381   void doc_page(void){
   371    382     const char *zName;                /* Argument to the /doc page */
          383  +  const char *zOrigName;            /* Original document name */
   372    384     const char *zMime;                /* Document MIME type */
   373         -  int vid = 0;                      /* Artifact of baseline */
          385  +  char *zCheckin;                   /* The checkin holding the document */
          386  +  int vid = 0;                      /* Artifact of checkin */
   374    387     int rid = 0;                      /* Artifact of file */
   375    388     int i;                            /* Loop counter */
   376    389     Blob filebody;                    /* Content of the documentation file */
   377         -  char zBaseline[UUID_SIZE+1];      /* Baseline UUID */
          390  +  int nMiss = 0;                    /* Failed attempts to find the document */
   378    391   
   379    392     login_check_credentials();
   380    393     if( !g.perm.Read ){ login_needed(); return; }
   381    394     zName = PD("name", "tip/index.wiki");
   382    395     for(i=0; zName[i] && zName[i]!='/'; i++){}
   383         -  if( zName[i]==0 || i>UUID_SIZE ){
   384         -    zName = "index.html";
   385         -    goto doc_not_found;
          396  +  zCheckin = mprintf("%.*s", i, zName);
          397  +  if( zName[i]==0 ){
          398  +    zName = "index.wiki";
          399  +  }else{
          400  +    zName += i;
   386    401     }
   387         -  g.zPath = mprintf("%s/%s", g.zPath, zName);
   388         -  memcpy(zBaseline, zName, i);
   389         -  zBaseline[i] = 0;
   390         -  zName += i;
   391    402     while( zName[0]=='/' ){ zName++; }
          403  +  g.zPath = mprintf("%s/%s/%s", g.zPath, zCheckin, zName);
          404  +  zOrigName = zName;
   392    405     if( !file_is_simple_pathname(zName, 1) ){
   393         -    int n = strlen(zName);
   394         -    if( n>0 && zName[n-1]=='/' ){
   395         -      zName = mprintf("%sindex.html", zName);
          406  +    if( sqlite3_strglob("*/", zName)==0 ){
          407  +      zOrigName = zName = mprintf("%sindex.wiki", zName);
   396    408         if( !file_is_simple_pathname(zName, 1) ){
   397    409           goto doc_not_found;
   398    410         }
   399    411       }else{
   400    412         goto doc_not_found;
   401    413       }
   402    414     }
   403         -  if( fossil_strcmp(zBaseline,"ckout")==0 && db_open_local(0)==0 ){
   404         -    sqlite3_snprintf(sizeof(zBaseline), zBaseline, "tip");
          415  +  if( fossil_strcmp(zCheckin,"ckout")==0 && db_open_local(0)==0 ){
          416  +    sqlite3_snprintf(sizeof(zCheckin), zCheckin, "tip");
   405    417     }
   406         -  if( fossil_strcmp(zBaseline,"ckout")==0 ){
          418  +  if( fossil_strcmp(zCheckin,"ckout")==0 ){
   407    419       /* Read from the local checkout */
   408    420       char *zFullpath;
   409    421       db_must_be_within_tree();
   410         -    zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
   411         -    if( !file_isfile(zFullpath) ){
   412         -      goto doc_not_found;
   413         -    }
   414         -    if( blob_read_from_file(&filebody, zFullpath)<0 ){
   415         -      goto doc_not_found;
          422  +    while( rid==0 && nMiss<2 ){
          423  +      zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
          424  +      if( file_isfile(zFullpath)
          425  +       && blob_read_from_file(&filebody, zFullpath)<0 ){
          426  +        rid = 1;  /* Fake RID just to get the loop to end */
          427  +      }
          428  +      fossil_free(zFullpath);
          429  +      if( rid ) break;
          430  +      nMiss++;
          431  +      zName = "404.md";
   416    432       }
   417    433     }else{
   418    434       db_begin_transaction();
   419         -    if( fossil_strcmp(zBaseline,"tip")==0 ){
   420         -      vid = db_int(0, "SELECT objid FROM event WHERE type='ci'"
   421         -                      " ORDER BY mtime DESC LIMIT 1");
   422         -    }else{
   423         -      vid = name_to_typed_rid(zBaseline, "ci");
   424         -    }
   425         -
   426         -    /* Create the baseline cache if it does not already exist */
          435  +    vid = name_to_typed_rid(zCheckin, "ci");
   427    436       db_multi_exec(
   428    437         "CREATE TABLE IF NOT EXISTS vcache(\n"
   429         -      "  vid INTEGER,         -- baseline ID\n"
          438  +      "  vid INTEGER,         -- checkin ID\n"
   430    439         "  fname TEXT,          -- filename\n"
   431    440         "  rid INTEGER,         -- artifact ID\n"
   432         -      "  UNIQUE(vid,fname,rid)\n"
   433         -      ")"
          441  +      "  PRIMARY KEY(vid,fname)\n"
          442  +      ") WITHOUT ROWID"
   434    443       );
   435         -
   436         -
   437         -
   438         -    /* Check to see if the documentation file artifact ID is contained
   439         -    ** in the baseline cache */
   440         -    rid = db_int(0, "SELECT rid FROM vcache"
   441         -                    " WHERE vid=%d AND fname=%Q", vid, zName);
   442         -    if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
   443         -      goto doc_not_found;
   444         -    }
   445         -
   446         -    if( rid==0 ){
   447         -      Stmt s;
   448         -      Manifest *pM;
   449         -      ManifestFile *pFile;
   450         -
   451         -      /* Add the vid baseline to the cache */
   452         -      if( db_int(0, "SELECT count(*) FROM vcache")>10000 ){
   453         -        db_multi_exec("DELETE FROM vcache");
   454         -      }
   455         -      pM = manifest_get(vid, CFTYPE_MANIFEST, 0);
   456         -      if( pM==0 ){
   457         -        goto doc_not_found;
   458         -      }
   459         -      db_prepare(&s,
          444  +    if( !db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
          445  +      db_multi_exec(
          446  +        "DELETE FROM vcache;\n"
          447  +        "CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;\n"
   460    448           "INSERT INTO vcache(vid,fname,rid)"
   461         -        " SELECT %d, :fname, rid FROM blob"
   462         -        "  WHERE uuid=:uuid",
          449  +        "  SELECT checkinID, filename, blob.rid FROM foci, blob"
          450  +        "   WHERE blob.uuid=foci.uuid"
          451  +        "     AND foci.checkinID=%d;",
   463    452           vid
   464    453         );
   465         -      manifest_file_rewind(pM);
   466         -      while( (pFile = manifest_file_next(pM,0))!=0 ){
   467         -        db_bind_text(&s, ":fname", pFile->zName);
   468         -        db_bind_text(&s, ":uuid", pFile->zUuid);
   469         -        db_step(&s);
   470         -        db_reset(&s);
   471         -      }
   472         -      db_finalize(&s);
   473         -      manifest_destroy(pM);
   474         -
   475         -      /* Try again to find the file */
          454  +    }
          455  +    while( rid==0 && nMiss<2 ){
   476    456         rid = db_int(0, "SELECT rid FROM vcache"
   477    457                         " WHERE vid=%d AND fname=%Q", vid, zName);
   478         -    }
   479         -    if( rid==0 ){
   480         -      goto doc_not_found;
          458  +      if( rid ) break;
          459  +      nMiss++;
          460  +      zName = "404.md";
   481    461       }
   482         -
   483         -    /* Get the file content */
   484         -    if( content_get(rid, &filebody)==0 ){
          462  +    if( rid==0 || content_get(rid, &filebody)==0 ){
   485    463         goto doc_not_found;
   486    464       }
   487    465       db_end_transaction(0);
   488    466     }
   489    467     blob_to_utf8_no_bom(&filebody, 0);
   490    468   
   491    469     /* The file is now contained in the filebody blob.  Deliver the
   492    470     ** file to the user
   493    471     */
   494         -  zMime = P("mimetype");
          472  +  zMime = nMiss==0 ? P("mimetype") : 0;
   495    473     if( zMime==0 ){
   496    474       zMime = mimetype_from_name(zName);
   497    475     }
   498    476     Th_Store("doc_name", zName);
   499    477     Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
   500    478                                        "  FROM blob WHERE rid=%d", vid));
   501    479     Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
   502    480                                     " WHERE objid=%d AND type='ci'", vid));
   503    481     if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
   504    482       Blob title, tail;
          483  +    style_adunit_config(ADUNIT_RIGHT_OK);
   505    484       if( wiki_find_title(&filebody, &title, &tail) ){
   506    485         style_header("%s", blob_str(&title));
   507    486         wiki_convert(&tail, 0, WIKI_BUTTONS);
   508    487       }else{
   509    488         style_header("Documentation");
   510    489         wiki_convert(&filebody, 0, WIKI_BUTTONS);
   511    490       }
................................................................................
   513    492     }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){
   514    493       Blob title = BLOB_INITIALIZER;
   515    494       Blob tail = BLOB_INITIALIZER;
   516    495       markdown_to_html(&filebody, &title, &tail);
   517    496       if( blob_size(&title)>0 ){
   518    497         style_header("%s", blob_str(&title));
   519    498       }else{
   520         -      style_header("Documentation");
          499  +      style_header("%s", nMiss?"Not Found":"Documentation");
   521    500       }
   522    501       blob_append(cgi_output_blob(), blob_buffer(&tail), blob_size(&tail));
   523    502       style_footer();
   524    503     }else if( fossil_strcmp(zMime, "text/plain")==0 ){
   525    504       style_header("Documentation");
   526    505       @ <blockquote><pre>
   527    506       @ %h(blob_str(&filebody))
................................................................................
   534    513       Th_Render(blob_str(&filebody));
   535    514       style_footer();
   536    515   #endif
   537    516     }else{
   538    517       cgi_set_content_type(zMime);
   539    518       cgi_set_content(&filebody);
   540    519     }
          520  +  if( nMiss ) cgi_set_status(404, "Not Found");
   541    521     return;
   542    522   
   543         -doc_not_found:
   544    523     /* Jump here when unable to locate the document */
          524  +doc_not_found:
   545    525     db_end_transaction(0);
   546         -  style_header("Document Not Found");
   547         -  @ <p>No such document: %h(zName)</p>
          526  +  cgi_set_status(404, "Not Found");
          527  +  style_header("Not Found");
          528  +  @ <p>Document %h(zOrigName) not found
          529  +  if( fossil_strcmp(zCheckin,"ckout")!=0 ){
          530  +    @ in %z(href("%R/tree?ci=%T",zCheckin))%h(zCheckin)</a>
          531  +  }
   548    532     style_footer();
   549    533     return;
   550    534   }
   551    535   
   552    536   /*
   553    537   ** The default logo.
   554    538   */

Changes to src/file.c.

  1260   1260     fossil_unicode_free(uName);
  1261   1261   #else
  1262   1262     char *zValue = getenv(zName);
  1263   1263   #endif
  1264   1264     if( zValue ) zValue = fossil_filename_to_utf8(zValue);
  1265   1265     return zValue;
  1266   1266   }
         1267  +
         1268  +/*
         1269  +** Sets the value of an environment variable as UTF8.
         1270  +*/
         1271  +int fossil_setenv(const char *zName, const char *zValue){
         1272  +  int rc;
         1273  +  char *zString = mprintf("%s=%s", zName, zValue);
         1274  +#ifdef _WIN32
         1275  +  wchar_t *uString = fossil_utf8_to_unicode(zString);
         1276  +  rc = _wputenv(uString);
         1277  +  fossil_unicode_free(uString);
         1278  +  fossil_free(zString);
         1279  +#else
         1280  +  rc = putenv(zString);
         1281  +  /* NOTE: Cannot free the string on POSIX. */
         1282  +  /* fossil_free(zString); */
         1283  +#endif
         1284  +  return rc;
         1285  +}
  1267   1286   
  1268   1287   /*
  1269   1288   ** Like fopen() but always takes a UTF8 argument.
  1270   1289   */
  1271   1290   FILE *fossil_fopen(const char *zName, const char *zMode){
  1272   1291   #ifdef _WIN32
  1273   1292     wchar_t *uMode = fossil_utf8_to_unicode(zMode);

Changes to src/http_socket.c.

    25     25   ** Low-level sockets are abstracted out into this module because they
    26     26   ** are handled different on Unix and windows.
    27     27   */
    28     28   
    29     29   #include "config.h"
    30     30   #include "http_socket.h"
    31     31   #if defined(_WIN32)
           32  +#  if !defined(_WIN32_WINNT)
           33  +#    define _WIN32_WINNT 0x0501
           34  +#  endif
    32     35   #  include <winsock2.h>
    33     36   #  include <ws2tcpip.h>
    34     37   #else
    35     38   #  include <netinet/in.h>
    36     39   #  include <arpa/inet.h>
    37     40   #  include <sys/socket.h>
    38     41   #  include <netdb.h>
................................................................................
    43     46   
    44     47   /*
    45     48   ** There can only be a single socket connection open at a time.
    46     49   ** State information about that socket is stored in the following
    47     50   ** local variables:
    48     51   */
    49     52   static int socketIsInit = 0;    /* True after global initialization */
    50         -static int addrIsInit = 0;      /* True once addr is initialized */
    51     53   #if defined(_WIN32)
    52     54   static WSADATA socketInfo;      /* Windows socket initialize data */
    53     55   #endif
    54     56   static int iSocket = -1;        /* The socket on which we talk to the server */
    55     57   static char *socketErrMsg = 0;  /* Text of most recent socket error */
    56     58   
    57     59   
................................................................................
   104    106     if( socketIsInit ){
   105    107   #if defined(_WIN32)
   106    108       WSACleanup();
   107    109   #endif
   108    110       socket_clear_errmsg();
   109    111       socketIsInit = 0;
   110    112     }
   111         -  addrIsInit = 0;
   112    113   }
   113    114   
   114    115   /*
   115    116   ** Close the currently open socket.  If no socket is open, this routine
   116    117   ** is a no-op.
   117    118   */
   118    119   void socket_close(void){
................................................................................
   132    133   **
   133    134   **    pUrlDAta->name       Name of the server.  Ex: www.fossil-scm.org
   134    135   **    pUrlDAta->port       TCP/IP port to use.  Ex: 80
   135    136   **
   136    137   ** Return the number of errors.
   137    138   */
   138    139   int socket_open(UrlData *pUrlData){
   139         -  static struct sockaddr_in addr;  /* The server address */
          140  +  int rc = 0;
          141  +  struct addrinfo *ai = 0;
          142  +  struct addrinfo *p;
          143  +  struct addrinfo hints;
          144  +  char zPort[30];
          145  +  char zRemote[NI_MAXHOST];
   140    146   
   141    147     socket_global_init();
   142         -  if( !addrIsInit ){
   143         -    memset(&addr, 0, sizeof(addr));
   144         -    addr.sin_family = AF_INET;
   145         -    addr.sin_port = htons(pUrlData->port);
   146         -    *(int*)&addr.sin_addr = inet_addr(pUrlData->name);
   147         -    if( -1 == *(int*)&addr.sin_addr ){
   148         -#ifndef FOSSIL_STATIC_LINK
   149         -      struct hostent *pHost;
   150         -      pHost = gethostbyname(pUrlData->name);
   151         -      if( pHost!=0 ){
   152         -        memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
   153         -      }else
   154         -#endif
   155         -      {
   156         -        socket_set_errmsg("can't resolve host name: %s", pUrlData->name);
   157         -        return 1;
   158         -      }
          148  +  memset(&hints, 0, sizeof(struct addrinfo));
          149  +  assert( iSocket<0 );
          150  +  hints.ai_family = g.fIPv4 ? AF_INET : AF_UNSPEC;
          151  +  hints.ai_socktype = SOCK_STREAM;
          152  +  hints.ai_protocol = IPPROTO_TCP;
          153  +  sqlite3_snprintf(sizeof(zPort),zPort,"%d", pUrlData->port);
          154  +  rc = getaddrinfo(pUrlData->name, zPort, &hints, &ai);
          155  +  if( rc ){
          156  +    socket_set_errmsg("getaddrinfo() fails: %s", gai_strerror(rc));
          157  +    goto end_socket_open;
          158  +  }
          159  +  for(p=ai; p; p=p->ai_next){
          160  +    iSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
          161  +    if( iSocket<0 ) continue;
          162  +    if( connect(iSocket,p->ai_addr,p->ai_addrlen)<0 ){
          163  +      socket_close();
          164  +      continue;
          165  +    }
          166  +    rc = getnameinfo(p->ai_addr, p->ai_addrlen, zRemote, sizeof(zRemote),
          167  +                     0, 0, NI_NUMERICHOST);
          168  +    if( rc ){
          169  +      socket_set_errmsg("getnameinfo() failed: %s", gai_strerror(rc));
          170  +      goto end_socket_open;
   159    171       }
   160         -    addrIsInit = 1;
   161         -
   162         -    /* Set the Global.zIpAddr variable to the server we are talking to.
   163         -    ** This is used to populate the ipaddr column of the rcvfrom table,
   164         -    ** if any files are received from the server.
   165         -    */
   166         -    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
          172  +    g.zIpAddr = mprintf("%s", zRemote);
          173  +    break;
   167    174     }
   168         -  iSocket = socket(AF_INET,SOCK_STREAM,0);
   169         -  if( iSocket<0 ){
   170         -    socket_set_errmsg("cannot create a socket");
   171         -    return 1;
   172         -  }
   173         -  if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
          175  +  if( p==0 ){
   174    176       socket_set_errmsg("cannot connect to host %s:%d", pUrlData->name,
   175    177                         pUrlData->port);
   176         -    socket_close();
   177         -    return 1;
   178    178     }
   179    179   #if !defined(_WIN32)
   180    180     signal(SIGPIPE, SIG_IGN);
   181    181   #endif
   182         -  return 0;
          182  +end_socket_open:
          183  +  if( rc && iSocket>=0 ) socket_close();
          184  +  if( ai ) freeaddrinfo(ai);
          185  +  return rc;
   183    186   }
   184    187   
   185    188   /*
   186    189   ** Send content out over the open socket connection.
   187    190   */
   188    191   size_t socket_send(void *NotUsed, void *pContent, size_t N){
   189    192     size_t sent;

Changes to src/info.c.

   196    196   void info_cmd(void){
   197    197     i64 fsize;
   198    198     int verboseFlag = find_option("verbose","v",0)!=0;
   199    199     if( !verboseFlag ){
   200    200       verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
   201    201     }
   202    202   
   203         -  /* We should be done with options.. */
   204         -  verify_all_options();
   205         -
   206    203     if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
   207    204       db_open_config(0);
   208    205       db_open_repository(g.argv[2]);
   209    206       db_record_repository_filename(g.argv[2]);
   210    207       fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
   211    208       fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
   212    209       extraRepoInfo();
   213    210       return;
   214    211     }
   215    212     db_find_and_open_repository(0,0);
          213  +  verify_all_options();
   216    214     if( g.argc==2 ){
   217    215       int vid;
   218    216            /* 012345678901234 */
   219    217       db_record_repository_filename(0);
   220    218       fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
   221    219       if( g.localOpen ){
   222    220         fossil_print("repository:   %s\n", db_repository_filename());

Changes to src/login.c.

   573    573         ** code prefix, and LOGIN is the user name.
   574    574         */
   575    575         login_set_user_cookie(zUsername, uid, NULL);
   576    576         redirect_to_g();
   577    577       }
   578    578     }
   579    579     style_header("Login/Logout");
          580  +  style_adunit_config(ADUNIT_OFF);
   580    581     @ %s(zErrMsg)
   581    582     if( zGoto && P("anon")==0 ){
   582    583       @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
   583    584     }
   584    585     form_begin(0, "%R/login");
   585    586     if( zGoto ){
   586    587       @ <input type="hidden" name="g" value="%h(zGoto)" />

Changes to src/main.c.

   147    147     int fHttpTrace;         /* Trace outbound HTTP requests */
   148    148     char *zHttpAuth;        /* HTTP Authorization user:pass information */
   149    149     int fSystemTrace;       /* Trace calls to fossil_system(), --systemtrace */
   150    150     int fSshTrace;          /* Trace the SSH setup traffic */
   151    151     int fSshClient;         /* HTTP client flags for SSH client */
   152    152     char *zSshCmd;          /* SSH command string */
   153    153     int fNoSync;            /* Do not do an autosync ever.  --nosync */
          154  +  int fIPv4;              /* Use only IPv4, not IPv6. --ipv4 */
   154    155     char *zPath;            /* Name of webpage being served */
   155    156     char *zExtra;           /* Extra path information past the webpage name */
   156    157     char *zBaseURL;         /* Full text of the URL being served */
   157    158     char *zHttpsURL;        /* zBaseURL translated to https: */
   158    159     char *zTop;             /* Parent directory of zPath */
   159    160     const char *zContentType;  /* The content type of the input HTTP request */
   160    161     int iErrPriority;       /* Priority of current error message */
................................................................................
  1785   1786     fossil_binary_mode(g.httpOut);
  1786   1787     fossil_binary_mode(g.httpIn);
  1787   1788     g.cgiOutput = 1;
  1788   1789     blob_read_from_file(&config, zFile);
  1789   1790     while( blob_line(&config, &line) ){
  1790   1791       if( !blob_token(&line, &key) ) continue;
  1791   1792       if( blob_buffer(&key)[0]=='#' ) continue;
  1792         -    if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
  1793         -      g.fDebug = fossil_fopen(blob_str(&value), "ab");
  1794         -      blob_reset(&value);
  1795         -      continue;
  1796         -    }
  1797         -    if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){
  1798         -      g.zErrlog = mprintf("%s", blob_str(&value));
  1799         -      continue;
  1800         -    }
  1801         -    if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
  1802         -      cgi_setenv("HOME", blob_str(&value));
  1803         -      blob_reset(&value);
  1804         -      continue;
  1805         -    }
  1806   1793       if( blob_eq(&key, "repository:") && blob_tail(&line, &value) ){
         1794  +      /* repository: FILENAME
         1795  +      **
         1796  +      ** The name of the Fossil repository to be served via CGI.  Most
         1797  +      ** fossil CGI scripts have a single non-comment line that contains
         1798  +      ** this one entry.
         1799  +      */
  1807   1800         blob_trim(&value);
  1808   1801         db_open_repository(blob_str(&value));
  1809   1802         blob_reset(&value);
  1810   1803         continue;
  1811   1804       }
  1812   1805       if( blob_eq(&key, "directory:") && blob_token(&line, &value) ){
         1806  +      /* directory: DIRECTORY
         1807  +      **
         1808  +      ** If repository: is omitted, then terms of the PATH_INFO cgi parameter
         1809  +      ** are appended to DIRECTORY looking for a repository (whose name ends
         1810  +      ** in ".fossil") or a file in "files:".
         1811  +      */
  1813   1812         db_close(1);
  1814   1813         g.zRepositoryName = mprintf("%s", blob_str(&value));
  1815   1814         blob_reset(&value);
  1816   1815         continue;
  1817   1816       }
  1818   1817       if( blob_eq(&key, "notfound:") && blob_token(&line, &value) ){
         1818  +      /* notfound: URL
         1819  +      **
         1820  +      ** If using directory: and no suitable repository or file is found,
         1821  +      ** then redirect to URL.
         1822  +      */
  1819   1823         zNotFound = mprintf("%s", blob_str(&value));
  1820   1824         blob_reset(&value);
  1821   1825         continue;
  1822   1826       }
  1823   1827       if( blob_eq(&key, "localauth") ){
         1828  +      /* localauth
         1829  +      **
         1830  +      ** Grant "administrator" privileges to users connecting with HTTP
         1831  +      ** from IP address 127.0.0.1.  Do not bother checking credentials.
         1832  +      */
  1824   1833         g.useLocalauth = 1;
  1825   1834         continue;
  1826   1835       }
  1827   1836       if( blob_eq(&key, "redirect:") && blob_token(&line, &value)
  1828   1837               && blob_token(&line, &value2) ){
         1838  +      /* See the header comment on the redirect_web_page() function
         1839  +      ** above for details. */
  1829   1840         nRedirect++;
  1830   1841         azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*));
  1831   1842         azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value));
  1832   1843         azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2));
  1833   1844         blob_reset(&value);
  1834   1845         blob_reset(&value2);
  1835   1846         continue;
  1836   1847       }
  1837   1848       if( blob_eq(&key, "files:") && blob_token(&line, &value) ){
         1849  +      /* files: GLOBLIST
         1850  +      **
         1851  +      ** GLOBLIST is a comma-separated list of filename globs.  For
         1852  +      ** example:  *.html,*.css,*.js
         1853  +      **
         1854  +      ** If the repository: line is omitted and then PATH_INFO is searched
         1855  +      ** for files that match any of these GLOBs and if any such file is
         1856  +      ** found it is returned verbatim.  This feature allows "fossil server"
         1857  +      ** to function as a primitive web-server delivering arbitrary content.
         1858  +      */
  1838   1859         pFileGlob = glob_create(blob_str(&value));
         1860  +      blob_reset(&value);
         1861  +      continue;
         1862  +    }
         1863  +    if( blob_eq(&key, "setenv:") && blob_token(&line, &value)
         1864  +            && blob_token(&line, &value2) ){
         1865  +      /* setenv: NAME VALUE
         1866  +      **
         1867  +      ** Sets environment variable NAME to VALUE
         1868  +      */
         1869  +      fossil_setenv(blob_str(&value), blob_str(&value2));
         1870  +      blob_reset(&value);
         1871  +      blob_reset(&value2);
         1872  +      continue;
         1873  +    }
         1874  +    if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
         1875  +      /* debug: FILENAME
         1876  +      **
         1877  +      ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
         1878  +      ** into FILENAME. 
         1879  +      */
         1880  +      g.fDebug = fossil_fopen(blob_str(&value), "ab");
         1881  +      blob_reset(&value);
         1882  +      continue;
         1883  +    }
         1884  +    if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){
         1885  +      /* errorlog: FILENAME
         1886  +      **
         1887  +      ** Causes messages from warnings, errors, and panics to be appended
         1888  +      ** to FILENAME.
         1889  +      */
         1890  +      g.zErrlog = mprintf("%s", blob_str(&value));
         1891  +      blob_reset(&value);
         1892  +      continue;
         1893  +    }
         1894  +    if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
         1895  +      /* HOME: VALUE
         1896  +      **
         1897  +      ** Set CGI parameter "HOME" to VALUE.  This is legacy.  Use
         1898  +      ** setenv: instead.
         1899  +      */
         1900  +      cgi_setenv("HOME", blob_str(&value));
         1901  +      blob_reset(&value);
  1839   1902         continue;
  1840   1903       }
  1841   1904     }
  1842   1905     blob_reset(&config);
  1843   1906     if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
  1844   1907       cgi_panic("Unable to find or open the project repository");
  1845   1908     }

Changes to src/main.mk.

   129    129     $(SRCDIR)/winhttp.c \
   130    130     $(SRCDIR)/wysiwyg.c \
   131    131     $(SRCDIR)/xfer.c \
   132    132     $(SRCDIR)/xfersetup.c \
   133    133     $(SRCDIR)/zip.c
   134    134   
   135    135   EXTRA_FILES = \
          136  +  $(SRCDIR)/../skins/black_and_white/css.txt \
          137  +  $(SRCDIR)/../skins/black_and_white/footer.txt \
          138  +  $(SRCDIR)/../skins/black_and_white/header.txt \
          139  +  $(SRCDIR)/../skins/default/css.txt \
          140  +  $(SRCDIR)/../skins/default/footer.txt \
          141  +  $(SRCDIR)/../skins/default/header.txt \
          142  +  $(SRCDIR)/../skins/eagle/css.txt \
          143  +  $(SRCDIR)/../skins/eagle/footer.txt \
          144  +  $(SRCDIR)/../skins/eagle/header.txt \
          145  +  $(SRCDIR)/../skins/enhanced1/css.txt \
          146  +  $(SRCDIR)/../skins/enhanced1/footer.txt \
          147  +  $(SRCDIR)/../skins/enhanced1/header.txt \
          148  +  $(SRCDIR)/../skins/etienne1/css.txt \
          149  +  $(SRCDIR)/../skins/etienne1/footer.txt \
          150  +  $(SRCDIR)/../skins/etienne1/header.txt \
          151  +  $(SRCDIR)/../skins/khaki/css.txt \
          152  +  $(SRCDIR)/../skins/khaki/footer.txt \
          153  +  $(SRCDIR)/../skins/khaki/header.txt \
          154  +  $(SRCDIR)/../skins/plain_gray/css.txt \
          155  +  $(SRCDIR)/../skins/plain_gray/footer.txt \
          156  +  $(SRCDIR)/../skins/plain_gray/header.txt \
          157  +  $(SRCDIR)/../skins/rounded1/css.txt \
          158  +  $(SRCDIR)/../skins/rounded1/footer.txt \
          159  +  $(SRCDIR)/../skins/rounded1/header.txt \
   136    160     $(SRCDIR)/diff.tcl
   137    161   
   138    162   TRANS_SRC = \
   139    163     $(OBJDIR)/add_.c \
   140    164     $(OBJDIR)/allrepo_.c \
   141    165     $(OBJDIR)/attach_.c \
   142    166     $(OBJDIR)/bag_.c \

Changes to src/makeheaders.c.

   110    110   ** doesn't tell about the objects structure.  A typical forward declaration
   111    111   ** is:
   112    112   **
   113    113   **          struct Xyzzy;
   114    114   **
   115    115   ** Not every object has a forward declaration.  If it does, thought, the
   116    116   ** forward declaration will be contained in the zFwd field for C and
   117         -** the zFwdCpp for C++.  The zDecl field contains the complete 
   118         -** declaration text.  
          117  +** the zFwdCpp for C++.  The zDecl field contains the complete
          118  +** declaration text.
   119    119   */
   120    120   typedef struct Decl Decl;
   121    121   struct Decl {
   122    122     char *zName;       /* Name of the object being declared.  The appearance
   123    123                        ** of this name is a source file triggers the declaration
   124    124                        ** to be added to the header for that file. */
   125         -  char *zFile;       /* File from which extracted.  */
          125  +  const char *zFile; /* File from which extracted.  */
   126    126     char *zIf;         /* Surround the declaration with this #if */
   127    127     char *zFwd;        /* A forward declaration.  NULL if there is none. */
   128    128     char *zFwdCpp;     /* Use this forward declaration for C++. */
   129    129     char *zDecl;       /* A full declaration of this object */
   130    130     char *zExtra;      /* Extra declaration text inserted into class objects */
   131    131     int extraType;     /* Last public:, protected: or private: in zExtraDecl */
   132    132     struct Include *pInclude;   /* #includes that come before this declaration */
................................................................................
   161    161   **                        a library, then the object is not visible to users
   162    162   **                        of the library.  (i.e. the object does not appear
   163    163   **                        in the output when using the -H option.)
   164    164   **
   165    165   **    EXPORT scope        The object is visible and usable everywhere.
   166    166   **
   167    167   ** The DP_Flag is a temporary use flag that is used during processing to
   168         -** prevent an infinite loop.  It's use is localized.  
          168  +** prevent an infinite loop.  It's use is localized.
   169    169   **
   170    170   ** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent
   171    171   ** and are used to specify what type of declaration the object requires.
   172    172   */
   173    173   #define DP_Forward      0x001   /* Has a forward declaration in this file */
   174    174   #define DP_Declared     0x002   /* Has a full declaration in this file */
   175    175   #define DP_Export       0x004   /* Export this declaration */
................................................................................
   199    199   ** the same "flags" field.
   200    200   **
   201    201   ** Be careful not to confuse PS_Export with DP_Export or
   202    202   ** PS_Local with DP_Local.  Their names are similar, but the meanings
   203    203   ** of these flags are very different.
   204    204   */
   205    205   #define PS_Extern        0x000800    /* "extern" has been seen */
   206         -#define PS_Export        0x001000    /* If between "#if EXPORT_INTERFACE" 
          206  +#define PS_Export        0x001000    /* If between "#if EXPORT_INTERFACE"
   207    207                                        ** and "#endif" */
   208    208   #define PS_Export2       0x002000    /* If "EXPORT" seen */
   209    209   #define PS_Typedef       0x004000    /* If "typedef" has been seen */
   210    210   #define PS_Static        0x008000    /* If "static" has been seen */
   211    211   #define PS_Interface     0x010000    /* If within #if INTERFACE..#endif */
   212    212   #define PS_Method        0x020000    /* If "::" token has been seen */
   213    213   #define PS_Local         0x040000    /* If within #if LOCAL_INTERFACE..#endif */
................................................................................
   229    229   #define TY_Variable      0x01000000
   230    230   #define TY_Structure     0x02000000
   231    231   #define TY_Union         0x04000000
   232    232   #define TY_Enumeration   0x08000000
   233    233   #define TY_Defunct       0x10000000  /* Used to erase a declaration */
   234    234   
   235    235   /*
   236         -** Each nested #if (or #ifdef or #ifndef) is stored in a stack of 
          236  +** Each nested #if (or #ifdef or #ifndef) is stored in a stack of
   237    237   ** instances of the following structure.
   238    238   */
   239    239   typedef struct Ifmacro Ifmacro;
   240    240   struct Ifmacro {
   241    241     int nLine;         /* Line number where this macro occurs */
   242    242     char *zCondition;  /* Text of the condition for this macro */
   243    243     Ifmacro *pNext;    /* Next down in the stack */
................................................................................
   291    291     char *zHdr;              /* Name of the generated .h file for this input.
   292    292                              ** Will be NULL if input is to be scanned only */
   293    293     int flags;               /* One or more DP_, PS_ and/or TY_ flags */
   294    294     InFile *pNext;           /* Next input file in the list of them all */
   295    295     IdentTable idTable;      /* All identifiers in this input file */
   296    296   };
   297    297   
   298         -/* 
          298  +/*
   299    299   ** An unbounded string is able to grow without limit.  We use these
   300    300   ** to construct large in-memory strings from lots of smaller components.
   301    301   */
   302    302   typedef struct String String;
   303    303   struct String {
   304    304     int nAlloc;      /* Number of bytes allocated */
   305    305     int nUsed;       /* Number of bytes used (not counting null terminator) */
................................................................................
   330    330   ** The following text line appears at the top of every file generated
   331    331   ** by this program.  By recognizing this line, the program can be sure
   332    332   ** never to read a file that it generated itself.
   333    333   **
   334    334   ** The "#undef INTERFACE" part is a hack to work around a name collision
   335    335   ** in MSVC 2008.
   336    336   */
   337         -const char zTopLine[] = 
          337  +const char zTopLine[] =
   338    338     "/* \aThis file was automatically generated.  Do not edit! */\n"
   339    339     "#undef INTERFACE\n";
   340    340   #define nTopLine (sizeof(zTopLine)-1)
   341    341   
   342    342   /*
   343    343   ** The name of the file currently being parsed.
   344    344   */
   345         -static char *zFilename;
          345  +static const char *zFilename;
   346    346   
   347    347   /*
   348    348   ** The stack of #if macros for the file currently being parsed.
   349    349   */
   350    350   static Ifmacro *ifStack = 0;
   351    351   
   352    352   /*
................................................................................
   700    700   */
   701    701   static char *ReadFile(const char *zFilename){
   702    702     struct stat sStat;
   703    703     FILE *pIn;
   704    704     char *zBuf;
   705    705     int n;
   706    706   
   707         -  if( stat(zFilename,&sStat)!=0 
          707  +  if( stat(zFilename,&sStat)!=0
   708    708   #ifndef WIN32
   709    709       || !S_ISREG(sStat.st_mode)
   710    710   #endif
   711    711     ){
   712    712       return 0;
   713    713     }
   714    714     pIn = fopen(zFilename,"r");
................................................................................
   887    887                 }else{
   888    888                    isBlockComment = 0;
   889    889                 }
   890    890               }
   891    891             }
   892    892             i++;
   893    893           }
   894         -        if( z[i] ){ 
   895         -          i += 2; 
          894  +        if( z[i] ){
          895  +          i += 2;
   896    896           }else{
   897    897             isBlockComment = 0;
   898    898             fprintf(stderr,"%s:%d: Unterminated comment\n",
   899    899               zFilename, startLine);
   900    900             nErr++;
   901    901           }
   902    902           pToken->eType = isBlockComment==2 ? TT_BlockComment : TT_Comment;
................................................................................
   904    904         }else{
   905    905           /* A divide operator */
   906    906           pToken->eType = TT_Other;
   907    907           pToken->nText = 1 + (z[i+1]=='+');
   908    908         }
   909    909         break;
   910    910   
   911         -    case '0': 
          911  +    case '0':
   912    912         if( z[i+1]=='x' || z[i+1]=='X' ){
   913    913           /* A hex constant */
   914    914           i += 2;
   915    915           while( isxdigit(z[i]) ){ i++; }
   916    916         }else{
   917    917           /* An octal constant */
   918    918           while( isdigit(z[i]) ){ i++; }
................................................................................
   961    961       case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W':
   962    962       case 'X': case 'Y': case 'Z': case '_':
   963    963         while( isalnum(z[i]) || z[i]=='_' ){ i++; };
   964    964         pToken->eType = TT_Id;
   965    965         pToken->nText = i - pIn->i;
   966    966         break;
   967    967   
   968         -    case ':': 
          968  +    case ':':
   969    969         pToken->eType = TT_Other;
   970    970         pToken->nText = 1 + (z[i+1]==':');
   971    971         break;
   972    972   
   973    973       case '=':
   974    974       case '<':
   975    975       case '>':
   976    976       case '+':
   977    977       case '-':
   978    978       case '*':
   979    979       case '%':
   980    980       case '^':
   981    981       case '&':
   982         -    case '|': 
          982  +    case '|':
   983    983         pToken->eType = TT_Other;
   984    984         pToken->nText = 1 + (z[i+1]=='=');
   985    985         break;
   986    986   
   987    987       default:
   988    988         pToken->eType = TT_Other;
   989    989         pToken->nText = 1;
................................................................................
  1062   1062           }
  1063   1063           break;
  1064   1064       }
  1065   1065     }
  1066   1066     /* NOT REACHED */
  1067   1067   }
  1068   1068   
  1069         -/* 
         1069  +/*
  1070   1070   ** This routine looks for identifiers (strings of contiguous alphanumeric
  1071   1071   ** characters) within a preprocessor directive and adds every such string
  1072   1072   ** found to the given identifier table
  1073   1073   */
  1074   1074   static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){
  1075   1075     Token sToken;
  1076   1076     InStream sIn;
................................................................................
  1155   1155           return nErr;
  1156   1156   
  1157   1157         case TT_Id:
  1158   1158           if( pTable ){
  1159   1159             IdentTableInsert(pTable,pToken->zText,pToken->nText);
  1160   1160           }
  1161   1161           break;
  1162         -  
         1162  +
  1163   1163         case TT_Preprocessor:
  1164   1164           if( pTable!=0 ){
  1165   1165             FindIdentifiersInMacro(pToken,pTable);
  1166   1166           }
  1167   1167           break;
  1168   1168   
  1169   1169         case TT_Other:
................................................................................
  1261   1261     if( zFile==0 ){
  1262   1262       fprintf(stderr,"Can't read file \"%s\"\n",argv[1]);
  1263   1263       exit(1);
  1264   1264     }
  1265   1265     pList = TokenizeFile(zFile,&sTable);
  1266   1266     for(p=pList; p; p=p->pNext){
  1267   1267       int j;
  1268         -    switch( p->eType ){ 
         1268  +    switch( p->eType ){
  1269   1269         case TT_Space:
  1270   1270           printf("%4d: Space\n",p->nLine);
  1271   1271           break;
  1272   1272         case TT_Id:
  1273   1273           printf("%4d: Id           %.*s\n",p->nLine,p->nText,p->zText);
  1274   1274           break;
  1275   1275         case TT_Preprocessor:
................................................................................
  1328   1328         case TT_Number:
  1329   1329           printf("%s%.*s", needSpace ? " " : "", pFirst->nText, pFirst->zText);
  1330   1330           needSpace = 1;
  1331   1331           break;
  1332   1332   
  1333   1333         default:
  1334   1334           c = pFirst->zText[0];
  1335         -        printf("%s%.*s", 
         1335  +        printf("%s%.*s",
  1336   1336             (needSpace && (c=='*' || c=='{')) ? " " : "",
  1337   1337             pFirst->nText, pFirst->zText);
  1338   1338           needSpace = pFirst->zText[0]==',';
  1339   1339           break;
  1340   1340       }
  1341   1341       pFirst = pFirst->pNext;
  1342   1342     }
................................................................................
  1369   1369     int iSkip = 0;
  1370   1370     int skipOne = 0;
  1371   1371   
  1372   1372     StringInit(&str);
  1373   1373     pLast = pLast->pNext;
  1374   1374     while( pFirst!=pLast ){
  1375   1375       if( pFirst==pSkip ){ iSkip = nSkip; }
  1376         -    if( iSkip>0 ){ 
         1376  +    if( iSkip>0 ){
  1377   1377         iSkip--;
  1378         -      pFirst=pFirst->pNext; 
         1378  +      pFirst=pFirst->pNext;
  1379   1379         continue;
  1380   1380       }
  1381   1381       switch( pFirst->eType ){
  1382   1382         case TT_Preprocessor:
  1383   1383           StringAppend(&str,"\n",1);
  1384   1384           StringAppend(&str,pFirst->zText,pFirst->nText);
  1385   1385           StringAppend(&str,"\n",1);
  1386   1386           needSpace = 0;
  1387   1387           break;
  1388   1388   
  1389         -      case TT_Id: 
         1389  +      case TT_Id:
  1390   1390           switch( pFirst->zText[0] ){
  1391         -          case 'E':        
         1391  +          case 'E':
  1392   1392               if( pFirst->nText==6 && strncmp(pFirst->zText,"EXPORT",6)==0 ){
  1393   1393                 skipOne = 1;
  1394   1394               }
  1395   1395               break;
  1396   1396             case 'P':
  1397   1397               switch( pFirst->nText ){
  1398   1398                 case 6:  skipOne = !strncmp(pFirst->zText,"PUBLIC", 6);    break;
................................................................................
  1643   1643       return 0;
  1644   1644     }
  1645   1645     pLast = pLast->pNext;
  1646   1646     for(p=pFirst; p && p!=pLast; p=p->pNext){
  1647   1647       if( p->eType==TT_Id ){
  1648   1648         static IdentTable sReserved;
  1649   1649         static int isInit = 0;
  1650         -      static char *aWords[] = { "char", "class", 
  1651         -       "const", "double", "enum", "extern", "EXPORT", "ET_PROC", 
         1650  +      static const char *aWords[] = { "char", "class",
         1651  +       "const", "double", "enum", "extern", "EXPORT", "ET_PROC",
  1652   1652          "float", "int", "long",
  1653   1653          "PRIVATE", "PROTECTED", "PUBLIC",
  1654         -       "register", "static", "struct", "sizeof", "signed", "typedef", 
         1654  +       "register", "static", "struct", "sizeof", "signed", "typedef",
  1655   1655          "union", "volatile", "virtual", "void", };
  1656         -  
         1656  +
  1657   1657         if( !isInit ){
  1658   1658           int i;
  1659   1659           for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){
  1660   1660             IdentTableInsert(&sReserved,aWords[i],0);
  1661   1661           }
  1662   1662           isInit = 1;
  1663   1663         }
................................................................................
  1766   1766       return 0;
  1767   1767     }
  1768   1768     pCode = pLast;
  1769   1769     while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){
  1770   1770       pLast = pLast->pPrev;
  1771   1771     }
  1772   1772     if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){
  1773         -    fprintf(stderr,"%s:%d: Unrecognized syntax.\n", 
         1773  +    fprintf(stderr,"%s:%d: Unrecognized syntax.\n",
  1774   1774         zFilename, pFirst->nLine);
  1775   1775       return 1;
  1776   1776     }
  1777   1777     if( flags & (PS_Interface|PS_Export|PS_Local) ){
  1778   1778       fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n",
  1779   1779         zFilename, pFirst->nLine);
  1780   1780       return 1;
................................................................................
  1847   1847       fprintf(stderr,"%s:%d: malformed inline procedure definition\n",
  1848   1848         zFilename, pFirst->nLine);
  1849   1849       return 1;
  1850   1850     }
  1851   1851   
  1852   1852   #ifdef DEBUG
  1853   1853     if( debugMask & PARSER ){
  1854         -    printf("**** Found inline routine: %.*s on line %d...\n", 
         1854  +    printf("**** Found inline routine: %.*s on line %d...\n",
  1855   1855          pName->nText, pName->zText, pFirst->nLine);
  1856   1856       PrintTokens(pFirst,pEnd);
  1857   1857       printf("\n");
  1858   1858     }
  1859   1859   #endif
  1860   1860     pDecl = CreateDecl(pName->zText,pName->nText);
  1861   1861     pDecl->pComment = pFirst->pComment;
................................................................................
  1886   1886   **
  1887   1887   ** If pEnd is ';', then the determination is more difficult.  We have
  1888   1888   ** to search for an occurrence of an ID followed immediately by '('.
  1889   1889   ** If found, we have a prototype.  Otherwise we are dealing with a
  1890   1890   ** variable definition.
  1891   1891   */
  1892   1892   static int isVariableDef(Token *pFirst, Token *pEnd){
  1893         -  if( pEnd && pEnd->zText[0]=='=' && 
         1893  +  if( pEnd && pEnd->zText[0]=='=' &&
  1894   1894       (pEnd->pPrev->nText!=8 || strncmp(pEnd->pPrev->zText,"operator",8)!=0)
  1895   1895     ){
  1896   1896       return 1;
  1897   1897     }
  1898   1898     while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){
  1899   1899       if( pFirst->eType==TT_Id && pFirst->pNext->zText[0]=='(' ){
  1900   1900         return 0;
................................................................................
  1947   1947         ** option was specified or the "LOCAL" keyword is used. */
  1948   1948         return nErr;
  1949   1949       }
  1950   1950       while( pFirst!=0 && pFirst->pNext!=pEnd &&
  1951   1951          ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0)
  1952   1952           || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0))
  1953   1953       ){
  1954         -      /* Lose the initial "static" or local from local variables. 
         1954  +      /* Lose the initial "static" or local from local variables.
  1955   1955         ** We'll prepend "extern" later. */
  1956   1956         pFirst = pFirst->pNext;
  1957   1957         isLocal = 1;
  1958   1958       }
  1959   1959       if( pFirst==0 || !isLocal ){
  1960   1960         return nErr;
  1961   1961       }
  1962   1962     }else if( flags & PS_Method ){
  1963   1963       /* Methods are declared by their class.  Don't declare separately. */
  1964   1964       return nErr;
  1965   1965     }
  1966   1966     isVar =  (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd);
  1967         -  if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 
         1967  +  if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0
  1968   1968     && (flags & PS_Extern)==0 ){
  1969   1969       fprintf(stderr,"%s:%d: Can't define a variable in this context\n",
  1970   1970         zFilename, pFirst->nLine);
  1971   1971       nErr++;
  1972   1972     }
  1973   1973     pName = FindDeclName(pFirst,pEnd->pPrev);
  1974   1974     if( pName==0 ){
................................................................................
  2093   2093     nCmd = 1;
  2094   2094     while( isalpha(zCmd[nCmd]) ){
  2095   2095       nCmd++;
  2096   2096     }
  2097   2097   
  2098   2098     if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){
  2099   2099       /*
  2100         -    ** Pop the if stack 
         2100  +    ** Pop the if stack
  2101   2101       */
  2102   2102       pIf = ifStack;
  2103   2103       if( pIf==0 ){
  2104   2104         fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine);
  2105   2105         return 1;
  2106   2106       }
  2107   2107       ifStack = pIf->pNext;
  2108   2108       SafeFree(pIf);
  2109   2109     }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){
  2110   2110       /*
  2111         -    ** Record a #define if we are in PS_Interface or PS_Export 
         2111  +    ** Record a #define if we are in PS_Interface or PS_Export
  2112   2112       */
  2113   2113       Decl *pDecl;
  2114   2114       if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; }
  2115   2115       zArg = &zCmd[6];
  2116   2116       while( *zArg && isspace(*zArg) && *zArg!='\n' ){
  2117   2117         zArg++;
  2118   2118       }
................................................................................
  2127   2127       if( flags & PS_Export ){
  2128   2128         DeclSetProperty(pDecl,DP_Export);
  2129   2129       }else if( flags & PS_Local ){
  2130   2130         DeclSetProperty(pDecl,DP_Local);
  2131   2131       }
  2132   2132     }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){
  2133   2133       /*
  2134         -    ** Record an #include if we are in PS_Interface or PS_Export 
         2134  +    ** Record an #include if we are in PS_Interface or PS_Export
  2135   2135       */
  2136   2136       Include *pInclude;
  2137   2137       char *zIf;
  2138   2138   
  2139   2139       if( !(flags & (PS_Interface|PS_Export)) ){ return 0; }
  2140   2140       zArg = &zCmd[7];
  2141   2141       while( *zArg && isspace(*zArg) ){ zArg++; }
................................................................................
  2182   2182         PushIfMacro(0,0,0,pToken->nLine,PS_Export);
  2183   2183       }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
  2184   2184         PushIfMacro(0,0,0,pToken->nLine,PS_Local);
  2185   2185       }else{
  2186   2186         PushIfMacro(0,zArg,nArg,pToken->nLine,0);
  2187   2187       }
  2188   2188     }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
  2189         -    /* 
         2189  +    /*
  2190   2190       ** Push an #ifdef.
  2191   2191       */
  2192   2192       zArg = &zCmd[5];
  2193   2193       while( *zArg && isspace(*zArg) && *zArg!='\n' ){
  2194   2194         zArg++;
  2195   2195       }
  2196   2196       if( *zArg==0 || *zArg=='\n' ){ return 0; }
................................................................................
  2205   2205         zArg++;
  2206   2206       }
  2207   2207       if( *zArg==0 || *zArg=='\n' ){ return 0; }
  2208   2208       nArg = pToken->nText + (int)(pToken->zText - zArg);
  2209   2209       PushIfMacro("!defined",zArg,nArg,pToken->nLine,0);
  2210   2210     }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){
  2211   2211       /*
  2212         -    ** Invert the #if on the top of the stack 
         2212  +    ** Invert the #if on the top of the stack
  2213   2213       */
  2214   2214       if( ifStack==0 ){
  2215   2215         fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename,
  2216   2216            pToken->nLine);
  2217   2217         return 1;
  2218   2218       }
  2219   2219       pIf = ifStack;
................................................................................
  2222   2222         PushIfMacro("!",pIf->zCondition,strlen(pIf->zCondition),pIf->nLine,0);
  2223   2223         SafeFree(pIf);
  2224   2224       }else{
  2225   2225         pIf->flags = 0;
  2226   2226       }
  2227   2227     }else{
  2228   2228       /*
  2229         -    ** This directive can be safely ignored 
         2229  +    ** This directive can be safely ignored
  2230   2230       */
  2231   2231       return 0;
  2232   2232     }
  2233   2233   
  2234         -  /* 
  2235         -  ** Recompute the preset flags 
         2234  +  /*
         2235  +  ** Recompute the preset flags
  2236   2236     */
  2237   2237     *pPresetFlags = 0;
  2238   2238     for(pIf = ifStack; pIf; pIf=pIf->pNext){
  2239   2239       *pPresetFlags |= pIf->flags;
  2240   2240     }
  2241         -    
         2241  +
  2242   2242     return nErr;
  2243   2243   }
  2244   2244   
  2245   2245   /*
  2246   2246   ** Parse an entire file.  Return the number of errors.
  2247   2247   **
  2248   2248   ** pList is a list of tokens in the file.  Whitespace tokens have been
  2249   2249   ** eliminated, and text with {...} has been collapsed into a
  2250   2250   ** single TT_Brace token.
  2251         -** 
         2251  +**
  2252   2252   ** initFlags are a set of parse flags that should always be set for this
  2253   2253   ** file.  For .c files this is normally 0.  For .h files it is PS_Interface.
  2254   2254   */
  2255   2255   static int ParseFile(Token *pList, int initFlags){
  2256   2256     int nErr = 0;
  2257   2257     Token *pStart = 0;
  2258   2258     int flags = initFlags;
................................................................................
  2277   2277         case ';':
  2278   2278           nErr += ProcessDecl(pStart,pList,flags);
  2279   2279           pStart = 0;
  2280   2280           flags = presetFlags;
  2281   2281           break;
  2282   2282   
  2283   2283         case '=':
  2284         -        if( pList->pPrev->nText==8 
         2284  +        if( pList->pPrev->nText==8
  2285   2285               && strncmp(pList->pPrev->zText,"operator",8)==0 ){
  2286   2286             break;
  2287   2287           }
  2288   2288           nErr += ProcessDecl(pStart,pList,flags);
  2289   2289           pStart = 0;
  2290   2290           while( pList && pList->zText[0]!=';' ){
  2291   2291             pList = pList->pNext;
................................................................................
  2469   2469     pDecl->zDecl = StrDup(StringGet(&str), 0);
  2470   2470     StringReset(&str);
  2471   2471     pDecl->zExtra = 0;
  2472   2472   }
  2473   2473   
  2474   2474   /*
  2475   2475   ** Reset the DP_Forward and DP_Declared flags on all Decl structures.
  2476         -** Set both flags for anything that is tagged as local and isn't 
         2476  +** Set both flags for anything that is tagged as local and isn't
  2477   2477   ** in the file zFilename so that it won't be printing in other files.
  2478   2478   */
  2479   2479   static void ResetDeclFlags(char *zFilename){
  2480   2480     Decl *pDecl;
  2481   2481   
  2482   2482     for(pDecl = pDeclFirst; pDecl; pDecl = pDecl->pNext){
  2483   2483       DeclClearProperty(pDecl,DP_Forward|DP_Declared);
................................................................................
  2572   2572   ){
  2573   2573     Decl *p;               /* The object to be declared */
  2574   2574     int flag;
  2575   2575     int isCpp;             /* True if generating C++ */
  2576   2576     int doneTypedef = 0;   /* True if a typedef has been done for this object */
  2577   2577   
  2578   2578     /* printf("BEGIN %s of %s\n",needFullDecl?"FULL":"PROTOTYPE",pDecl->zName);*/
  2579         -  /* 
         2579  +  /*
  2580   2580     ** For any object that has a forward declaration, go ahead and do the
  2581   2581     ** forward declaration first.
  2582   2582     */
  2583   2583     isCpp = (pState->flags & DP_Cplusplus) != 0;
  2584   2584     for(p=pDecl; p; p=p->pSameName){
  2585   2585       if( p->zFwd ){
  2586   2586         if( !DeclHasProperty(p,DP_Forward) ){
................................................................................
  2624   2624     ** with the DP_Flag bit.  We are only able to use DP_Flag in this
  2625   2625     ** way because we know we'll never execute this far into this
  2626   2626     ** function on a recursive call with the same pDecl.  Hence, recursive
  2627   2627     ** calls to this function (through ScanText()) can never change the
  2628   2628     ** value of DP_Flag out from under us.
  2629   2629     */
  2630   2630     for(p=pDecl; p; p=p->pSameName){
  2631         -    if( !DeclHasProperty(p,DP_Declared) 
  2632         -     && (p->zFwd==0 || needFullDecl) 
         2631  +    if( !DeclHasProperty(p,DP_Declared)
         2632  +     && (p->zFwd==0 || needFullDecl)
  2633   2633        && p->zDecl!=0
  2634   2634       ){
  2635   2635         DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag);
  2636   2636       }else{
  2637   2637         DeclClearProperty(p,DP_Flag);
  2638   2638       }
  2639   2639     }
................................................................................
  2733   2733         /*
  2734   2734         ** See if there is a declaration in the database with the name given
  2735   2735         ** by sToken.
  2736   2736         */
  2737   2737         pDecl = FindDecl(sToken.zText,sToken.nText);
  2738   2738         if( pDecl==0 ) continue;
  2739   2739   
  2740         -      /* 
  2741         -      ** If we get this far, we've found an identifier that has a 
         2740  +      /*
         2741  +      ** If we get this far, we've found an identifier that has a
  2742   2742         ** declaration in the database.  Now see if we the full declaration
  2743   2743         ** or just a forward declaration.
  2744   2744         */
  2745   2745         GetNonspaceToken(&sIn,&sNext);
  2746   2746         if( sNext.zText[0]=='*' ){
  2747   2747           needFullDecl = 0;
  2748   2748         }else{
................................................................................
  2768   2768   static void CompleteForwardDeclarations(GenState *pState){
  2769   2769     Decl *pDecl;
  2770   2770     int progress;
  2771   2771   
  2772   2772     do{
  2773   2773       progress = 0;
  2774   2774       for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){
  2775         -      if( DeclHasProperty(pDecl,DP_Forward) 
  2776         -       && !DeclHasProperty(pDecl,DP_Declared) 
         2775  +      if( DeclHasProperty(pDecl,DP_Forward)
         2776  +       && !DeclHasProperty(pDecl,DP_Declared)
  2777   2777         ){
  2778   2778           DeclareObject(pDecl,pState,1);
  2779   2779           progress = 1;
  2780   2780           assert( DeclHasProperty(pDecl,DP_Declared) );
  2781   2781         }
  2782   2782       }
  2783   2783     }while( progress );
................................................................................
  2840   2840       if( WriteFile(pFile->zHdr,zNewVersion) ){
  2841   2841         fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr);
  2842   2842         nErr++;
  2843   2843       }
  2844   2844     }else if( report ){
  2845   2845       fprintf(report,"unchanged\n");
  2846   2846     }
  2847         -  SafeFree(zOldVersion); 
         2847  +  SafeFree(zOldVersion);
  2848   2848     IdentTableReset(&includeTable);
  2849   2849     StringReset(&outStr);
  2850   2850     return nErr;
  2851   2851   }
  2852   2852   
  2853   2853   /*
  2854   2854   ** Generate a global header file -- a header file that contains all
................................................................................
  2876   2876         DeclareObject(pDecl,&sState,1);
  2877   2877       }
  2878   2878     }
  2879   2879     ChangeIfContext(0,&sState);
  2880   2880     printf("%s",StringGet(&outStr));
  2881   2881     IdentTableReset(&includeTable);
  2882   2882     StringReset(&outStr);
  2883         -  return 0;  
         2883  +  return 0;
  2884   2884   }
  2885   2885   
  2886   2886   #ifdef DEBUG
  2887   2887   /*
  2888   2888   ** Return the number of characters in the given string prior to the
  2889   2889   ** first newline.
  2890   2890   */
................................................................................
  3038   3038   */
  3039   3039   static InFile *CreateInFile(char *zArg, int *pnErr){
  3040   3040     int nSrc;
  3041   3041     char *zSrc;
  3042   3042     InFile *pFile;
  3043   3043     int i;
  3044   3044   
  3045         -  /* 
         3045  +  /*
  3046   3046     ** Get the name of the input file to be scanned.  The input file is
  3047   3047     ** everything before the first ':' or the whole file if no ':' is seen.
  3048   3048     **
  3049   3049     ** Except, on windows, ignore any ':' that occurs as the second character
  3050   3050     ** since it might be part of the drive specifier.  So really, the ":' has
  3051   3051     ** to be the 3rd or later character in the name.  This precludes 1-character
  3052   3052     ** file names, which really should not be a problem.
................................................................................
  3097   3097         SafeFree(pFile->zHdr);
  3098   3098         pFile->zHdr = 0;
  3099   3099       }
  3100   3100     }
  3101   3101   
  3102   3102     /*
  3103   3103     ** If pFile->zSrc contains no 'c' or 'C' in its extension, it
  3104         -  ** must be a header file.   In that case, we need to set the 
         3104  +  ** must be a header file.   In that case, we need to set the
  3105   3105     ** PS_Interface flag.
  3106   3106     */
  3107   3107     pFile->flags |= PS_Interface;
  3108   3108     for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){
  3109   3109       if( zSrc[i]=='c' || zSrc[i]=='C' ){
  3110   3110         pFile->flags &= ~PS_Interface;
  3111   3111         break;
  3112   3112       }
  3113   3113     }
  3114   3114   
  3115         -  /* Done! 
         3115  +  /* Done!
  3116   3116     */
  3117   3117     return pFile;
  3118   3118   }
  3119   3119   
  3120   3120   /* MS-Windows and MS-DOS both have the following serious OS bug:  the
  3121   3121   ** length of a command line is severely restricted.  But this program
  3122   3122   ** occasionally requires long command lines.  Hence the following
................................................................................
  3160   3160     }
  3161   3161     c = ' ';
  3162   3162     while( c!=EOF ){
  3163   3163       while( c!=EOF && isspace(c) ){
  3164   3164         if( c=='\n' ){
  3165   3165           startOfLine = 1;
  3166   3166         }
  3167         -      c = getc(in); 
         3167  +      c = getc(in);
  3168   3168         if( startOfLine && c=='#' ){
  3169   3169           while( c!=EOF && c!='\n' ){
  3170   3170             c = getc(in);
  3171   3171           }
  3172   3172         }
  3173   3173       }
  3174   3174       n = 0;
................................................................................
  3182   3182         nNew++;
  3183   3183         if( nNew + argc > nAlloc ){
  3184   3184           if( nAlloc==0 ){
  3185   3185             nAlloc = 100 + argc;
  3186   3186             zNew = malloc( sizeof(char*) * nAlloc );
  3187   3187           }else{
  3188   3188             nAlloc *= 2;
  3189         -          zNew = realloc( zNew, sizeof(char*) * nAlloc );  
         3189  +          zNew = realloc( zNew, sizeof(char*) * nAlloc );
  3190   3190           }
  3191   3191         }
  3192   3192         if( zNew ){
  3193   3193           int j = nNew + index;
  3194   3194           zNew[j] = malloc( n + 1 );
  3195   3195           if( zNew[j] ){
  3196   3196             strcpy( zNew[j], zBuf );
................................................................................
  3252   3252     );
  3253   3253   }
  3254   3254   
  3255   3255   /*
  3256   3256   ** The following text contains a few simple #defines that we want
  3257   3257   ** to be available to every file.
  3258   3258   */
  3259         -static char zInit[] = 
         3259  +static const char zInit[] =
  3260   3260     "#define INTERFACE 0\n"
  3261   3261     "#define EXPORT_INTERFACE 0\n"
  3262   3262     "#define LOCAL_INTERFACE 0\n"
  3263   3263     "#define EXPORT\n"
  3264   3264     "#define LOCAL static\n"
  3265   3265     "#define PUBLIC\n"
  3266   3266     "#define PRIVATE\n"

Changes to src/makemake.tcl.

     1      1   #!/usr/bin/tclsh
     2      2   #
     3         -# Run this TCL script to generate the various makefiles for a variety
            3  +# Run this Tcl script to generate the various makefiles for a variety
     4      4   # of platforms.  Files generated include:
     5      5   #
     6      6   #     src/main.mk           # makefile for all unix systems
     7      7   #     win/Makefile.mingw    # makefile for mingw on windows
     8      8   #     win/Makefile.*        # makefiles for other windows compilers
     9      9   #
    10     10   # Run this script while in the "src" subdirectory.  Like this:
................................................................................
   140    140     http_ssl
   141    141   }
   142    142   
   143    143   # Additional resource files that get built into the executable.
   144    144   #
   145    145   set extra_files {
   146    146     diff.tcl
          147  +  ../skins/*/*.txt
   147    148   }
   148    149   
   149    150   # Options used to compile the included SQLite library.
   150    151   #
   151    152   set SQLITE_OPTIONS {
   152    153     -DNDEBUG=1
   153    154     -DSQLITE_OMIT_LOAD_EXTENSION=1
................................................................................
   201    202       puts $output_file [lindex $args 0]
   202    203     }
   203    204   }
   204    205   
   205    206   # STOP HERE.
   206    207   # Unless the build procedures changes, you should not have to edit anything
   207    208   # below this line.
          209  +
          210  +# Expand any wildcards in "extra_files"
          211  +set new_extra_files {}
          212  +foreach file $extra_files {
          213  +  foreach x [glob -nocomplain $file] {
          214  +    lappend new_extra_files $x
          215  +  }
          216  +}
          217  +set extra_files $new_extra_files
   208    218   
   209    219   ##############################################################################
   210    220   ##############################################################################
   211    221   ##############################################################################
   212    222   # Start by generating the "main.mk" makefile used for all unix systems.
   213    223   #
   214    224   puts "building main.mk"
................................................................................
   571    581   endif
   572    582   
   573    583   #### The directories where the OpenSSL include and library files are located.
   574    584   #    The recommended usage here is to use the Sysinternals junction tool
   575    585   #    to create a hard link between an "openssl-1.x" sub-directory of the
   576    586   #    Fossil source code directory and the target OpenSSL source directory.
   577    587   #
   578         -OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include
   579         -OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k
          588  +OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l
          589  +OPENSSLINCDIR = $(OPENSSLDIR)/include
          590  +OPENSSLLIBDIR = $(OPENSSLDIR)
   580    591   
   581    592   #### Either the directory where the Tcl library is installed or the Tcl
   582    593   #    source code directory resides (depending on the value of the macro
   583    594   #    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
   584    595   #    this directory must have "include" and "lib" sub-directories.  If
   585    596   #    this points to the Tcl source code directory, this directory must
   586    597   #    have "generic" and "win" sub-directories.  The recommended usage
................................................................................
  1303   1314   # Uncomment to enable TH1 hooks
  1304   1315   # FOSSIL_ENABLE_TH1_HOOKS = 1
  1305   1316   
  1306   1317   # Uncomment to enable Tcl support
  1307   1318   # FOSSIL_ENABLE_TCL = 1
  1308   1319   
  1309   1320   !ifdef FOSSIL_ENABLE_SSL
  1310         -SSLDIR    = $(B)\compat\openssl-1.0.1k
         1321  +SSLDIR    = $(B)\compat\openssl-1.0.1l
  1311   1322   SSLINCDIR = $(SSLDIR)\inc32
  1312   1323   SSLLIBDIR = $(SSLDIR)\out32
  1313   1324   SSLLFLAGS = /nologo /opt:ref /debug
  1314   1325   SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
  1315   1326   !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
  1316   1327   !message Using 'x64' platform for OpenSSL...
  1317   1328   # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.

Changes to src/mkbuiltin.c.

    27     27   #include <stdio.h>
    28     28   #include <stdlib.h>
    29     29   #include <string.h>
    30     30   
    31     31   
    32     32   /*
    33     33   ** Read the entire content of the file named zFilename into memory obtained
    34         -** from malloc() and retur a pointer to that memory.  Write the size of the
           34  +** from malloc() and return a pointer to that memory.  Write the size of the
    35     35   ** file into *pnByte.
    36     36   */
    37     37   static unsigned char *read_file(const char *zFilename, int *pnByte){
    38     38     FILE *in;
    39     39     unsigned char *z;
    40     40     int nByte;
    41     41     int got;
................................................................................
    60     60   /*
    61     61   ** There is an instance of the following for each file translated.
    62     62   */
    63     63   typedef struct Resource Resource;
    64     64   struct Resource {
    65     65     const char *zName;
    66     66     int nByte;
           67  +  int idx;
    67     68   };
    68     69   
    69     70   /*
    70     71   ** Compare two Resource objects for sorting purposes.  They sort
    71     72   ** in zName order so that Fossil can search for resources using
    72     73   ** a binary search.
    73     74   */
................................................................................
    80     81   int main(int argc, char **argv){
    81     82     int i, sz;
    82     83     int j, n;
    83     84     Resource *aRes;
    84     85     int nRes = argc-1;
    85     86     unsigned char *pData;
    86     87     int nErr = 0;
           88  +  int nSkip;
    87     89   
    88     90     aRes = malloc( nRes*sizeof(aRes[0]) );
    89     91     if( aRes==0 ){
    90     92       fprintf(stderr, "malloc failed\n");
    91     93       return 1;
    92     94     }
    93     95     for(i=0; i<argc-1; i++){
................................................................................
   101    103     for(i=0; i<nRes; i++){
   102    104       pData = read_file(aRes[i].zName, &sz);
   103    105       if( pData==0 ){
   104    106         fprintf(stderr, "Cannot open file [%s]\n", aRes[i].zName);
   105    107         nErr++;
   106    108         continue;
   107    109       }
   108         -    aRes[i].nByte = sz;
          110  +
          111  +    /* Skip initial lines beginning with # */
          112  +    nSkip = 0;
          113  +    while( pData[nSkip]=='#' ){
          114  +      while( pData[nSkip]!=0 && pData[nSkip]!='\n' ){ nSkip++; }
          115  +      if( pData[nSkip]=='\n' ) nSkip++;
          116  +    }
          117  +
          118  +    aRes[i].nByte = sz - nSkip;
          119  +    aRes[i].idx = i;
   109    120       printf("/* Content of file %s */\n", aRes[i].zName);
   110    121       printf("static const unsigned char bidata%d[%d] = {\n  ",
   111         -           i, sz+1);
   112         -    for(j=n=0; j<=sz; j++){
          122  +           i, sz+1-nSkip);
          123  +    for(j=nSkip, n=0; j<=sz; j++){
   113    124         printf("%3d", pData[j]);
   114    125         if( j==sz ){
   115    126           printf(" };\n");
   116    127         }else if( n==14 ){
   117    128           printf(",\n  ");
   118    129           n = 0;
   119    130         }else{
................................................................................
   127    138     printf("struct BuiltinFileTable {\n");
   128    139     printf("  const char *zName;\n");
   129    140     printf("  const unsigned char *pData;\n");
   130    141     printf("  int nByte;\n");
   131    142     printf("};\n");
   132    143     printf("static const BuiltinFileTable aBuiltinFiles[] = {\n");
   133    144     for(i=0; i<nRes; i++){
   134         -    const char *zTail;
   135    145       const char *z = aRes[i].zName;
          146  +    const char *zTail;
          147  +    int nSlash = 0;
   136    148       zTail = z;
   137    149       while( z && z[0] ){
   138         -      if( z[0]=='/' || z[0]=='\\' ) zTail = &z[1];
          150  +      if( z[0]=='/' || z[0]=='\\' ){
          151  +        nSlash++;
          152  +        if( nSlash<=2 || z[-1]=='.' ) zTail = &z[1];
          153  +      }
   139    154         z++;
   140    155       }
   141         -    printf("  { \"%s\", bidata%d, %d },\n", zTail, i, aRes[i].nByte);
          156  +    aRes[i].zName = zTail;
          157  +  }
          158  +  qsort(aRes, nRes, sizeof(aRes[0]), compareResource);
          159  +  for(i=0; i<nRes; i++){
          160  +    printf("  { \"%s\", bidata%d, %d },\n",
          161  +           aRes[i].zName, aRes[i].idx, aRes[i].nByte);
   142    162     }
   143    163     printf("};\n");
   144    164     return nErr;
   145    165   }

Changes to src/mkindex.c.

   215    215     i+=j;
   216    216     while( isspace(zLine[i]) ){ i++; }
   217    217     if( zLine[i]!='(' ) goto page_skip;
   218    218     nFixed = nUsed;
   219    219     nHelp = 0;
   220    220     return;
   221    221   
   222         -page_skip:   
          222  +page_skip:
   223    223      for(i=nFixed; i<nUsed; i++){
   224    224         fprintf(stderr,"%s:%d: skipping page \"%s\"\n",
   225    225            zFile, nLine, aEntry[i].zPath);
   226    226      }
   227    227      nUsed = nFixed;
   228    228   }
   229    229   
................................................................................
   325    325         printf("\";\n");
   326    326         if( aEntry[i].zIf ) printf("#endif\n");
   327    327         aEntry[i].zHelp[0] = 0;
   328    328       }
   329    329     }
   330    330     puts("struct CmdHelp {"
   331    331          "int eType; "
   332         -       "char const * zText;"
          332  +       "const char *zText;"
   333    333          "};");
   334    334     puts("static struct CmdHelp aCmdHelp[] = {");
   335    335     for(i=0; i<nFixed; i++){
   336    336       if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
   337    337       if( aEntry[i].zHelp==0 ){
   338    338         printf("{%d, 0},\n", aEntry[i].eType);
   339    339       }else{
................................................................................
   359    359       nLine++;
   360    360       scan_for_if(zLine);
   361    361       scan_for_label("WEBPAGE:",zLine,0);
   362    362       scan_for_label("COMMAND:",zLine,1);
   363    363       scan_for_func(zLine);
   364    364     }
   365    365     fclose(in);
   366         -  nUsed = nFixed; 
          366  +  nUsed = nFixed;
   367    367   }
   368    368   
   369    369   int main(int argc, char **argv){
   370    370     int i;
   371    371     for(i=1; i<argc; i++){
   372    372       zFile = argv[i];
   373    373       process_file();
   374    374     }
   375    375     build_table();
   376    376     return 0;
   377    377   }

Changes to src/mkversion.c.

    41     41       if( fgets(b, sizeof(b)-1,v)==0 ){
    42     42         fprintf(stderr, "malformed VERSION file: %s\n", argv[3]);
    43     43         exit(1);
    44     44       }
    45     45       fclose(v);
    46     46       for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
    47     47       *z = 0;
    48         -    printf("#define RELEASE_VERSION \"%s\"\n", b);   
           48  +    printf("#define RELEASE_VERSION \"%s\"\n", b);
    49     49       x=0;
    50     50       i=0;
    51     51       z=b;
    52     52       while(1){
    53     53         if( z[0]>='0' && z[0]<='9' ){
    54     54           x = x*10 + z[0] - '0';
    55     55         }else{

Changes to src/report.c.

   169    169     int rc = SQLITE_OK;
   170    170     if( *(char**)pError ){
   171    171       /* We've already seen an error.  No need to continue. */
   172    172       return SQLITE_OK;
   173    173     }
   174    174     switch( code ){
   175    175       case SQLITE_SELECT:
          176  +    case SQLITE_RECURSIVE:
   176    177       case SQLITE_FUNCTION: {
   177    178         break;
   178    179       }
   179    180       case SQLITE_READ: {
   180    181         static const char *const azAllowed[] = {
   181    182            "ticket",
   182    183            "ticketchng",
................................................................................
   199    200           *(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1);
   200    201           rc = SQLITE_DENY;
   201    202         }else if( !g.perm.RdAddr && strncmp(zArg2, "private_", 8)==0 ){
   202    203           rc = SQLITE_IGNORE;
   203    204         }
   204    205         break;
   205    206       }
   206         -    case SQLITE_RECURSIVE: {
   207         -      *(char**)pError = mprintf("recursive queries are not allowed");
   208         -      rc = SQLITE_DENY;
   209         -      break;
   210         -    }
   211    207       default: {
   212    208         *(char**)pError = mprintf("only SELECT statements are allowed");
   213    209         rc = SQLITE_DENY;
   214    210         break;
   215    211       }
   216    212     }
   217    213     return rc;
................................................................................
   238    234     int i;
   239    235     char *zErr = 0;
   240    236     const char *zTail;
   241    237     sqlite3_stmt *pStmt;
   242    238     int rc;
   243    239   
   244    240     /* First make sure the SQL is a single query command by verifying that
   245         -  ** the first token is "SELECT" and that there are no unquoted semicolons.
          241  +  ** the first token is "SELECT" or "WITH" and that there are no unquoted
          242  +  ** semicolons.
   246    243     */
   247    244     for(i=0; fossil_isspace(zSql[i]); i++){}
   248         -  if( fossil_strnicmp(&zSql[i],"select",6)!=0 ){
   249         -    return mprintf("The SQL must be a SELECT statement");
          245  +  if( fossil_strnicmp(&zSql[i], "select", 6)!=0
          246  +      && fossil_strnicmp(&zSql[i], "with", 4)!=0 ){
          247  +    return mprintf("The SQL must be a SELECT or WITH statement");
   250    248     }
   251    249     for(i=0; zSql[i]; i++){
   252    250       if( zSql[i]==';' ){
   253    251         int bad;
   254    252         int c = zSql[i+1];
   255    253         zSql[i+1] = 0;
   256    254         bad = sqlite3_complete(zSql);
................................................................................
   934    932   ** argument.  Each character of the second argument represent a column.
   935    933   **
   936    934   **       t      Sort by text
   937    935   **       n      Sort numerically
   938    936   **       k      Sort by the data-sortkey property
   939    937   **       x      This column is not sortable
   940    938   **
          939  +** Capital letters mean sort in reverse order.
   941    940   ** If there are fewer characters in zColumnTypes[] than their are columns,
   942    941   ** the all extra columns assume type "t" (text).
   943    942   **
   944    943   ** The third parameter is the column that was initially sorted (using 1-based
   945    944   ** column numbers, like SQL).  Make this value 0 if none of the columns are
   946    945   ** initially sorted.  Make the value negative if the column is initially sorted
   947    946   ** in reverse order.
................................................................................
   957    956     @ function SortableTable(tableEl,columnTypes,initSort){
   958    957     @   this.tbody = tableEl.getElementsByTagName('tbody');
   959    958     @   this.columnTypes = columnTypes;
   960    959     @   this.sort = function (cell) {
   961    960     @     var column = cell.cellIndex;
   962    961     @     var sortFn;
   963    962     @     switch( cell.sortType ){
   964         -  @       case "n":  sortFn = this.sortNumeric;  break;
   965         -  @       case "t":  sortFn = this.sortText;     break;
   966         -  @       case "k":  sortFn = this.sortKey;      break;
   967         -  @       case "x":  return;
          963  +  @       case "N": case "n":  sortFn = this.sortNumeric;  break;
          964  +  @       case "T": case "t":  sortFn = this.sortText;     break;
          965  +  @       case "K": case "k":  sortFn = this.sortKey;      break;
          966  +  @       default:  return;
   968    967     @     }
   969    968     @     this.sortIndex = column;
   970    969     @     var newRows = new Array();
   971    970     @     for (j = 0; j < this.tbody[0].rows.length; j++) {
   972    971     @        newRows[j] = this.tbody[0].rows[j];
   973    972     @     }
   974    973     @     if( this.sortIndex==Math.abs(this.prevColumn)-1 ){
   975    974     @       newRows.reverse();
   976    975     @       this.prevColumn = -this.prevColumn;
   977    976     @     }else{
   978    977     @       newRows.sort(sortFn);
   979    978     @       this.prevColumn = this.sortIndex+1;
          979  +  @       if( cell.sortType>="A" && cell.sortType<="Z" ){
          980  +  @         newRows.reverse();
          981  +  @       }
   980    982     @     }
   981    983     @     for (i=0;i<newRows.length;i++) {
   982    984     @       this.tbody[0].appendChild(newRows[i]);
   983    985     @     }
   984    986     @     this.setHdrIcons();
   985    987     @   }
   986    988     @   this.setHdrIcons = function() {
................................................................................
  1000   1002     @       hdrCell.className = clsName;
  1001   1003     @     }
  1002   1004     @   }
  1003   1005     @   this.sortText = function(a,b) {
  1004   1006     @     var i = thisObject.sortIndex;
  1005   1007     @     aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
  1006   1008     @     bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase();
  1007         -  @     if(aa==bb) return 0;
         1009  +  @     if(aa==bb) return a.rowIndex-b.rowIndex;
  1008   1010     @     if(aa<bb) return -1;
  1009   1011     @     return 1;
  1010   1012     @   }
  1011   1013     @   this.sortNumeric = function(a,b) {
  1012   1014     @     var i = thisObject.sortIndex;
  1013   1015     @     aa = parseFloat(a.cells[i].textContent);
  1014   1016     @     if (isNaN(aa)) aa = 0;
  1015   1017     @     bb = parseFloat(b.cells[i].textContent);
  1016   1018     @     if (isNaN(bb)) bb = 0;
         1019  +  @     if(aa==bb) return a.rowIndex-b.rowIndex;
  1017   1020     @     return aa-bb;
  1018   1021     @   }
  1019   1022     @   this.sortKey = function(a,b) {
  1020   1023     @     var i = thisObject.sortIndex;
  1021   1024     @     aa = a.cells[i].getAttribute("data-sortkey");
  1022   1025     @     bb = b.cells[i].getAttribute("data-sortkey");
  1023         -  @     if(aa==bb) return 0;
         1026  +  @     if(aa==bb) return a.rowIndex-b.rowIndex;
  1024   1027     @     if(aa<bb) return -1;
  1025   1028     @     return 1;
  1026   1029     @   }
  1027   1030     @   var x = tableEl.getElementsByTagName('thead');
  1028   1031     @   if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){
  1029   1032     @     return;
  1030   1033     @   }

Changes to src/search.c.

   163    163     const char **azDoc;
   164    164     int score;
   165    165     int i;
   166    166   
   167    167     azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
   168    168     for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
   169    169     score = search_score(p, argc, azDoc);
   170         -  fossil_free(azDoc);
          170  +  fossil_free((void *)azDoc);
   171    171     sqlite3_result_int(context, score);
   172    172   }
   173    173   
   174    174   /*
   175    175   ** Register the "score()" SQL function to score its input text
   176    176   ** using the given Search object.  Once this function is registered,
   177    177   ** do not delete the Search object.

Changes to src/setup.c.

  1523   1523     login_check_credentials();
  1524   1524     if( !g.perm.Setup ){
  1525   1525       login_needed();
  1526   1526     }
  1527   1527     db_begin_transaction();
  1528   1528     if( P("clear")!=0 ){
  1529   1529       db_multi_exec("DELETE FROM config WHERE name='css'");
  1530         -    cgi_replace_parameter("css", zDefaultCSS);
         1530  +    cgi_replace_parameter("css", builtin_text("skins/default.css"));
  1531   1531       db_end_transaction(0);
  1532   1532       cgi_redirect("setup_editcss");
  1533   1533     }
  1534   1534     if( P("submit")!=0 ){
  1535         -    textarea_attribute(0, 0, 0, "css", "css", zDefaultCSS, 0);
         1535  +    textarea_attribute(0, 0, 0, "css", "css",
         1536  +                       builtin_text("skins/default.css"), 0);
  1536   1537       db_end_transaction(0);
  1537   1538       cgi_redirect("setup_editcss");
  1538   1539     }
  1539   1540     style_header("Edit CSS");
  1540   1541     @ <form action="%s(g.zTop)/setup_editcss" method="post"><div>
  1541   1542     login_insert_csrf_secret();
  1542   1543     @ Edit the CSS below:<br />
  1543         -  textarea_attribute("", 35, 80, "css", "css", zDefaultCSS, 0);
         1544  +  textarea_attribute("", 35, 80, "css", "css",
         1545  +                     builtin_text("skins/default.css"), 0);
  1544   1546     @ <br />
  1545   1547     @ <input type="submit" name="submit" value="Apply Changes" />
  1546   1548     @ <input type="submit" name="clear" value="Revert To Default" />
  1547   1549     @ </div></form>
  1548   1550     @ <p><span class="note">Note:</span> Press your browser Reload button after
  1549   1551     @ modifying the CSS in order to pull in the modified CSS file.</p>
  1550   1552     @ <hr />
................................................................................
  1566   1568     login_check_credentials();
  1567   1569     if( !g.perm.Setup ){
  1568   1570       login_needed();
  1569   1571     }
  1570   1572     db_begin_transaction();
  1571   1573     if( P("clear")!=0 ){
  1572   1574       db_multi_exec("DELETE FROM config WHERE name='header'");
  1573         -    cgi_replace_parameter("header", zDefaultHeader);
         1575  +    cgi_replace_parameter("header", builtin_text("skins/default.header"));
  1574   1576     }else if( P("submit")!=0 ){
  1575         -    textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader, 0);
         1577  +    textarea_attribute(0, 0, 0, "header", "header",
         1578  +                       builtin_text("skins/default.header"), 0);
  1576   1579     }else if( P("fixbase")!=0 ){
  1577         -    const char *z = db_get("header", (char*)zDefaultHeader);
         1580  +    const char *z = db_get("header",
         1581  +                           (char*)builtin_text("skins/default.header"));
  1578   1582       char *zHead = strstr(z, "<head>");
  1579   1583       if( strstr(z, "<base href=")==0 && zHead!=0 ){
  1580   1584         char *zNew;
  1581   1585         char *zTail = &zHead[6];
  1582   1586         while( fossil_isspace(zTail[0]) ) zTail++;
  1583   1587         zNew = mprintf("%.*s\n<base href=\"$secureurl/$current_page\" />\n%s",
  1584   1588                        zHead+6-z, z, zTail);
................................................................................
  1596   1600       @ <p class="generalError">Please add
  1597   1601       @ <tt>&lt;base href="$secureurl/$current_page"&gt;</tt> after
  1598   1602       @ <tt>&lt;head&gt;</tt> in the header!
  1599   1603       @ <input type="submit" name="fixbase" value="Add &lt;base&gt; Now"></p>
  1600   1604     }
  1601   1605   
  1602   1606     login_insert_csrf_secret();
  1603         -  @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
         1607  +  @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
  1604   1608     @ generate the beginning of every page through start of the main
  1605   1609     @ menu.</p>
  1606         -  textarea_attribute("", 35, 80, "header", "header", zDefaultHeader, 0);
         1610  +  textarea_attribute("", 35, 80, "header", "header",
         1611  +                     builtin_text("skins/default.header"), 0);
  1607   1612     @ <br />
  1608   1613     @ <input type="submit" name="submit" value="Apply Changes" />
  1609   1614     @ <input type="submit" name="clear" value="Revert To Default" />
  1610   1615     @ </div></form>
  1611   1616     @ <hr />
  1612   1617     @ The default header is shown below for reference.  Other examples
  1613   1618     @ of headers can be seen on the <a href="setup_skin">skins page</a>.
  1614   1619     @ See also the <a href="setup_editcss">CSS</a> and
  1615   1620     @ <a href="setup_footer">footer</a> editing screens.
  1616   1621     @ <blockquote><pre>
  1617         -  @ %h(zDefaultHeader)
         1622  +  @ %h(builtin_text("skins/default.header"))
  1618   1623     @ </pre></blockquote>
  1619   1624     style_footer();
  1620   1625     db_end_transaction(0);
  1621   1626   }
  1622   1627   
  1623   1628   /*
  1624   1629   ** WEBPAGE: setup_footer
................................................................................
  1627   1632     login_check_credentials();
  1628   1633     if( !g.perm.Setup ){
  1629   1634       login_needed();
  1630   1635     }
  1631   1636     db_begin_transaction();
  1632   1637     if( P("clear")!=0 ){
  1633   1638       db_multi_exec("DELETE FROM config WHERE name='footer'");
  1634         -    cgi_replace_parameter("footer", zDefaultFooter);
         1639  +    cgi_replace_parameter("footer", builtin_text("skins/default.footer"));
  1635   1640     }
  1636   1641   
  1637   1642     style_header("Edit Page Footer");
  1638   1643     @ <form action="%s(g.zTop)/setup_footer" method="post"><div>
  1639   1644     login_insert_csrf_secret();
  1640         -  @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
         1645  +  @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
  1641   1646     @ generate the end of every page.</p>
  1642         -  textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter, 0);
         1647  +  textarea_attribute("", 20, 80, "footer", "footer",
         1648  +                     builtin_text("skins/default.footer"), 0);
  1643   1649     @ <br />
  1644   1650     @ <input type="submit" name="submit" value="Apply Changes" />
  1645   1651     @ <input type="submit" name="clear" value="Revert To Default" />
  1646   1652     @ </div></form>
  1647   1653     @ <hr />
  1648   1654     @ The default footer is shown below for reference.  Other examples
  1649   1655     @ of footers can be seen on the <a href="setup_skin">skins page</a>.
  1650   1656     @ See also the <a href="setup_editcss">CSS</a> and
  1651   1657     @ <a href="setup_header">header</a> editing screens.
  1652   1658     @ <blockquote><pre>
  1653         -  @ %h(zDefaultFooter)
         1659  +  @ %h(builtin_text("skins/default.footer"))
  1654   1660     @ </pre></blockquote>
  1655   1661     style_footer();
  1656   1662     db_end_transaction(0);
  1657   1663   }
  1658   1664   
  1659   1665   /*
  1660   1666   ** WEBPAGE: setup_modreq
................................................................................
  1713   1719       db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
  1714   1720       cgi_replace_parameter("adunit","");
  1715   1721     }
  1716   1722   
  1717   1723     style_header("Edit Ad Unit");
  1718   1724     @ <form action="%s(g.zTop)/setup_adunit" method="post"><div>
  1719   1725     login_insert_csrf_secret();
  1720         -  @ <p>Edit HTML text for an ad unit that will be inserted after the
  1721         -  @ menu bar and above the content of every page.</p>
  1722         -  textarea_attribute("", 20, 80, "adunit", "adunit", "", 0);
         1726  +  @ <b>Banner Ad-Unit:</b><br />
         1727  + textarea_attribute("", 6, 80, "adunit", "adunit", "", 0);
         1728  +  @ <br />
         1729  +  @ <b>Right-Column Ad-Unit:</b><br />
         1730  +  textarea_attribute("", 6, 80, "adunit-right", "adright", "", 0);
  1723   1731     @ <br />
  1724   1732     onoff_attribute("Omit ads to administrator",
  1725   1733        "adunit-omit-if-admin", "oia", 0, 0);
  1726   1734     @ <br />
  1727   1735     onoff_attribute("Omit ads to logged-in users",
  1728   1736        "adunit-omit-if-user", "oiu", 0, 0);
  1729   1737     @ <br />
  1730   1738     @ <input type="submit" name="submit" value="Apply Changes" />
  1731   1739     @ <input type="submit" name="clear" value="Delete Ad-Unit" />
  1732   1740     @ </div></form>
         1741  +  @ <hr />
         1742  +  @ <b>Ad-Unit Notes:</b><ul>
         1743  +  @ <li>Leave both Ad-Units blank to disable all advertising.
         1744  +  @ <li>The "Banner Ad-Unit" is used for wide pages.
         1745  +  @ <li>The "Right-Column Ad-Unit" is used on pages with tall, narrow content.
         1746  +  @ <li>If the "Right-Column Ad-Unit" is blank, the "Banner Ad-Unit" is used on all pages.
         1747  +  @ <li>Suggested <a href="setup_editcss">CSS</a> changes:
         1748  +  @ <blockquote><pre>
         1749  +  @ div.adunit_banner {
         1750  +  @   margin: auto;
         1751  +  @   width: 100%;
         1752  +  @ }
         1753  +  @ div.adunit_right {
         1754  +  @   float: right;
         1755  +  @ }
         1756  +  @ div.adunit_right_container {
         1757  +  @   min-height: <i>height-of-right-column-ad-unit</i>;
         1758  +  @ }
         1759  +  @ </pre></blockquote>
         1760  +  @ <li>For a place-holder Ad-Unit for testing, Copy/Paste the following
         1761  +  @ with appropriate adjustments to "width:" and "height:".
         1762  +  @ <blockquote><pre>
         1763  +  @ &lt;div style='
         1764  +  @   margin: 0 auto;
         1765  +  @   width: 600px;
         1766  +  @   height: 90px;
         1767  +  @   border: 1px solid #f11;
         1768  +  @   background-color: #fcc;
         1769  +  @ '&gt;Demo Ad&lt;/div&gt;
         1770  +  @ </pre></blockquote>
         1771  +  @ </li>
  1733   1772     style_footer();
  1734   1773     db_end_transaction(0);
  1735   1774   }
  1736   1775   
  1737   1776   /*
  1738   1777   ** WEBPAGE: setup_logo
  1739   1778   */

Changes to src/sitemap.c.

    25     25   ** WEBPAGE:  sitemap
    26     26   **
    27     27   ** Show an incomplete list of web pages offered by the Fossil web engine.
    28     28   */
    29     29   void sitemap_page(void){
    30     30     login_check_credentials();
    31     31     style_header("Site Map");
           32  +  style_adunit_config(ADUNIT_RIGHT_OK);
    32     33     @ <p>
    33     34     @ The following links are just a few of the many web-pages available for
    34     35     @ this Fossil repository:
    35     36     @ </p>
    36     37     @
    37     38     @ <ul>
    38     39     @ <li>%z(href("%R/home"))Home Page</a></li>

Changes to src/skins.c.

    17     17   **
    18     18   ** Implementation of the Setup page for "skins".
    19     19   */
    20     20   #include "config.h"
    21     21   #include <assert.h>
    22     22   #include "skins.h"
    23     23   
    24         -/* @-comment: ## */
    25         -/*
    26         -** A black-and-white theme with the project title in a bar across the top
    27         -** and no logo image.
    28         -*/
    29         -static const char zBuiltinSkin1[] =
    30         -@ REPLACE INTO config(name,mtime,value)
    31         -@ VALUES('css',now(),'/* General settings for the entire page */
    32         -@ body {
    33         -@   margin: 0ex 1ex;
    34         -@   padding: 0px;
    35         -@   background-color: white;
    36         -@   font-family: sans-serif;
    37         -@ }
    38         -@
    39         -@ /* The project logo in the upper left-hand corner of each page */
    40         -@ div.logo {
    41         -@   display: table-row;
    42         -@   text-align: center;
    43         -@   /* vertical-align: bottom;*/
    44         -@   font-size: 2em;
    45         -@   font-weight: bold;
    46         -@   background-color: #707070;
    47         -@   color: #ffffff;
    48         -@   min-width: 200px;
    49         -@   white-space: nowrap;
    50         -@ }
    51         -@
    52         -@ /* The page title centered at the top of each page */
    53         -@ div.title {
    54         -@   display: table-cell;
    55         -@   font-size: 1.5em;
    56         -@   font-weight: bold;
    57         -@   text-align: center;
    58         -@   padding: 0 0 0 10px;
    59         -@   color: #404040;
    60         -@   vertical-align: bottom;
    61         -@   width: 100%;
    62         -@ }
    63         -@
    64         -@ /* The login status message in the top right-hand corner */
    65         -@ div.status {
    66         -@   display: table-cell;
    67         -@   text-align: right;
    68         -@   vertical-align: bottom;
    69         -@   color: #404040;
    70         -@   font-size: 0.8em;
    71         -@   font-weight: bold;
    72         -@   min-width: 200px;
    73         -@   white-space: nowrap;
    74         -@ }
    75         -@
    76         -@ /* The header across the top of the page */
    77         -@ div.header {
    78         -@   display: table;
    79         -@   width: 100%;
    80         -@ }
    81         -@
    82         -@ /* The main menu bar that appears at the top of the page beneath
    83         -@ ** the header */
    84         -@ div.mainmenu {
    85         -@   padding: 5px 10px 5px 10px;
    86         -@   font-size: 0.9em;
    87         -@   font-weight: bold;
    88         -@   text-align: center;
    89         -@   letter-spacing: 1px;
    90         -@   background-color: #404040;
    91         -@   color: white;
    92         -@ }
    93         -@
    94         -@ /* The submenu bar that *sometimes* appears below the main menu */
    95         -@ div.submenu, div.sectionmenu {
    96         -@   padding: 3px 10px 3px 0px;
    97         -@   font-size: 0.9em;
    98         -@   text-align: center;
    99         -@   background-color: #606060;
   100         -@   color: white;
   101         -@ }
   102         -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
   103         -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
   104         -@   padding: 3px 10px 3px 10px;
   105         -@   color: white;
   106         -@   text-decoration: none;
   107         -@ }
   108         -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
   109         -@   color: #404040;
   110         -@   background-color: white;
   111         -@ }
   112         -@
   113         -@ /* All page content from the bottom of the menu or submenu down to
   114         -@ ** the footer */
   115         -@ div.content {
   116         -@   padding: 0ex 0ex 0ex 0ex;
   117         -@ }
   118         -@ /* Hyperlink colors */
   119         -@ div.content a { color: #604000; }
   120         -@ div.content a:link { color: #604000;}
   121         -@ div.content a:visited { color: #600000; }
   122         -@
   123         -@ /* <verbatim> blocks */
   124         -@ pre.verbatim {
   125         -@   background-color: #ffffff;
   126         -@   padding: 0.5em;
   127         -@   white-space: pre-wrap;
   128         -@ }
   129         -@
   130         -@ /* Some pages have section dividers */
   131         -@ div.section {
   132         -@   margin-bottom: 0px;
   133         -@   margin-top: 1em;
   134         -@   padding: 1px 1px 1px 1px;
   135         -@   font-size: 1.2em;
   136         -@   font-weight: bold;
   137         -@   background-color: #404040;
   138         -@   color: white;
   139         -@   white-space: nowrap;
   140         -@ }
   141         -@
   142         -@ /* The "Date" that occurs on the left hand side of timelines */
   143         -@ div.divider {
   144         -@   background: #a0a0a0;
   145         -@   border: 2px #505050 solid;
   146         -@   font-size: 1em; font-weight: normal;
   147         -@   padding: .25em;
   148         -@   margin: .2em 0 .2em 0;
   149         -@   float: left;
   150         -@   clear: left;
   151         -@   white-space: nowrap;
   152         -@ }
   153         -@
   154         -@ /* The footer at the very bottom of the page */
   155         -@ div.footer {
   156         -@   font-size: 0.8em;
   157         -@   margin-top: 12px;
   158         -@   padding: 5px 10px 5px 10px;
   159         -@   text-align: right;
   160         -@   background-color: #404040;
   161         -@   color: white;
   162         -@ }
   163         -@
   164         -@ /* The label/value pairs on (for example) the vinfo page */
   165         -@ table.label-value th {
   166         -@   vertical-align: top;
   167         -@   text-align: right;
   168         -@   padding: 0.2ex 2ex;
   169         -@ }');
   170         -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
   171         -@ <head>
   172         -@ <base href="$baseurl/$current_page" />
   173         -@ <title>$<project_name>: $<title></title>
   174         -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
   175         -@       href="$home/timeline.rss">
   176         -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css"
   177         -@       media="screen">
   178         -@ </head>
   179         -@ <body>
   180         -@ <div class="header">
   181         -@   <div class="title"><small>$<project_name></small><br />$<title></div>
   182         -@   <div class="status"><th1>
   183         -@      if {[info exists login]} {
   184         -@        puts "Logged in as $login"
   185         -@      } else {
   186         -@        puts "Not logged in"
   187         -@      }
   188         -@   </th1></div>
   189         -@ </div>
   190         -@ <div class="mainmenu">
   191         -@ <th1>
   192         -@ html "<a href=''$home$index_page''>Home</a>\n"
   193         -@ if {[anycap jor]} {
   194         -@   html "<a href=''$home/timeline''>Timeline</a>\n"
   195         -@ }
   196         -@ if {[hascap oh]} {
   197         -@   html "<a href=''$home/tree?ci=tip''>Files</a>\n"
   198         -@ }
   199         -@ if {[hascap o]} {
   200         -@   html "<a href=''$home/brlist''>Branches</a>\n"
   201         -@   html "<a href=''$home/taglist''>Tags</a>\n"
   202         -@ }
   203         -@ if {[hascap r]} {
   204         -@   html "<a href=''$home/reportlist''>Tickets</a>\n"
   205         -@ }
   206         -@ if {[hascap j]} {
   207         -@   html "<a href=''$home/wiki''>Wiki</a>\n"
   208         -@ }
   209         -@ if {[hascap s]} {
   210         -@   html "<a href=''$home/setup''>Admin</a>\n"
   211         -@ } elseif {[hascap a]} {
   212         -@   html "<a href=''$home/setup_ulist''>Users</a>\n"
   213         -@ }
   214         -@ if {[info exists login]} {
   215         -@   html "<a href=''$home/login''>Logout</a>\n"
   216         -@ } else {
   217         -@   html "<a href=''$home/login''>Login</a>\n"
   218         -@ }
   219         -@ </th1></div>
   220         -@ ');
   221         -@ REPLACE INTO config(name,mtime,value)
   222         -@ VALUES('footer',now(),'<div class="footer">
   223         -@ Fossil version $manifest_version $manifest_date
   224         -@ </div>
   225         -@ </body></html>
   226         -@ ');
   227         -;
   228         -
   229         -/*
   230         -** A tan theme with the project title above the user identification
   231         -** and no logo image.
   232         -*/
   233         -static const char zBuiltinSkin2[] =
   234         -@ REPLACE INTO config(name,mtime,value)
   235         -@ VALUES('css',now(),'/* General settings for the entire page */
   236         -@ body {
   237         -@   margin: 0ex 0ex;
   238         -@   padding: 0px;
   239         -@   background-color: #fef3bc;
   240         -@   font-family: sans-serif;
   241         -@ }
   242         -@
   243         -@ /* The project logo in the upper left-hand corner of each page */
   244         -@ div.logo {
   245         -@   display: inline;
   246         -@   text-align: center;
   247         -@   vertical-align: bottom;
   248         -@   font-weight: bold;
   249         -@   font-size: 2.5em;
   250         -@   color: #a09048;
   251         -@   white-space: nowrap;
   252         -@ }
   253         -@
   254         -@ /* The page title centered at the top of each page */
   255         -@ div.title {
   256         -@   display: table-cell;
   257         -@   font-size: 2em;
   258         -@   font-weight: bold;
   259         -@   text-align: left;
   260         -@   padding: 0 0 0 5px;
   261         -@   color: #a09048;
   262         -@   vertical-align: bottom;
   263         -@   width: 100%;
   264         -@ }
   265         -@
   266         -@ /* The login status message in the top right-hand corner */
   267         -@ div.status {
   268         -@   display: table-cell;
   269         -@   text-align: right;
   270         -@   vertical-align: bottom;
   271         -@   color: #a09048;
   272         -@   padding: 5px 5px 0 0;
   273         -@   font-size: 0.8em;
   274         -@   font-weight: bold;
   275         -@   white-space: nowrap;
   276         -@ }
   277         -@
   278         -@ /* The header across the top of the page */
   279         -@ div.header {
   280         -@   display: table;
   281         -@   width: 100%;
   282         -@ }
   283         -@
   284         -@ /* The main menu bar that appears at the top of the page beneath
   285         -@ ** the header */
   286         -@ div.mainmenu {
   287         -@   padding: 5px 10px 5px 10px;
   288         -@   font-size: 0.9em;
   289         -@   font-weight: bold;
   290         -@   text-align: center;
   291         -@   letter-spacing: 1px;
   292         -@   background-color: #a09048;
   293         -@   color: black;
   294         -@ }
   295         -@
   296         -@ /* The submenu bar that *sometimes* appears below the main menu */
   297         -@ div.submenu, div.sectionmenu {
   298         -@   padding: 3px 10px 3px 0px;
   299         -@   font-size: 0.9em;
   300         -@   text-align: center;
   301         -@   background-color: #c0af58;
   302         -@   color: white;
   303         -@ }
   304         -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
   305         -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
   306         -@   padding: 3px 10px 3px 10px;
   307         -@   color: white;
   308         -@   text-decoration: none;
   309         -@ }
   310         -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
   311         -@   color: #a09048;
   312         -@   background-color: white;
   313         -@ }
   314         -@
   315         -@ /* All page content from the bottom of the menu or submenu down to
   316         -@ ** the footer */
   317         -@ div.content {
   318         -@   padding: 1ex 5px;
   319         -@ }
   320         -@ div.content a { color: #706532; }
   321         -@ div.content a:link { color: #706532; }
   322         -@ div.content a:visited { color: #704032; }
   323         -@ div.content a:hover { background-color: white; color: #706532; }
   324         -@
   325         -@ /* Some pages have section dividers */
   326         -@ div.section {
   327         -@   margin-bottom: 0px;
   328         -@   margin-top: 1em;
   329         -@   padding: 3px 3px 0 3px;
   330         -@   font-size: 1.2em;
   331         -@   font-weight: bold;
   332         -@   background-color: #a09048;
   333         -@   color: white;
   334         -@   white-space: nowrap;
   335         -@ }
   336         -@
   337         -@ /* The "Date" that occurs on the left hand side of timelines */
   338         -@ div.divider {
   339         -@   background: #e1d498;
   340         -@   border: 2px #a09048 solid;
   341         -@   font-size: 1em; font-weight: normal;
   342         -@   padding: .25em;
   343         -@   margin: .2em 0 .2em 0;
   344         -@   float: left;
   345         -@   clear: left;
   346         -@   white-space: nowrap;
   347         -@ }
   348         -@
   349         -@ /* The footer at the very bottom of the page */
   350         -@ div.footer {
   351         -@   font-size: 0.8em;
   352         -@   margin-top: 12px;
   353         -@   padding: 5px 10px 5px 10px;
   354         -@   text-align: right;
   355         -@   background-color: #a09048;
   356         -@   color: white;
   357         -@ }
   358         -@
   359         -@ /* Hyperlink colors */
   360         -@ div.footer a { color: white; }
   361         -@ div.footer a:link { color: white; }
   362         -@ div.footer a:visited { color: white; }
   363         -@ div.footer a:hover { background-color: white; color: #558195; }
   364         -@
   365         -@ /* <verbatim> blocks */
   366         -@ pre.verbatim {
   367         -@   background-color: #f5f5f5;
   368         -@   padding: 0.5em;
   369         -@   white-space: pre-wrap;
   370         -@ }
   371         -@
   372         -@ /* The label/value pairs on (for example) the ci page */
   373         -@ table.label-value th {
   374         -@   vertical-align: top;
   375         -@   text-align: right;
   376         -@   padding: 0.2ex 2ex;
   377         -@ }');
   378         -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
   379         -@ <head>
   380         -@ <base href="$baseurl/$current_page" />
   381         -@ <title>$<project_name>: $<title></title>
   382         -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
   383         -@       href="$home/timeline.rss">
   384         -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css"
   385         -@       media="screen">
   386         -@ </head>
   387         -@ <body>
   388         -@ <div class="header">
   389         -@   <div class="title">$<title></div>
   390         -@   <div class="status">
   391         -@     <div class="logo">$<project_name></div><br/>
   392         -@     <th1>
   393         -@      if {[info exists login]} {
   394         -@        puts "Logged in as $login"
   395         -@      } else {
   396         -@        puts "Not logged in"
   397         -@      }
   398         -@   </th1></div>
   399         -@ </div>
   400         -@ <div class="mainmenu">
   401         -@ <th1>
   402         -@ html "<a href=''$home$index_page''>Home</a>\n"
   403         -@ if {[anycap jor]} {
   404         -@   html "<a href=''$home/timeline''>Timeline</a>\n"
   405         -@ }
   406         -@ if {[hascap oh]} {
   407         -@   html "<a href=''$home/tree?ci=tip''>Files</a>\n"
   408         -@ }
   409         -@ if {[hascap o]} {
   410         -@   html "<a href=''$home/brlist''>Branches</a>\n"
   411         -@   html "<a href=''$home/taglist''>Tags</a>\n"
   412         -@ }
   413         -@ if {[hascap r]} {
   414         -@   html "<a href=''$home/reportlist''>Tickets</a>\n"
   415         -@ }
   416         -@ if {[hascap j]} {
   417         -@   html "<a href=''$home/wiki''>Wiki</a>\n"
   418         -@ }
   419         -@ if {[hascap s]} {
   420         -@   html "<a href=''$home/setup''>Admin</a>\n"
   421         -@ } elseif {[hascap a]} {
   422         -@   html "<a href=''$home/setup_ulist''>Users</a>\n"
   423         -@ }
   424         -@ if {[info exists login]} {
   425         -@   html "<a href=''$home/login''>Logout</a>\n"
   426         -@ } else {
   427         -@   html "<a href=''$home/login''>Login</a>\n"
   428         -@ }
   429         -@ </th1></div>
   430         -@ ');
   431         -@ REPLACE INTO config(name,mtime,value)
   432         -@ VALUES('footer',now(),'<div class="footer">
   433         -@ Fossil version $manifest_version $manifest_date
   434         -@ </div>
   435         -@ </body></html>
   436         -@ ');
   437         -;
   438         -
   439         -/*
   440         -** Black letters on a white or cream background with the main menu
   441         -** stuck on the left-hand side.
   442         -*/
   443         -static const char zBuiltinSkin3[] =
   444         -@ REPLACE INTO config(name,mtime,value)
   445         -@ VALUES('css',now(),'/* General settings for the entire page */
   446         -@ body {
   447         -@     margin:0px 0px 0px 0px;
   448         -@     padding:0px;
   449         -@     font-family:verdana, arial, helvetica, "sans serif";
   450         -@     color:#333;
   451         -@     background-color:white;
   452         -@ }
   453         -@
   454         -@ /* consistent colours */
   455         -@ h2 {
   456         -@   color: #333;
   457         -@ }
   458         -@ h3 {
   459         -@   color: #333;
   460         -@ }
   461         -@
   462         -@ /* The project logo in the upper left-hand corner of each page */
   463         -@ div.logo {
   464         -@   display: table-cell;
   465         -@   text-align: left;
   466         -@   vertical-align: bottom;
   467         -@   font-weight: bold;
   468         -@   color: #333;
   469         -@   white-space: nowrap;
   470         -@ }
   471         -@
   472         -@ /* The page title centered at the top of each page */
   473         -@ div.title {
   474         -@   display: table-cell;
   475         -@   font-size: 2em;
   476         -@   font-weight: bold;
   477         -@   text-align: center;
   478         -@   color: #333;
   479         -@   vertical-align: bottom;
   480         -@   width: 100%;
   481         -@ }
   482         -@
   483         -@ /* The login status message in the top right-hand corner */
   484         -@ div.status {
   485         -@   display: table-cell;
   486         -@   padding-right: 10px;
   487         -@   text-align: right;
   488         -@   vertical-align: bottom;
   489         -@   padding-bottom: 5px;
   490         -@   color: #333;
   491         -@   font-size: 0.8em;
   492         -@   font-weight: bold;
   493         -@   white-space: nowrap;
   494         -@ }
   495         -@
   496         -@ /* The header across the top of the page */
   497         -@ div.header {
   498         -@     margin:10px 0px 10px 0px;
   499         -@     padding:1px 0px 0px 20px;
   500         -@     border-style:solid;
   501         -@     border-color:black;
   502         -@     border-width:1px 0px;
   503         -@     background-color:#eee;
   504         -@ }
   505         -@
   506         -@ /* The main menu bar that appears at the top left of the page beneath
   507         -@ ** the header. Width must be co-ordinated with the container below */
   508         -@ div.mainmenu {
   509         -@   float: left;
   510         -@   margin-left: 10px;
   511         -@   margin-right: 10px;
   512         -@   font-size: 0.9em;
   513         -@   font-weight: bold;
   514         -@   padding:5px;
   515         -@   background-color:#eee;
   516         -@   border:1px solid #999;
   517         -@   width:8em;
   518         -@ }
   519         -@
   520         -@ /* Main menu is now a list */
   521         -@ div.mainmenu ul {
   522         -@   padding: 0;
   523         -@   list-style:none;
   524         -@ }
   525         -@ div.mainmenu a, div.mainmenu a:visited{
   526         -@   padding: 1px 10px 1px 10px;
   527         -@   color: #333;
   528         -@   text-decoration: none;
   529         -@ }
   530         -@ div.mainmenu a:hover {
   531         -@   color: #eee;
   532         -@   background-color: #333;
   533         -@ }
   534         -@
   535         -@ /* Container for the sub-menu and content so they don''t spread
   536         -@ ** out underneath the main menu */
   537         -@ #container {
   538         -@   padding-left: 9em;
   539         -@ }
   540         -@
   541         -@ /* The submenu bar that *sometimes* appears below the main menu */
   542         -@ div.submenu, div.sectionmenu {
   543         -@   padding: 3px 10px 3px 10px;
   544         -@   font-size: 0.9em;
   545         -@   text-align: center;
   546         -@   border:1px solid #999;
   547         -@   border-width:1px 0px;
   548         -@   background-color: #eee;
   549         -@   color: #333;
   550         -@ }
   551         -@ div.submenu a, div.submenu a:visited, div.sectionmenu>a.button:link,
   552         -@ div.sectionmenu>a.button:visited {
   553         -@   padding: 3px 10px 3px 10px;
   554         -@   color: #333;
   555         -@   text-decoration: none;
   556         -@ }
   557         -@ div.submenu a:hover, div.sectionmenu>a.button:hover {
   558         -@   color: #eee;
   559         -@   background-color: #333;
   560         -@ }
   561         -@
   562         -@ /* All page content from the bottom of the menu or submenu down to
   563         -@ ** the footer */
   564         -@ div.content {
   565         -@   padding: 2ex 1ex 0ex 2ex;
   566         -@ }
   567         -@
   568         -@ /* Some pages have section dividers */
   569         -@ div.section {
   570         -@   margin-bottom: 0px;
   571         -@   margin-top: 1em;
   572         -@   padding: 1px 1px 1px 1px;
   573         -@   font-size: 1.2em;
   574         -@   font-weight: bold;
   575         -@   border-style:solid;
   576         -@   border-color:#999;
   577         -@   border-width:1px 0px;
   578         -@   background-color: #eee;
   579         -@   color: #333;
   580         -@   white-space: nowrap;
   581         -@ }
   582         -@
   583         -@ /* The "Date" that occurs on the left hand side of timelines */
   584         -@ div.divider {
   585         -@   background: #eee;
   586         -@   border: 2px #999 solid;
   587         -@   font-size: 1em; font-weight: normal;
   588         -@   padding: .25em;
   589         -@   margin: .2em 0 .2em 0;
   590         -@   float: left;
   591         -@   clear: left;
   592         -@   color: #333;
   593         -@   white-space: nowrap;
   594         -@ }
   595         -@
   596         -@ /* The footer at the very bottom of the page */
   597         -@ div.footer {
   598         -@   font-size: 0.8em;
   599         -@   margin-top: 12px;
   600         -@   padding: 5px 10px 5px 10px;
   601         -@   text-align: right;
   602         -@   background-color: #eee;
   603         -@   color: #555;
   604         -@ }
   605         -@
   606         -@ /* <verbatim> blocks */
   607         -@ pre.verbatim {
   608         -@   background-color: #f5f5f5;
   609         -@   padding: 0.5em;
   610         -@   white-space: pre-wrap;
   611         -@ }
   612         -@
   613         -@ /* The label/value pairs on (for example) the ci page */
   614         -@ table.label-value th {
   615         -@   vertical-align: top;
   616         -@   text-align: right;
   617         -@   padding: 0.2ex 2ex;
   618         -@ }');
   619         -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
   620         -@ <head>
   621         -@ <base href="$baseurl/$current_page" />
   622         -@ <title>$<project_name>: $<title></title>
   623         -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
   624         -@       href="$home/timeline.rss">
   625         -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css"
   626         -@       media="screen">
   627         -@ </head>
   628         -@ <body>
   629         -@ <div class="header">
   630         -@   <div class="logo">
   631         -@     <img src="$logo_image_url" alt="logo">
   632         -@     <br />$<project_name>
   633         -@   </div>
   634         -@   <div class="title">$<title></div>
   635         -@   <div class="status"><th1>
   636         -@      if {[info exists login]} {
   637         -@        puts "Logged in as $login"
   638         -@      } else {
   639         -@        puts "Not logged in"
   640         -@      }
   641         -@   </th1></div>
   642         -@ </div>
   643         -@ <div class="mainmenu">
   644         -@ <th1>
   645         -@ html "<a href=''$home$index_page''>Home</a>\n"
   646         -@ if {[anycap jor]} {
   647         -@   html "<a href=''$home/timeline''>Timeline</a>\n"
   648         -@ }
   649         -@ if {[hascap oh]} {
   650         -@   html "<a href=''$home/tree?ci=tip''>Files</a>\n"
   651         -@ }
   652         -@ if {[hascap o]} {
   653         -@   html "<a href=''$home/brlist''>Branches</a>\n"
   654         -@   html "<a href=''$home/taglist''>Tags</a>\n"
   655         -@ }
   656         -@ if {[hascap r]} {
   657         -@   html "<a href=''$home/reportlist''>Tickets</a>\n"
   658         -@ }
   659         -@ if {[hascap j]} {
   660         -@   html "<a href=''$home/wiki''>Wiki</a>\n"
   661         -@ }
   662         -@ if {[hascap s]} {
   663         -@   html "<a href=''$home/setup''>Admin</a>\n"
   664         -@ } elseif {[hascap a]} {
   665         -@   html "<a href=''$home/setup_ulist''>Users</a>\n"
   666         -@ }
   667         -@ if {[info exists login]} {
   668         -@   html "<a href=''$home/login''>Logout</a>\n"
   669         -@ } else {
   670         -@   html "<a href=''$home/login''>Login</a>\n"
   671         -@ }
   672         -@ </th1></ul></div>
   673         -@ <div id="container">
   674         -@ ');
   675         -@ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div>
   676         -@ <div class="footer">
   677         -@ Fossil version $manifest_version $manifest_date
   678         -@ </div>
   679         -@ </body></html>
   680         -@ ');
   681         -;
   682         -
   683         -
   684         -/*
   685         -** Shadow boxes and rounded corners.
   686         -*/
   687         -static const char zBuiltinSkin4[] =
   688         -@ REPLACE INTO config(name,mtime,value)
   689         -@ VALUES('css',now(),'/* General settings for the entire page */
   690         -@ html {
   691         -@   min-height: 100%;
   692         -@ }
   693         -@ body {
   694         -@   margin: 0ex 1ex;
   695         -@   padding: 0px;
   696         -@   background-color: white;
   697         -@   color: #333;
   698         -@   font-family: Verdana, sans-serif;
   699         -@   font-size: 0.8em;
   700         -@ }
   701         -@
   702         -@ /* The project logo in the upper left-hand corner of each page */
   703         -@ div.logo {
   704         -@   display: table-cell;
   705         -@   text-align: right;
   706         -@   vertical-align: bottom;
   707         -@   font-weight: normal;
   708         -@   white-space: nowrap;
   709         -@ }
   710         -@
   711         -@ /* Widths */
   712         -@ div.header, div.mainmenu, div.submenu, div.content, div.footer {
   713         -@   max-width: 900px;
   714         -@   margin: auto;
   715         -@   padding: 3px 20px 3px 20px;
   716         -@   clear: both;
   717         -@ }
   718         -@
   719         -@ /* The page title at the top of each page */
   720         -@ div.title {
   721         -@   display: table-cell;
   722         -@   padding-left: 10px;
   723         -@   font-size: 2em;
   724         -@   margin: 10px 0 10px -20px;
   725         -@   vertical-align: bottom;
   726         -@   text-align: left;
   727         -@   width: 80%;
   728         -@   font-family: Verdana, sans-serif;
   729         -@   font-weight: bold;
   730         -@   color: #558195;
   731         -@   text-shadow: 0px 2px 2px #999999;
   732         -@ }
   733         -@
   734         -@ /* The login status message in the top right-hand corner */
   735         -@ div.status {
   736         -@   display: table-cell;
   737         -@   text-align: right;
   738         -@   vertical-align: bottom;
   739         -@   color: #333;
   740         -@   margin-right: -20px;
   741         -@   white-space: nowrap;
   742         -@ }
   743         -@
   744         -@ /* The main menu bar that appears at the top of the page beneath
   745         -@  ** the header */
   746         -@ div.mainmenu {
   747         -@   text-align: center;
   748         -@   color: white;
   749         -@   border-top-left-radius: 5px;
   750         -@   border-top-right-radius: 5px;
   751         -@   vertical-align: middle;
   752         -@   padding-top: 8px;
   753         -@   padding-bottom: 8px;
   754         -@   background-color: #446979;
   755         -@   box-shadow: 0px 3px 4px #333333;
   756         -@ }
   757         -@
   758         -@ /* The submenu bar that *sometimes* appears below the main menu */
   759         -@ div.submenu {
   760         -@   padding-top:10px;
   761         -@   padding-bottom:0;
   762         -@   text-align: right;
   763         -@   color: #000;
   764         -@   background-color: #fff;
   765         -@   height: 1.5em;
   766         -@   vertical-align:middle;
   767         -@   box-shadow: 0px 3px 4px #999;
   768         -@ }
   769         -@ div.mainmenu a, div.mainmenu a:visited {
   770         -@   padding: 3px 10px 3px 10px;
   771         -@   color: white;
   772         -@   text-decoration: none;
   773         -@ }
   774         -@ div.submenu a, div.submenu a:visited, a.button,
   775         -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
   776         -@   padding: 2px 8px;
   777         -@   color: #000;
   778         -@   font-family: Arial;
   779         -@   text-decoration: none;
   780         -@   margin:auto;
   781         -@   border-radius: 5px;
   782         -@   background-color: #e0e0e0;
   783         -@   text-shadow: 0px -1px 0px #eee;
   784         -@   border: 1px solid #000;
   785         -@ }
   786         -@
   787         -@ div.mainmenu a:hover {
   788         -@   color: #000;
   789         -@   background-color: white;
   790         -@ }
   791         -@
   792         -@ div.submenu a:hover, div.sectionmenu>a.button:hover {
   793         -@   background-color: #c0c0c0;
   794         -@ }
   795         -@
   796         -@ /* All page content from the bottom of the menu or submenu down to
   797         -@  ** the footer */
   798         -@ div.content {
   799         -@   background-color: #fff;
   800         -@   box-shadow: 0px 3px 4px #999;
   801         -@   border-bottom-right-radius: 5px;
   802         -@   border-bottom-left-radius: 5px;
   803         -@   padding-bottom: 1em;
   804         -@   min-height:40%;
   805         -@ }
   806         -@
   807         -@
   808         -@ /* Some pages have section dividers */
   809         -@ div.section {
   810         -@   margin-bottom: 0.5em;
   811         -@   margin-top: 1em;
   812         -@   margin-right: auto;
   813         -@   padding: 1px 1px 1px 1px;
   814         -@   font-size: 1.2em;
   815         -@   font-weight: bold;
   816         -@   text-align: center;
   817         -@   color: white;
   818         -@   border-radius: 5px;
   819         -@   background-color: #446979;
   820         -@   box-shadow: 0px 3px 4px #333333;
   821         -@   white-space: nowrap;
   822         -@ }
   823         -@
   824         -@ /* The "Date" that occurs on the left hand side of timelines */
   825         -@ div.divider {
   826         -@   font-size: 1.2em;
   827         -@   font-family: Georgia, serif;
   828         -@   font-weight: bold;
   829         -@   margin-top: 1em;
   830         -@   white-space: nowrap;
   831         -@ }
   832         -@
   833         -@ /* The footer at the very bottom of the page */
   834         -@ div.footer {
   835         -@   font-size: 0.9em;
   836         -@   text-align: right;
   837         -@   margin-bottom: 1em;
   838         -@   color: #666;
   839         -@ }
   840         -@
   841         -@ /* Hyperlink colors in the footer */
   842         -@ div.footer a { color: white; }
   843         -@ div.footer a:link { color: white; }
   844         -@ div.footer a:visited { color: white; }
   845         -@ div.footer a:hover { background-color: white; color: #558195; }
   846         -@
   847         -@ /* <verbatim> blocks */
   848         -@ pre.verbatim, blockquote pre {
   849         -@   font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace;
   850         -@   background-color: #f3f3f3;
   851         -@   padding: 0.5em;
   852         -@   white-space: pre-wrap;
   853         -@ }
   854         -@
   855         -@ blockquote pre {
   856         -@   border: 1px #000 dashed;
   857         -@ }
   858         -@
   859         -@ /* The label/value pairs on (for example) the ci page */
   860         -@ table.label-value th {
   861         -@   vertical-align: top;
   862         -@   text-align: right;
   863         -@   padding: 0.2ex 2ex;
   864         -@ }
   865         -@
   866         -@ table.report tr th {
   867         -@   padding: 3px 5px;
   868         -@   text-transform: capitalize;
   869         -@   cursor: pointer;
   870         -@ }
   871         -@
   872         -@ table.report tr td {
   873         -@   padding: 3px 5px;
   874         -@   cursor: pointer;
   875         -@ }
   876         -@
   877         -@ textarea {
   878         -@   font-size: 1em;
   879         -@ }
   880         -@
   881         -@ .fullsize-text {
   882         -@   font-size: 1.25em;
   883         -@ }');
   884         -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
   885         -@ <head>
   886         -@ <base href="$baseurl/$current_page" />
   887         -@ <title>$<project_name>: $<title></title>
   888         -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
   889         -@       href="$home/timeline.rss">
   890         -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css"
   891         -@       media="screen">
   892         -@ </head>
   893         -@ <body>
   894         -@ <div class="header">
   895         -@   <div class="logo">
   896         -@     <img src="$logo_image_url" alt="logo">
   897         -@     <br />$<project_name>
   898         -@   </div>
   899         -@   <div class="title">$<title></div>
   900         -@   <div class="status"><th1>
   901         -@      if {[info exists login]} {
   902         -@        puts "Logged in as $login"
   903         -@      } else {
   904         -@        puts "Not logged in"
   905         -@      }
   906         -@   </th1></div>
   907         -@ </div>
   908         -@ <div class="mainmenu">
   909         -@ <th1>
   910         -@ html "<a href=''$home$index_page''>Home</a>\n"
   911         -@ if {[anycap jor]} {
   912         -@   html "<a href=''$home/timeline''>Timeline</a>\n"
   913         -@ }
   914         -@ if {[hascap oh]} {
   915         -@   html "<a href=''$home/tree?ci=tip''>Files</a>\n"
   916         -@ }
   917         -@ if {[hascap o]} {
   918         -@   html "<a href=''$home/brlist''>Branches</a>\n"
   919         -@   html "<a href=''$home/taglist''>Tags</a>\n"
   920         -@ }
   921         -@ if {[hascap r]} {
   922         -@   html "<a href=''$home/reportlist''>Tickets</a>\n"
   923         -@ }
   924         -@ if {[hascap j]} {
   925         -@   html "<a href=''$home/wiki''>Wiki</a>\n"
   926         -@ }
   927         -@ if {[hascap s]} {
   928         -@   html "<a href=''$home/setup''>Admin</a>\n"
   929         -@ } elseif {[hascap a]} {
   930         -@   html "<a href=''$home/setup_ulist''>Users</a>\n"
   931         -@ }
   932         -@ if {[info exists login]} {
   933         -@   html "<a href=''$home/login''>Logout</a>\n"
   934         -@ } else {
   935         -@   html "<a href=''$home/login''>Login</a>\n"
   936         -@ }
   937         -@ </th1></div>
   938         -@ <div id="container">
   939         -@ ');
   940         -@ REPLACE INTO config(name,mtime,value) VALUES('footer',now(),'</div>
   941         -@ <div class="footer">
   942         -@ Fossil version $manifest_version $manifest_date
   943         -@ </div>
   944         -@ </body></html>
   945         -@ ');
   946         -;
   947         -
   948         -
   949         -/*
   950         -** This skin is intended to be almost identical to the default one, with the
   951         -** following changes to the header and footer:
   952         -**
   953         -** 1. The logo image in the header has been modified to be a hyperlink to the
   954         -**    root of the web site containing the repository using the same scheme
   955         -**    (i.e. HTTP or HTTPS) as the base URL for the repository.  The header
   956         -**    contains a TH1 script block to help accomplish these tasks.
   957         -**
   958         -** 2. The Fossil version information in the footer has been augmented with
   959         -**    hyperlinks to the corresponding points on the timeline in the official
   960         -**    Fossil repository.  Additionally, if the Tcl integration feature is
   961         -**    enabled, the loaded version of Tcl is included, with a hyperlink to the
   962         -**    official Tcl/Tk web site.  The footer also contains a TH1 script block
   963         -**    to help accomplish these tasks.
   964         -*/
   965         -static const char zBuiltinSkin5[] =
   966         -@ REPLACE INTO config(name,mtime,value)
   967         -@ VALUES('css',now(),'/* General settings for the entire page */
   968         -@ body {
   969         -@   margin: 0ex 1ex;
   970         -@   padding: 0px;
   971         -@   background-color: white;
   972         -@   font-family: sans-serif;
   973         -@ }
   974         -@
   975         -@ /* The project logo in the upper left-hand corner of each page */
   976         -@ div.logo {
   977         -@   display: table-cell;
   978         -@   text-align: center;
   979         -@   vertical-align: bottom;
   980         -@   font-weight: bold;
   981         -@   color: #558195;
   982         -@   min-width: 200px;
   983         -@   white-space: nowrap;
   984         -@ }
   985         -@
   986         -@ /* The page title centered at the top of each page */
   987         -@ div.title {
   988         -@   display: table-cell;
   989         -@   font-size: 2em;
   990         -@   font-weight: bold;
   991         -@   text-align: center;
   992         -@   padding: 0 0 0 1em;
   993         -@   color: #558195;
   994         -@   vertical-align: bottom;
   995         -@   width: 100%;
   996         -@ }
   997         -@
   998         -@ /* The login status message in the top right-hand corner */
   999         -@ div.status {
  1000         -@   display: table-cell;
  1001         -@   text-align: right;
  1002         -@   vertical-align: bottom;
  1003         -@   color: #558195;
  1004         -@   font-size: 0.8em;
  1005         -@   font-weight: bold;
  1006         -@   min-width: 200px;
  1007         -@   white-space: nowrap;
  1008         -@ }
  1009         -@
  1010         -@ /* The header across the top of the page */
  1011         -@ div.header {
  1012         -@   display: table;
  1013         -@   width: 100%;
  1014         -@ }
  1015         -@
  1016         -@ /* The main menu bar that appears at the top of the page beneath
  1017         -@ ** the header */
  1018         -@ div.mainmenu {
  1019         -@   padding: 5px 10px 5px 10px;
  1020         -@   font-size: 0.9em;
  1021         -@   font-weight: bold;
  1022         -@   text-align: center;
  1023         -@   letter-spacing: 1px;
  1024         -@   background-color: #558195;
  1025         -@   border-top-left-radius: 8px;
  1026         -@   border-top-right-radius: 8px;
  1027         -@   color: white;
  1028         -@ }
  1029         -@
  1030         -@ /* The submenu bar that *sometimes* appears below the main menu */
  1031         -@ div.submenu, div.sectionmenu {
  1032         -@   padding: 3px 10px 3px 0px;
  1033         -@   font-size: 0.9em;
  1034         -@   text-align: center;
  1035         -@   background-color: #456878;
  1036         -@   color: white;
  1037         -@ }
  1038         -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
  1039         -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
  1040         -@   padding: 3px 10px 3px 10px;
  1041         -@   color: white;
  1042         -@   text-decoration: none;
  1043         -@ }
  1044         -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
  1045         -@   color: #558195;
  1046         -@   background-color: white;
  1047         -@ }
  1048         -@
  1049         -@ /* All page content from the bottom of the menu or submenu down to
  1050         -@ ** the footer */
  1051         -@ div.content {
  1052         -@   padding: 0ex 1ex 1ex 1ex;
  1053         -@   border: solid #aaa;
  1054         -@   border-width: 1px;
  1055         -@ }
  1056         -@
  1057         -@ /* Some pages have section dividers */
  1058         -@ div.section {
  1059         -@   margin-bottom: 0px;
  1060         -@   margin-top: 1em;
  1061         -@   padding: 1px 1px 1px 1px;
  1062         -@   font-size: 1.2em;
  1063         -@   font-weight: bold;
  1064         -@   background-color: #558195;
  1065         -@   color: white;
  1066         -@   white-space: nowrap;
  1067         -@ }
  1068         -@
  1069         -@ /* The "Date" that occurs on the left hand side of timelines */
  1070         -@ div.divider {
  1071         -@   background: #a1c4d4;
  1072         -@   border: 2px #558195 solid;
  1073         -@   font-size: 1em; font-weight: normal;
  1074         -@   padding: .25em;
  1075         -@   margin: .2em 0 .2em 0;
  1076         -@   float: left;
  1077         -@   clear: left;
  1078         -@   white-space: nowrap;
  1079         -@ }
  1080         -@
  1081         -@ /* The footer at the very bottom of the page */
  1082         -@ div.footer {
  1083         -@   clear: both;
  1084         -@   font-size: 0.8em;
  1085         -@   padding: 5px 10px 5px 10px;
  1086         -@   text-align: right;
  1087         -@   background-color: #558195;
  1088         -@   border-bottom-left-radius: 8px;
  1089         -@   border-bottom-right-radius: 8px;
  1090         -@   color: white;
  1091         -@ }
  1092         -@
  1093         -@ /* Hyperlink colors in the footer */
  1094         -@ div.footer a { color: white; }
  1095         -@ div.footer a:link { color: white; }
  1096         -@ div.footer a:visited { color: white; }
  1097         -@ div.footer a:hover { background-color: white; color: #558195; }
  1098         -@
  1099         -@ /* verbatim blocks */
  1100         -@ pre.verbatim {
  1101         -@   background-color: #f5f5f5;
  1102         -@   padding: 0.5em;
  1103         -@   white-space: pre-wrap;
  1104         -@ }
  1105         -@
  1106         -@ /* The label/value pairs on (for example) the ci page */
  1107         -@ table.label-value th {
  1108         -@   vertical-align: top;
  1109         -@   text-align: right;
  1110         -@   padding: 0.2ex 2ex;
  1111         -@ }');
  1112         -@ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html>
  1113         -@ <head>
  1114         -@ <base href="$baseurl/$current_page" />
  1115         -@ <title>$<project_name>: $<title></title>
  1116         -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
  1117         -@       href="$home/timeline.rss" />
  1118         -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css"
  1119         -@       media="screen" />
  1120         -@ </head>
  1121         -@ <body>
  1122         -@ <div class="header">
  1123         -@   <div class="logo">
  1124         -@     <th1>
  1125         -@     ##
  1126         -@     ## NOTE: The purpose of this procedure is to take the base URL of the
  1127         -@     ##       Fossil project and return the root of the entire web site using
  1128         -@     ##       the same URI scheme as the base URL (e.g. http or https).
  1129         -@     ##
  1130         -@     proc getLogoUrl { baseurl } {
  1131         -@       set idx(first) [string first // $baseurl]
  1132         -@       if {$idx(first) != -1} {
  1133         -@         ##
  1134         -@         ## NOTE: Skip second slash.
  1135         -@         ##
  1136         -@         set idx(first+1) [expr {$idx(first) + 2}]
  1137         -@         ##
  1138         -@         ## NOTE: (part 1) The [string first] command does NOT actually
  1139         -@         ##       the optional startIndex argument as specified in the
  1140         -@         ##       TH1 support manual; therefore, we fake it by using the
  1141         -@         ##       [string range] command and then adding the necessary
  1142         -@         ##       offset to the resulting index manually (below).  In Tcl,
  1143         -@         ##       we could use the following instead:
  1144         -@         ##
  1145         -@         ##       set idx(next) [string first / $baseurl $idx(first+1)]
  1146         -@         ##
  1147         -@         set idx(nextRange) [string range $baseurl $idx(first+1) end]
  1148         -@         set idx(next) [string first / $idx(nextRange)]
  1149         -@         if {$idx(next) != -1} {
  1150         -@           ##
  1151         -@           ## NOTE: (part 2) Add the necessary offset to the result of the
  1152         -@           ##       search for the next slash (i.e. the one after the initial
  1153         -@           ##       search for the two slashes).
  1154         -@           ##
  1155         -@           set idx(next) [expr {$idx(next) + $idx(first+1)}]
  1156         -@           ##
  1157         -@           ## NOTE: Back up one character from the next slash.
  1158         -@           ##
  1159         -@           set idx(next-1) [expr {$idx(next) - 1}]
  1160         -@           ##
  1161         -@           ## NOTE: Extract the URI scheme and host from the base URL.
  1162         -@           ##
  1163         -@           set scheme [string range $baseurl 0 $idx(first)]
  1164         -@           set host [string range $baseurl $idx(first+1) $idx(next-1)]
  1165         -@           ##
  1166         -@           ## NOTE: Try to stay in SSL mode if we are there now.
  1167         -@           ##
  1168         -@           if {[string compare $scheme http:/] == 0} {
  1169         -@             set scheme http://
  1170         -@           } else {
  1171         -@             set scheme https://
  1172         -@           }
  1173         -@           set logourl $scheme$host/
  1174         -@         } else {
  1175         -@           set logourl $baseurl
  1176         -@         }
  1177         -@       } else {
  1178         -@         set logourl $baseurl
  1179         -@       }
  1180         -@       return $logourl
  1181         -@     }
  1182         -@     set logourl [getLogoUrl $baseurl]
  1183         -@     </th1>
  1184         -@     <a href="$logourl">
  1185         -@       <img src="$logo_image_url" border="0" alt="$project_name">
  1186         -@     </a>
  1187         -@   </div>
  1188         -@   <div class="title"><small>$<project_name></small><br />$<title></div>
  1189         -@   <div class="status"><th1>
  1190         -@      if {[info exists login]} {
  1191         -@        puts "Logged in as $login"
  1192         -@      } else {
  1193         -@        puts "Not logged in"
  1194         -@      }
  1195         -@   </th1></div>
  1196         -@ </div>
  1197         -@ <div class="mainmenu">
  1198         -@ <th1>
  1199         -@ html "<a href=''$home$index_page''>Home</a>\n"
  1200         -@ if {[anycap jor]} {
  1201         -@   html "<a href=''$home/timeline''>Timeline</a>\n"
  1202         -@ }
  1203         -@ if {[hascap oh]} {
  1204         -@   html "<a href=''$home/tree?ci=tip''>Files</a>\n"
  1205         -@ }
  1206         -@ if {[hascap o]} {
  1207         -@   html "<a href=''$home/brlist''>Branches</a>\n"
  1208         -@   html "<a href=''$home/taglist''>Tags</a>\n"
  1209         -@ }
  1210         -@ if {[hascap r]} {
  1211         -@   html "<a href=''$home/reportlist''>Tickets</a>\n"
  1212         -@ }
  1213         -@ if {[hascap j]} {
  1214         -@   html "<a href=''$home/wiki''>Wiki</a>\n"
  1215         -@ }
  1216         -@ if {[hascap s]} {
  1217         -@   html "<a href=''$home/setup''>Admin</a>\n"
  1218         -@ } elseif {[hascap a]} {
  1219         -@   html "<a href=''$home/setup_ulist''>Users</a>\n"
  1220         -@ }
  1221         -@ if {[info exists login]} {
  1222         -@   html "<a href=''$home/login''>Logout</a>\n"
  1223         -@ } else {
  1224         -@   html "<a href=''$home/login''>Login</a>\n"
  1225         -@ }
  1226         -@ </th1></div>
  1227         -@ ');
  1228         -@ REPLACE INTO config(name,mtime,value)
  1229         -@ VALUES('footer',now(),'<div class="footer">
  1230         -@   <th1>
  1231         -@   proc getTclVersion {} {
  1232         -@     if {[catch {tclEval info patchlevel} tclVersion] == 0} {
  1233         -@       return "<a href=\"http://www.tcl.tk/\">Tcl</a> version $tclVersion"
  1234         -@     }
  1235         -@     return ""
  1236         -@   }
  1237         -@   proc getVersion { version } {
  1238         -@     set length [string length $version]
  1239         -@     return [string range $version 1 [expr {$length - 2}]]
  1240         -@   }
  1241         -@   set version [getVersion $manifest_version]
  1242         -@   set tclVersion [getTclVersion]
  1243         -@   set fossilUrl http://www.fossil-scm.org
  1244         -@   </th1>
  1245         -@   This page was generated in about
  1246         -@   <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
  1247         -@   <a href="$fossilUrl/">Fossil</a>
  1248         -@   version $release_version $tclVersion
  1249         -@   <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
  1250         -@   <a href="$fossilUrl/index.html/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
  1251         -@ </div>
  1252         -@ </body></html>
  1253         -@ ');
  1254         -;
  1255         -
  1256     24   /*
  1257     25   ** An array of available built-in skins.
           26  +**
           27  +** To add new built-in skins:
           28  +**
           29  +**    1.  Pick a name for the new skin.  (Here we use "xyzzy").
           30  +**
           31  +**    2.  Install files skins/xyzzy/css.txt, skins/xyzzy/header.txt, 
           32  +**        and skins/xyzzy/footer.txt into the source tree.
           33  +**
           34  +**    3.  Rerun "tclsh makemake.tcl" in the src/ folder in order to
           35  +**        rebuild the makefiles to reference the new CSS, headers, and footers.
           36  +**
           37  +**    4.  Make an entry in the following array for the new skin.
  1258     38   */
  1259     39   static struct BuiltinSkin {
  1260         -  const char *zName;
  1261         -  const char *zValue;
           40  +  const char *zDesc;    /* Description of this skin */
           41  +  const char *zLabel;   /* The directory under skins/ holding this skin */
           42  +  char *zSQL;           /* Filled in at run-time with SQL to insert this skin */
  1262     43   } aBuiltinSkin[] = {
  1263         -  { "Default",                     0 /* Filled in at runtime */ },
  1264         -  { "Plain Gray, No Logo",         zBuiltinSkin1                },
  1265         -  { "Khaki, No Logo",              zBuiltinSkin2                },
  1266         -  { "Black & White, Menu on Left", zBuiltinSkin3                },
  1267         -  { "Shadow boxes & Rounded Corners", zBuiltinSkin4             },
  1268         -  { "Enhanced Default",            zBuiltinSkin5                },
           44  +  { "Default",                           "default",           0 },
           45  +  { "Plain Gray, No Logo",               "plain_gray",        0 },
           46  +  { "Khaki, No Logo",                    "khaki",             0 },
           47  +  { "Black & White, Menu on Left",       "black_and_white",   0 }, 
           48  +  { "Shadow boxes & Rounded Corners",    "rounded1",          0 },
           49  +  { "Enhanced Default",                  "enhanced1",         0 },
           50  +  { "San Francisco Modern",              "etienne1",          0 },
           51  +  { "Eagle",                             "eagle",             0 },
  1269     52   };
  1270     53   
  1271     54   /*
  1272     55   ** For a skin named zSkinName, compute the name of the CONFIG table
  1273     56   ** entry where that skin is stored and return it.
  1274     57   **
  1275     58   ** Return NULL if zSkinName is NULL or an empty string.
................................................................................
  1284     67       free(z);
  1285     68       z = 0;
  1286     69     }
  1287     70     return z;
  1288     71   }
  1289     72   
  1290     73   /*
  1291         -** Construct and return a string that represents the current skin if
  1292         -** useDefault==0 or a string for the default skin if useDefault==1.
           74  +** Return true if there exists a skin name "zSkinName".
           75  +*/
           76  +static int skinExists(const char *zSkinName){
           77  +  int i;
           78  +  if( zSkinName==0 ) return 0;
           79  +  for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
           80  +    if( fossil_strcmp(zSkinName, aBuiltinSkin[i].zDesc)==0 ) return 1;
           81  +  }
           82  +  return db_exists("SELECT 1 FROM config WHERE name='skin:%q'", zSkinName);
           83  +}
           84  +
           85  +/*
           86  +** Construct and return an string of SQL statements that represents
           87  +** a "skin" setting.  If zName==0 then return the skin currently
           88  +** installed.  Otherwise, return one of the built-in skins designated
           89  +** by zName.
  1293     90   **
  1294     91   ** Memory to hold the returned string is obtained from malloc.
  1295     92   */
  1296         -static char *getSkin(int useDefault){
           93  +static char *getSkin(const char *zName){
           94  +  const char *z;
           95  +  char *zLabel;
           96  +  static const char *azType[] = { "css", "header", "footer" };
           97  +  int i;
  1297     98     Blob val;
  1298     99     blob_zero(&val);
  1299         -  blob_appendf(&val,
  1300         -     "REPLACE INTO config(name,value,mtime) VALUES('css',%Q,now());\n",
  1301         -     useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS)
  1302         -  );
  1303         -  blob_appendf(&val,
  1304         -     "REPLACE INTO config(name,value,mtime) VALUES('header',%Q,now());\n",
  1305         -     useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader)
  1306         -  );
  1307         -  blob_appendf(&val,
  1308         -     "REPLACE INTO config(name,value,mtime) VALUES('footer',%Q,now());\n",
  1309         -     useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter)
  1310         -  );
          100  +  for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
          101  +    if( zName ){
          102  +      zLabel = mprintf("skins/%s/%s.txt", zName, azType[i]);
          103  +      z = builtin_text(zLabel);
          104  +      fossil_free(zLabel);
          105  +    }else{
          106  +      z = db_get(azType[i], 0);
          107  +      if( z==0 ){
          108  +        zLabel = mprintf("skins/default/%s.txt", azType[i]);
          109  +        z = builtin_text(zLabel);
          110  +        fossil_free(zLabel);
          111  +      }
          112  +    }
          113  +    blob_appendf(&val,
          114  +       "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now());\n",
          115  +       azType[i], z
          116  +    );
          117  +  }
  1311    118     return blob_str(&val);
  1312    119   }
  1313    120   
  1314    121   /*
  1315         -** Construct the default skin string and fill in the corresponding
  1316         -** entry in aBuildinSkin[]
          122  +** Respond to a Rename button press.  Return TRUE if a dialog was painted.
          123  +** Return FALSE to continue with the main Skins page.
          124  +*/
          125  +static int skinRename(void){
          126  +  const char *zOldName;
          127  +  const char *zNewName;
          128  +  int ex = 0;
          129  +  if( P("rename")==0 ) return 0;
          130  +  zOldName = P("sn");
          131  +  zNewName = P("newname");
          132  +  if( zOldName==0 ) return 0;
          133  +  if( zNewName==0 || zNewName[0]==0 || (ex = skinExists(zNewName))!=0 ){
          134  +    if( zNewName==0 ) zNewName = zOldName;
          135  +    style_header("Rename A Skin");
          136  +    if( ex ){
          137  +      @ <p><span class="generalError">There is already another skin
          138  +      @ named "%h(zNewName)".  Choose a different name.</span></p>
          139  +    }
          140  +    @ <form action="%s(g.zTop)/setup_skin" method="post"><div>
          141  +    @ <table border="0"><tr>
          142  +    @ <tr><td align="right">Current name:<td align="left"><b>%h(zOldName)</b>
          143  +    @ <tr><td align="right">New name:<td align="left">
          144  +    @ <input type="text" size="35" name="newname" value="%h(zNewName)">
          145  +    @ <tr><td><td>
          146  +    @ <input type="hidden" name="sn" value="%h(zOldName)">
          147  +    @ <input type="submit" name="rename" value="Rename">
          148  +    @ <input type="submit" name="canren" value="Cancel">
          149  +    @ </table>
          150  +    login_insert_csrf_secret();
          151  +    @ </div></form>
          152  +    style_footer();
          153  +    return 1;
          154  +  }
          155  +  db_multi_exec(
          156  +    "UPDATE config SET name='skin:%q' WHERE name='skin:%q';",
          157  +    zNewName, zOldName
          158  +  );
          159  +  return 0;
          160  +}
          161  +
          162  +/*
          163  +** Respond to a Save button press.  Return TRUE if a dialog was painted.
          164  +** Return FALSE to continue with the main Skins page.
  1317    165   */
  1318         -static void setDefaultSkin(void){
  1319         -  aBuiltinSkin[0].zValue = getSkin(1);
          166  +static int skinSave(const char *zCurrent){
          167  +  const char *zNewName;
          168  +  int ex = 0;
          169  +  if( P("save")==0 ) return 0;
          170  +  zNewName = P("svname");
          171  +  if( zNewName && zNewName[0]!=0 ){
          172  +  }
          173  +  if( zNewName==0 || zNewName[0]==0 || (ex = skinExists(zNewName))!=0 ){
          174  +    if( zNewName==0 ) zNewName = "";
          175  +    style_header("Save Current Skin");
          176  +    if( ex ){
          177  +      @ <p><span class="generalError">There is already another skin
          178  +      @ named "%h(zNewName)".  Choose a different name.</span></p>
          179  +    }
          180  +    @ <form action="%s(g.zTop)/setup_skin" method="post"><div>
          181  +    @ <table border="0"><tr>
          182  +    @ <tr><td align="right">Name for this skin:<td align="left">
          183  +    @ <input type="text" size="35" name="svname" value="%h(zNewName)">
          184  +    @ <tr><td><td>
          185  +    @ <input type="submit" name="save" value="Save">
          186  +    @ <input type="submit" name="cansave" value="Cancel">
          187  +    @ </table>
          188  +    login_insert_csrf_secret();
          189  +    @ </div></form>
          190  +    style_footer();
          191  +    return 1;
          192  +  }
          193  +  db_multi_exec(
          194  +    "INSERT OR IGNORE INTO config(name, value, mtime)"
          195  +    "VALUES('skin:%q',%Q,now())",
          196  +    zNewName, zCurrent
          197  +  );
          198  +  return 0;
  1320    199   }
  1321    200   
  1322    201   /*
  1323    202   ** WEBPAGE: setup_skin
  1324    203   */
  1325    204   void setup_skin(void){
  1326    205     const char *z;
  1327    206     char *zName;
  1328    207     char *zErr = 0;
  1329         -  const char *zCurrent;  /* Current skin */
  1330         -  int i;                 /* Loop counter */
          208  +  const char *zCurrent = 0;  /* Current skin */
          209  +  int i;                     /* Loop counter */
  1331    210     Stmt q;
          211  +  int seenCurrent = 0;
  1332    212   
  1333    213     login_check_credentials();
  1334    214     if( !g.perm.Setup ){
  1335    215       login_needed();
  1336    216     }
  1337    217     db_begin_transaction();
          218  +  zCurrent = getSkin(0);
          219  +  for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
          220  +    aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
          221  +  }
  1338    222   
  1339    223     /* Process requests to delete a user-defined skin */
  1340    224     if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
  1341    225       style_header("Confirm Custom Skin Delete");
  1342    226       @ <form action="%s(g.zTop)/setup_skin" method="post"><div>
  1343    227       @ <p>Deletion of a custom skin is a permanent action that cannot
  1344    228       @ be undone.  Please confirm that this is what you want to do:</p>
................................................................................
  1349    233       @ </div></form>
  1350    234       style_footer();
  1351    235       return;
  1352    236     }
  1353    237     if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
  1354    238       db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
  1355    239     }
  1356         -
  1357         -  setDefaultSkin();
  1358         -  zCurrent = getSkin(0);
          240  +  if( skinRename() ) return;
          241  +  if( skinSave(zCurrent) ) return;
  1359    242   
  1360         -  if( P("save")!=0 && (zName = skinVarName(P("save"),0))!=0 ){
  1361         -    if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName)
  1362         -          || fossil_strcmp(zName, "Default")==0 ){
  1363         -      zErr = mprintf("Skin name \"%h\" already exists. "
  1364         -                     "Choose a different name.", P("sn"));
  1365         -    }else{
  1366         -      db_multi_exec("INSERT INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
  1367         -         zName, zCurrent
  1368         -      );
  1369         -    }
  1370         -  }
  1371         -
  1372         -  /* The user pressed the "Use This Skin" button. */
          243  +  /* The user pressed one of the "Install" buttons. */
  1373    244     if( P("load") && (z = P("sn"))!=0 && z[0] ){
  1374    245       int seen = 0;
          246  +
          247  +    /* Check to see if the current skin is already saved.  If it is, there
          248  +    ** is no need to create a backup */
          249  +    zCurrent = getSkin(0);
  1375    250       for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
  1376         -      if( fossil_strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){
          251  +      if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
  1377    252           seen = 1;
  1378    253           break;
  1379    254         }
  1380    255       }
  1381    256       if( !seen ){
  1382    257         seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
  1383    258                          " AND value=%Q", zCurrent);
  1384         -    }
  1385         -    if( !seen ){
  1386         -      db_multi_exec(
  1387         -        "INSERT INTO config(name,value,mtime) VALUES("
  1388         -        "  strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
  1389         -        "  %Q,now())", zCurrent
  1390         -      );
          259  +      if( !seen ){
          260  +        db_multi_exec(
          261  +          "INSERT INTO config(name,value,mtime) VALUES("
          262  +          "  strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
          263  +          "  %Q,now())", zCurrent
          264  +        );
          265  +      }
  1391    266       }
  1392    267       seen = 0;
  1393    268       for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
  1394         -      if( fossil_strcmp(aBuiltinSkin[i].zName, z)==0 ){
          269  +      if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
  1395    270           seen = 1;
  1396         -        zCurrent = aBuiltinSkin[i].zValue;
          271  +        zCurrent = aBuiltinSkin[i].zSQL;
  1397    272           db_multi_exec("%s", zCurrent/*safe-for-%s*/);
  1398    273           break;
  1399    274         }
  1400    275       }
  1401    276       if( !seen ){
  1402    277         zName = skinVarName(z,0);
  1403    278         zCurrent = db_get(zName, 0);
................................................................................
  1407    282   
  1408    283     style_header("Skins");
  1409    284     if( zErr ){
  1410    285       @ <p><font color="red">%h(zErr)</font></p>
  1411    286     }
  1412    287     @ <p>A "skin" is a combination of
  1413    288     @ <a href="setup_editcss">CSS</a>,
  1414         -  @ <a href="setup_header">Header</a>,
  1415         -  @ <a href="setup_footer">Footer</a>, and
  1416         -  @ <a href="setup_logo">Logo</a> that determines the look and feel
          289  +  @ <a href="setup_header">Header</a>, and
          290  +  @ <a href="setup_footer">Footer</a> that determines the look and feel
  1417    291     @ of the web interface.</p>
  1418    292     @
  1419    293     @ <h2>Available Skins:</h2>
  1420         -  @ <ol>
          294  +  @ <table border="0">
  1421    295     for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
  1422         -    z = aBuiltinSkin[i].zName;
  1423         -    if( fossil_strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){
  1424         -      @ <li><p>%h(z).&nbsp;&nbsp; <b>Currently In Use</b></p>
          296  +    z = aBuiltinSkin[i].zDesc;
          297  +    @ <tr><td>%d(i+1).<td>%h(z)<td>&nbsp;&nbsp;<td>
          298  +    if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
          299  +      @ (Currently In Use)
          300  +      seenCurrent = 1;
  1425    301       }else{
  1426         -      @ <li><form action="%s(g.zTop)/setup_skin" method="post"><div>
  1427         -      @ %h(z).&nbsp;&nbsp;
          302  +      @ <form action="%s(g.zTop)/setup_skin" method="post">
  1428    303         @ <input type="hidden" name="sn" value="%h(z)" />
  1429         -      @ <input type="submit" name="load" value="Use This Skin" />
  1430         -      @ </div></form></li>
          304  +      @ <input type="submit" name="load" value="Install" />
          305  +      @ </form>
  1431    306       }
          307  +    @ </tr>
  1432    308     }
  1433    309     db_prepare(&q,
  1434    310        "SELECT substr(name, 6), value FROM config"
  1435    311        " WHERE name GLOB 'skin:*'"
  1436    312        " ORDER BY name"
  1437    313     );
  1438    314     while( db_step(&q)==SQLITE_ROW ){
  1439    315       const char *zN = db_column_text(&q, 0);
  1440    316       const char *zV = db_column_text(&q, 1);
          317  +    i++;
          318  +    @ <tr><td>%d(i).<td>%h(zN)<td>&nbsp;&nbsp;<td>
          319  +    @ <form action="%s(g.zTop)/setup_skin" method="post">
  1441    320       if( fossil_strcmp(zV, zCurrent)==0 ){
  1442         -      @ <li><p>%h(zN).&nbsp;&nbsp;  <b>Currently In Use</b></p>
          321  +      @ (Currently In Use)
          322  +      seenCurrent = 1;
  1443    323       }else{
  1444         -      @ <li><form action="%s(g.zTop)/setup_skin" method="post">
  1445         -      @ %h(zN).&nbsp;&nbsp;
  1446         -      @ <input type="hidden" name="sn" value="%h(zN)">
  1447         -      @ <input type="submit" name="load" value="Use This Skin">
  1448         -      @ <input type="submit" name="del1" value="Delete This Skin">
  1449         -      @ </form></li>
          324  +      @ <input type="submit" name="load" value="Install">
          325  +      @ <input type="submit" name="del1" value="Delete">
  1450    326       }
          327  +    @ <input type="submit" name="rename" value="Rename">
          328  +    @ <input type="hidden" name="sn" value="%h(zN)">
          329  +    @ </form></tr>
  1451    330     }
  1452    331     db_finalize(&q);
  1453         -  @ </ol>
          332  +  if( !seenCurrent ){
          333  +    i++;
          334  +    @ <tr><td>%d(i).<td><i>Current Configuration</i><td>&nbsp;&nbsp;<td>
          335  +    @ <form action="%s(g.zTop)/setup_skin" method="post">
          336  +    @ <input type="submit" name="save" value="Save">
          337  +    @ </form>
          338  +  }
          339  +  @ </table>
  1454    340     style_footer();
  1455    341     db_end_transaction(0);
  1456    342   }

Changes to src/sqlcmd.c.

   168    168   **                              compress(X).
   169    169   **
   170    170   **    checkin_mtime(X,Y)        Return the mtime for the file Y (a BLOB.RID)
   171    171   **                              found in check-in X (another BLOB.RID value).
   172    172   **
   173    173   **    symbolic_name_to_rid(X)   Return a the BLOB.RID corresponding to symbolic
   174    174   **                              name X.
          175  +**
          176  +**    now()                     Return the number of seconds since 1970.
   175    177   **
   176    178   **    REGEXP                    The REGEXP operator works, unlike in
   177    179   **                              standard SQLite.
   178    180   **
   179    181   **    files_of_checkin          The "files_of_check" virtual table is
   180    182   **                              available for decoding manifests.
   181    183   **

Changes to src/sqlite3.c.

     1      1   /******************************************************************************
     2      2   ** This file is an amalgamation of many separate C source files from SQLite
     3         -** version 3.8.8.  By combining all the individual C code files into this 
            3  +** version 3.8.8.1.  By combining all the individual C code files into this 
     4      4   ** single large file, the entire code can be compiled as a single translation
     5      5   ** unit.  This allows many compilers to do optimizations that would not be
     6      6   ** possible if the files were compiled separately.  Performance improvements
     7      7   ** of 5% or more are commonly seen when SQLite is compiled as a single
     8      8   ** translation unit.
     9      9   **
    10     10   ** This file is all you need to compile SQLite.  To use SQLite in other
................................................................................
   274    274   ** string contains the date and time of the check-in (UTC) and an SHA1
   275    275   ** hash of the entire source tree.
   276    276   **
   277    277   ** See also: [sqlite3_libversion()],
   278    278   ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
   279    279   ** [sqlite_version()] and [sqlite_source_id()].
   280    280   */
   281         -#define SQLITE_VERSION        "3.8.8"
          281  +#define SQLITE_VERSION        "3.8.8.1"
   282    282   #define SQLITE_VERSION_NUMBER 3008008
   283         -#define SQLITE_SOURCE_ID      "2015-01-16 12:08:06 7d68a42face3ab14ed88407d4331872f5b243fdf"
          283  +#define SQLITE_SOURCE_ID      "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55"
   284    284   
   285    285   /*
   286    286   ** CAPI3REF: Run-Time Library Version Numbers
   287    287   ** KEYWORDS: sqlite3_version, sqlite3_sourceid
   288    288   **
   289    289   ** These interfaces provide the same information as the [SQLITE_VERSION],
   290    290   ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
 19868  19868   */
 19869  19869   #if SQLITE_OS_WINCE
 19870  19870   # define SQLITE_WIN32_VOLATILE
 19871  19871   #else
 19872  19872   # define SQLITE_WIN32_VOLATILE volatile
 19873  19873   #endif
 19874  19874   
        19875  +/*
        19876  +** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
        19877  +** functions are not available (e.g. those not using MSVC, Cygwin, etc).
        19878  +*/
        19879  +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
        19880  +    SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
        19881  +# define SQLITE_OS_WIN_THREADS 1
        19882  +#else
        19883  +# define SQLITE_OS_WIN_THREADS 0
        19884  +#endif
        19885  +
 19875  19886   #endif /* _OS_WIN_H_ */
 19876  19887   
 19877  19888   /************** End of os_win.h **********************************************/
 19878  19889   /************** Continuing where we left off in mutex_w32.c ******************/
 19879  19890   #endif
 19880  19891   
 19881  19892   /*
................................................................................
 22431  22442   }
 22432  22443   
 22433  22444   #endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
 22434  22445   /******************************** End Unix Pthreads *************************/
 22435  22446   
 22436  22447   
 22437  22448   /********************************* Win32 Threads ****************************/
 22438         -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
        22449  +#if SQLITE_OS_WIN_THREADS
 22439  22450   
 22440  22451   #define SQLITE_THREADS_IMPLEMENTED 1  /* Prevent the single-thread code below */
 22441  22452   #include <process.h>
 22442  22453   
 22443  22454   /* A running thread */
 22444  22455   struct SQLiteThread {
 22445  22456     void *tid;               /* The thread handle */
................................................................................
 22524  22535       assert( bRc );
 22525  22536     }
 22526  22537     if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
 22527  22538     sqlite3_free(p);
 22528  22539     return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
 22529  22540   }
 22530  22541   
 22531         -#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */
        22542  +#endif /* SQLITE_OS_WIN_THREADS */
 22532  22543   /******************************** End Win32 Threads *************************/
 22533  22544   
 22534  22545   
 22535  22546   /********************************* Single-Threaded **************************/
 22536  22547   #ifndef SQLITE_THREADS_IMPLEMENTED
 22537  22548   /*
 22538  22549   ** This implementation does not actually create a new thread.  It does the
................................................................................
 67494  67505     if( desiredResult>0 && rc>0 ) return 1;
 67495  67506     if( CORRUPT_DB ) return 1;
 67496  67507     if( pKeyInfo->db->mallocFailed ) return 1;
 67497  67508     return 0;
 67498  67509   }
 67499  67510   #endif
 67500  67511   
        67512  +#if SQLITE_DEBUG
        67513  +/*
        67514  +** Count the number of fields (a.k.a. columns) in the record given by
        67515  +** pKey,nKey.  The verify that this count is less than or equal to the
        67516  +** limit given by pKeyInfo->nField + pKeyInfo->nXField.
        67517  +**
        67518  +** If this constraint is not satisfied, it means that the high-speed
        67519  +** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will
        67520  +** not work correctly.  If this assert() ever fires, it probably means
        67521  +** that the KeyInfo.nField or KeyInfo.nXField values were computed
        67522  +** incorrectly.
        67523  +*/
        67524  +static void vdbeAssertFieldCountWithinLimits(
        67525  +  int nKey, const void *pKey,   /* The record to verify */ 
        67526  +  const KeyInfo *pKeyInfo       /* Compare size with this KeyInfo */
        67527  +){
        67528  +  int nField = 0;
        67529  +  u32 szHdr;
        67530  +  u32 idx;
        67531  +  u32 notUsed;
        67532  +  const unsigned char *aKey = (const unsigned char*)pKey;
        67533  +
        67534  +  if( CORRUPT_DB ) return;
        67535  +  idx = getVarint32(aKey, szHdr);
        67536  +  assert( szHdr<=nKey );
        67537  +  while( idx<szHdr ){
        67538  +    idx += getVarint32(aKey+idx, notUsed);
        67539  +    nField++;
        67540  +  }
        67541  +  assert( nField <= pKeyInfo->nField+pKeyInfo->nXField );
        67542  +}
        67543  +#else
        67544  +# define vdbeAssertFieldCountWithinLimits(A,B,C)
        67545  +#endif
        67546  +
 67501  67547   /*
 67502  67548   ** Both *pMem1 and *pMem2 contain string values. Compare the two values
 67503  67549   ** using the collation sequence pColl. As usual, return a negative , zero
 67504  67550   ** or positive value if *pMem1 is less than, equal to or greater than 
 67505  67551   ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
 67506  67552   */
 67507  67553   static int vdbeCompareMemString(
................................................................................
 67905  67951     int serial_type = ((const u8*)pKey1)[1];
 67906  67952     int res;
 67907  67953     u32 y;
 67908  67954     u64 x;
 67909  67955     i64 v = pPKey2->aMem[0].u.i;
 67910  67956     i64 lhs;
 67911  67957   
        67958  +  vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
 67912  67959     assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
 67913  67960     switch( serial_type ){
 67914  67961       case 1: { /* 1-byte signed integer */
 67915  67962         lhs = ONE_BYTE_INT(aKey);
 67916  67963         testcase( lhs<0 );
 67917  67964         break;
 67918  67965       }
................................................................................
 67992  68039     int nKey1, const void *pKey1, /* Left key */
 67993  68040     UnpackedRecord *pPKey2        /* Right key */
 67994  68041   ){
 67995  68042     const u8 *aKey1 = (const u8*)pKey1;
 67996  68043     int serial_type;
 67997  68044     int res;
 67998  68045   
        68046  +  vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
 67999  68047     getVarint32(&aKey1[1], serial_type);
 68000  68048     if( serial_type<12 ){
 68001  68049       res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
 68002  68050     }else if( !(serial_type & 0x01) ){ 
 68003  68051       res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
 68004  68052     }else{
 68005  68053       int nCmp;
................................................................................
105793 105841       sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
105794 105842       pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
105795 105843       if( pParse->db->mallocFailed ) return;
105796 105844       pOp->p2 = nKey + nData;
105797 105845       pKI = pOp->p4.pKeyInfo;
105798 105846       memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
105799 105847       sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
105800         -    pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1);
       105848  +    testcase( pKI->nXField>2 );
       105849  +    pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat,
       105850  +                                           pKI->nXField-1);
105801 105851       addrJmp = sqlite3VdbeCurrentAddr(v);
105802 105852       sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
105803 105853       pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
105804 105854       pSort->regReturn = ++pParse->nMem;
105805 105855       sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
105806 105856       sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
105807 105857       sqlite3VdbeJumpHere(v, addrFirst);
................................................................................
106304 106354     int nExpr;
106305 106355     KeyInfo *pInfo;
106306 106356     struct ExprList_item *pItem;
106307 106357     sqlite3 *db = pParse->db;
106308 106358     int i;
106309 106359   
106310 106360     nExpr = pList->nExpr;
106311         -  pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1);
       106361  +  pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
106312 106362     if( pInfo ){
106313 106363       assert( sqlite3KeyInfoIsWriteable(pInfo) );
106314 106364       for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
106315 106365         CollSeq *pColl;
106316 106366         pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
106317 106367         if( !pColl ) pColl = db->pDfltColl;
106318 106368         pInfo->aColl[i-iStart] = pColl;
................................................................................
110174 110224     ** extracted in pre-sorted order.  If that is the case, then the
110175 110225     ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
110176 110226     ** we figure out that the sorting index is not needed.  The addrSortIndex
110177 110227     ** variable is used to facilitate that change.
110178 110228     */
110179 110229     if( sSort.pOrderBy ){
110180 110230       KeyInfo *pKeyInfo;
110181         -    pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0);
       110231  +    pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr);
110182 110232       sSort.iECursor = pParse->nTab++;
110183 110233       sSort.addrSortIndex =
110184 110234         sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
110185 110235             sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0,
110186 110236             (char*)pKeyInfo, P4_KEYINFO
110187 110237         );
110188 110238     }else{
................................................................................
110348 110398   
110349 110399         /* If there is a GROUP BY clause we might need a sorting index to
110350 110400         ** implement it.  Allocate that sorting index now.  If it turns out
110351 110401         ** that we do not need it after all, the OP_SorterOpen instruction
110352 110402         ** will be converted into a Noop.  
110353 110403         */
110354 110404         sAggInfo.sortingIdx = pParse->nTab++;
110355         -      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0);
       110405  +      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn);
110356 110406         addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
110357 110407             sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
110358 110408             0, (char*)pKeyInfo, P4_KEYINFO);
110359 110409   
110360 110410         /* Initialize memory locations used by GROUP BY aggregate processing
110361 110411         */
110362 110412         iUseFlag = ++pParse->nMem;

Changes to src/sqlite3.h.

   103    103   ** string contains the date and time of the check-in (UTC) and an SHA1
   104    104   ** hash of the entire source tree.
   105    105   **
   106    106   ** See also: [sqlite3_libversion()],
   107    107   ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
   108    108   ** [sqlite_version()] and [sqlite_source_id()].
   109    109   */
   110         -#define SQLITE_VERSION        "3.8.8"
          110  +#define SQLITE_VERSION        "3.8.8.1"
   111    111   #define SQLITE_VERSION_NUMBER 3008008
   112         -#define SQLITE_SOURCE_ID      "2015-01-16 12:08:06 7d68a42face3ab14ed88407d4331872f5b243fdf"
          112  +#define SQLITE_SOURCE_ID      "2015-01-20 16:51:25 f73337e3e289915a76ca96e7a05a1a8d4e890d55"
   113    113   
   114    114   /*
   115    115   ** CAPI3REF: Run-Time Library Version Numbers
   116    116   ** KEYWORDS: sqlite3_version, sqlite3_sourceid
   117    117   **
   118    118   ** These interfaces provide the same information as the [SQLITE_VERSION],
   119    119   ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros

Changes to src/stat.c.

    53     53     char zBuf[100];
    54     54     const char *p;
    55     55   
    56     56     login_check_credentials();
    57     57     if( !g.perm.Read ){ login_needed(); return; }
    58     58     brief = P("brief")!=0;
    59     59     style_header("Repository Statistics");
           60  +  style_adunit_config(ADUNIT_RIGHT_OK);
    60     61     if( g.perm.Admin ){
    61     62       style_submenu_element("URLs", "URLs and Checkouts", "urllist");
    62     63       style_submenu_element("Schema", "Repository Schema", "repo_schema");
    63     64       style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
    64     65     }
    65     66     @ <table class="label-value">
    66     67     @ <tr><th>Repository&nbsp;Size:</th><td>
................................................................................
   288    289   void urllist_page(void){
   289    290     Stmt q;
   290    291     int cnt;
   291    292     login_check_credentials();
   292    293     if( !g.perm.Admin ){ login_needed(); return; }
   293    294   
   294    295     style_header("URLs and Checkouts");
          296  +  style_adunit_config(ADUNIT_RIGHT_OK);
   295    297     style_submenu_element("Stat", "Repository Stats", "stat");
   296    298     style_submenu_element("Schema", "Repository Schema", "repo_schema");
   297    299     @ <div class="section">URLs</div>
   298    300     @ <table border="0" width='100%%'>
   299    301     db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')"
   300    302                    "  FROM config WHERE name GLOB 'baseurl:*' ORDER BY 2 DESC");
   301    303     cnt = 0;
................................................................................
   334    336   */
   335    337   void repo_schema_page(void){
   336    338     Stmt q;
   337    339     login_check_credentials();
   338    340     if( !g.perm.Admin ){ login_needed(); return; }
   339    341   
   340    342     style_header("Repository Schema");
          343  +  style_adunit_config(ADUNIT_RIGHT_OK);
   341    344     style_submenu_element("Stat", "Repository Stats", "stat");
   342    345     style_submenu_element("URLs", "URLs and Checkouts", "urllist");
   343    346     db_prepare(&q, "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL",
   344    347                db_name("repository"));
   345    348     @ <pre>
   346    349     while( db_step(&q)==SQLITE_ROW ){
   347    350       @ %h(db_column_text(&q, 0));
   348    351     }
   349    352     @ </pre>
   350    353     db_finalize(&q);
   351    354     style_footer();
   352    355   }

Changes to src/style.c.

    44     44   static int headerHasBeenGenerated = 0;
    45     45   
    46     46   /*
    47     47   ** remember, if a sidebox was used
    48     48   */
    49     49   static int sideboxUsed = 0;
    50     50   
           51  +/*
           52  +** Ad-unit styles.
           53  +*/
           54  +static unsigned adUnitFlags = 0;
           55  +
    51     56   
    52     57   /*
    53     58   ** List of hyperlinks and forms that need to be resolved by javascript in
    54     59   ** the footer.
    55     60   */
    56     61   char **aHref = 0;
    57     62   int nHref = 0;
................................................................................
   282    287   
   283    288   /*
   284    289   ** Draw the header.
   285    290   */
   286    291   void style_header(const char *zTitleFormat, ...){
   287    292     va_list ap;
   288    293     char *zTitle;
   289         -  const char *zHeader = db_get("header", (char*)zDefaultHeader);
          294  +  const char *zHeader = db_get("header", 0);
          295  +  if( zHeader==0 ) zHeader = builtin_text("skins/default/header.txt");
   290    296     login_check_credentials();
   291    297   
   292    298     va_start(ap, zTitleFormat);
   293    299     zTitle = vmprintf(zTitleFormat, ap);
   294    300     va_end(ap);
   295    301   
   296    302     cgi_destination(CGI_HEADER);
................................................................................
   342    348     @ if(/^#/.test(x)) x = x.substr(1);
   343    349     @ var e = document.getElementById(x);
   344    350     @ if(!e) throw new Error("Expecting element with ID "+x);
   345    351     @ else return e;}
   346    352     @ </script>
   347    353   }
   348    354   
          355  +#if INTERFACE
          356  +/* Allowed parameters for style_adunit() */
          357  +#define ADUNIT_OFF        0x0001       /* Do not allow ads on this page */
          358  +#define ADUNIT_RIGHT_OK   0x0002       /* Right-side vertical ads ok here */
          359  +#endif   
          360  +
   349    361   /*
   350         -** Append ad unit text if appropriate.
          362  +** Various page implementations can invoke this interface to let the
          363  +** style manager know what kinds of ads are appropriate for this page.
          364  +*/
          365  +void style_adunit_config(unsigned int mFlags){
          366  +  adUnitFlags = mFlags;
          367  +}
          368  +
          369  +/*
          370  +** Return the text of an ad-unit, if one should be rendered.  Return
          371  +** NULL if no ad-unit is desired.
          372  +**
          373  +** The *pAdFlag value might be set to ADUNIT_RIGHT_OK if this is
          374  +** a right-hand vertical ad.
   351    375   */
   352         -static void style_ad_unit(void){
   353         -  const char *zAd;
          376  +static const char *style_adunit_text(unsigned int *pAdFlag){
          377  +  const char *zAd = 0;
          378  +  *pAdFlag = 0;
          379  +  if( adUnitFlags & ADUNIT_OFF ) return 0;  /* Disallow ads on this page */
   354    380     if( g.perm.Admin && db_get_boolean("adunit-omit-if-admin",0) ){
   355         -    return;
          381  +    return 0;
   356    382     }
   357    383     if( !login_is_nobody()
   358    384      && fossil_strcmp(g.zLogin,"anonymous")!=0
   359    385      && db_get_boolean("adunit-omit-if-user",0)
   360    386     ){
   361         -    return;
          387  +    return 0;
   362    388     }
   363         -  zAd = db_get("adunit", 0);
   364         -  if( zAd ) cgi_append_content(zAd, -1);
          389  +  if( (adUnitFlags & ADUNIT_RIGHT_OK)!=0
          390  +   && !fossil_all_whitespace(zAd = db_get("adunit-right", 0))
          391  +   && !cgi_body_contains("<table")
          392  +  ){
          393  +    *pAdFlag = ADUNIT_RIGHT_OK;
          394  +    return zAd;
          395  +  }else if( !fossil_all_whitespace(zAd = db_get("adunit",0)) ){
          396  +    return zAd;
          397  +  }
          398  +  return 0;
   365    399   }
   366    400   
   367    401   /*
   368    402   ** Draw the footer at the bottom of the page.
   369    403   */
   370    404   void style_footer(void){
   371    405     const char *zFooter;
          406  +  const char *zAd = 0;
          407  +  unsigned int mAdFlags = 0;
   372    408   
   373    409     if( !headerHasBeenGenerated ) return;
   374    410   
   375    411     /* Go back and put the submenu at the top of the page.  We delay the
   376    412     ** creation of the submenu until the end so that we can add elements
   377    413     ** to the submenu while generating page text.
   378    414     */
................................................................................
   387    423           @ <span class="label">%h(p->zLabel)</span>
   388    424         }else{
   389    425           @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
   390    426         }
   391    427       }
   392    428       @ </div>
   393    429     }
   394         -  style_ad_unit();
   395         -  @ <div class="content">
          430  +
          431  +  zAd = style_adunit_text(&mAdFlags);
          432  +  if( (mAdFlags & ADUNIT_RIGHT_OK)!=0  ){
          433  +    @ <div class="content adunit_right_container">
          434  +    @ <div class="adunit_right">
          435  +    cgi_append_content(zAd, -1);
          436  +    @ </div>
          437  +  }else{
          438  +    if( zAd ){
          439  +      @ <div class="adunit_banner">
          440  +      cgi_append_content(zAd, -1);
          441  +      @ </div>
          442  +    }
          443  +    @ <div class="content">
          444  +  }
   396    445     cgi_destination(CGI_BODY);
   397    446   
   398    447     if( sideboxUsed ){
   399    448       /* Put the footer at the bottom of the page.
   400    449       ** the additional clear/both is needed to extend the content
   401    450       ** part to the end of an optional sidebox.
   402    451       */
................................................................................
   404    453     }
   405    454     @ </div>
   406    455   
   407    456     /* Set the href= field on hyperlinks.  Do this before the footer since
   408    457     ** the footer will be generating </html> */
   409    458     style_resolve_href();
   410    459   
   411         -  zFooter = db_get("footer", (char*)zDefaultFooter);
          460  +  zFooter = db_get("footer", 0);
          461  +  if( zFooter==0 ) zFooter = builtin_text("skins/default/footer.txt");
   412    462     if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
   413    463     Th_Render(zFooter);
   414    464     if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
   415    465   
   416    466     /* Render trace log if TH1 tracing is enabled. */
   417    467     if( g.thTrace ){
   418    468       cgi_append_content("<span class=\"thTrace\"><hr />\n", -1);
................................................................................
   434    484   
   435    485   /* End the side-box
   436    486   */
   437    487   void style_sidebox_end(void){
   438    488     @ </div>
   439    489   }
   440    490   
   441         -/* @-comment: // */
   442         -/*
   443         -** The default page header.
   444         -*/
   445         -const char zDefaultHeader[] =
   446         -@ <html>
   447         -@ <head>
   448         -@ <base href="$baseurl/$current_page" />
   449         -@ <title>$<project_name>: $<title></title>
   450         -@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
   451         -@       href="$home/timeline.rss" />
   452         -@ <link rel="stylesheet" href="$stylesheet_url" type="text/css"
   453         -@       media="screen" />
   454         -@ </head>
   455         -@ <body>
   456         -@ <div class="header">
   457         -@   <div class="logo">
   458         -@     <img src="$logo_image_url" alt="logo" />
   459         -@   </div>
   460         -@   <div class="title"><small>$<project_name></small><br />$<title></div>
   461         -@   <div class="status"><th1>
   462         -@      if {[info exists login]} {
   463         -@        puts "Logged in as $login"
   464         -@      } else {
   465         -@        puts "Not logged in"
   466         -@      }
   467         -@   </th1></div>
   468         -@ </div>
   469         -@ <div class="mainmenu">
   470         -@ <th1>
   471         -@ html "<a href='$home$index_page'>Home</a>\n"
   472         -@ if {[anycap jor]} {
   473         -@   html "<a href='$home/timeline'>Timeline</a>\n"
   474         -@ }
   475         -@ if {[hascap oh]} {
   476         -@   html "<a href='$home/tree?ci=tip'>Files</a>\n"
   477         -@ }
   478         -@ if {[hascap o]} {
   479         -@   html "<a href='$home/brlist'>Branches</a>\n"
   480         -@   html "<a href='$home/taglist'>Tags</a>\n"
   481         -@ }
   482         -@ if {[hascap r]} {
   483         -@   html "<a href='$home/reportlist'>Tickets</a>\n"
   484         -@ }
   485         -@ if {[hascap j]} {
   486         -@   html "<a href='$home/wiki'>Wiki</a>\n"
   487         -@ }
   488         -@ if {[hascap s]} {
   489         -@   html "<a href='$home/setup'>Admin</a>\n"
   490         -@ } elseif {[hascap a]} {
   491         -@   html "<a href='$home/setup_ulist'>Users</a>\n"
   492         -@ }
   493         -@ if {[info exists login]} {
   494         -@   html "<a href='$home/login'>Logout</a>\n"
   495         -@ } else {
   496         -@   html "<a href='$home/login'>Login</a>\n"
   497         -@ }
   498         -@ </th1></div>
   499         -;
   500         -
   501         -/*
   502         -** The default page footer
   503         -*/
   504         -const char zDefaultFooter[] =
   505         -@ <div class="footer">
   506         -@ This page was generated in about
   507         -@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
   508         -@ Fossil version $manifest_version $manifest_date
   509         -@ </div>
   510         -@ </body></html>
   511         -;
   512         -
   513         -/*
   514         -** The default Cascading Style Sheet.
   515         -** It's assembled by different strings for each class.
   516         -** The default css contains all definitions.
   517         -** The style sheet, send to the client only contains the ones,
   518         -** not defined in the user defined css.
   519         -*/
   520         -const char zDefaultCSS[] =
   521         -@ /* General settings for the entire page */
   522         -@ body {
   523         -@   margin: 0ex 1ex;
   524         -@   padding: 0px;
   525         -@   background-color: white;
   526         -@   font-family: sans-serif;
   527         -@ }
   528         -@
   529         -@ /* The project logo in the upper left-hand corner of each page */
   530         -@ div.logo {
   531         -@   display: table-cell;
   532         -@   text-align: center;
   533         -@   vertical-align: bottom;
   534         -@   font-weight: bold;
   535         -@   color: #558195;
   536         -@   min-width: 200px;
   537         -@   white-space: nowrap;
   538         -@ }
   539         -@
   540         -@ /* The page title centered at the top of each page */
   541         -@ div.title {
   542         -@   display: table-cell;
   543         -@   font-size: 2em;
   544         -@   font-weight: bold;
   545         -@   text-align: center;
   546         -@   padding: 0 0 0 1em;
   547         -@   color: #558195;
   548         -@   vertical-align: bottom;
   549         -@   width: 100%;
   550         -@ }
   551         -@
   552         -@ /* The login status message in the top right-hand corner */
   553         -@ div.status {
   554         -@   display: table-cell;
   555         -@   text-align: right;
   556         -@   vertical-align: bottom;
   557         -@   color: #558195;
   558         -@   font-size: 0.8em;
   559         -@   font-weight: bold;
   560         -@   min-width: 200px;
   561         -@   white-space: nowrap;
   562         -@ }
   563         -@
   564         -@ /* The header across the top of the page */
   565         -@ div.header {
   566         -@   display: table;
   567         -@   width: 100%;
   568         -@ }
   569         -@
   570         -@ /* The main menu bar that appears at the top of the page beneath
   571         -@ ** the header */
   572         -@ div.mainmenu {
   573         -@   padding: 5px 10px 5px 10px;
   574         -@   font-size: 0.9em;
   575         -@   font-weight: bold;
   576         -@   text-align: center;
   577         -@   letter-spacing: 1px;
   578         -@   background-color: #558195;
   579         -@   border-top-left-radius: 8px;
   580         -@   border-top-right-radius: 8px;
   581         -@   color: white;
   582         -@ }
   583         -@
   584         -@ /* The submenu bar that *sometimes* appears below the main menu */
   585         -@ div.submenu, div.sectionmenu {
   586         -@   padding: 3px 10px 3px 0px;
   587         -@   font-size: 0.9em;
   588         -@   text-align: center;
   589         -@   background-color: #456878;
   590         -@   color: white;
   591         -@ }
   592         -@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited,
   593         -@ div.sectionmenu>a.button:link, div.sectionmenu>a.button:visited {
   594         -@   padding: 3px 10px 3px 10px;
   595         -@   color: white;
   596         -@   text-decoration: none;
   597         -@ }
   598         -@ div.mainmenu a:hover, div.submenu a:hover, div.sectionmenu>a.button:hover {
   599         -@   color: #558195;
   600         -@   background-color: white;
   601         -@ }
   602         -@
   603         -@ /* All page content from the bottom of the menu or submenu down to
   604         -@ ** the footer */
   605         -@ div.content {
   606         -@   padding: 0ex 1ex 1ex 1ex;
   607         -@   border: solid #aaa;
   608         -@   border-width: 1px;
   609         -@ }
   610         -@
   611         -@ /* Some pages have section dividers */
   612         -@ div.section {
   613         -@   margin-bottom: 0px;
   614         -@   margin-top: 1em;
   615         -@   padding: 1px 1px 1px 1px;
   616         -@   font-size: 1.2em;
   617         -@   font-weight: bold;
   618         -@   background-color: #558195;
   619         -@   color: white;
   620         -@   white-space: nowrap;
   621         -@ }
   622         -@
   623         -@ /* The "Date" that occurs on the left hand side of timelines */
   624         -@ div.divider {
   625         -@   background: #a1c4d4;
   626         -@   border: 2px #558195 solid;
   627         -@   font-size: 1em; font-weight: normal;
   628         -@   padding: .25em;
   629         -@   margin: .2em 0 .2em 0;
   630         -@   float: left;
   631         -@   clear: left;
   632         -@   white-space: nowrap;
   633         -@ }
   634         -@
   635         -@ /* The footer at the very bottom of the page */
   636         -@ div.footer {
   637         -@   clear: both;
   638         -@   font-size: 0.8em;
   639         -@   padding: 5px 10px 5px 10px;
   640         -@   text-align: right;
   641         -@   background-color: #558195;
   642         -@   border-bottom-left-radius: 8px;
   643         -@   border-bottom-right-radius: 8px;
   644         -@   color: white;
   645         -@ }
   646         -@
   647         -@ /* Hyperlink colors in the footer */
   648         -@ div.footer a { color: white; }
   649         -@ div.footer a:link { color: white; }
   650         -@ div.footer a:visited { color: white; }
   651         -@ div.footer a:hover { background-color: white; color: #558195; }
   652         -@
   653         -@ /* verbatim blocks */
   654         -@ pre.verbatim {
   655         -@   background-color: #f5f5f5;
   656         -@   padding: 0.5em;
   657         -@   white-space: pre-wrap;
   658         -@}
   659         -;
   660         -
   661    491   
   662    492   /* The following table contains bits of default CSS that must
   663    493   ** be included if they are not found in the application-defined
   664    494   ** CSS.
   665    495   */
   666    496   const struct strctCssDefaults {
   667    497     const char *elementClass;  /* Name of element needed */
   668    498     const char *comment;       /* Comment text */
   669    499     const char *value;         /* CSS text */
   670    500   } cssDefaultList[] = {
   671         -  { "",
   672         -    "",
   673         -    zDefaultCSS
   674         -  },
   675    501     { "div.sidebox",
   676    502       "The nomenclature sidebox for branches,..",
   677    503       @   float: right;
   678    504       @   background-color: white;
   679    505       @   border-width: medium;
   680    506       @   border-style: double;
   681    507       @   margin: 10px;
................................................................................
  1277   1103     },
  1278   1104     { ".brlist table th",  "Branch list table headers",
  1279   1105       @ text-align: left;
  1280   1106       @ padding: 0px 1em 0.5ex 0px;
  1281   1107     },
  1282   1108     { ".brlist table td",  "Branch list table headers",
  1283   1109       @ padding: 0px 2em 0px 0px;
         1110  +    @ white-space: nowrap;
  1284   1111     },
  1285   1112     { "th.sort:after",
  1286   1113       "General styles for sortable column marker",
  1287   1114       @ margin-left: .4em;
  1288   1115       @ cursor: pointer;
  1289   1116       @ text-shadow: 0 0 0 #000; /* Makes arrow darker */
  1290   1117     },
................................................................................
  1308   1135   
  1309   1136   /*
  1310   1137   ** Append all of the default CSS to the CGI output.
  1311   1138   */
  1312   1139   void cgi_append_default_css(void) {
  1313   1140     int i;
  1314   1141   
         1142  +  cgi_printf("%s", builtin_text("skins/default/css.txt"));
  1315   1143     for( i=0; cssDefaultList[i].elementClass; i++ ){
  1316   1144       if( cssDefaultList[i].elementClass[0] ){
  1317   1145         cgi_printf("/* %s */\n%s {\n%s\n}\n\n",
  1318   1146                    cssDefaultList[i].comment,
  1319   1147                    cssDefaultList[i].elementClass,
  1320         -                 cssDefaultList[i].value
  1321         -                );
  1322         -    }else{
  1323         -      cgi_printf("%s",
  1324   1148                    cssDefaultList[i].value
  1325   1149                   );
  1326   1150       }
  1327   1151     }
  1328   1152   }
  1329   1153   
  1330   1154   /*
................................................................................
  1331   1155   ** WEBPAGE: style.css
  1332   1156   */
  1333   1157   void page_style_css(void){
  1334   1158     Blob css;
  1335   1159     int i;
  1336   1160   
  1337   1161     cgi_set_content_type("text/css");
  1338         -  blob_init(&css, db_get("css",(char*)zDefaultCSS), -1);
         1162  +  blob_init(&css, db_get("css",(char*)builtin_text("skins/default/css.txt")), -1);
  1339   1163   
  1340   1164     /* add special missing definitions */
  1341   1165     for(i=1; cssDefaultList[i].elementClass; i++){
  1342   1166       if( strstr(blob_str(&css), cssDefaultList[i].elementClass)==0 ){
  1343   1167         blob_appendf(&css, "/* %s */\n%s {\n%s}\n",
  1344   1168             cssDefaultList[i].comment,
  1345   1169             cssDefaultList[i].elementClass,

Changes to src/tag.c.

   533    533     return;
   534    534   
   535    535   tag_cmd_usage:
   536    536     usage("add|cancel|find|list ...");
   537    537   }
   538    538   
   539    539   /*
   540         -** WEBPAGE: /taglist
          540  +** WEBPAGE: taglist
   541    541   */
   542    542   void taglist_page(void){
   543    543     Stmt q;
   544    544   
   545    545     login_check_credentials();
   546    546     if( !g.perm.Read ){
   547    547       login_needed();
   548    548     }
   549    549     login_anonymous_available();
   550    550     style_header("Tags");
          551  +  style_adunit_config(ADUNIT_RIGHT_OK);
   551    552     style_submenu_element("Timeline", "Timeline", "tagtimeline");
   552    553     @ <h2>Non-propagating tags:</h2>
   553    554     db_prepare(&q,
   554    555       "SELECT substr(tagname,5)"
   555    556       "  FROM tag"
   556    557       " WHERE EXISTS(SELECT 1 FROM tagxref"
   557    558       "               WHERE tagid=tag.tagid"

Changes to src/th.h.

     1      1   
     2      2   /* This header file defines the external interface to the custom Scripting
     3         -** Language (TH) interpreter.  TH is very similar to TCL but is not an
            3  +** Language (TH) interpreter.  TH is very similar to Tcl but is not an
     4      4   ** exact clone.
     5      5   */
     6      6   
     7      7   /*
     8      8   ** Before creating an interpreter, the application must allocate and
     9      9   ** populate an instance of the following structure. It must remain valid
    10     10   ** for the lifetime of the interpreter.

Changes to src/translate.c.

    40     40   ** rather than text that is to be output via cgi_printf().  Render it
    41     41   ** as such.
    42     42   **
    43     43   ** Enhancement #2:
    44     44   **
    45     45   ** Comments of the form:  "/* @-comment: CC" cause CC to become a
    46     46   ** comment character for the @-substitution.  Typical values for CC are
    47         -** "--" (for SQL text) or "#" (for TCL script) or "//" (for C++ code).
           47  +** "--" (for SQL text) or "#" (for Tcl script) or "//" (for C++ code).
    48     48   ** Lines of subsequent @-blocks that begin with CC are omitted from the
    49     49   ** output.
    50     50   **
    51     51   */
    52     52   #include <stdio.h>
    53     53   #include <ctype.h>
    54     54   #include <stdlib.h>

Changes to src/url.c.

   360    360   ** This also happens to be a convenient function to use to look for
   361    361   ** the --nosync option that will temporarily disable the "autosync"
   362    362   ** feature.
   363    363   */
   364    364   void url_proxy_options(void){
   365    365     zProxyOpt = find_option("proxy", 0, 1);
   366    366     if( find_option("nosync",0,0) ) g.fNoSync = 1;
          367  +  if( find_option("ipv4",0,0) ) g.fIPv4 = 1;
   367    368   }
   368    369   
   369    370   /*
   370    371   ** If the "proxy" setting is defined, then change the URL settings
   371    372   ** (initialized by a prior call to url_parse()) so that the HTTP
   372    373   ** header will be appropriate for the proxy and so that the TCP/IP
   373    374   ** connection will be opened to the proxy rather than to the server.

Changes to src/user.c.

   465    465     blob_append_sql(&sql,"  ORDER BY rowid DESC LIMIT %d OFFSET %d", n+1, skip);
   466    466     if( skip ){
   467    467       style_submenu_element("Newer", "Newer entries",
   468    468                 "%s/access_log?o=%d&n=%d&y=%d", g.zTop, skip>=n ? skip-n : 0,
   469    469                 n, y);
   470    470     }
   471    471     rc = db_prepare_ignore_error(&q, "%s", blob_sql_text(&sql));
   472         -  @ <center><table border="1" cellpadding="5">
   473         -  @ <tr><th width="33%%">Date</th><th width="34%%">User</th>
   474         -  @ <th width="33%%">IP Address</th></tr>
          472  +  @ <center><table border="1" cellpadding="5" id='logtable'>
          473  +  @ <thead><tr><th width="33%%">Date</th><th width="34%%">User</th>
          474  +  @ <th width="33%%">IP Address</th></tr></thead><tbody>
   475    475     while( rc==SQLITE_OK && db_step(&q)==SQLITE_ROW ){
   476    476       const char *zName = db_column_text(&q, 0);
   477    477       const char *zIP = db_column_text(&q, 1);
   478    478       const char *zDate = db_column_text(&q, 2);
   479    479       int bSuccess = db_column_int(&q, 3);
   480    480       cnt++;
   481    481       if( cnt>n ){
................................................................................
   490    490       }
   491    491       @ <td>%s(zDate)</td><td>%h(zName)</td><td>%h(zIP)</td></tr>
   492    492     }
   493    493     if( skip>0 || cnt>n ){
   494    494       style_submenu_element("All", "All entries",
   495    495             "%s/access_log?n=10000000", g.zTop);
   496    496     }
   497         -  @ </table></center>
          497  +  @ </tbody></table></center>
   498    498     db_finalize(&q);
   499    499     @ <hr>
   500    500     @ <form method="post" action="%s(g.zTop)/access_log">
   501    501     @ <label><input type="checkbox" name="delold">
   502    502     @ Delete all but the most recent 200 entries</input></label>
   503    503     @ <input type="submit" name="deloldbtn" value="Delete"></input>
   504    504     @ </form>
................................................................................
   513    513     @ <input type="submit" name="delfailbtn" value="Delete"></input>
   514    514     @ </form>
   515    515     @ <form method="post" action="%s(g.zTop)/access_log">
   516    516     @ <label><input type="checkbox" name="delall">
   517    517     @ Delete all entries</input></label>
   518    518     @ <input type="submit" name="delallbtn" value="Delete"></input>
   519    519     @ </form>
          520  +  output_table_sorting_javascript("logtable", "Ttt", 1);
   520    521     style_footer();
   521    522   }

Changes to src/util.c.

   329    329   ** only lower-case ASCII hexadecimal values.
   330    330   */
   331    331   int fossil_is_uuid(const char *zSym){
   332    332     return zSym
   333    333       && (UUID_SIZE==strlen(zSym))
   334    334       && validate16(zSym, UUID_SIZE);
   335    335   }
          336  +
          337  +/*
          338  +** Return true if the input string is NULL or all whitespace.
          339  +** Return false if the input string contains text.
          340  +*/
          341  +int fossil_all_whitespace(const char *z){
          342  +  if( z==0 ) return 1;
          343  +  while( fossil_isspace(z[0]) ){ z++; }
          344  +  return z[0]==0;
          345  +}

Changes to src/xfer.c.

  1964   1964        fossil_warning("*** time skew *** server is slow by %s",
  1965   1965                       db_timespan_name(-rSkew));
  1966   1966        g.clockSkewSeen = 1;
  1967   1967     }
  1968   1968   
  1969   1969     fossil_force_newline();
  1970   1970     fossil_print(
  1971         -     "%s finished with %lld bytes sent, %lld bytes received\n",
  1972         -     zOpType, nSent, nRcvd);
         1971  +     "%s done, sent: %lld  received: %lld  ip: %s\n",
         1972  +     zOpType, nSent, nRcvd, g.zIpAddr);
  1973   1973     transport_close(&g.url);
  1974   1974     transport_global_shutdown(&g.url);
  1975   1975     if( nErr && go==2 ){
  1976   1976       db_multi_exec("DROP TABLE onremote");
  1977   1977       manifest_crosslink_end(MC_PERMIT_HOOKS);
  1978   1978       content_enable_dephantomize(1);
  1979   1979       db_end_transaction(0);
  1980   1980     }
  1981   1981     return nErr;
  1982   1982   }

Changes to win/Makefile.mingw.

   144    144   endif
   145    145   
   146    146   #### The directories where the OpenSSL include and library files are located.
   147    147   #    The recommended usage here is to use the Sysinternals junction tool
   148    148   #    to create a hard link between an "openssl-1.x" sub-directory of the
   149    149   #    Fossil source code directory and the target OpenSSL source directory.
   150    150   #
   151         -OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include
   152         -OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k
          151  +OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l
          152  +OPENSSLINCDIR = $(OPENSSLDIR)/include
          153  +OPENSSLLIBDIR = $(OPENSSLDIR)
   153    154   
   154    155   #### Either the directory where the Tcl library is installed or the Tcl
   155    156   #    source code directory resides (depending on the value of the macro
   156    157   #    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
   157    158   #    this directory must have "include" and "lib" sub-directories.  If
   158    159   #    this points to the Tcl source code directory, this directory must
   159    160   #    have "generic" and "win" sub-directories.  The recommended usage
................................................................................
   481    482     $(SRCDIR)/winhttp.c \
   482    483     $(SRCDIR)/wysiwyg.c \
   483    484     $(SRCDIR)/xfer.c \
   484    485     $(SRCDIR)/xfersetup.c \
   485    486     $(SRCDIR)/zip.c
   486    487   
   487    488   EXTRA_FILES = \
          489  +  $(SRCDIR)/../skins/black_and_white/css.txt \
          490  +  $(SRCDIR)/../skins/black_and_white/footer.txt \
          491  +  $(SRCDIR)/../skins/black_and_white/header.txt \
          492  +  $(SRCDIR)/../skins/default/css.txt \
          493  +  $(SRCDIR)/../skins/default/footer.txt \
          494  +  $(SRCDIR)/../skins/default/header.txt \
          495  +  $(SRCDIR)/../skins/eagle/css.txt \
          496  +  $(SRCDIR)/../skins/eagle/footer.txt \
          497  +  $(SRCDIR)/../skins/eagle/header.txt \
          498  +  $(SRCDIR)/../skins/enhanced1/css.txt \
          499  +  $(SRCDIR)/../skins/enhanced1/footer.txt \
          500  +  $(SRCDIR)/../skins/enhanced1/header.txt \
          501  +  $(SRCDIR)/../skins/etienne1/css.txt \
          502  +  $(SRCDIR)/../skins/etienne1/footer.txt \
          503  +  $(SRCDIR)/../skins/etienne1/header.txt \
          504  +  $(SRCDIR)/../skins/khaki/css.txt \
          505  +  $(SRCDIR)/../skins/khaki/footer.txt \
          506  +  $(SRCDIR)/../skins/khaki/header.txt \
          507  +  $(SRCDIR)/../skins/plain_gray/css.txt \
          508  +  $(SRCDIR)/../skins/plain_gray/footer.txt \
          509  +  $(SRCDIR)/../skins/plain_gray/header.txt \
          510  +  $(SRCDIR)/../skins/rounded1/css.txt \
          511  +  $(SRCDIR)/../skins/rounded1/footer.txt \
          512  +  $(SRCDIR)/../skins/rounded1/header.txt \
   488    513     $(SRCDIR)/diff.tcl
   489    514   
   490    515   TRANS_SRC = \
   491    516     $(OBJDIR)/add_.c \
   492    517     $(OBJDIR)/allrepo_.c \
   493    518     $(OBJDIR)/attach_.c \
   494    519     $(OBJDIR)/bag_.c \

Changes to win/Makefile.mingw.mistachkin.

   144    144   endif
   145    145   
   146    146   #### The directories where the OpenSSL include and library files are located.
   147    147   #    The recommended usage here is to use the Sysinternals junction tool
   148    148   #    to create a hard link between an "openssl-1.x" sub-directory of the
   149    149   #    Fossil source code directory and the target OpenSSL source directory.
   150    150   #
   151         -OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1k/include
   152         -OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1k
          151  +OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.1l
          152  +OPENSSLINCDIR = $(OPENSSLDIR)/include
          153  +OPENSSLLIBDIR = $(OPENSSLDIR)
   153    154   
   154    155   #### Either the directory where the Tcl library is installed or the Tcl
   155    156   #    source code directory resides (depending on the value of the macro
   156    157   #    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
   157    158   #    this directory must have "include" and "lib" sub-directories.  If
   158    159   #    this points to the Tcl source code directory, this directory must
   159    160   #    have "generic" and "win" sub-directories.  The recommended usage
................................................................................
   481    482     $(SRCDIR)/winhttp.c \
   482    483     $(SRCDIR)/wysiwyg.c \
   483    484     $(SRCDIR)/xfer.c \
   484    485     $(SRCDIR)/xfersetup.c \
   485    486     $(SRCDIR)/zip.c
   486    487   
   487    488   EXTRA_FILES = \
          489  +  $(SRCDIR)/../skins/black_and_white/css.txt \
          490  +  $(SRCDIR)/../skins/black_and_white/footer.txt \
          491  +  $(SRCDIR)/../skins/black_and_white/header.txt \
          492  +  $(SRCDIR)/../skins/default/css.txt \
          493  +  $(SRCDIR)/../skins/default/footer.txt \
          494  +  $(SRCDIR)/../skins/default/header.txt \
          495  +  $(SRCDIR)/../skins/eagle/css.txt \
          496  +  $(SRCDIR)/../skins/eagle/footer.txt \
          497  +  $(SRCDIR)/../skins/eagle/header.txt \
          498  +  $(SRCDIR)/../skins/enhanced1/css.txt \
          499  +  $(SRCDIR)/../skins/enhanced1/footer.txt \
          500  +  $(SRCDIR)/../skins/enhanced1/header.txt \
          501  +  $(SRCDIR)/../skins/khaki/css.txt \
          502  +  $(SRCDIR)/../skins/khaki/footer.txt \
          503  +  $(SRCDIR)/../skins/khaki/header.txt \
          504  +  $(SRCDIR)/../skins/plain_gray/css.txt \
          505  +  $(SRCDIR)/../skins/plain_gray/footer.txt \
          506  +  $(SRCDIR)/../skins/plain_gray/header.txt \
          507  +  $(SRCDIR)/../skins/rounded1/css.txt \
          508  +  $(SRCDIR)/../skins/rounded1/footer.txt \
          509  +  $(SRCDIR)/../skins/rounded1/header.txt \
   488    510     $(SRCDIR)/diff.tcl
   489    511   
   490    512   TRANS_SRC = \
   491    513     $(OBJDIR)/add_.c \
   492    514     $(OBJDIR)/allrepo_.c \
   493    515     $(OBJDIR)/attach_.c \
   494    516     $(OBJDIR)/bag_.c \

Changes to win/Makefile.msc.

    53     53   # Uncomment to enable TH1 hooks
    54     54   # FOSSIL_ENABLE_TH1_HOOKS = 1
    55     55   
    56     56   # Uncomment to enable Tcl support
    57     57   # FOSSIL_ENABLE_TCL = 1
    58     58   
    59     59   !ifdef FOSSIL_ENABLE_SSL
    60         -SSLDIR    = $(B)\compat\openssl-1.0.1k
           60  +SSLDIR    = $(B)\compat\openssl-1.0.1l
    61     61   SSLINCDIR = $(SSLDIR)\inc32
    62     62   SSLLIBDIR = $(SSLDIR)\out32
    63     63   SSLLFLAGS = /nologo /opt:ref /debug
    64     64   SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
    65     65   !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64"
    66     66   !message Using 'x64' platform for OpenSSL...
    67     67   # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build.
................................................................................
   320    320           winfile_.c \
   321    321           winhttp_.c \
   322    322           wysiwyg_.c \
   323    323           xfer_.c \
   324    324           xfersetup_.c \
   325    325           zip_.c
   326    326   
   327         -EXTRA_FILES   = $(SRCDIR)\diff.tcl
          327  +EXTRA_FILES   = $(SRCDIR)\../skins/black_and_white/css.txt \
          328  +        $(SRCDIR)\../skins/black_and_white/footer.txt \
          329  +        $(SRCDIR)\../skins/black_and_white/header.txt \
          330  +        $(SRCDIR)\../skins/default/css.txt \
          331  +        $(SRCDIR)\../skins/default/footer.txt \
          332  +        $(SRCDIR)\../skins/default/header.txt \
          333  +        $(SRCDIR)\../skins/eagle/css.txt \
          334  +        $(SRCDIR)\../skins/eagle/footer.txt \
          335  +        $(SRCDIR)\../skins/eagle/header.txt \
          336  +        $(SRCDIR)\../skins/enhanced1/css.txt \
          337  +        $(SRCDIR)\../skins/enhanced1/footer.txt \
          338  +        $(SRCDIR)\../skins/enhanced1/header.txt \
          339  +        $(SRCDIR)\../skins/etienne1/css.txt \
          340  +        $(SRCDIR)\../skins/etienne1/footer.txt \
          341  +        $(SRCDIR)\../skins/etienne1/header.txt \
          342  +        $(SRCDIR)\../skins/khaki/css.txt \
          343  +        $(SRCDIR)\../skins/khaki/footer.txt \
          344  +        $(SRCDIR)\../skins/khaki/header.txt \
          345  +        $(SRCDIR)\../skins/plain_gray/css.txt \
          346  +        $(SRCDIR)\../skins/plain_gray/footer.txt \
          347  +        $(SRCDIR)\../skins/plain_gray/header.txt \
          348  +        $(SRCDIR)\../skins/rounded1/css.txt \
          349  +        $(SRCDIR)\../skins/rounded1/footer.txt \
          350  +        $(SRCDIR)\../skins/rounded1/header.txt \
          351  +        $(SRCDIR)\diff.tcl
   328    352   
   329    353   OBJ   = $(OX)\add$O \
   330    354           $(OX)\allrepo$O \
   331    355           $(OX)\attach$O \
   332    356           $(OX)\bag$O \
   333    357           $(OX)\bisect$O \
   334    358           $(OX)\blob$O \

Changes to win/include/unistd.h.

     1      1   #ifndef _UNISTD_H
     2      2   #define _UNISTD_H	 1
     3      3   
     4         -/* This file intended to serve as a drop-in replacement for 
            4  +/* This file intended to serve as a drop-in replacement for
     5      5    *  unistd.h on Windows
     6         - *  Please add functionality as neeeded 
            6  + *  Please add functionality as neeeded
     7      7    */
     8      8   
     9      9   #include <stdlib.h>
    10     10   #include <io.h>
    11     11   #define srandom srand
    12     12   #define random rand
    13     13   #if defined(__DMC__)

Changes to www/build.wiki.

   120    120   file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to
   121    121   detect and use the latest installed version of MSVC.<br><br>To enable
   122    122   the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
   123    123   first <a href="https://www.openssl.org/source/">download the official
   124    124   source code for OpenSSL</a> and extract it to an appropriately named
   125    125   "<b>openssl-X.Y.ZA</b>" subdirectory within the local
   126    126   [/tree?ci=trunk&name=compat | compat] directory (e.g.
   127         -"<b>compat/openssl-1.0.1k</b>"), then make sure that some recent
          127  +"<b>compat/openssl-1.0.1l</b>"), then make sure that some recent
   128    128   <a href="http://www.perl.org/">Perl</a> binaries are installed locally,
   129    129   and finally run one of the following commands:
   130    130   <blockquote><pre>
   131    131   nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
   132    132   </pre></blockquote>
   133    133   <blockquote><pre>
   134    134   buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin