Fossil SCM

Add the ability to specify one of the built-in skins as an override of the current configuration, using the --skin option to "server", "ui", and "http" commands, or the "skin:" line in the CGI script.

drh 2015-02-11 15:05 trunk
Commit ed36e2eb510fbd26c05fae76b74dd23d02302a82
+1 -1
--- src/diff.c
+++ src/diff.c
@@ -2294,11 +2294,11 @@
22942294
}
22952295
if( iLimit>20 ){
22962296
style_submenu_element("20 Ancestors", "20 Ancestors",
22972297
"%s", url_render(&url, "limit", "20", 0, 0));
22982298
}
2299
- if( db_get_boolean("white-foreground", 0) ){
2299
+ if( skin_white_foreground() ){
23002300
clr1 = 0xa04040;
23012301
clr2 = 0x4059a0;
23022302
}else{
23032303
clr1 = 0xffb5b5; /* Recent changes: red (hot) */
23042304
clr2 = 0xb5e0ff; /* Older changes: blue (cold) */
23052305
--- src/diff.c
+++ src/diff.c
@@ -2294,11 +2294,11 @@
2294 }
2295 if( iLimit>20 ){
2296 style_submenu_element("20 Ancestors", "20 Ancestors",
2297 "%s", url_render(&url, "limit", "20", 0, 0));
2298 }
2299 if( db_get_boolean("white-foreground", 0) ){
2300 clr1 = 0xa04040;
2301 clr2 = 0x4059a0;
2302 }else{
2303 clr1 = 0xffb5b5; /* Recent changes: red (hot) */
2304 clr2 = 0xb5e0ff; /* Older changes: blue (cold) */
2305
--- src/diff.c
+++ src/diff.c
@@ -2294,11 +2294,11 @@
2294 }
2295 if( iLimit>20 ){
2296 style_submenu_element("20 Ancestors", "20 Ancestors",
2297 "%s", url_render(&url, "limit", "20", 0, 0));
2298 }
2299 if( skin_white_foreground() ){
2300 clr1 = 0xa04040;
2301 clr2 = 0x4059a0;
2302 }else{
2303 clr1 = 0xffb5b5; /* Recent changes: red (hot) */
2304 clr2 = 0xb5e0ff; /* Older changes: blue (cold) */
2305
+12
--- src/main.c
+++ src/main.c
@@ -1920,10 +1920,22 @@
19201920
** setenv: instead.
19211921
*/
19221922
cgi_setenv("HOME", blob_str(&value));
19231923
blob_reset(&value);
19241924
continue;
1925
+ }
1926
+ if( blob_eq(&key, "skin:") && blob_token(&line, &value) ){
1927
+ /* skin: LABEL
1928
+ **
1929
+ ** Use one of the built-in skins defined by LABEL. LABEL is the
1930
+ ** name of the subdirectory under the skins/ directory that holds
1931
+ ** the elements of the built-in skin. If LABEL does not match,
1932
+ ** this directive is a silent no-op.
1933
+ */
1934
+ skin_use_alternative(blob_str(&value));
1935
+ blob_reset(&value);
1936
+ continue;
19251937
}
19261938
}
19271939
blob_reset(&config);
19281940
if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
19291941
cgi_panic("Unable to find or open the project repository");
19301942
--- src/main.c
+++ src/main.c
@@ -1920,10 +1920,22 @@
1920 ** setenv: instead.
1921 */
1922 cgi_setenv("HOME", blob_str(&value));
1923 blob_reset(&value);
1924 continue;
 
 
 
 
 
 
 
 
 
 
 
 
1925 }
1926 }
1927 blob_reset(&config);
1928 if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
1929 cgi_panic("Unable to find or open the project repository");
1930
--- src/main.c
+++ src/main.c
@@ -1920,10 +1920,22 @@
1920 ** setenv: instead.
1921 */
1922 cgi_setenv("HOME", blob_str(&value));
1923 blob_reset(&value);
1924 continue;
1925 }
1926 if( blob_eq(&key, "skin:") && blob_token(&line, &value) ){
1927 /* skin: LABEL
1928 **
1929 ** Use one of the built-in skins defined by LABEL. LABEL is the
1930 ** name of the subdirectory under the skins/ directory that holds
1931 ** the elements of the built-in skin. If LABEL does not match,
1932 ** this directive is a silent no-op.
1933 */
1934 skin_use_alternative(blob_str(&value));
1935 blob_reset(&value);
1936 continue;
1937 }
1938 }
1939 blob_reset(&config);
1940 if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){
1941 cgi_panic("Unable to find or open the project repository");
1942
+86 -8
--- src/skins.c
+++ src/skins.c
@@ -37,21 +37,88 @@
3737
** 4. Make an entry in the following array for the new skin.
3838
*/
3939
static struct BuiltinSkin {
4040
const char *zDesc; /* Description of this skin */
4141
const char *zLabel; /* The directory under skins/ holding this skin */
42
+ int whiteForeground; /* True if this skin uses a light-colored foreground */
4243
char *zSQL; /* Filled in at run-time with SQL to insert this skin */
4344
} aBuiltinSkin[] = {
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 },
45
+ { "Default", "default", 0, 0 },
46
+ { "Plain Gray, No Logo", "plain_gray", 0, 0 },
47
+ { "Khaki, No Logo", "khaki", 0, 0 },
48
+ { "Black & White, Menu on Left", "black_and_white", 0, 0 },
49
+ { "Shadow boxes & Rounded Corners", "rounded1", 0, 0 },
50
+ { "Enhanced Default", "enhanced1", 0, 0 },
51
+ { "San Francisco Modern", "etienne1", 0, 0 },
52
+ { "Eagle", "eagle", 1, 0 },
5253
};
54
+
55
+/*
56
+** Alternative skins can be specified in the CGI script or by options
57
+** on the "http", "ui", and "server" commands. The alternative skin
58
+** name must be one of the aBuiltinSkin[].zLabel names. If there is
59
+** a match, that alternative is used.
60
+**
61
+** The following static variable holds the name of the alternative skin,
62
+** or NULL if the skin should be as configured.
63
+*/
64
+static struct BuiltinSkin *pAltSkin = 0;
65
+
66
+/*
67
+** Invoke this routine to set the alternative skin. Return NULL if the
68
+** alternative was successfully installed. Return a string listing all
69
+** available skins if zName does not match an available skin. Memory
70
+** for the returned string comes from fossil_malloc() and should be freed
71
+** by the caller.
72
+*/
73
+char *skin_use_alternative(const char *zName){
74
+ int i;
75
+ Blob err;
76
+ for(i=0; i<ArraySize(aBuiltinSkin); i++){
77
+ if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
78
+ pAltSkin = &aBuiltinSkin[i];
79
+ return 0;
80
+ }
81
+ }
82
+ blob_init(&err, aBuiltinSkin[0].zLabel, -1);
83
+ for(i=1; i<ArraySize(aBuiltinSkin); i++){
84
+ blob_append(&err, " ", 1);
85
+ blob_append(&err, aBuiltinSkin[i].zLabel, -1);
86
+ }
87
+ return blob_str(&err);
88
+}
89
+
90
+/*
91
+** The following routines return the various components of the skin
92
+** that should be used for the current run.
93
+*/
94
+const char *skin_get(const char *zWhat){
95
+ const char *zOut;
96
+ char *z;
97
+ if( pAltSkin ){
98
+ z = mprintf("skins/%s/%s.txt", pAltSkin->zLabel, zWhat);
99
+ zOut = builtin_text(z);
100
+ fossil_free(z);
101
+ }else{
102
+ zOut = db_get(zWhat, 0);
103
+ if( zOut==0 ){
104
+ z = mprintf("skins/default/%s.txt", zWhat);
105
+ zOut = builtin_text(z);
106
+ fossil_free(z);
107
+ }
108
+ }
109
+ return zOut;
110
+}
111
+int skin_white_foreground(void){
112
+ int rc;
113
+ if( pAltSkin ){
114
+ rc = pAltSkin->whiteForeground;
115
+ }else{
116
+ rc = db_get_boolean("white-foreground",0);
117
+ }
118
+ return rc;
119
+}
53120
54121
/*
55122
** For a skin named zSkinName, compute the name of the CONFIG table
56123
** entry where that skin is stored and return it.
57124
**
@@ -288,10 +355,18 @@
288355
@ <a href="setup_editcss">CSS</a>,
289356
@ <a href="setup_header">Header</a>, and
290357
@ <a href="setup_footer">Footer</a> that determines the look and feel
291358
@ of the web interface.</p>
292359
@
360
+ if( pAltSkin ){
361
+ @ <p class="generalError">
362
+ @ This page is generated using an skin override named
363
+ @ "%h(pAltSkin->zLabel)". You can change the skin configuration
364
+ @ below, but the changes will not take effect until the Fossil server
365
+ @ is restarted without the override.</p>
366
+ @
367
+ }
293368
@ <h2>Available Skins:</h2>
294369
@ <table border="0">
295370
for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
296371
z = aBuiltinSkin[i].zDesc;
297372
@ <tr><td>%d(i+1).<td>%h(z)<td>&nbsp;&nbsp;<td>
@@ -300,10 +375,13 @@
300375
seenCurrent = 1;
301376
}else{
302377
@ <form action="%s(g.zTop)/setup_skin" method="post">
303378
@ <input type="hidden" name="sn" value="%h(z)" />
304379
@ <input type="submit" name="load" value="Install" />
380
+ if( pAltSkin==&aBuiltinSkin[i] ){
381
+ @ (Current override)
382
+ }
305383
@ </form>
306384
}
307385
@ </tr>
308386
}
309387
db_prepare(&q,
310388
--- src/skins.c
+++ src/skins.c
@@ -37,21 +37,88 @@
37 ** 4. Make an entry in the following array for the new skin.
38 */
39 static struct BuiltinSkin {
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 */
43 } aBuiltinSkin[] = {
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 },
52 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
54 /*
55 ** For a skin named zSkinName, compute the name of the CONFIG table
56 ** entry where that skin is stored and return it.
57 **
@@ -288,10 +355,18 @@
288 @ <a href="setup_editcss">CSS</a>,
289 @ <a href="setup_header">Header</a>, and
290 @ <a href="setup_footer">Footer</a> that determines the look and feel
291 @ of the web interface.</p>
292 @
 
 
 
 
 
 
 
 
293 @ <h2>Available Skins:</h2>
294 @ <table border="0">
295 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
296 z = aBuiltinSkin[i].zDesc;
297 @ <tr><td>%d(i+1).<td>%h(z)<td>&nbsp;&nbsp;<td>
@@ -300,10 +375,13 @@
300 seenCurrent = 1;
301 }else{
302 @ <form action="%s(g.zTop)/setup_skin" method="post">
303 @ <input type="hidden" name="sn" value="%h(z)" />
304 @ <input type="submit" name="load" value="Install" />
 
 
 
305 @ </form>
306 }
307 @ </tr>
308 }
309 db_prepare(&q,
310
--- src/skins.c
+++ src/skins.c
@@ -37,21 +37,88 @@
37 ** 4. Make an entry in the following array for the new skin.
38 */
39 static struct BuiltinSkin {
40 const char *zDesc; /* Description of this skin */
41 const char *zLabel; /* The directory under skins/ holding this skin */
42 int whiteForeground; /* True if this skin uses a light-colored foreground */
43 char *zSQL; /* Filled in at run-time with SQL to insert this skin */
44 } aBuiltinSkin[] = {
45 { "Default", "default", 0, 0 },
46 { "Plain Gray, No Logo", "plain_gray", 0, 0 },
47 { "Khaki, No Logo", "khaki", 0, 0 },
48 { "Black & White, Menu on Left", "black_and_white", 0, 0 },
49 { "Shadow boxes & Rounded Corners", "rounded1", 0, 0 },
50 { "Enhanced Default", "enhanced1", 0, 0 },
51 { "San Francisco Modern", "etienne1", 0, 0 },
52 { "Eagle", "eagle", 1, 0 },
53 };
54
55 /*
56 ** Alternative skins can be specified in the CGI script or by options
57 ** on the "http", "ui", and "server" commands. The alternative skin
58 ** name must be one of the aBuiltinSkin[].zLabel names. If there is
59 ** a match, that alternative is used.
60 **
61 ** The following static variable holds the name of the alternative skin,
62 ** or NULL if the skin should be as configured.
63 */
64 static struct BuiltinSkin *pAltSkin = 0;
65
66 /*
67 ** Invoke this routine to set the alternative skin. Return NULL if the
68 ** alternative was successfully installed. Return a string listing all
69 ** available skins if zName does not match an available skin. Memory
70 ** for the returned string comes from fossil_malloc() and should be freed
71 ** by the caller.
72 */
73 char *skin_use_alternative(const char *zName){
74 int i;
75 Blob err;
76 for(i=0; i<ArraySize(aBuiltinSkin); i++){
77 if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
78 pAltSkin = &aBuiltinSkin[i];
79 return 0;
80 }
81 }
82 blob_init(&err, aBuiltinSkin[0].zLabel, -1);
83 for(i=1; i<ArraySize(aBuiltinSkin); i++){
84 blob_append(&err, " ", 1);
85 blob_append(&err, aBuiltinSkin[i].zLabel, -1);
86 }
87 return blob_str(&err);
88 }
89
90 /*
91 ** The following routines return the various components of the skin
92 ** that should be used for the current run.
93 */
94 const char *skin_get(const char *zWhat){
95 const char *zOut;
96 char *z;
97 if( pAltSkin ){
98 z = mprintf("skins/%s/%s.txt", pAltSkin->zLabel, zWhat);
99 zOut = builtin_text(z);
100 fossil_free(z);
101 }else{
102 zOut = db_get(zWhat, 0);
103 if( zOut==0 ){
104 z = mprintf("skins/default/%s.txt", zWhat);
105 zOut = builtin_text(z);
106 fossil_free(z);
107 }
108 }
109 return zOut;
110 }
111 int skin_white_foreground(void){
112 int rc;
113 if( pAltSkin ){
114 rc = pAltSkin->whiteForeground;
115 }else{
116 rc = db_get_boolean("white-foreground",0);
117 }
118 return rc;
119 }
120
121 /*
122 ** For a skin named zSkinName, compute the name of the CONFIG table
123 ** entry where that skin is stored and return it.
124 **
@@ -288,10 +355,18 @@
355 @ <a href="setup_editcss">CSS</a>,
356 @ <a href="setup_header">Header</a>, and
357 @ <a href="setup_footer">Footer</a> that determines the look and feel
358 @ of the web interface.</p>
359 @
360 if( pAltSkin ){
361 @ <p class="generalError">
362 @ This page is generated using an skin override named
363 @ "%h(pAltSkin->zLabel)". You can change the skin configuration
364 @ below, but the changes will not take effect until the Fossil server
365 @ is restarted without the override.</p>
366 @
367 }
368 @ <h2>Available Skins:</h2>
369 @ <table border="0">
370 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
371 z = aBuiltinSkin[i].zDesc;
372 @ <tr><td>%d(i+1).<td>%h(z)<td>&nbsp;&nbsp;<td>
@@ -300,10 +375,13 @@
375 seenCurrent = 1;
376 }else{
377 @ <form action="%s(g.zTop)/setup_skin" method="post">
378 @ <input type="hidden" name="sn" value="%h(z)" />
379 @ <input type="submit" name="load" value="Install" />
380 if( pAltSkin==&aBuiltinSkin[i] ){
381 @ (Current override)
382 }
383 @ </form>
384 }
385 @ </tr>
386 }
387 db_prepare(&q,
388
+3 -5
--- src/style.c
+++ src/style.c
@@ -353,12 +353,11 @@
353353
** Draw the header.
354354
*/
355355
void style_header(const char *zTitleFormat, ...){
356356
va_list ap;
357357
char *zTitle;
358
- const char *zHeader = db_get("header", 0);
359
- if( zHeader==0 ) zHeader = builtin_text("skins/default/header.txt");
358
+ const char *zHeader = skin_get("header");
360359
login_check_credentials();
361360
362361
va_start(ap, zTitleFormat);
363362
zTitle = vmprintf(zTitleFormat, ap);
364363
va_end(ap);
@@ -592,12 +591,11 @@
592591
593592
/* Set the href= field on hyperlinks. Do this before the footer since
594593
** the footer will be generating </html> */
595594
style_resolve_href();
596595
597
- zFooter = db_get("footer", 0);
598
- if( zFooter==0 ) zFooter = builtin_text("skins/default/footer.txt");
596
+ zFooter = skin_get("footer");
599597
if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
600598
Th_Render(zFooter);
601599
if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
602600
603601
/* Render trace log if TH1 tracing is enabled. */
@@ -1367,11 +1365,11 @@
13671365
void page_style_css(void){
13681366
Blob css;
13691367
int i;
13701368
13711369
cgi_set_content_type("text/css");
1372
- blob_init(&css,db_get("css",(char*)builtin_text("skins/default/css.txt")),-1);
1370
+ blob_init(&css,skin_get("css"),-1);
13731371
13741372
/* add special missing definitions */
13751373
for(i=1; cssDefaultList[i].elementClass; i++){
13761374
char *z = blob_str(&css);
13771375
if( !containsString(z, cssDefaultList[i].elementClass) ){
13781376
--- src/style.c
+++ src/style.c
@@ -353,12 +353,11 @@
353 ** Draw the header.
354 */
355 void style_header(const char *zTitleFormat, ...){
356 va_list ap;
357 char *zTitle;
358 const char *zHeader = db_get("header", 0);
359 if( zHeader==0 ) zHeader = builtin_text("skins/default/header.txt");
360 login_check_credentials();
361
362 va_start(ap, zTitleFormat);
363 zTitle = vmprintf(zTitleFormat, ap);
364 va_end(ap);
@@ -592,12 +591,11 @@
592
593 /* Set the href= field on hyperlinks. Do this before the footer since
594 ** the footer will be generating </html> */
595 style_resolve_href();
596
597 zFooter = db_get("footer", 0);
598 if( zFooter==0 ) zFooter = builtin_text("skins/default/footer.txt");
599 if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
600 Th_Render(zFooter);
601 if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
602
603 /* Render trace log if TH1 tracing is enabled. */
@@ -1367,11 +1365,11 @@
1367 void page_style_css(void){
1368 Blob css;
1369 int i;
1370
1371 cgi_set_content_type("text/css");
1372 blob_init(&css,db_get("css",(char*)builtin_text("skins/default/css.txt")),-1);
1373
1374 /* add special missing definitions */
1375 for(i=1; cssDefaultList[i].elementClass; i++){
1376 char *z = blob_str(&css);
1377 if( !containsString(z, cssDefaultList[i].elementClass) ){
1378
--- src/style.c
+++ src/style.c
@@ -353,12 +353,11 @@
353 ** Draw the header.
354 */
355 void style_header(const char *zTitleFormat, ...){
356 va_list ap;
357 char *zTitle;
358 const char *zHeader = skin_get("header");
 
359 login_check_credentials();
360
361 va_start(ap, zTitleFormat);
362 zTitle = vmprintf(zTitleFormat, ap);
363 va_end(ap);
@@ -592,12 +591,11 @@
591
592 /* Set the href= field on hyperlinks. Do this before the footer since
593 ** the footer will be generating </html> */
594 style_resolve_href();
595
596 zFooter = skin_get("footer");
 
597 if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
598 Th_Render(zFooter);
599 if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
600
601 /* Render trace log if TH1 tracing is enabled. */
@@ -1367,11 +1365,11 @@
1365 void page_style_css(void){
1366 Blob css;
1367 int i;
1368
1369 cgi_set_content_type("text/css");
1370 blob_init(&css,skin_get("css"),-1);
1371
1372 /* add special missing definitions */
1373 for(i=1; cssDefaultList[i].elementClass; i++){
1374 char *z = blob_str(&css);
1375 if( !containsString(z, cssDefaultList[i].elementClass) ){
1376

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button