Fossil SCM

Merged in trunk for builtin_request_js() changes and ported wikiedit/fileedit/forumpost to use those.

stephan 2020-07-31 23:33 ajax-wiki-editor merge
Commit 2ec332a0c2208e8a657fca5c76f8b927da7131dbb1c3cf6d23fcbd412ab6d592
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -497,11 +497,11 @@
497497
border: 0;
498498
border-radius: 5px;
499499
box-shadow: none;
500500
box-sizing: border-box
501501
}
502
-textarea {
502
+textarea, select {
503503
height: initial;
504504
}
505505
input[type=email]:hover,
506506
input[type=number]:hover,
507507
input[type=password]:hover,
508508
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -497,11 +497,11 @@
497 border: 0;
498 border-radius: 5px;
499 box-shadow: none;
500 box-sizing: border-box
501 }
502 textarea {
503 height: initial;
504 }
505 input[type=email]:hover,
506 input[type=number]:hover,
507 input[type=password]:hover,
508
--- skins/ardoise/css.txt
+++ skins/ardoise/css.txt
@@ -497,11 +497,11 @@
497 border: 0;
498 border-radius: 5px;
499 box-shadow: none;
500 box-sizing: border-box
501 }
502 textarea, select {
503 height: initial;
504 }
505 input[type=email]:hover,
506 input[type=number]:hover,
507 input[type=password]:hover,
508
+1 -1
--- src/browse.c
+++ src/browse.c
@@ -911,11 +911,11 @@
911911
}
912912
}
913913
}
914914
@ </ul>
915915
@ </ul></div>
916
- style_load_one_js_file("tree.js");
916
+ builtin_request_js("tree.js");
917917
style_footer();
918918
919919
/* We could free memory used by sTree here if we needed to. But
920920
** the process is about to exit, so doing so would not really accomplish
921921
** anything useful. */
922922
--- src/browse.c
+++ src/browse.c
@@ -911,11 +911,11 @@
911 }
912 }
913 }
914 @ </ul>
915 @ </ul></div>
916 style_load_one_js_file("tree.js");
917 style_footer();
918
919 /* We could free memory used by sTree here if we needed to. But
920 ** the process is about to exit, so doing so would not really accomplish
921 ** anything useful. */
922
--- src/browse.c
+++ src/browse.c
@@ -911,11 +911,11 @@
911 }
912 }
913 }
914 @ </ul>
915 @ </ul></div>
916 builtin_request_js("tree.js");
917 style_footer();
918
919 /* We could free memory used by sTree here if we needed to. But
920 ** the process is about to exit, so doing so would not really accomplish
921 ** anything useful. */
922
+236 -10
--- src/builtin.c
+++ src/builtin.c
@@ -28,13 +28,15 @@
2828
** builtin_data.h file. Include that information here:
2929
*/
3030
#include "builtin_data.h"
3131
3232
/*
33
-** Return a pointer to built-in content
33
+** Return the index in the aBuiltinFiles[] array for the file
34
+** whose name is zFilename. Or return -1 if the file is not
35
+** found.
3436
*/
35
-const unsigned char *builtin_file(const char *zFilename, int *piSize){
37
+static int builtin_file_index(const char *zFilename){
3638
int lwr, upr, i, c;
3739
lwr = 0;
3840
upr = count(aBuiltinFiles) - 1;
3941
while( upr>=lwr ){
4042
i = (upr+lwr)/2;
@@ -42,16 +44,28 @@
4244
if( c<0 ){
4345
lwr = i+1;
4446
}else if( c>0 ){
4547
upr = i-1;
4648
}else{
47
- if( piSize ) *piSize = aBuiltinFiles[i].nByte;
48
- return aBuiltinFiles[i].pData;
49
+ return i;
4950
}
5051
}
51
- if( piSize ) *piSize = 0;
52
- return 0;
52
+ return -1;
53
+}
54
+
55
+/*
56
+** Return a pointer to built-in content
57
+*/
58
+const unsigned char *builtin_file(const char *zFilename, int *piSize){
59
+ int i = builtin_file_index(zFilename);
60
+ if( i>=0 ){
61
+ if( piSize ) *piSize = aBuiltinFiles[i].nByte;
62
+ return aBuiltinFiles[i].pData;
63
+ }else{
64
+ if( piSize ) *piSize = 0;
65
+ return 0;
66
+ }
5367
}
5468
const char *builtin_text(const char *zFilename){
5569
return (char*)builtin_file(zFilename, 0);
5670
}
5771
@@ -65,11 +79,11 @@
6579
*/
6680
void test_builtin_list(void){
6781
int i, size = 0;;
6882
for(i=0; i<count(aBuiltinFiles); i++){
6983
const int n = aBuiltinFiles[i].nByte;
70
- fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,n);
84
+ fossil_print("%3d. %-45s %6d\n", i+1, aBuiltinFiles[i].zName,n);
7185
size += n;
7286
}
7387
if(find_option("verbose","v",0)!=0){
7488
fossil_print("%d entries totaling %d bytes\n", i, size);
7589
}
@@ -81,16 +95,18 @@
8195
** Show all built-in text files.
8296
*/
8397
void test_builtin_list_page(void){
8498
int i;
8599
style_header("Built-in Text Files");
86
- @ <ul>
100
+ @ <ol>
87101
for(i=0; i<count(aBuiltinFiles); i++){
88102
const char *z = aBuiltinFiles[i].zName;
89
- @ <li>%z(href("%R/builtin?name=%T&id=%S",z,MANIFEST_UUID))%h(z)</a>
103
+ char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain",
104
+ z,fossil_exe_id());
105
+ @ <li>%z(zUrl)%h(z)</a>
90106
}
91
- @ </ul>
107
+ @ </ol>
92108
style_footer();
93109
}
94110
95111
/*
96112
** COMMAND: test-builtin-get
@@ -110,5 +126,215 @@
110126
}
111127
blob_init(&x, (const char*)pData, nByte);
112128
blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-");
113129
blob_reset(&x);
114130
}
131
+
132
+/*
133
+** Input zList is a list of numeric identifiers for files in
134
+** aBuiltinFiles[]. Return the concatenation of all of those
135
+** files using mimetype zType, or as application/javascript if
136
+** zType is 0.
137
+*/
138
+static void builtin_deliver_multiple_js_files(
139
+ const char *zList, /* List of numeric identifiers */
140
+ const char *zType /* Override mimetype */
141
+){
142
+ Blob *pOut;
143
+ if( zType==0 ) zType = "application/javascript";
144
+ cgi_set_content_type(zType);
145
+ pOut = cgi_output_blob();
146
+ while( zList[0] ){
147
+ int i = atoi(zList);
148
+ if( i>0 && i<=count(aBuiltinFiles) ){
149
+ blob_append(pOut, (const char*)aBuiltinFiles[i-1].pData,
150
+ aBuiltinFiles[i-1].nByte);
151
+ }
152
+ while( fossil_isdigit(zList[0]) ) zList++;
153
+ if( zList[0]==',' ) zList++;
154
+ }
155
+ return;
156
+}
157
+
158
+/*
159
+** WEBPAGE: builtin
160
+**
161
+** Return one of many built-in content files. Query parameters:
162
+**
163
+** name=FILENAME Return the single file whose name is FILENAME.
164
+** mimetype=TYPE Override the mimetype in the returned file to
165
+** be TYPE. If this query parameter is omitted
166
+** (the usual case) then the mimetype is inferred
167
+** from the suffix on FILENAME
168
+** m=IDLIST IDLIST is a comma-separated list of integers
169
+** that specify multiple javascript files to be
170
+** concatenated and returned all at once.
171
+** id=UNIQUEID Version number of the "builtin" files. Used
172
+** for cache control only.
173
+**
174
+** At least one of the name= or m= query parameters must be present.
175
+**
176
+** If the id= query parameter is present, then Fossil assumes that the
177
+** result is immutable and sets a very large cache retention time (1 year).
178
+*/
179
+void builtin_webpage(void){
180
+ Blob out;
181
+ const char *zName = P("name");
182
+ const char *zTxt = 0;
183
+ const char *zId = P("id");
184
+ const char *zType = P("mimetype");
185
+ int nId;
186
+ if( zName ) zTxt = builtin_text(zName);
187
+ if( zTxt==0 ){
188
+ const char *zM = P("m");
189
+ if( zM ){
190
+ builtin_deliver_multiple_js_files(zM, zType);
191
+ return;
192
+ }
193
+ cgi_set_status(404, "Not Found");
194
+ @ File "%h(zName)" not found
195
+ return;
196
+ }
197
+ if( zType==0 ){
198
+ if( sqlite3_strglob("*.js", zName)==0 ){
199
+ zType = "application/javascript";
200
+ }else{
201
+ zType = mimetype_from_name(zName);
202
+ }
203
+ }
204
+ cgi_set_content_type(zType);
205
+ if( zId
206
+ && (nId = (int)strlen(zId))>=8
207
+ && strncmp(zId,fossil_exe_id(),nId)==0
208
+ ){
209
+ g.isConst = 1;
210
+ }else{
211
+ etag_check(0,0);
212
+ }
213
+ blob_init(&out, zTxt, -1);
214
+ cgi_set_content(&out);
215
+}
216
+
217
+/* Variables controlling the JS cache.
218
+*/
219
+static struct {
220
+ int aReq[30]; /* Indexes of all requested built-in JS files */
221
+ int nReq; /* Number of slots in aReq[] currently used */
222
+ int nSent; /* Number of slots in aReq[] fulfilled */
223
+ int eDelivery; /* Delivery mechanism */
224
+} builtin;
225
+
226
+#if INTERFACE
227
+/* Various delivery mechanisms. The 0 option is the default.
228
+*/
229
+#define JS_INLINE 0 /* inline, batched together at end of file */
230
+#define JS_SEPARATE 1 /* Separate HTTP request for each JS file */
231
+#define JS_BUNDLED 2 /* One HTTP request to load all JS files */
232
+ /* concatenated together into a bundle */
233
+#endif /* INTERFACE */
234
+
235
+/*
236
+** The argument is a request to change the javascript delivery mode.
237
+** The argument is a string which is a command-line option or CGI
238
+** parameter. Try to match it against one of the delivery options
239
+** and set things up accordingly. Throw an error if no match unless
240
+** bSilent is true.
241
+*/
242
+void builtin_set_js_delivery_mode(const char *zMode, int bSilent){
243
+ if( zMode==0 ) return;
244
+ if( strcmp(zMode, "inline")==0 ){
245
+ builtin.eDelivery = JS_INLINE;
246
+ }else
247
+ if( strcmp(zMode, "separate")==0 ){
248
+ builtin.eDelivery = JS_SEPARATE;
249
+ }else
250
+ if( strcmp(zMode, "bundled")==0 ){
251
+ builtin.eDelivery = JS_BUNDLED;
252
+ }else if( !bSilent ){
253
+ fossil_fatal("unknown javascript delivery mode \"%s\" - should be"
254
+ " one of: inline separate bundled", zMode);
255
+ }
256
+}
257
+
258
+/*
259
+** The caller wants the Javascript file named by zFilename to be
260
+** included in the generated page. Add the file to the queue of
261
+** requested javascript resources, if it is not there already.
262
+**
263
+** The current implementation queues the file to be included in the
264
+** output later. However, the caller should not depend on that
265
+** behavior. In the future, this routine might decide to insert
266
+** the requested javascript inline, immedaitely, or to insert
267
+** a <script src=..> element to reference the javascript as a
268
+** separate resource. The exact behavior might change in the future
269
+** so pages that use this interface must not rely on any particular
270
+** behavior.
271
+**
272
+** All this routine guarantees is that the named javascript file
273
+** will be requested by the browser at some point. This routine
274
+** does not guarantee when the javascript will be included, and it
275
+** does not guarantee whether the javascript will be added inline or
276
+** delivered as a separate resource.
277
+*/
278
+void builtin_request_js(const char *zFilename){
279
+ int i = builtin_file_index(zFilename);
280
+ int j;
281
+ if( i<0 ){
282
+ fossil_panic("unknown javascript file: \"%s\"", zFilename);
283
+ }
284
+ for(j=0; j<builtin.nReq; j++){
285
+ if( builtin.aReq[j]==i ) return; /* Already queued or sent */
286
+ }
287
+ if( builtin.nReq>=count(builtin.aReq) ){
288
+ fossil_panic("too many javascript files requested");
289
+ }
290
+ builtin.aReq[builtin.nReq++] = i;
291
+}
292
+
293
+/*
294
+** Fulfill all pending requests for javascript files.
295
+**
296
+** The current implementation delivers all javascript in-line. However,
297
+** the caller should not depend on this. Future changes to this routine
298
+** might choose to deliver javascript as separate resources.
299
+*/
300
+void builtin_fulfill_js_requests(void){
301
+ if( builtin.nSent>=builtin.nReq ) return; /* nothing to do */
302
+ switch( builtin.eDelivery ){
303
+ case JS_INLINE: {
304
+ CX("<script nonce='%h'>\n",style_nonce());
305
+ do{
306
+ int i = builtin.aReq[builtin.nSent++];
307
+ CX("/* %s */\n", aBuiltinFiles[i].zName);
308
+ cgi_append_content((const char*)aBuiltinFiles[i].pData,
309
+ aBuiltinFiles[i].nByte);
310
+ }while( builtin.nSent<builtin.nReq );
311
+ CX("</script>\n");
312
+ break;
313
+ }
314
+ case JS_BUNDLED: {
315
+ if( builtin.nSent+1<builtin.nReq ){
316
+ Blob aList;
317
+ blob_init(&aList,0,0);
318
+ while( builtin.nSent<builtin.nReq ){
319
+ blob_appendf(&aList, ",%d", builtin.aReq[builtin.nSent++]+1);
320
+ }
321
+ CX("<script src='%R/builtin?m=%s&id=%.8s'></script>\n",
322
+ blob_str(&aList)+1, fossil_exe_id());
323
+ blob_reset(&aList);
324
+ break;
325
+ }
326
+ /* If there is only one JS file, fall through into the
327
+ ** JS_SEPARATE case below. */
328
+ /*FALLTHROUGH*/
329
+ }
330
+ case JS_SEPARATE: {
331
+ /* Each JS file as a separate resource */
332
+ while( builtin.nSent<builtin.nReq ){
333
+ int i = builtin.aReq[builtin.nSent++];
334
+ CX("<script src='%R/builtin?name=%t&id=%.8s'></script>\n",
335
+ aBuiltinFiles[i].zName, fossil_exe_id());
336
+ }
337
+ break;
338
+ }
339
+ }
340
+}
115341
--- src/builtin.c
+++ src/builtin.c
@@ -28,13 +28,15 @@
28 ** builtin_data.h file. Include that information here:
29 */
30 #include "builtin_data.h"
31
32 /*
33 ** Return a pointer to built-in content
 
 
34 */
35 const unsigned char *builtin_file(const char *zFilename, int *piSize){
36 int lwr, upr, i, c;
37 lwr = 0;
38 upr = count(aBuiltinFiles) - 1;
39 while( upr>=lwr ){
40 i = (upr+lwr)/2;
@@ -42,16 +44,28 @@
42 if( c<0 ){
43 lwr = i+1;
44 }else if( c>0 ){
45 upr = i-1;
46 }else{
47 if( piSize ) *piSize = aBuiltinFiles[i].nByte;
48 return aBuiltinFiles[i].pData;
49 }
50 }
51 if( piSize ) *piSize = 0;
52 return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
53 }
54 const char *builtin_text(const char *zFilename){
55 return (char*)builtin_file(zFilename, 0);
56 }
57
@@ -65,11 +79,11 @@
65 */
66 void test_builtin_list(void){
67 int i, size = 0;;
68 for(i=0; i<count(aBuiltinFiles); i++){
69 const int n = aBuiltinFiles[i].nByte;
70 fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,n);
71 size += n;
72 }
73 if(find_option("verbose","v",0)!=0){
74 fossil_print("%d entries totaling %d bytes\n", i, size);
75 }
@@ -81,16 +95,18 @@
81 ** Show all built-in text files.
82 */
83 void test_builtin_list_page(void){
84 int i;
85 style_header("Built-in Text Files");
86 @ <ul>
87 for(i=0; i<count(aBuiltinFiles); i++){
88 const char *z = aBuiltinFiles[i].zName;
89 @ <li>%z(href("%R/builtin?name=%T&id=%S",z,MANIFEST_UUID))%h(z)</a>
 
 
90 }
91 @ </ul>
92 style_footer();
93 }
94
95 /*
96 ** COMMAND: test-builtin-get
@@ -110,5 +126,215 @@
110 }
111 blob_init(&x, (const char*)pData, nByte);
112 blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-");
113 blob_reset(&x);
114 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
--- src/builtin.c
+++ src/builtin.c
@@ -28,13 +28,15 @@
28 ** builtin_data.h file. Include that information here:
29 */
30 #include "builtin_data.h"
31
32 /*
33 ** Return the index in the aBuiltinFiles[] array for the file
34 ** whose name is zFilename. Or return -1 if the file is not
35 ** found.
36 */
37 static int builtin_file_index(const char *zFilename){
38 int lwr, upr, i, c;
39 lwr = 0;
40 upr = count(aBuiltinFiles) - 1;
41 while( upr>=lwr ){
42 i = (upr+lwr)/2;
@@ -42,16 +44,28 @@
44 if( c<0 ){
45 lwr = i+1;
46 }else if( c>0 ){
47 upr = i-1;
48 }else{
49 return i;
 
50 }
51 }
52 return -1;
53 }
54
55 /*
56 ** Return a pointer to built-in content
57 */
58 const unsigned char *builtin_file(const char *zFilename, int *piSize){
59 int i = builtin_file_index(zFilename);
60 if( i>=0 ){
61 if( piSize ) *piSize = aBuiltinFiles[i].nByte;
62 return aBuiltinFiles[i].pData;
63 }else{
64 if( piSize ) *piSize = 0;
65 return 0;
66 }
67 }
68 const char *builtin_text(const char *zFilename){
69 return (char*)builtin_file(zFilename, 0);
70 }
71
@@ -65,11 +79,11 @@
79 */
80 void test_builtin_list(void){
81 int i, size = 0;;
82 for(i=0; i<count(aBuiltinFiles); i++){
83 const int n = aBuiltinFiles[i].nByte;
84 fossil_print("%3d. %-45s %6d\n", i+1, aBuiltinFiles[i].zName,n);
85 size += n;
86 }
87 if(find_option("verbose","v",0)!=0){
88 fossil_print("%d entries totaling %d bytes\n", i, size);
89 }
@@ -81,16 +95,18 @@
95 ** Show all built-in text files.
96 */
97 void test_builtin_list_page(void){
98 int i;
99 style_header("Built-in Text Files");
100 @ <ol>
101 for(i=0; i<count(aBuiltinFiles); i++){
102 const char *z = aBuiltinFiles[i].zName;
103 char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain",
104 z,fossil_exe_id());
105 @ <li>%z(zUrl)%h(z)</a>
106 }
107 @ </ol>
108 style_footer();
109 }
110
111 /*
112 ** COMMAND: test-builtin-get
@@ -110,5 +126,215 @@
126 }
127 blob_init(&x, (const char*)pData, nByte);
128 blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-");
129 blob_reset(&x);
130 }
131
132 /*
133 ** Input zList is a list of numeric identifiers for files in
134 ** aBuiltinFiles[]. Return the concatenation of all of those
135 ** files using mimetype zType, or as application/javascript if
136 ** zType is 0.
137 */
138 static void builtin_deliver_multiple_js_files(
139 const char *zList, /* List of numeric identifiers */
140 const char *zType /* Override mimetype */
141 ){
142 Blob *pOut;
143 if( zType==0 ) zType = "application/javascript";
144 cgi_set_content_type(zType);
145 pOut = cgi_output_blob();
146 while( zList[0] ){
147 int i = atoi(zList);
148 if( i>0 && i<=count(aBuiltinFiles) ){
149 blob_append(pOut, (const char*)aBuiltinFiles[i-1].pData,
150 aBuiltinFiles[i-1].nByte);
151 }
152 while( fossil_isdigit(zList[0]) ) zList++;
153 if( zList[0]==',' ) zList++;
154 }
155 return;
156 }
157
158 /*
159 ** WEBPAGE: builtin
160 **
161 ** Return one of many built-in content files. Query parameters:
162 **
163 ** name=FILENAME Return the single file whose name is FILENAME.
164 ** mimetype=TYPE Override the mimetype in the returned file to
165 ** be TYPE. If this query parameter is omitted
166 ** (the usual case) then the mimetype is inferred
167 ** from the suffix on FILENAME
168 ** m=IDLIST IDLIST is a comma-separated list of integers
169 ** that specify multiple javascript files to be
170 ** concatenated and returned all at once.
171 ** id=UNIQUEID Version number of the "builtin" files. Used
172 ** for cache control only.
173 **
174 ** At least one of the name= or m= query parameters must be present.
175 **
176 ** If the id= query parameter is present, then Fossil assumes that the
177 ** result is immutable and sets a very large cache retention time (1 year).
178 */
179 void builtin_webpage(void){
180 Blob out;
181 const char *zName = P("name");
182 const char *zTxt = 0;
183 const char *zId = P("id");
184 const char *zType = P("mimetype");
185 int nId;
186 if( zName ) zTxt = builtin_text(zName);
187 if( zTxt==0 ){
188 const char *zM = P("m");
189 if( zM ){
190 builtin_deliver_multiple_js_files(zM, zType);
191 return;
192 }
193 cgi_set_status(404, "Not Found");
194 @ File "%h(zName)" not found
195 return;
196 }
197 if( zType==0 ){
198 if( sqlite3_strglob("*.js", zName)==0 ){
199 zType = "application/javascript";
200 }else{
201 zType = mimetype_from_name(zName);
202 }
203 }
204 cgi_set_content_type(zType);
205 if( zId
206 && (nId = (int)strlen(zId))>=8
207 && strncmp(zId,fossil_exe_id(),nId)==0
208 ){
209 g.isConst = 1;
210 }else{
211 etag_check(0,0);
212 }
213 blob_init(&out, zTxt, -1);
214 cgi_set_content(&out);
215 }
216
217 /* Variables controlling the JS cache.
218 */
219 static struct {
220 int aReq[30]; /* Indexes of all requested built-in JS files */
221 int nReq; /* Number of slots in aReq[] currently used */
222 int nSent; /* Number of slots in aReq[] fulfilled */
223 int eDelivery; /* Delivery mechanism */
224 } builtin;
225
226 #if INTERFACE
227 /* Various delivery mechanisms. The 0 option is the default.
228 */
229 #define JS_INLINE 0 /* inline, batched together at end of file */
230 #define JS_SEPARATE 1 /* Separate HTTP request for each JS file */
231 #define JS_BUNDLED 2 /* One HTTP request to load all JS files */
232 /* concatenated together into a bundle */
233 #endif /* INTERFACE */
234
235 /*
236 ** The argument is a request to change the javascript delivery mode.
237 ** The argument is a string which is a command-line option or CGI
238 ** parameter. Try to match it against one of the delivery options
239 ** and set things up accordingly. Throw an error if no match unless
240 ** bSilent is true.
241 */
242 void builtin_set_js_delivery_mode(const char *zMode, int bSilent){
243 if( zMode==0 ) return;
244 if( strcmp(zMode, "inline")==0 ){
245 builtin.eDelivery = JS_INLINE;
246 }else
247 if( strcmp(zMode, "separate")==0 ){
248 builtin.eDelivery = JS_SEPARATE;
249 }else
250 if( strcmp(zMode, "bundled")==0 ){
251 builtin.eDelivery = JS_BUNDLED;
252 }else if( !bSilent ){
253 fossil_fatal("unknown javascript delivery mode \"%s\" - should be"
254 " one of: inline separate bundled", zMode);
255 }
256 }
257
258 /*
259 ** The caller wants the Javascript file named by zFilename to be
260 ** included in the generated page. Add the file to the queue of
261 ** requested javascript resources, if it is not there already.
262 **
263 ** The current implementation queues the file to be included in the
264 ** output later. However, the caller should not depend on that
265 ** behavior. In the future, this routine might decide to insert
266 ** the requested javascript inline, immedaitely, or to insert
267 ** a <script src=..> element to reference the javascript as a
268 ** separate resource. The exact behavior might change in the future
269 ** so pages that use this interface must not rely on any particular
270 ** behavior.
271 **
272 ** All this routine guarantees is that the named javascript file
273 ** will be requested by the browser at some point. This routine
274 ** does not guarantee when the javascript will be included, and it
275 ** does not guarantee whether the javascript will be added inline or
276 ** delivered as a separate resource.
277 */
278 void builtin_request_js(const char *zFilename){
279 int i = builtin_file_index(zFilename);
280 int j;
281 if( i<0 ){
282 fossil_panic("unknown javascript file: \"%s\"", zFilename);
283 }
284 for(j=0; j<builtin.nReq; j++){
285 if( builtin.aReq[j]==i ) return; /* Already queued or sent */
286 }
287 if( builtin.nReq>=count(builtin.aReq) ){
288 fossil_panic("too many javascript files requested");
289 }
290 builtin.aReq[builtin.nReq++] = i;
291 }
292
293 /*
294 ** Fulfill all pending requests for javascript files.
295 **
296 ** The current implementation delivers all javascript in-line. However,
297 ** the caller should not depend on this. Future changes to this routine
298 ** might choose to deliver javascript as separate resources.
299 */
300 void builtin_fulfill_js_requests(void){
301 if( builtin.nSent>=builtin.nReq ) return; /* nothing to do */
302 switch( builtin.eDelivery ){
303 case JS_INLINE: {
304 CX("<script nonce='%h'>\n",style_nonce());
305 do{
306 int i = builtin.aReq[builtin.nSent++];
307 CX("/* %s */\n", aBuiltinFiles[i].zName);
308 cgi_append_content((const char*)aBuiltinFiles[i].pData,
309 aBuiltinFiles[i].nByte);
310 }while( builtin.nSent<builtin.nReq );
311 CX("</script>\n");
312 break;
313 }
314 case JS_BUNDLED: {
315 if( builtin.nSent+1<builtin.nReq ){
316 Blob aList;
317 blob_init(&aList,0,0);
318 while( builtin.nSent<builtin.nReq ){
319 blob_appendf(&aList, ",%d", builtin.aReq[builtin.nSent++]+1);
320 }
321 CX("<script src='%R/builtin?m=%s&id=%.8s'></script>\n",
322 blob_str(&aList)+1, fossil_exe_id());
323 blob_reset(&aList);
324 break;
325 }
326 /* If there is only one JS file, fall through into the
327 ** JS_SEPARATE case below. */
328 /*FALLTHROUGH*/
329 }
330 case JS_SEPARATE: {
331 /* Each JS file as a separate resource */
332 while( builtin.nSent<builtin.nReq ){
333 int i = builtin.aReq[builtin.nSent++];
334 CX("<script src='%R/builtin?name=%t&id=%.8s'></script>\n",
335 aBuiltinFiles[i].zName, fossil_exe_id());
336 }
337 break;
338 }
339 }
340 }
341
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -407,11 +407,10 @@
407407
{ "smtp_send_line", 2, FMT_SAFE },
408408
{ "smtp_server_send", 2, FMT_SAFE },
409409
{ "socket_set_errmsg", 1, FMT_SAFE },
410410
{ "ssl_set_errmsg", 1, FMT_SAFE },
411411
{ "style_header", 1, FMT_HTML },
412
- { "style_js_onload", 1, FMT_HTML },
413412
{ "style_set_current_page", 1, FMT_URL },
414413
{ "style_submenu_element", 2, FMT_URL },
415414
{ "style_submenu_sql", 3, FMT_SQL },
416415
{ "webpage_error", 1, FMT_SAFE },
417416
{ "xhref", 2, FMT_URL },
418417
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -407,11 +407,10 @@
407 { "smtp_send_line", 2, FMT_SAFE },
408 { "smtp_server_send", 2, FMT_SAFE },
409 { "socket_set_errmsg", 1, FMT_SAFE },
410 { "ssl_set_errmsg", 1, FMT_SAFE },
411 { "style_header", 1, FMT_HTML },
412 { "style_js_onload", 1, FMT_HTML },
413 { "style_set_current_page", 1, FMT_URL },
414 { "style_submenu_element", 2, FMT_URL },
415 { "style_submenu_sql", 3, FMT_SQL },
416 { "webpage_error", 1, FMT_SAFE },
417 { "xhref", 2, FMT_URL },
418
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -407,11 +407,10 @@
407 { "smtp_send_line", 2, FMT_SAFE },
408 { "smtp_server_send", 2, FMT_SAFE },
409 { "socket_set_errmsg", 1, FMT_SAFE },
410 { "ssl_set_errmsg", 1, FMT_SAFE },
411 { "style_header", 1, FMT_HTML },
 
412 { "style_set_current_page", 1, FMT_URL },
413 { "style_submenu_element", 2, FMT_URL },
414 { "style_submenu_sql", 3, FMT_SQL },
415 { "webpage_error", 1, FMT_SAFE },
416 { "xhref", 2, FMT_URL },
417
--- src/configure.c
+++ src/configure.c
@@ -94,10 +94,12 @@
9494
{ "js", CONFIGSET_SKIN },
9595
{ "logo-mimetype", CONFIGSET_SKIN },
9696
{ "logo-image", CONFIGSET_SKIN },
9797
{ "background-mimetype", CONFIGSET_SKIN },
9898
{ "background-image", CONFIGSET_SKIN },
99
+ { "icon-mimetype", CONFIGSET_SKIN },
100
+ { "icon-image", CONFIGSET_SKIN },
99101
{ "timeline-block-markup", CONFIGSET_SKIN },
100102
{ "timeline-date-format", CONFIGSET_SKIN },
101103
{ "timeline-default-style", CONFIGSET_SKIN },
102104
{ "timeline-dwelltime", CONFIGSET_SKIN },
103105
{ "timeline-closetime", CONFIGSET_SKIN },
104106
--- src/configure.c
+++ src/configure.c
@@ -94,10 +94,12 @@
94 { "js", CONFIGSET_SKIN },
95 { "logo-mimetype", CONFIGSET_SKIN },
96 { "logo-image", CONFIGSET_SKIN },
97 { "background-mimetype", CONFIGSET_SKIN },
98 { "background-image", CONFIGSET_SKIN },
 
 
99 { "timeline-block-markup", CONFIGSET_SKIN },
100 { "timeline-date-format", CONFIGSET_SKIN },
101 { "timeline-default-style", CONFIGSET_SKIN },
102 { "timeline-dwelltime", CONFIGSET_SKIN },
103 { "timeline-closetime", CONFIGSET_SKIN },
104
--- src/configure.c
+++ src/configure.c
@@ -94,10 +94,12 @@
94 { "js", CONFIGSET_SKIN },
95 { "logo-mimetype", CONFIGSET_SKIN },
96 { "logo-image", CONFIGSET_SKIN },
97 { "background-mimetype", CONFIGSET_SKIN },
98 { "background-image", CONFIGSET_SKIN },
99 { "icon-mimetype", CONFIGSET_SKIN },
100 { "icon-image", CONFIGSET_SKIN },
101 { "timeline-block-markup", CONFIGSET_SKIN },
102 { "timeline-date-format", CONFIGSET_SKIN },
103 { "timeline-default-style", CONFIGSET_SKIN },
104 { "timeline-dwelltime", CONFIGSET_SKIN },
105 { "timeline-closetime", CONFIGSET_SKIN },
106
+16 -11
--- src/doc.c
+++ src/doc.c
@@ -147,11 +147,11 @@
147147
{ "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
148148
{ "jar", 3, "application/java-archive" },
149149
{ "jpe", 3, "image/jpeg" },
150150
{ "jpeg", 4, "image/jpeg" },
151151
{ "jpg", 3, "image/jpeg" },
152
- { "js", 2, "application/x-javascript" },
152
+ { "js", 2, "application/javascript" },
153153
{ "kar", 3, "audio/midi" },
154154
{ "latex", 5, "application/x-latex" },
155155
{ "lha", 3, "application/octet-stream" },
156156
{ "lsp", 3, "application/x-lisp" },
157157
{ "lzh", 3, "application/octet-stream" },
@@ -1132,29 +1132,34 @@
11321132
11331133
11341134
/*
11351135
** WEBPAGE: favicon.ico
11361136
**
1137
-** Return the default favicon.ico image. The returned image is for the
1138
-** Fossil lizard icon.
1137
+** Return the configured "favicon.ico" image. If no "favicon.ico" image
1138
+** is defined, the returned image is for the Fossil lizard icon.
11391139
**
1140
-** The intended use case here is to supply a favicon for the "fossil ui"
1140
+** The intended use case here is to supply an icon for the "fossil ui"
11411141
** command. For a permanent website, the recommended process is for
1142
-** the admin to set up a project-specific favicon and reference that
1143
-** icon in the HTML header using a line like:
1142
+** the admin to set up a project-specific icon and reference that icon
1143
+** in the HTML header using a line like:
11441144
**
11451145
** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/>
11461146
**
11471147
*/
11481148
void favicon_page(void){
1149
- Blob favicon;
1149
+ Blob icon;
1150
+ char *zMime;
11501151
11511152
etag_check(ETAG_CONFIG, 0);
1152
- blob_zero(&favicon);
1153
- blob_init(&favicon, (char*)aLogo, sizeof(aLogo));
1154
- cgi_set_content_type("image/gif");
1155
- cgi_set_content(&favicon);
1153
+ zMime = db_get("icon-mimetype", "image/gif");
1154
+ blob_zero(&icon);
1155
+ db_blob(&icon, "SELECT value FROM config WHERE name='icon-image'");
1156
+ if( blob_size(&icon)==0 ){
1157
+ blob_init(&icon, (char*)aLogo, sizeof(aLogo));
1158
+ }
1159
+ cgi_set_content_type(zMime);
1160
+ cgi_set_content(&icon);
11561161
}
11571162
11581163
/*
11591164
** WEBPAGE: docsrch
11601165
**
11611166
--- src/doc.c
+++ src/doc.c
@@ -147,11 +147,11 @@
147 { "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
148 { "jar", 3, "application/java-archive" },
149 { "jpe", 3, "image/jpeg" },
150 { "jpeg", 4, "image/jpeg" },
151 { "jpg", 3, "image/jpeg" },
152 { "js", 2, "application/x-javascript" },
153 { "kar", 3, "audio/midi" },
154 { "latex", 5, "application/x-latex" },
155 { "lha", 3, "application/octet-stream" },
156 { "lsp", 3, "application/x-lisp" },
157 { "lzh", 3, "application/octet-stream" },
@@ -1132,29 +1132,34 @@
1132
1133
1134 /*
1135 ** WEBPAGE: favicon.ico
1136 **
1137 ** Return the default favicon.ico image. The returned image is for the
1138 ** Fossil lizard icon.
1139 **
1140 ** The intended use case here is to supply a favicon for the "fossil ui"
1141 ** command. For a permanent website, the recommended process is for
1142 ** the admin to set up a project-specific favicon and reference that
1143 ** icon in the HTML header using a line like:
1144 **
1145 ** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/>
1146 **
1147 */
1148 void favicon_page(void){
1149 Blob favicon;
 
1150
1151 etag_check(ETAG_CONFIG, 0);
1152 blob_zero(&favicon);
1153 blob_init(&favicon, (char*)aLogo, sizeof(aLogo));
1154 cgi_set_content_type("image/gif");
1155 cgi_set_content(&favicon);
 
 
 
 
1156 }
1157
1158 /*
1159 ** WEBPAGE: docsrch
1160 **
1161
--- src/doc.c
+++ src/doc.c
@@ -147,11 +147,11 @@
147 { "jad", 3, "text/vnd.sun.j2me.app-descriptor" },
148 { "jar", 3, "application/java-archive" },
149 { "jpe", 3, "image/jpeg" },
150 { "jpeg", 4, "image/jpeg" },
151 { "jpg", 3, "image/jpeg" },
152 { "js", 2, "application/javascript" },
153 { "kar", 3, "audio/midi" },
154 { "latex", 5, "application/x-latex" },
155 { "lha", 3, "application/octet-stream" },
156 { "lsp", 3, "application/x-lisp" },
157 { "lzh", 3, "application/octet-stream" },
@@ -1132,29 +1132,34 @@
1132
1133
1134 /*
1135 ** WEBPAGE: favicon.ico
1136 **
1137 ** Return the configured "favicon.ico" image. If no "favicon.ico" image
1138 ** is defined, the returned image is for the Fossil lizard icon.
1139 **
1140 ** The intended use case here is to supply an icon for the "fossil ui"
1141 ** command. For a permanent website, the recommended process is for
1142 ** the admin to set up a project-specific icon and reference that icon
1143 ** in the HTML header using a line like:
1144 **
1145 ** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/>
1146 **
1147 */
1148 void favicon_page(void){
1149 Blob icon;
1150 char *zMime;
1151
1152 etag_check(ETAG_CONFIG, 0);
1153 zMime = db_get("icon-mimetype", "image/gif");
1154 blob_zero(&icon);
1155 db_blob(&icon, "SELECT value FROM config WHERE name='icon-image'");
1156 if( blob_size(&icon)==0 ){
1157 blob_init(&icon, (char*)aLogo, sizeof(aLogo));
1158 }
1159 cgi_set_content_type(zMime);
1160 cgi_set_content(&icon);
1161 }
1162
1163 /*
1164 ** WEBPAGE: docsrch
1165 **
1166
+16 -21
--- src/fileedit.c
+++ src/fileedit.c
@@ -1481,30 +1481,10 @@
14811481
blob_reset(&err);
14821482
blob_reset(&manifest);
14831483
CheckinMiniInfo_cleanup(&cimi);
14841484
}
14851485
1486
-/*
1487
-** Emits all of the "core" static JS needed by /fileedit. Intended to
1488
-** be mapped to style.c:BundleEmitters with the name "fileedit.js".
1489
-*/
1490
-void fileedit_emit_js_bundle(void){
1491
- style_emit_script_fossil_bootstrap(1);
1492
- style_emit_script_builtin(1,0,"sbsdiff.js");
1493
- style_emit_script_fetch(1,0);
1494
- style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1495
- style_emit_script_confirmer(1,0);
1496
- style_emit_script_builtin(1, 0, "fossil.storage.js");
1497
- /*
1498
- ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1499
- ** used for dynamically toggling certain UI components on and off.
1500
- ** Must come before fossil.page.fileedit.js.
1501
- */
1502
- ajax_emit_js_preview_modes(0);
1503
- style_emit_script_builtin(1, 0, "fossil.page.fileedit.js");
1504
-}
1505
-
15061486
/*
15071487
** WEBPAGE: fileedit
15081488
**
15091489
** Enables the online editing and committing of individual text files.
15101490
** Requires that the user have Write permissions.
@@ -1978,11 +1958,26 @@
19781958
blob_appendf(&endScript,");\n");
19791959
}
19801960
19811961
blob_reset(&err);
19821962
CheckinMiniInfo_cleanup(&cimi);
1983
- style_emit_script_bundle("fileedit.js");
1963
+
1964
+ builtin_request_js("sbsdiff.js");
1965
+ style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1966
+ "storage", 0);
1967
+ builtin_fulfill_js_requests();
1968
+ /*
1969
+ ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1970
+ ** used for dynamically toggling certain UI components on and off.
1971
+ ** Must come after window.fossil has been intialized and before
1972
+ ** fossil.page.fileedit.js. Potential TODO: move this into the
1973
+ ** window.fossil bootstrapping so that we don't have to "fulfill"
1974
+ ** the JS multiple times.
1975
+ */
1976
+ ajax_emit_js_preview_modes(1);
1977
+ builtin_request_js("fossil.page.fileedit.js");
1978
+ builtin_fulfill_js_requests();
19841979
if(blob_size(&endScript)>0){
19851980
style_emit_script_tag(0,0);
19861981
CX("\n(function(){\n");
19871982
CX("try{\n%b}\n"
19881983
"catch(e){"
19891984
--- src/fileedit.c
+++ src/fileedit.c
@@ -1481,30 +1481,10 @@
1481 blob_reset(&err);
1482 blob_reset(&manifest);
1483 CheckinMiniInfo_cleanup(&cimi);
1484 }
1485
1486 /*
1487 ** Emits all of the "core" static JS needed by /fileedit. Intended to
1488 ** be mapped to style.c:BundleEmitters with the name "fileedit.js".
1489 */
1490 void fileedit_emit_js_bundle(void){
1491 style_emit_script_fossil_bootstrap(1);
1492 style_emit_script_builtin(1,0,"sbsdiff.js");
1493 style_emit_script_fetch(1,0);
1494 style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1495 style_emit_script_confirmer(1,0);
1496 style_emit_script_builtin(1, 0, "fossil.storage.js");
1497 /*
1498 ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1499 ** used for dynamically toggling certain UI components on and off.
1500 ** Must come before fossil.page.fileedit.js.
1501 */
1502 ajax_emit_js_preview_modes(0);
1503 style_emit_script_builtin(1, 0, "fossil.page.fileedit.js");
1504 }
1505
1506 /*
1507 ** WEBPAGE: fileedit
1508 **
1509 ** Enables the online editing and committing of individual text files.
1510 ** Requires that the user have Write permissions.
@@ -1978,11 +1958,26 @@
1978 blob_appendf(&endScript,");\n");
1979 }
1980
1981 blob_reset(&err);
1982 CheckinMiniInfo_cleanup(&cimi);
1983 style_emit_script_bundle("fileedit.js");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1984 if(blob_size(&endScript)>0){
1985 style_emit_script_tag(0,0);
1986 CX("\n(function(){\n");
1987 CX("try{\n%b}\n"
1988 "catch(e){"
1989
--- src/fileedit.c
+++ src/fileedit.c
@@ -1481,30 +1481,10 @@
1481 blob_reset(&err);
1482 blob_reset(&manifest);
1483 CheckinMiniInfo_cleanup(&cimi);
1484 }
1485
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1486 /*
1487 ** WEBPAGE: fileedit
1488 **
1489 ** Enables the online editing and committing of individual text files.
1490 ** Requires that the user have Write permissions.
@@ -1978,11 +1958,26 @@
1958 blob_appendf(&endScript,");\n");
1959 }
1960
1961 blob_reset(&err);
1962 CheckinMiniInfo_cleanup(&cimi);
1963
1964 builtin_request_js("sbsdiff.js");
1965 style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1966 "storage", 0);
1967 builtin_fulfill_js_requests();
1968 /*
1969 ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1970 ** used for dynamically toggling certain UI components on and off.
1971 ** Must come after window.fossil has been intialized and before
1972 ** fossil.page.fileedit.js. Potential TODO: move this into the
1973 ** window.fossil bootstrapping so that we don't have to "fulfill"
1974 ** the JS multiple times.
1975 */
1976 ajax_emit_js_preview_modes(1);
1977 builtin_request_js("fossil.page.fileedit.js");
1978 builtin_fulfill_js_requests();
1979 if(blob_size(&endScript)>0){
1980 style_emit_script_tag(0,0);
1981 CX("\n(function(){\n");
1982 CX("try{\n%b}\n"
1983 "catch(e){"
1984
+16 -21
--- src/fileedit.c
+++ src/fileedit.c
@@ -1481,30 +1481,10 @@
14811481
blob_reset(&err);
14821482
blob_reset(&manifest);
14831483
CheckinMiniInfo_cleanup(&cimi);
14841484
}
14851485
1486
-/*
1487
-** Emits all of the "core" static JS needed by /fileedit. Intended to
1488
-** be mapped to style.c:BundleEmitters with the name "fileedit.js".
1489
-*/
1490
-void fileedit_emit_js_bundle(void){
1491
- style_emit_script_fossil_bootstrap(1);
1492
- style_emit_script_builtin(1,0,"sbsdiff.js");
1493
- style_emit_script_fetch(1,0);
1494
- style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1495
- style_emit_script_confirmer(1,0);
1496
- style_emit_script_builtin(1, 0, "fossil.storage.js");
1497
- /*
1498
- ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1499
- ** used for dynamically toggling certain UI components on and off.
1500
- ** Must come before fossil.page.fileedit.js.
1501
- */
1502
- ajax_emit_js_preview_modes(0);
1503
- style_emit_script_builtin(1, 0, "fossil.page.fileedit.js");
1504
-}
1505
-
15061486
/*
15071487
** WEBPAGE: fileedit
15081488
**
15091489
** Enables the online editing and committing of individual text files.
15101490
** Requires that the user have Write permissions.
@@ -1978,11 +1958,26 @@
19781958
blob_appendf(&endScript,");\n");
19791959
}
19801960
19811961
blob_reset(&err);
19821962
CheckinMiniInfo_cleanup(&cimi);
1983
- style_emit_script_bundle("fileedit.js");
1963
+
1964
+ builtin_request_js("sbsdiff.js");
1965
+ style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1966
+ "storage", 0);
1967
+ builtin_fulfill_js_requests();
1968
+ /*
1969
+ ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1970
+ ** used for dynamically toggling certain UI components on and off.
1971
+ ** Must come after window.fossil has been intialized and before
1972
+ ** fossil.page.fileedit.js. Potential TODO: move this into the
1973
+ ** window.fossil bootstrapping so that we don't have to "fulfill"
1974
+ ** the JS multiple times.
1975
+ */
1976
+ ajax_emit_js_preview_modes(1);
1977
+ builtin_request_js("fossil.page.fileedit.js");
1978
+ builtin_fulfill_js_requests();
19841979
if(blob_size(&endScript)>0){
19851980
style_emit_script_tag(0,0);
19861981
CX("\n(function(){\n");
19871982
CX("try{\n%b}\n"
19881983
"catch(e){"
19891984
--- src/fileedit.c
+++ src/fileedit.c
@@ -1481,30 +1481,10 @@
1481 blob_reset(&err);
1482 blob_reset(&manifest);
1483 CheckinMiniInfo_cleanup(&cimi);
1484 }
1485
1486 /*
1487 ** Emits all of the "core" static JS needed by /fileedit. Intended to
1488 ** be mapped to style.c:BundleEmitters with the name "fileedit.js".
1489 */
1490 void fileedit_emit_js_bundle(void){
1491 style_emit_script_fossil_bootstrap(1);
1492 style_emit_script_builtin(1,0,"sbsdiff.js");
1493 style_emit_script_fetch(1,0);
1494 style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1495 style_emit_script_confirmer(1,0);
1496 style_emit_script_builtin(1, 0, "fossil.storage.js");
1497 /*
1498 ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1499 ** used for dynamically toggling certain UI components on and off.
1500 ** Must come before fossil.page.fileedit.js.
1501 */
1502 ajax_emit_js_preview_modes(0);
1503 style_emit_script_builtin(1, 0, "fossil.page.fileedit.js");
1504 }
1505
1506 /*
1507 ** WEBPAGE: fileedit
1508 **
1509 ** Enables the online editing and committing of individual text files.
1510 ** Requires that the user have Write permissions.
@@ -1978,11 +1958,26 @@
1978 blob_appendf(&endScript,");\n");
1979 }
1980
1981 blob_reset(&err);
1982 CheckinMiniInfo_cleanup(&cimi);
1983 style_emit_script_bundle("fileedit.js");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1984 if(blob_size(&endScript)>0){
1985 style_emit_script_tag(0,0);
1986 CX("\n(function(){\n");
1987 CX("try{\n%b}\n"
1988 "catch(e){"
1989
--- src/fileedit.c
+++ src/fileedit.c
@@ -1481,30 +1481,10 @@
1481 blob_reset(&err);
1482 blob_reset(&manifest);
1483 CheckinMiniInfo_cleanup(&cimi);
1484 }
1485
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1486 /*
1487 ** WEBPAGE: fileedit
1488 **
1489 ** Enables the online editing and committing of individual text files.
1490 ** Requires that the user have Write permissions.
@@ -1978,11 +1958,26 @@
1958 blob_appendf(&endScript,");\n");
1959 }
1960
1961 blob_reset(&err);
1962 CheckinMiniInfo_cleanup(&cimi);
1963
1964 builtin_request_js("sbsdiff.js");
1965 style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1966 "storage", 0);
1967 builtin_fulfill_js_requests();
1968 /*
1969 ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1970 ** used for dynamically toggling certain UI components on and off.
1971 ** Must come after window.fossil has been intialized and before
1972 ** fossil.page.fileedit.js. Potential TODO: move this into the
1973 ** window.fossil bootstrapping so that we don't have to "fulfill"
1974 ** the JS multiple times.
1975 */
1976 ajax_emit_js_preview_modes(1);
1977 builtin_request_js("fossil.page.fileedit.js");
1978 builtin_fulfill_js_requests();
1979 if(blob_size(&endScript)>0){
1980 style_emit_script_tag(0,0);
1981 CX("\n(function(){\n");
1982 CX("try{\n%b}\n"
1983 "catch(e){"
1984
+11 -8
--- src/forum.c
+++ src/forum.c
@@ -749,18 +749,21 @@
749749
forumthread_delete(pThread);
750750
return target;
751751
}
752752
753753
/*
754
-** Callback for use with style.c:BundleEmitters. Emits all JS code
755
-** required by this page.
754
+** Emits all JS code required by /forumpost.
756755
*/
757
-void forumpost_emit_js_bundle(void){
758
- style_emit_script_builtin(1, 0, "forum.js");
759
- style_emit_script_fossil_bootstrap(1);
760
- style_emit_script_dom(1, 0);
761
- style_emit_script_builtin(1, 0, "fossil.page.forumpost.js");
756
+static void forumpost_emit_page_js(){
757
+ static int once = 0;
758
+ if(0==once){
759
+ once = 1;
760
+ style_emit_script_fossil_bootstrap(1);
761
+ builtin_request_js("forum.js");
762
+ builtin_request_js("fossil.dom.js");
763
+ builtin_request_js("fossil.page.forumpost.js");
764
+ }
762765
}
763766
764767
/*
765768
** WEBPAGE: forumpost
766769
**
@@ -887,11 +890,11 @@
887890
}else{
888891
style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
889892
style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName);
890893
forum_display_hierarchical(froot, fpid);
891894
}
892
- style_emit_script_bundle("forum.js");
895
+ forumpost_emit_page_js();
893896
style_footer();
894897
}
895898
896899
/*
897900
** Return true if a forum post should be moderated.
898901
--- src/forum.c
+++ src/forum.c
@@ -749,18 +749,21 @@
749 forumthread_delete(pThread);
750 return target;
751 }
752
753 /*
754 ** Callback for use with style.c:BundleEmitters. Emits all JS code
755 ** required by this page.
756 */
757 void forumpost_emit_js_bundle(void){
758 style_emit_script_builtin(1, 0, "forum.js");
759 style_emit_script_fossil_bootstrap(1);
760 style_emit_script_dom(1, 0);
761 style_emit_script_builtin(1, 0, "fossil.page.forumpost.js");
 
 
 
 
762 }
763
764 /*
765 ** WEBPAGE: forumpost
766 **
@@ -887,11 +890,11 @@
887 }else{
888 style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
889 style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName);
890 forum_display_hierarchical(froot, fpid);
891 }
892 style_emit_script_bundle("forum.js");
893 style_footer();
894 }
895
896 /*
897 ** Return true if a forum post should be moderated.
898
--- src/forum.c
+++ src/forum.c
@@ -749,18 +749,21 @@
749 forumthread_delete(pThread);
750 return target;
751 }
752
753 /*
754 ** Emits all JS code required by /forumpost.
 
755 */
756 static void forumpost_emit_page_js(){
757 static int once = 0;
758 if(0==once){
759 once = 1;
760 style_emit_script_fossil_bootstrap(1);
761 builtin_request_js("forum.js");
762 builtin_request_js("fossil.dom.js");
763 builtin_request_js("fossil.page.forumpost.js");
764 }
765 }
766
767 /*
768 ** WEBPAGE: forumpost
769 **
@@ -887,11 +890,11 @@
890 }else{
891 style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
892 style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName);
893 forum_display_hierarchical(froot, fpid);
894 }
895 forumpost_emit_page_js();
896 style_footer();
897 }
898
899 /*
900 ** Return true if a forum post should be moderated.
901
+11 -8
--- src/forum.c
+++ src/forum.c
@@ -749,18 +749,21 @@
749749
forumthread_delete(pThread);
750750
return target;
751751
}
752752
753753
/*
754
-** Callback for use with style.c:BundleEmitters. Emits all JS code
755
-** required by this page.
754
+** Emits all JS code required by /forumpost.
756755
*/
757
-void forumpost_emit_js_bundle(void){
758
- style_emit_script_builtin(1, 0, "forum.js");
759
- style_emit_script_fossil_bootstrap(1);
760
- style_emit_script_dom(1, 0);
761
- style_emit_script_builtin(1, 0, "fossil.page.forumpost.js");
756
+static void forumpost_emit_page_js(){
757
+ static int once = 0;
758
+ if(0==once){
759
+ once = 1;
760
+ style_emit_script_fossil_bootstrap(1);
761
+ builtin_request_js("forum.js");
762
+ builtin_request_js("fossil.dom.js");
763
+ builtin_request_js("fossil.page.forumpost.js");
764
+ }
762765
}
763766
764767
/*
765768
** WEBPAGE: forumpost
766769
**
@@ -887,11 +890,11 @@
887890
}else{
888891
style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
889892
style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName);
890893
forum_display_hierarchical(froot, fpid);
891894
}
892
- style_emit_script_bundle("forum.js");
895
+ forumpost_emit_page_js();
893896
style_footer();
894897
}
895898
896899
/*
897900
** Return true if a forum post should be moderated.
898901
--- src/forum.c
+++ src/forum.c
@@ -749,18 +749,21 @@
749 forumthread_delete(pThread);
750 return target;
751 }
752
753 /*
754 ** Callback for use with style.c:BundleEmitters. Emits all JS code
755 ** required by this page.
756 */
757 void forumpost_emit_js_bundle(void){
758 style_emit_script_builtin(1, 0, "forum.js");
759 style_emit_script_fossil_bootstrap(1);
760 style_emit_script_dom(1, 0);
761 style_emit_script_builtin(1, 0, "fossil.page.forumpost.js");
 
 
 
 
762 }
763
764 /*
765 ** WEBPAGE: forumpost
766 **
@@ -887,11 +890,11 @@
887 }else{
888 style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
889 style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName);
890 forum_display_hierarchical(froot, fpid);
891 }
892 style_emit_script_bundle("forum.js");
893 style_footer();
894 }
895
896 /*
897 ** Return true if a forum post should be moderated.
898
--- src/forum.c
+++ src/forum.c
@@ -749,18 +749,21 @@
749 forumthread_delete(pThread);
750 return target;
751 }
752
753 /*
754 ** Emits all JS code required by /forumpost.
 
755 */
756 static void forumpost_emit_page_js(){
757 static int once = 0;
758 if(0==once){
759 once = 1;
760 style_emit_script_fossil_bootstrap(1);
761 builtin_request_js("forum.js");
762 builtin_request_js("fossil.dom.js");
763 builtin_request_js("fossil.page.forumpost.js");
764 }
765 }
766
767 /*
768 ** WEBPAGE: forumpost
769 **
@@ -887,11 +890,11 @@
890 }else{
891 style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
892 style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName);
893 forum_display_hierarchical(froot, fpid);
894 }
895 forumpost_emit_page_js();
896 style_footer();
897 }
898
899 /*
900 ** Return true if a forum post should be moderated.
901
+3 -3
--- src/info.c
+++ src/info.c
@@ -441,11 +441,11 @@
441441
/*
442442
** Generate javascript to enhance HTML diffs.
443443
*/
444444
void append_diff_javascript(int sideBySide){
445445
if( !sideBySide ) return;
446
- style_load_one_js_file("sbsdiff.js");
446
+ builtin_request_js("sbsdiff.js");
447447
}
448448
449449
/*
450450
** Construct an appropriate diffFlag for text_diff() based on query
451451
** parameters and the to boolean arguments.
@@ -2089,11 +2089,11 @@
20892089
if( z[0]=='\n' ) z++;
20902090
}
20912091
if( n<iEnd ) cgi_printf("</div>");
20922092
@ </pre>
20932093
if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094
- style_load_one_js_file("scroll.js");
2094
+ builtin_request_js("scroll.js");
20952095
}
20962096
}
20972097
20982098
20992099
/*
@@ -3113,11 +3113,11 @@
31133113
@ <input type="submit" name="apply" value="Apply Changes" />
31143114
}
31153115
@ </td></tr>
31163116
@ </table>
31173117
@ </div></form>
3118
- style_load_one_js_file("ci_edit.js");
3118
+ builtin_request_js("ci_edit.js");
31193119
style_footer();
31203120
}
31213121
31223122
/*
31233123
** Prepare an ammended commit comment. Let the user modify it using the
31243124
--- src/info.c
+++ src/info.c
@@ -441,11 +441,11 @@
441 /*
442 ** Generate javascript to enhance HTML diffs.
443 */
444 void append_diff_javascript(int sideBySide){
445 if( !sideBySide ) return;
446 style_load_one_js_file("sbsdiff.js");
447 }
448
449 /*
450 ** Construct an appropriate diffFlag for text_diff() based on query
451 ** parameters and the to boolean arguments.
@@ -2089,11 +2089,11 @@
2089 if( z[0]=='\n' ) z++;
2090 }
2091 if( n<iEnd ) cgi_printf("</div>");
2092 @ </pre>
2093 if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094 style_load_one_js_file("scroll.js");
2095 }
2096 }
2097
2098
2099 /*
@@ -3113,11 +3113,11 @@
3113 @ <input type="submit" name="apply" value="Apply Changes" />
3114 }
3115 @ </td></tr>
3116 @ </table>
3117 @ </div></form>
3118 style_load_one_js_file("ci_edit.js");
3119 style_footer();
3120 }
3121
3122 /*
3123 ** Prepare an ammended commit comment. Let the user modify it using the
3124
--- src/info.c
+++ src/info.c
@@ -441,11 +441,11 @@
441 /*
442 ** Generate javascript to enhance HTML diffs.
443 */
444 void append_diff_javascript(int sideBySide){
445 if( !sideBySide ) return;
446 builtin_request_js("sbsdiff.js");
447 }
448
449 /*
450 ** Construct an appropriate diffFlag for text_diff() based on query
451 ** parameters and the to boolean arguments.
@@ -2089,11 +2089,11 @@
2089 if( z[0]=='\n' ) z++;
2090 }
2091 if( n<iEnd ) cgi_printf("</div>");
2092 @ </pre>
2093 if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094 builtin_request_js("scroll.js");
2095 }
2096 }
2097
2098
2099 /*
@@ -3113,11 +3113,11 @@
3113 @ <input type="submit" name="apply" value="Apply Changes" />
3114 }
3115 @ </td></tr>
3116 @ </table>
3117 @ </div></form>
3118 builtin_request_js("ci_edit.js");
3119 style_footer();
3120 }
3121
3122 /*
3123 ** Prepare an ammended commit comment. Let the user modify it using the
3124
--- src/json_config.c
+++ src/json_config.c
@@ -61,10 +61,12 @@
6161
{ "details", CONFIGSET_SKIN },
6262
{ "logo-mimetype", CONFIGSET_SKIN },
6363
{ "logo-image", CONFIGSET_SKIN },
6464
{ "background-mimetype", CONFIGSET_SKIN },
6565
{ "background-image", CONFIGSET_SKIN },
66
+{ "icon-mimetype", CONFIGSET_SKIN },
67
+{ "icon-image", CONFIGSET_SKIN },
6668
{ "timeline-block-markup", CONFIGSET_SKIN },
6769
{ "timeline-max-comment", CONFIGSET_SKIN },
6870
{ "timeline-plaintext", CONFIGSET_SKIN },
6971
{ "adunit", CONFIGSET_SKIN },
7072
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
7173
--- src/json_config.c
+++ src/json_config.c
@@ -61,10 +61,12 @@
61 { "details", CONFIGSET_SKIN },
62 { "logo-mimetype", CONFIGSET_SKIN },
63 { "logo-image", CONFIGSET_SKIN },
64 { "background-mimetype", CONFIGSET_SKIN },
65 { "background-image", CONFIGSET_SKIN },
 
 
66 { "timeline-block-markup", CONFIGSET_SKIN },
67 { "timeline-max-comment", CONFIGSET_SKIN },
68 { "timeline-plaintext", CONFIGSET_SKIN },
69 { "adunit", CONFIGSET_SKIN },
70 { "adunit-omit-if-admin", CONFIGSET_SKIN },
71
--- src/json_config.c
+++ src/json_config.c
@@ -61,10 +61,12 @@
61 { "details", CONFIGSET_SKIN },
62 { "logo-mimetype", CONFIGSET_SKIN },
63 { "logo-image", CONFIGSET_SKIN },
64 { "background-mimetype", CONFIGSET_SKIN },
65 { "background-image", CONFIGSET_SKIN },
66 { "icon-mimetype", CONFIGSET_SKIN },
67 { "icon-image", CONFIGSET_SKIN },
68 { "timeline-block-markup", CONFIGSET_SKIN },
69 { "timeline-max-comment", CONFIGSET_SKIN },
70 { "timeline-plaintext", CONFIGSET_SKIN },
71 { "adunit", CONFIGSET_SKIN },
72 { "adunit-omit-if-admin", CONFIGSET_SKIN },
73
+1 -1
--- src/login.c
+++ src/login.c
@@ -752,11 +752,11 @@
752752
@ %h(zCaptcha)
753753
@ </pre></td></tr></table>
754754
if( bAutoCaptcha ) {
755755
@ <input type="button" value="Fill out captcha" id='autofillButton' \
756756
@ data-af='%s(zDecoded)' />
757
- style_load_one_js_file("login.js");
757
+ builtin_request_js("login.js");
758758
}
759759
@ </div>
760760
free(zCaptcha);
761761
}
762762
@ </form>
763763
--- src/login.c
+++ src/login.c
@@ -752,11 +752,11 @@
752 @ %h(zCaptcha)
753 @ </pre></td></tr></table>
754 if( bAutoCaptcha ) {
755 @ <input type="button" value="Fill out captcha" id='autofillButton' \
756 @ data-af='%s(zDecoded)' />
757 style_load_one_js_file("login.js");
758 }
759 @ </div>
760 free(zCaptcha);
761 }
762 @ </form>
763
--- src/login.c
+++ src/login.c
@@ -752,11 +752,11 @@
752 @ %h(zCaptcha)
753 @ </pre></td></tr></table>
754 if( bAutoCaptcha ) {
755 @ <input type="button" value="Fill out captcha" id='autofillButton' \
756 @ data-af='%s(zDecoded)' />
757 builtin_request_js("login.js");
758 }
759 @ </div>
760 free(zCaptcha);
761 }
762 @ </form>
763
+31
--- src/main.c
+++ src/main.c
@@ -2270,10 +2270,23 @@
22702270
** this directive is a silent no-op.
22712271
*/
22722272
skin_use_alternative(blob_str(&value));
22732273
blob_reset(&value);
22742274
continue;
2275
+ }
2276
+ if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
2277
+ /* jsmode: MODE
2278
+ **
2279
+ ** Change how javascript resources are delivered with each HTML
2280
+ ** page. MODE is "inline" to put all JS inline, or "separate" to
2281
+ ** cause each JS file to be requested using a separate HTTP request,
2282
+ ** or "bundled" to have all JS files to be fetched with a single
2283
+ ** auxiliary HTTP request.
2284
+ */
2285
+ builtin_set_js_delivery_mode(blob_str(&value),0);
2286
+ blob_reset(&value);
2287
+ continue;
22752288
}
22762289
if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
22772290
/* cgi-debug: FILENAME
22782291
**
22792292
** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
@@ -2455,10 +2468,18 @@
24552468
** --files GLOB comma-separate glob patterns for static file to serve
24562469
** --host NAME specify hostname of the server
24572470
** --https signal a request coming in via https
24582471
** --in FILE Take input from FILE instead of standard input
24592472
** --ipaddr ADDR Assume the request comes from the given IP address
2473
+** --jsmode MODE Determine how javascript is delivered with pages.
2474
+** Mode can be one of:
2475
+** inline All javascript is inserted inline at
2476
+** the end of the HTML file.
2477
+** separate Separate HTTP requests are made for
2478
+** each javascript file.
2479
+** bundled One single separate HTTP fetches all
2480
+** javascript concatenated together.
24602481
** --localauth enable automatic login for local connections
24612482
** --nocompress do not compress HTTP replies
24622483
** --nodelay omit backoffice processing if it would delay process exit
24632484
** --nojail drop root privilege but do not enter the chroot jail
24642485
** --nossl signal that no SSL connections are available
@@ -2484,10 +2505,11 @@
24842505
int useSCGI;
24852506
int noJail;
24862507
int allowRepoList;
24872508
24882509
Th_InitTraceLog();
2510
+ builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
24892511
24902512
/* The winhttp module passes the --files option as --files-urlenc with
24912513
** the argument being URL encoded, to avoid wildcard expansion in the
24922514
** shell. This option is for internal use and is undocumented.
24932515
*/
@@ -2714,10 +2736,18 @@
27142736
** --files GLOBLIST Comma-separated list of glob patterns for static files
27152737
** --localauth enable automatic login for requests from localhost
27162738
** --localhost listen on 127.0.0.1 only (always true for "ui")
27172739
** --https Indicates that the input is coming through a reverse
27182740
** proxy that has already translated HTTPS into HTTP.
2741
+** --jsmode MODE Determine how javascript is delivered with pages.
2742
+** Mode can be one of:
2743
+** inline All javascript is inserted inline at
2744
+** the end of the HTML file.
2745
+** separate Separate HTTP requests are made for
2746
+** each javascript file.
2747
+** bundled One single separate HTTP fetches all
2748
+** javascript concatenated together.
27192749
** --max-latency N Do not let any single HTTP request run for more than N
27202750
** seconds (only works on unix)
27212751
** --nocompress Do not compress HTTP replies
27222752
** --nojail Drop root privileges but do not enter the chroot jail
27232753
** --nossl signal that no SSL connections are available (Always
@@ -2760,10 +2790,11 @@
27602790
27612791
if( g.zErrlog==0 ){
27622792
g.zErrlog = "-";
27632793
}
27642794
g.zExtRoot = find_option("extroot",0,1);
2795
+ builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
27652796
zFileGlob = find_option("files-urlenc",0,1);
27662797
if( zFileGlob ){
27672798
char *z = mprintf("%s", zFileGlob);
27682799
dehttpize(z);
27692800
zFileGlob = z;
27702801
--- src/main.c
+++ src/main.c
@@ -2270,10 +2270,23 @@
2270 ** this directive is a silent no-op.
2271 */
2272 skin_use_alternative(blob_str(&value));
2273 blob_reset(&value);
2274 continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
2275 }
2276 if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
2277 /* cgi-debug: FILENAME
2278 **
2279 ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
@@ -2455,10 +2468,18 @@
2455 ** --files GLOB comma-separate glob patterns for static file to serve
2456 ** --host NAME specify hostname of the server
2457 ** --https signal a request coming in via https
2458 ** --in FILE Take input from FILE instead of standard input
2459 ** --ipaddr ADDR Assume the request comes from the given IP address
 
 
 
 
 
 
 
 
2460 ** --localauth enable automatic login for local connections
2461 ** --nocompress do not compress HTTP replies
2462 ** --nodelay omit backoffice processing if it would delay process exit
2463 ** --nojail drop root privilege but do not enter the chroot jail
2464 ** --nossl signal that no SSL connections are available
@@ -2484,10 +2505,11 @@
2484 int useSCGI;
2485 int noJail;
2486 int allowRepoList;
2487
2488 Th_InitTraceLog();
 
2489
2490 /* The winhttp module passes the --files option as --files-urlenc with
2491 ** the argument being URL encoded, to avoid wildcard expansion in the
2492 ** shell. This option is for internal use and is undocumented.
2493 */
@@ -2714,10 +2736,18 @@
2714 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2715 ** --localauth enable automatic login for requests from localhost
2716 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2717 ** --https Indicates that the input is coming through a reverse
2718 ** proxy that has already translated HTTPS into HTTP.
 
 
 
 
 
 
 
 
2719 ** --max-latency N Do not let any single HTTP request run for more than N
2720 ** seconds (only works on unix)
2721 ** --nocompress Do not compress HTTP replies
2722 ** --nojail Drop root privileges but do not enter the chroot jail
2723 ** --nossl signal that no SSL connections are available (Always
@@ -2760,10 +2790,11 @@
2760
2761 if( g.zErrlog==0 ){
2762 g.zErrlog = "-";
2763 }
2764 g.zExtRoot = find_option("extroot",0,1);
 
2765 zFileGlob = find_option("files-urlenc",0,1);
2766 if( zFileGlob ){
2767 char *z = mprintf("%s", zFileGlob);
2768 dehttpize(z);
2769 zFileGlob = z;
2770
--- src/main.c
+++ src/main.c
@@ -2270,10 +2270,23 @@
2270 ** this directive is a silent no-op.
2271 */
2272 skin_use_alternative(blob_str(&value));
2273 blob_reset(&value);
2274 continue;
2275 }
2276 if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
2277 /* jsmode: MODE
2278 **
2279 ** Change how javascript resources are delivered with each HTML
2280 ** page. MODE is "inline" to put all JS inline, or "separate" to
2281 ** cause each JS file to be requested using a separate HTTP request,
2282 ** or "bundled" to have all JS files to be fetched with a single
2283 ** auxiliary HTTP request.
2284 */
2285 builtin_set_js_delivery_mode(blob_str(&value),0);
2286 blob_reset(&value);
2287 continue;
2288 }
2289 if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
2290 /* cgi-debug: FILENAME
2291 **
2292 ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
@@ -2455,10 +2468,18 @@
2468 ** --files GLOB comma-separate glob patterns for static file to serve
2469 ** --host NAME specify hostname of the server
2470 ** --https signal a request coming in via https
2471 ** --in FILE Take input from FILE instead of standard input
2472 ** --ipaddr ADDR Assume the request comes from the given IP address
2473 ** --jsmode MODE Determine how javascript is delivered with pages.
2474 ** Mode can be one of:
2475 ** inline All javascript is inserted inline at
2476 ** the end of the HTML file.
2477 ** separate Separate HTTP requests are made for
2478 ** each javascript file.
2479 ** bundled One single separate HTTP fetches all
2480 ** javascript concatenated together.
2481 ** --localauth enable automatic login for local connections
2482 ** --nocompress do not compress HTTP replies
2483 ** --nodelay omit backoffice processing if it would delay process exit
2484 ** --nojail drop root privilege but do not enter the chroot jail
2485 ** --nossl signal that no SSL connections are available
@@ -2484,10 +2505,11 @@
2505 int useSCGI;
2506 int noJail;
2507 int allowRepoList;
2508
2509 Th_InitTraceLog();
2510 builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
2511
2512 /* The winhttp module passes the --files option as --files-urlenc with
2513 ** the argument being URL encoded, to avoid wildcard expansion in the
2514 ** shell. This option is for internal use and is undocumented.
2515 */
@@ -2714,10 +2736,18 @@
2736 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2737 ** --localauth enable automatic login for requests from localhost
2738 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2739 ** --https Indicates that the input is coming through a reverse
2740 ** proxy that has already translated HTTPS into HTTP.
2741 ** --jsmode MODE Determine how javascript is delivered with pages.
2742 ** Mode can be one of:
2743 ** inline All javascript is inserted inline at
2744 ** the end of the HTML file.
2745 ** separate Separate HTTP requests are made for
2746 ** each javascript file.
2747 ** bundled One single separate HTTP fetches all
2748 ** javascript concatenated together.
2749 ** --max-latency N Do not let any single HTTP request run for more than N
2750 ** seconds (only works on unix)
2751 ** --nocompress Do not compress HTTP replies
2752 ** --nojail Drop root privileges but do not enter the chroot jail
2753 ** --nossl signal that no SSL connections are available (Always
@@ -2760,10 +2790,11 @@
2790
2791 if( g.zErrlog==0 ){
2792 g.zErrlog = "-";
2793 }
2794 g.zExtRoot = find_option("extroot",0,1);
2795 builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
2796 zFileGlob = find_option("files-urlenc",0,1);
2797 if( zFileGlob ){
2798 char *z = mprintf("%s", zFileGlob);
2799 dehttpize(z);
2800 zFileGlob = z;
2801
+4 -1
--- src/main.mk
+++ src/main.mk
@@ -600,13 +600,16 @@
600600
# the run to just those test cases.
601601
#
602602
test: $(OBJDIR) $(APPNAME)
603603
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
604604
605
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
605
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
606606
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
607607
608
+$(OBJDIR)/phony.h:
609
+ # Force rebuild of VERSION.h every time we run "make"
610
+
608611
# Setup the options used to compile the included SQLite library.
609612
SQLITE_OPTIONS = -DNDEBUG=1 \
610613
-DSQLITE_DQS=0 \
611614
-DSQLITE_THREADSAFE=0 \
612615
-DSQLITE_DEFAULT_MEMSTATUS=0 \
613616
--- src/main.mk
+++ src/main.mk
@@ -600,13 +600,16 @@
600 # the run to just those test cases.
601 #
602 test: $(OBJDIR) $(APPNAME)
603 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
604
605 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
606 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
607
 
 
 
608 # Setup the options used to compile the included SQLite library.
609 SQLITE_OPTIONS = -DNDEBUG=1 \
610 -DSQLITE_DQS=0 \
611 -DSQLITE_THREADSAFE=0 \
612 -DSQLITE_DEFAULT_MEMSTATUS=0 \
613
--- src/main.mk
+++ src/main.mk
@@ -600,13 +600,16 @@
600 # the run to just those test cases.
601 #
602 test: $(OBJDIR) $(APPNAME)
603 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
604
605 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
606 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
607
608 $(OBJDIR)/phony.h:
609 # Force rebuild of VERSION.h every time we run "make"
610
611 # Setup the options used to compile the included SQLite library.
612 SQLITE_OPTIONS = -DNDEBUG=1 \
613 -DSQLITE_DQS=0 \
614 -DSQLITE_THREADSAFE=0 \
615 -DSQLITE_DEFAULT_MEMSTATUS=0 \
616
+4 -1
--- src/main.mk
+++ src/main.mk
@@ -600,13 +600,16 @@
600600
# the run to just those test cases.
601601
#
602602
test: $(OBJDIR) $(APPNAME)
603603
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
604604
605
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
605
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
606606
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
607607
608
+$(OBJDIR)/phony.h:
609
+ # Force rebuild of VERSION.h every time we run "make"
610
+
608611
# Setup the options used to compile the included SQLite library.
609612
SQLITE_OPTIONS = -DNDEBUG=1 \
610613
-DSQLITE_DQS=0 \
611614
-DSQLITE_THREADSAFE=0 \
612615
-DSQLITE_DEFAULT_MEMSTATUS=0 \
613616
--- src/main.mk
+++ src/main.mk
@@ -600,13 +600,16 @@
600 # the run to just those test cases.
601 #
602 test: $(OBJDIR) $(APPNAME)
603 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
604
605 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
606 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
607
 
 
 
608 # Setup the options used to compile the included SQLite library.
609 SQLITE_OPTIONS = -DNDEBUG=1 \
610 -DSQLITE_DQS=0 \
611 -DSQLITE_THREADSAFE=0 \
612 -DSQLITE_DEFAULT_MEMSTATUS=0 \
613
--- src/main.mk
+++ src/main.mk
@@ -600,13 +600,16 @@
600 # the run to just those test cases.
601 #
602 test: $(OBJDIR) $(APPNAME)
603 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
604
605 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
606 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
607
608 $(OBJDIR)/phony.h:
609 # Force rebuild of VERSION.h every time we run "make"
610
611 # Setup the options used to compile the included SQLite library.
612 SQLITE_OPTIONS = -DNDEBUG=1 \
613 -DSQLITE_DQS=0 \
614 -DSQLITE_THREADSAFE=0 \
615 -DSQLITE_DEFAULT_MEMSTATUS=0 \
616
+13 -4
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -370,15 +370,18 @@
370370
# the run to just those test cases.
371371
#
372372
test: $(OBJDIR) $(APPNAME)
373373
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
374374
375
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
375
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
376376
$(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
377377
$(SRCDIR)/../manifest \
378378
$(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
379379
380
+$(OBJDIR)/phony.h:
381
+ # Force rebuild of VERSION.h every time we run "make"
382
+
380383
# Setup the options used to compile the included SQLite library.
381384
SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>>
382385
383386
# Setup the options used to compile the included SQLite shell.
384387
SHELL_OPTIONS = <<<SHELL_OPTIONS>>>
@@ -1081,13 +1084,16 @@
10811084
# build is done from, i.e. the checkout belongs to. Do not sync/push
10821085
# the repository after running the tests.
10831086
test: $(OBJDIR) $(APPNAME)
10841087
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
10851088
1086
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
1089
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
10871090
$(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
10881091
1092
+$(OBJDIR)/phony.h:
1093
+ # Force rebuild of VERSION.h every time "make" is run
1094
+
10891095
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
10901096
# to 1. If it is set to 1, then there is no need to build or link
10911097
# the sqlite3.o object. Instead, the system SQLite will be linked
10921098
# using -lsqlite3.
10931099
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
@@ -1907,12 +1913,15 @@
19071913
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
19081914
19091915
"$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
19101916
$(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
19111917
1912
-"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION"
1913
- $** > $@
1918
+"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1919
+ "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1920
+
1921
+"$(B)\phony.h" :
1922
+ rem Force rebuild of VERSION.h whenever nmake is run
19141923
19151924
"$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
19161925
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
19171926
19181927
"$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
19191928
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -370,15 +370,18 @@
370 # the run to just those test cases.
371 #
372 test: $(OBJDIR) $(APPNAME)
373 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
374
375 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion
376 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
377 $(SRCDIR)/../manifest \
378 $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
379
 
 
 
380 # Setup the options used to compile the included SQLite library.
381 SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>>
382
383 # Setup the options used to compile the included SQLite shell.
384 SHELL_OPTIONS = <<<SHELL_OPTIONS>>>
@@ -1081,13 +1084,16 @@
1081 # build is done from, i.e. the checkout belongs to. Do not sync/push
1082 # the repository after running the tests.
1083 test: $(OBJDIR) $(APPNAME)
1084 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
1085
1086 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
1087 $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
1088
 
 
 
1089 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
1090 # to 1. If it is set to 1, then there is no need to build or link
1091 # the sqlite3.o object. Instead, the system SQLite will be linked
1092 # using -lsqlite3.
1093 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
@@ -1907,12 +1913,15 @@
1907 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1908
1909 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1910 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1911
1912 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION"
1913 $** > $@
 
 
 
1914
1915 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1916 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1917
1918 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1919
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -370,15 +370,18 @@
370 # the run to just those test cases.
371 #
372 test: $(OBJDIR) $(APPNAME)
373 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS)
374
375 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h
376 $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \
377 $(SRCDIR)/../manifest \
378 $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h
379
380 $(OBJDIR)/phony.h:
381 # Force rebuild of VERSION.h every time we run "make"
382
383 # Setup the options used to compile the included SQLite library.
384 SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>>
385
386 # Setup the options used to compile the included SQLite shell.
387 SHELL_OPTIONS = <<<SHELL_OPTIONS>>>
@@ -1081,13 +1084,16 @@
1084 # build is done from, i.e. the checkout belongs to. Do not sync/push
1085 # the repository after running the tests.
1086 test: $(OBJDIR) $(APPNAME)
1087 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
1088
1089 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
1090 $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
1091
1092 $(OBJDIR)/phony.h:
1093 # Force rebuild of VERSION.h every time "make" is run
1094
1095 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
1096 # to 1. If it is set to 1, then there is no need to build or link
1097 # the sqlite3.o object. Instead, the system SQLite will be linked
1098 # using -lsqlite3.
1099 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
@@ -1907,12 +1913,15 @@
1913 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1914
1915 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1916 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1917
1918 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1919 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1920
1921 "$(B)\phony.h" :
1922 rem Force rebuild of VERSION.h whenever nmake is run
1923
1924 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1925 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1926
1927 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1928
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -88,10 +88,11 @@
8888
i = k-1;
8989
continue;
9090
}
9191
}
9292
if( c=='\n' ){
93
+ if( j==0 ) continue;
9394
while( j>0 && isspace(z[j-1]) ) j--;
9495
z[j++] = '\n';
9596
while( i+1<n && isspace(z[i+1]) ) i++;
9697
continue;
9798
}
9899
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -88,10 +88,11 @@
88 i = k-1;
89 continue;
90 }
91 }
92 if( c=='\n' ){
 
93 while( j>0 && isspace(z[j-1]) ) j--;
94 z[j++] = '\n';
95 while( i+1<n && isspace(z[i+1]) ) i++;
96 continue;
97 }
98
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -88,10 +88,11 @@
88 i = k-1;
89 continue;
90 }
91 }
92 if( c=='\n' ){
93 if( j==0 ) continue;
94 while( j>0 && isspace(z[j-1]) ) j--;
95 z[j++] = '\n';
96 while( i+1<n && isspace(z[i+1]) ) i++;
97 continue;
98 }
99
+57 -1
--- src/setup.c
+++ src/setup.c
@@ -1235,11 +1235,11 @@
12351235
}
12361236
12371237
/*
12381238
** WEBPAGE: setup_logo
12391239
**
1240
-** Administrative page for changing the logo image.
1240
+** Administrative page for changing the logo, background, and icon images.
12411241
*/
12421242
void setup_logo(void){
12431243
const char *zLogoMtime = db_get_mtime("logo-image", 0, 0);
12441244
const char *zLogoMime = db_get("logo-mimetype","image/gif");
12451245
const char *aLogoImg = P("logoim");
@@ -1246,16 +1246,23 @@
12461246
int szLogoImg = atoi(PD("logoim:bytes","0"));
12471247
const char *zBgMtime = db_get_mtime("background-image", 0, 0);
12481248
const char *zBgMime = db_get("background-mimetype","image/gif");
12491249
const char *aBgImg = P("bgim");
12501250
int szBgImg = atoi(PD("bgim:bytes","0"));
1251
+ const char *zIconMtime = db_get_mtime("icon-image", 0, 0);
1252
+ const char *zIconMime = db_get("icon-mimetype","image/gif");
1253
+ const char *aIconImg = P("iconim");
1254
+ int szIconImg = atoi(PD("iconim:bytes","0"));
12511255
if( szLogoImg>0 ){
12521256
zLogoMime = PD("logoim:mimetype","image/gif");
12531257
}
12541258
if( szBgImg>0 ){
12551259
zBgMime = PD("bgim:mimetype","image/gif");
12561260
}
1261
+ if( szIconImg>0 ){
1262
+ zIconMime = PD("iconim:mimetype","image/gif");
1263
+ }
12571264
login_check_credentials();
12581265
if( !g.perm.Admin ){
12591266
login_needed(0);
12601267
return;
12611268
}
@@ -1309,10 +1316,35 @@
13091316
"DELETE FROM config WHERE name IN "
13101317
"('background-image','background-mimetype')"
13111318
);
13121319
db_end_transaction(0);
13131320
cgi_redirect("setup_logo");
1321
+ }else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){
1322
+ Blob img;
1323
+ Stmt ins;
1324
+ blob_init(&img, aIconImg, szIconImg);
1325
+ db_prepare(&ins,
1326
+ "REPLACE INTO config(name,value,mtime)"
1327
+ " VALUES('icon-image',:bytes,now())"
1328
+ );
1329
+ db_bind_blob(&ins, ":bytes", &img);
1330
+ db_step(&ins);
1331
+ db_finalize(&ins);
1332
+ db_multi_exec(
1333
+ "REPLACE INTO config(name,value,mtime)"
1334
+ " VALUES('icon-mimetype',%Q,now())",
1335
+ zIconMime
1336
+ );
1337
+ db_end_transaction(0);
1338
+ cgi_redirect("setup_logo");
1339
+ }else if( P("clricon")!=0 ){
1340
+ db_multi_exec(
1341
+ "DELETE FROM config WHERE name IN "
1342
+ "('icon-image','icon-mimetype')"
1343
+ );
1344
+ db_end_transaction(0);
1345
+ cgi_redirect("setup_logo");
13141346
}
13151347
style_header("Edit Project Logo And Background");
13161348
@ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b>
13171349
@ and looks like this:</p>
13181350
@ <blockquote><p><img src="%s(g.zTop)/logo/%z(zLogoMtime)" \
@@ -1358,10 +1390,34 @@
13581390
@ <input type="submit" name="setbg" value="Change Background" />
13591391
@ <input type="submit" name="clrbg" value="Revert To Default" /></p>
13601392
@ </div></form>
13611393
@ <p>(Properties: "background-image" and "background-mimetype")
13621394
@ <hr />
1395
+ @
1396
+ @ <p>The current icon image has a MIME-Type of <b>%h(zIconMime)</b>
1397
+ @ and looks like this:</p>
1398
+ @ <blockquote><p><img src="%s(g.zTop)/favicon.ico/%z(zIconMtime)" \
1399
+ @ alt="icon" border=1 />
1400
+ @ </p></blockquote>
1401
+ @
1402
+ @ <form action="%s(g.zTop)/setup_logo" method="post"
1403
+ @ enctype="multipart/form-data"><div>
1404
+ @ <p>The icon image is accessible to all users at this URL:
1405
+ @ <a href="%s(g.zBaseURL)/favicon.ico">%s(g.zBaseURL)/favicon.ico</a>.
1406
+ @ The icon image may or may not appear on each
1407
+ @ page depending on the web browser in use and the MIME-Types that it
1408
+ @ supports for icon images.
1409
+ @ To change the icon image, use the following form:</p>
1410
+ login_insert_csrf_secret();
1411
+ @ Icon image file:
1412
+ @ <input type="file" name="iconim" size="60" accept="image/*" />
1413
+ @ <p align="center">
1414
+ @ <input type="submit" name="seticon" value="Change Icon" />
1415
+ @ <input type="submit" name="clricon" value="Revert To Default" /></p>
1416
+ @ </div></form>
1417
+ @ <p>(Properties: "icon-image" and "icon-mimetype")
1418
+ @ <hr />
13631419
@
13641420
@ <p><span class="note">Note:</span> Your browser has probably cached these
13651421
@ images, so you may need to press the Reload button before changes will
13661422
@ take effect. </p>
13671423
style_footer();
13681424
--- src/setup.c
+++ src/setup.c
@@ -1235,11 +1235,11 @@
1235 }
1236
1237 /*
1238 ** WEBPAGE: setup_logo
1239 **
1240 ** Administrative page for changing the logo image.
1241 */
1242 void setup_logo(void){
1243 const char *zLogoMtime = db_get_mtime("logo-image", 0, 0);
1244 const char *zLogoMime = db_get("logo-mimetype","image/gif");
1245 const char *aLogoImg = P("logoim");
@@ -1246,16 +1246,23 @@
1246 int szLogoImg = atoi(PD("logoim:bytes","0"));
1247 const char *zBgMtime = db_get_mtime("background-image", 0, 0);
1248 const char *zBgMime = db_get("background-mimetype","image/gif");
1249 const char *aBgImg = P("bgim");
1250 int szBgImg = atoi(PD("bgim:bytes","0"));
 
 
 
 
1251 if( szLogoImg>0 ){
1252 zLogoMime = PD("logoim:mimetype","image/gif");
1253 }
1254 if( szBgImg>0 ){
1255 zBgMime = PD("bgim:mimetype","image/gif");
1256 }
 
 
 
1257 login_check_credentials();
1258 if( !g.perm.Admin ){
1259 login_needed(0);
1260 return;
1261 }
@@ -1309,10 +1316,35 @@
1309 "DELETE FROM config WHERE name IN "
1310 "('background-image','background-mimetype')"
1311 );
1312 db_end_transaction(0);
1313 cgi_redirect("setup_logo");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1314 }
1315 style_header("Edit Project Logo And Background");
1316 @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b>
1317 @ and looks like this:</p>
1318 @ <blockquote><p><img src="%s(g.zTop)/logo/%z(zLogoMtime)" \
@@ -1358,10 +1390,34 @@
1358 @ <input type="submit" name="setbg" value="Change Background" />
1359 @ <input type="submit" name="clrbg" value="Revert To Default" /></p>
1360 @ </div></form>
1361 @ <p>(Properties: "background-image" and "background-mimetype")
1362 @ <hr />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1363 @
1364 @ <p><span class="note">Note:</span> Your browser has probably cached these
1365 @ images, so you may need to press the Reload button before changes will
1366 @ take effect. </p>
1367 style_footer();
1368
--- src/setup.c
+++ src/setup.c
@@ -1235,11 +1235,11 @@
1235 }
1236
1237 /*
1238 ** WEBPAGE: setup_logo
1239 **
1240 ** Administrative page for changing the logo, background, and icon images.
1241 */
1242 void setup_logo(void){
1243 const char *zLogoMtime = db_get_mtime("logo-image", 0, 0);
1244 const char *zLogoMime = db_get("logo-mimetype","image/gif");
1245 const char *aLogoImg = P("logoim");
@@ -1246,16 +1246,23 @@
1246 int szLogoImg = atoi(PD("logoim:bytes","0"));
1247 const char *zBgMtime = db_get_mtime("background-image", 0, 0);
1248 const char *zBgMime = db_get("background-mimetype","image/gif");
1249 const char *aBgImg = P("bgim");
1250 int szBgImg = atoi(PD("bgim:bytes","0"));
1251 const char *zIconMtime = db_get_mtime("icon-image", 0, 0);
1252 const char *zIconMime = db_get("icon-mimetype","image/gif");
1253 const char *aIconImg = P("iconim");
1254 int szIconImg = atoi(PD("iconim:bytes","0"));
1255 if( szLogoImg>0 ){
1256 zLogoMime = PD("logoim:mimetype","image/gif");
1257 }
1258 if( szBgImg>0 ){
1259 zBgMime = PD("bgim:mimetype","image/gif");
1260 }
1261 if( szIconImg>0 ){
1262 zIconMime = PD("iconim:mimetype","image/gif");
1263 }
1264 login_check_credentials();
1265 if( !g.perm.Admin ){
1266 login_needed(0);
1267 return;
1268 }
@@ -1309,10 +1316,35 @@
1316 "DELETE FROM config WHERE name IN "
1317 "('background-image','background-mimetype')"
1318 );
1319 db_end_transaction(0);
1320 cgi_redirect("setup_logo");
1321 }else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){
1322 Blob img;
1323 Stmt ins;
1324 blob_init(&img, aIconImg, szIconImg);
1325 db_prepare(&ins,
1326 "REPLACE INTO config(name,value,mtime)"
1327 " VALUES('icon-image',:bytes,now())"
1328 );
1329 db_bind_blob(&ins, ":bytes", &img);
1330 db_step(&ins);
1331 db_finalize(&ins);
1332 db_multi_exec(
1333 "REPLACE INTO config(name,value,mtime)"
1334 " VALUES('icon-mimetype',%Q,now())",
1335 zIconMime
1336 );
1337 db_end_transaction(0);
1338 cgi_redirect("setup_logo");
1339 }else if( P("clricon")!=0 ){
1340 db_multi_exec(
1341 "DELETE FROM config WHERE name IN "
1342 "('icon-image','icon-mimetype')"
1343 );
1344 db_end_transaction(0);
1345 cgi_redirect("setup_logo");
1346 }
1347 style_header("Edit Project Logo And Background");
1348 @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b>
1349 @ and looks like this:</p>
1350 @ <blockquote><p><img src="%s(g.zTop)/logo/%z(zLogoMtime)" \
@@ -1358,10 +1390,34 @@
1390 @ <input type="submit" name="setbg" value="Change Background" />
1391 @ <input type="submit" name="clrbg" value="Revert To Default" /></p>
1392 @ </div></form>
1393 @ <p>(Properties: "background-image" and "background-mimetype")
1394 @ <hr />
1395 @
1396 @ <p>The current icon image has a MIME-Type of <b>%h(zIconMime)</b>
1397 @ and looks like this:</p>
1398 @ <blockquote><p><img src="%s(g.zTop)/favicon.ico/%z(zIconMtime)" \
1399 @ alt="icon" border=1 />
1400 @ </p></blockquote>
1401 @
1402 @ <form action="%s(g.zTop)/setup_logo" method="post"
1403 @ enctype="multipart/form-data"><div>
1404 @ <p>The icon image is accessible to all users at this URL:
1405 @ <a href="%s(g.zBaseURL)/favicon.ico">%s(g.zBaseURL)/favicon.ico</a>.
1406 @ The icon image may or may not appear on each
1407 @ page depending on the web browser in use and the MIME-Types that it
1408 @ supports for icon images.
1409 @ To change the icon image, use the following form:</p>
1410 login_insert_csrf_secret();
1411 @ Icon image file:
1412 @ <input type="file" name="iconim" size="60" accept="image/*" />
1413 @ <p align="center">
1414 @ <input type="submit" name="seticon" value="Change Icon" />
1415 @ <input type="submit" name="clricon" value="Revert To Default" /></p>
1416 @ </div></form>
1417 @ <p>(Properties: "icon-image" and "icon-mimetype")
1418 @ <hr />
1419 @
1420 @ <p><span class="note">Note:</span> Your browser has probably cached these
1421 @ images, so you may need to press the Reload button before changes will
1422 @ take effect. </p>
1423 style_footer();
1424
+1 -1
--- src/setupuser.c
+++ src/setupuser.c
@@ -702,11 +702,11 @@
702702
@ </tr>
703703
}
704704
@ </table>
705705
@ </div></form>
706706
@ </div>
707
- style_load_one_js_file("useredit.js");
707
+ builtin_request_js("useredit.js");
708708
@ <hr>
709709
@ <h1>Notes On Privileges And Capabilities:</h1>
710710
@ <ul>
711711
if( higherUser ){
712712
@ <li><p class="missingPriv">
713713
--- src/setupuser.c
+++ src/setupuser.c
@@ -702,11 +702,11 @@
702 @ </tr>
703 }
704 @ </table>
705 @ </div></form>
706 @ </div>
707 style_load_one_js_file("useredit.js");
708 @ <hr>
709 @ <h1>Notes On Privileges And Capabilities:</h1>
710 @ <ul>
711 if( higherUser ){
712 @ <li><p class="missingPriv">
713
--- src/setupuser.c
+++ src/setupuser.c
@@ -702,11 +702,11 @@
702 @ </tr>
703 }
704 @ </table>
705 @ </div></form>
706 @ </div>
707 builtin_request_js("useredit.js");
708 @ <hr>
709 @ <h1>Notes On Privileges And Capabilities:</h1>
710 @ <ul>
711 if( higherUser ){
712 @ <li><p class="missingPriv">
713
+1 -1
--- src/skins.c
+++ src/skins.c
@@ -1101,8 +1101,8 @@
11011101
@ undo a prior publish.
11021102
}else{
11031103
@ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page
11041104
@ for cleanup and recovery actions.
11051105
}
1106
- style_load_one_js_file("skin.js");
1106
+ builtin_request_js("skin.js");
11071107
style_footer();
11081108
}
11091109
--- src/skins.c
+++ src/skins.c
@@ -1101,8 +1101,8 @@
1101 @ undo a prior publish.
1102 }else{
1103 @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page
1104 @ for cleanup and recovery actions.
1105 }
1106 style_load_one_js_file("skin.js");
1107 style_footer();
1108 }
1109
--- src/skins.c
+++ src/skins.c
@@ -1101,8 +1101,8 @@
1101 @ undo a prior publish.
1102 }else{
1103 @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page
1104 @ for cleanup and recovery actions.
1105 }
1106 builtin_request_js("skin.js");
1107 style_footer();
1108 }
1109
+39 -302
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
8888
8989
/*
9090
** Flags for various javascript files needed prior to </body>
9191
*/
9292
static int needHrefJs = 0; /* href.js */
93
-static int needSortJs = 0; /* sorttable.js */
94
-static int needGraphJs = 0; /* graph.js */
95
-static int needCopyBtnJs = 0; /* copybtn.js */
96
-static int needAccordionJs = 0; /* accordion.js */
9793
9894
/*
9995
** Extra JS added to the end of the file.
10096
*/
10197
static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
484480
zBtnFmt/*works-like:"%h%s%h%h%d"*/,
485481
zTargetId,zText,zTargetId,zTargetId,cchLength);
486482
}
487483
}
488484
free(zText);
489
- style_copybutton_control();
485
+ builtin_request_js("copybtn.js");
490486
return zResult;
491487
}
492488
493489
/*
494490
** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
694690
695691
/*
696692
** Indicate that the table-sorting javascript is needed.
697693
*/
698694
void style_table_sorter(void){
699
- needSortJs = 1;
700
-}
701
-
702
-/*
703
-** Indicate that the accordion javascript is needed.
704
-*/
705
-void style_accordion(void){
706
- needAccordionJs = 1;
707
-}
708
-
709
-/*
710
-** Indicate that the timeline graph javascript is needed.
711
-*/
712
-void style_graph_generator(void){
713
- needGraphJs = 1;
714
-}
715
-
716
-/*
717
-** Indicate that the copy button javascript is needed.
718
-*/
719
-void style_copybutton_control(void){
720
- needCopyBtnJs = 1;
721
-}
722
-
723
-/*
724
-** Generate code to load a single javascript file
725
-*/
726
-void style_load_one_js_file(const char *zFile){
727
- @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
728
-}
729
-
730
-/*
731
-** All extra JS files to load.
732
-*/
733
-static const char *azJsToLoad[4];
734
-static int nJsToLoad = 0;
735
-
736
-/*
737
-** Register a new JS file to load at the end of the document.
738
-*/
739
-void style_load_js(const char *zName){
740
- int i;
741
- for(i=0; i<nJsToLoad; i++){
742
- if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return;
743
- }
744
- if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){
745
- fossil_panic("too many JS files");
746
- }
747
- azJsToLoad[nJsToLoad++] = zName;
695
+ builtin_request_js("sorttable.js");
748696
}
749697
750698
/*
751699
** Generate code to load all required javascript files.
752700
*/
753701
static void style_load_all_js_files(void){
754
- int i;
755702
if( needHrefJs ){
756703
int nDelay = db_get_int("auto-hyperlink-delay",0);
757704
int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
758705
@ <script id='href-data' type='application/json'>\
759706
@ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
762709
@ function debugMsg(msg){
763710
@ var n = document.getElementById("debugMsg");
764711
@ if(n){n.textContent=msg;}
765712
@ }
766713
if( needHrefJs ){
714
+ @ /* href.js */
767715
cgi_append_content(builtin_text("href.js"),-1);
768716
}
769
- if( needSortJs ){
770
- cgi_append_content(builtin_text("sorttable.js"),-1);
771
- }
772
- if( needGraphJs ){
773
- cgi_append_content(builtin_text("graph.js"),-1);
774
- }
775
- if( needCopyBtnJs ){
776
- cgi_append_content(builtin_text("copybtn.js"),-1);
777
- }
778
- if( needAccordionJs ){
779
- cgi_append_content(builtin_text("accordion.js"),-1);
780
- }
781
- for(i=0; i<nJsToLoad; i++){
782
- cgi_append_content(builtin_text(azJsToLoad[i]),-1);
783
- }
784717
if( blob_size(&blobOnLoad)>0 ){
785718
@ window.onload = function(){
786719
cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
787720
cgi_append_content("\n}\n", -1);
788721
}
789722
@ </script>
790
-}
791
-
792
-/*
793
-** Extra JS to run after all content is loaded.
794
-*/
795
-void style_js_onload(const char *zFormat, ...){
796
- va_list ap;
797
- va_start(ap, zFormat);
798
- blob_vappendf(&blobOnLoad, zFormat, ap);
799
- va_end(ap);
723
+ builtin_fulfill_js_requests();
800724
}
801725
802726
/*
803727
** Draw the footer at the bottom of the page.
804728
*/
@@ -916,11 +840,11 @@
916840
@ </div>
917841
if( nSubmenuCtrl ){
918842
cgi_query_parameters_to_hidden();
919843
cgi_tag_query_parameter(0);
920844
@ </form>
921
- style_load_one_js_file("menu.js");
845
+ builtin_request_js("menu.js");
922846
}
923847
}
924848
925849
zAd = style_adunit_text(&mAdFlags);
926850
if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1127,109 +1051,10 @@
11271051
11281052
/* Tell CGI that the content returned by this page is considered cacheable */
11291053
g.isConst = 1;
11301054
}
11311055
1132
-/*
1133
-** Maps a "bundle" name to a callback which emits the text of that
1134
-** bundle. For use in consolidating scripts for certain pages into a
1135
-** single cacheable request.
1136
-*/
1137
-typedef struct {
1138
- const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */
1139
- void (*xEmit)(void); /* Emits amalgamated text output for this
1140
- bundle */
1141
-} BundleEmitter;
1142
-/*
1143
-** Map each required bundle here...
1144
-*/
1145
-static const BundleEmitter BundleEmitters[] = {
1146
-/* Keep these sorted for bsearch() */
1147
-{"fileedit.js", fileedit_emit_js_bundle},
1148
-{"forum.js", forumpost_emit_js_bundle},
1149
-{"wikiedit.js", wikiedit_emit_js_bundle}
1150
-};
1151
-
1152
-/*
1153
-** Comparison function for bsearch() for searching a BundleEmitter
1154
-** list for a matching name.
1155
-*/
1156
-static int cmp_builtin_bundle_name(const void *a, const void *b){
1157
- const BundleEmitter * rA = (const BundleEmitter*)a;
1158
- const BundleEmitter * rB = (const BundleEmitter*)b;
1159
- return fossil_strcmp(rA->zName, rB->zName);
1160
-}
1161
-
1162
-/*
1163
-** Internal helper for /builtin/FILENAME for dispatching "bundles"
1164
-** of amalgamated text (primarily JS) code.
1165
-**
1166
-** Returns true if it finds a bundle matcing the given name, else
1167
-** false. On success it outputs the amalgamated bundle without any
1168
-** sort of wrapper, e.g. SCRIPT tag
1169
-*/
1170
-static int page_builtin_text_bundle(const char * zFilename){
1171
- const BundleEmitter * pBH;
1172
- BundleEmitter needle = {zFilename, 0};
1173
-
1174
- pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters,
1175
- count(BundleEmitters),
1176
- sizeof BundleEmitters[0],
1177
- cmp_builtin_bundle_name);
1178
- if(pBH!=0){
1179
- pBH->xEmit();
1180
- }
1181
- return pBH!=0;
1182
-}
1183
-
1184
-/*
1185
-** WEBPAGE: builtin
1186
-** URL: builtin/FILENAME
1187
-**
1188
-** Return the built-in text given by FILENAME. This is used internally
1189
-** by many Fossil web pages to load built-in javascript files.
1190
-**
1191
-** If the id= parameter is present, then Fossil assumes that the
1192
-** result is immutable and sets a very large cache retention time (1
1193
-** year).
1194
-*/
1195
-void page_builtin_text(void){
1196
- Blob out;
1197
- const char *zName = P("name");
1198
- const char *zTxt = 0;
1199
- const char *zId = P("id");
1200
- int nId;
1201
- int isBundle = 0;
1202
-
1203
- if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
1204
- g.isConst = 1;
1205
- }else{
1206
- etag_check(0,0)/*might not return*/;
1207
- }
1208
- if( zName ){
1209
- if( sqlite3_strglob("*.js", zName)==0 ){
1210
- cgi_set_content_type("application/javascript");
1211
- }else{
1212
- cgi_set_content_type("text/plain");
1213
- }
1214
- if(':'==zName[0]){
1215
- isBundle = 1;
1216
- zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL;
1217
- }else{
1218
- zTxt = builtin_text(zName);
1219
- }
1220
- }
1221
- if( zTxt==0 ){
1222
- cgi_set_content_type("text/html");
1223
- cgi_set_status(404, "Not Found");
1224
- @ File "%h(zName)" not found
1225
- }else if(isBundle==0){
1226
- blob_init(&out, zTxt, -1);
1227
- cgi_set_content(&out);
1228
- }
1229
-}
1230
-
12311056
/*
12321057
** All possible capabilities
12331058
*/
12341059
static const char allCap[] =
12351060
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
@@ -1605,21 +1430,18 @@
16051430
** 1) window.fossil core object, some of which depends on C-lelel
16061431
** runtime data. That part of the script is always emitted inline. If
16071432
** addScripTag is true then it is wrapped in its own SCRIPT tag, else
16081433
** it is assumed that the caller already opened a tag.
16091434
**
1610
-** 2) Emits the static fossil.bootstrap.js. If asInline is true then
1611
-** it is emitted inline with the components from (1), else it is
1612
-** emitted as a separate SCRIPT tag with
1613
-** src=/builtin/fossil.bootstrap.js (so causes another HTTP request).
1435
+** 2) Emits the static fossil.bootstrap.js using builtin_request_js().
16141436
*/
1615
-void style_emit_script_fossil_bootstrap(int asInline){
1437
+void style_emit_script_fossil_bootstrap(int addScriptTag){
16161438
static int once = 0;
16171439
if(0==once++){
16181440
/* Set up the generic/app-agnostic parts of window.fossil
16191441
** which require C-level state... */
1620
- if(asInline==0){
1442
+ if(addScriptTag!=0){
16211443
style_emit_script_tag(0,0);
16221444
}
16231445
CX("(function(){\n"
16241446
"if(!window.fossil) window.fossil={};\n"
16251447
"window.fossil.version = %!j;\n"
@@ -1646,18 +1468,16 @@
16461468
*/
16471469
CX("window.fossil.page = {"
16481470
"name:\"%T\""
16491471
"};\n", g.zPath);
16501472
CX("})();\n");
1651
- /* The remaining fossil object bootstrap code is not dependent on
1652
- ** C-runtime state... */
1653
- if(asInline!=0){
1654
- CX("%s\n", builtin_text("fossil.bootstrap.js"));
1655
- }else{
1473
+ if(addScriptTag!=0){
16561474
style_emit_script_tag(1,0);
1657
- style_emit_script_builtin(0,1,"fossil.bootstrap.js");
16581475
}
1476
+ /* The remaining window.fossil bootstrap code is not dependent on
1477
+ ** C-runtime state... */
1478
+ builtin_request_js("fossil.bootstrap.js");
16591479
}
16601480
}
16611481
16621482
/*
16631483
** If passed 0 as its first argument, it emits a script opener tag
@@ -1688,116 +1508,33 @@
16881508
CX("</script>\n");
16891509
}
16901510
}
16911511
16921512
/*
1693
-** Emits a script tag which uses content from a builtin script file.
1694
-**
1695
-** If asInline is false, the script is emitted as a SCRIPT tag with a
1696
-** src attribute of /builtin/zName and the 2nd parameter is
1697
-** ignored. If asInline is true then the contents of the script are
1698
-** emitted directly, with a wrapping SCRIPT tag if addScripTag is
1699
-** true, else no wrapping script tag..
1700
-**
1701
-** If it is false, a script tag loading it via
1702
-** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a
1703
-** build-time-dependent cache-buster value.
1704
-*/
1705
-void style_emit_script_builtin(int asInline, int addScripTag,
1706
- char const * zName){
1707
- if(asInline){
1708
- if(addScripTag){
1709
- style_emit_script_tag(0,0);
1710
- }
1711
- CX("%s", builtin_text(zName));
1712
- if(addScripTag){
1713
- style_emit_script_tag(1,0);
1714
- }
1715
- }else{
1716
- char * zFullName = mprintf("builtin/%s",zName);
1717
- const char * zHash = fossil_exe_id();
1718
- CX("<script src='%R/%T?cache=%.8s'></script>\n",
1719
- zFullName, zHash);
1720
- fossil_free(zFullName);
1721
- }
1722
-}
1723
-
1724
-/*
1725
-** A convenience wrapper arond style_emit_script_builtin() which
1726
-** prepends a ':' to zName and passes (0,0,newName) to that
1727
-** function. i.e. it emits a SCRIPT tag with
1728
-** src=.../builtin/:${zName}?cache=.... The given name is assumed to
1729
-** have been added to the style.c:BundleEmitters map.
1730
-*/
1731
-void style_emit_script_bundle(char const * zName){
1732
- char *zBundle = mprintf(":%s", zName);
1733
- style_emit_script_builtin(0, 0, zBundle);
1734
- fossil_free(zBundle);
1735
-}
1736
-
1737
-/*
1738
-** The first time this is called it emits the JS code from the
1739
-** built-in file fossil.fossil.js. Subsequent calls are no-ops.
1740
-**
1741
-** If passed a true first argument, it emits the contents directly
1742
-** to the page output, else it emits a script tag with a
1743
-** src=builtin/... to load the script.
1744
-**
1745
-** If asInline is true and addScripTag is true then the contents
1746
-** are emitted directly but wrapped in a SCRIPT tag. If asInline
1747
-** is false, addScriptTag is ignored.
1748
-**
1749
-** Note that this code relies on that loaded via
1750
-** style_emit_script_fossil_bootstrap() but it does not call that
1751
-** routine.
1752
-*/
1753
-void style_emit_script_fetch(int asInline, int addScripTag){
1754
- static int once = 0;
1755
- if(0==once++){
1756
- style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js");
1757
- }
1758
-}
1759
-
1760
-/*
1761
-** The first time this is called it emits the JS code from the
1762
-** built-in file fossil.dom.js. Subsequent calls are no-ops.
1763
-**
1764
-** If passed a true first argument, it emits the contents directly
1765
-** to the page output, else it emits a script tag with a
1766
-** src=builtin/... to load the script.
1767
-**
1768
-** If asInline is true and addScripTag is true then the contents
1769
-** are emitted directly but wrapped in a SCRIPT tag. If asInline
1770
-** is false, addScriptTag is ignored.
1771
-**
1772
-** Note that this code relies on that loaded via
1773
-** style_emit_script_fossil_bootstrap(), but it does not call that
1774
-** routine.
1775
-*/
1776
-void style_emit_script_dom(int asInline, int addScripTag){
1777
- static int once = 0;
1778
- if(0==once++){
1779
- style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js");
1780
- }
1781
-}
1782
-
1783
-/*
1784
-** The fossil.tabs.js counterpart of style_emit_script_fetch().
1785
-** Also emits fossil.dom.js.
1786
-*/
1787
-void style_emit_script_tabs(int asInline, int addScripTag){
1788
- static int once = 0;
1789
- if(0==once++){
1790
- style_emit_script_dom(asInline, addScripTag);
1791
- style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js");
1792
- }
1793
-}
1794
-
1795
-/*
1796
-** The fossil.confirmer.js counterpart of style_emit_script_fetch().
1797
-*/
1798
-void style_emit_script_confirmer(int asInline, int addScripTag){
1799
- static int once = 0;
1800
- if(0==once++){
1801
- style_emit_script_builtin(asInline, 0, "fossil.confirmer.js");
1802
- }
1513
+** Convenience wrapper which calls builtin_request_js() for a series
1514
+** of builtin scripts named fossil.NAME.js. The first time it is
1515
+** called, it also calls style_emit_script_fossil_bootstrap() to
1516
+** initialize the window.fossil JS API. The first argument is a
1517
+** no-meaning dummy required by the va_start() interface. All
1518
+** subsequent arguments must be strings of the NAME part of
1519
+** fossil.NAME.js, followed by a NULL argument to terminate the list.
1520
+**
1521
+** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3
1522
+** APIs. Do not forget the trailing 0!
1523
+*/
1524
+void style_emit_fossil_js_apis( int dummy, ... ) {
1525
+ static int once = 0;
1526
+ const char *zArg;
1527
+ char * zName;
1528
+ va_list vargs;
1529
+
1530
+ if(0==once++){
1531
+ style_emit_script_fossil_bootstrap(1);
1532
+ }
1533
+ va_start(vargs,dummy);
1534
+ while( (zArg = va_arg (vargs, const char *))!=0 ){
1535
+ zName = mprintf("fossil.%s.js", zArg);
1536
+ builtin_request_js(zName);
1537
+ fossil_free(zName);
1538
+ }
1539
+ va_end(vargs);
18031540
}
18041541
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
88
89 /*
90 ** Flags for various javascript files needed prior to </body>
91 */
92 static int needHrefJs = 0; /* href.js */
93 static int needSortJs = 0; /* sorttable.js */
94 static int needGraphJs = 0; /* graph.js */
95 static int needCopyBtnJs = 0; /* copybtn.js */
96 static int needAccordionJs = 0; /* accordion.js */
97
98 /*
99 ** Extra JS added to the end of the file.
100 */
101 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
484 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
485 zTargetId,zText,zTargetId,zTargetId,cchLength);
486 }
487 }
488 free(zText);
489 style_copybutton_control();
490 return zResult;
491 }
492
493 /*
494 ** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
694
695 /*
696 ** Indicate that the table-sorting javascript is needed.
697 */
698 void style_table_sorter(void){
699 needSortJs = 1;
700 }
701
702 /*
703 ** Indicate that the accordion javascript is needed.
704 */
705 void style_accordion(void){
706 needAccordionJs = 1;
707 }
708
709 /*
710 ** Indicate that the timeline graph javascript is needed.
711 */
712 void style_graph_generator(void){
713 needGraphJs = 1;
714 }
715
716 /*
717 ** Indicate that the copy button javascript is needed.
718 */
719 void style_copybutton_control(void){
720 needCopyBtnJs = 1;
721 }
722
723 /*
724 ** Generate code to load a single javascript file
725 */
726 void style_load_one_js_file(const char *zFile){
727 @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
728 }
729
730 /*
731 ** All extra JS files to load.
732 */
733 static const char *azJsToLoad[4];
734 static int nJsToLoad = 0;
735
736 /*
737 ** Register a new JS file to load at the end of the document.
738 */
739 void style_load_js(const char *zName){
740 int i;
741 for(i=0; i<nJsToLoad; i++){
742 if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return;
743 }
744 if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){
745 fossil_panic("too many JS files");
746 }
747 azJsToLoad[nJsToLoad++] = zName;
748 }
749
750 /*
751 ** Generate code to load all required javascript files.
752 */
753 static void style_load_all_js_files(void){
754 int i;
755 if( needHrefJs ){
756 int nDelay = db_get_int("auto-hyperlink-delay",0);
757 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
758 @ <script id='href-data' type='application/json'>\
759 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
762 @ function debugMsg(msg){
763 @ var n = document.getElementById("debugMsg");
764 @ if(n){n.textContent=msg;}
765 @ }
766 if( needHrefJs ){
 
767 cgi_append_content(builtin_text("href.js"),-1);
768 }
769 if( needSortJs ){
770 cgi_append_content(builtin_text("sorttable.js"),-1);
771 }
772 if( needGraphJs ){
773 cgi_append_content(builtin_text("graph.js"),-1);
774 }
775 if( needCopyBtnJs ){
776 cgi_append_content(builtin_text("copybtn.js"),-1);
777 }
778 if( needAccordionJs ){
779 cgi_append_content(builtin_text("accordion.js"),-1);
780 }
781 for(i=0; i<nJsToLoad; i++){
782 cgi_append_content(builtin_text(azJsToLoad[i]),-1);
783 }
784 if( blob_size(&blobOnLoad)>0 ){
785 @ window.onload = function(){
786 cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
787 cgi_append_content("\n}\n", -1);
788 }
789 @ </script>
790 }
791
792 /*
793 ** Extra JS to run after all content is loaded.
794 */
795 void style_js_onload(const char *zFormat, ...){
796 va_list ap;
797 va_start(ap, zFormat);
798 blob_vappendf(&blobOnLoad, zFormat, ap);
799 va_end(ap);
800 }
801
802 /*
803 ** Draw the footer at the bottom of the page.
804 */
@@ -916,11 +840,11 @@
916 @ </div>
917 if( nSubmenuCtrl ){
918 cgi_query_parameters_to_hidden();
919 cgi_tag_query_parameter(0);
920 @ </form>
921 style_load_one_js_file("menu.js");
922 }
923 }
924
925 zAd = style_adunit_text(&mAdFlags);
926 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1127,109 +1051,10 @@
1127
1128 /* Tell CGI that the content returned by this page is considered cacheable */
1129 g.isConst = 1;
1130 }
1131
1132 /*
1133 ** Maps a "bundle" name to a callback which emits the text of that
1134 ** bundle. For use in consolidating scripts for certain pages into a
1135 ** single cacheable request.
1136 */
1137 typedef struct {
1138 const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */
1139 void (*xEmit)(void); /* Emits amalgamated text output for this
1140 bundle */
1141 } BundleEmitter;
1142 /*
1143 ** Map each required bundle here...
1144 */
1145 static const BundleEmitter BundleEmitters[] = {
1146 /* Keep these sorted for bsearch() */
1147 {"fileedit.js", fileedit_emit_js_bundle},
1148 {"forum.js", forumpost_emit_js_bundle},
1149 {"wikiedit.js", wikiedit_emit_js_bundle}
1150 };
1151
1152 /*
1153 ** Comparison function for bsearch() for searching a BundleEmitter
1154 ** list for a matching name.
1155 */
1156 static int cmp_builtin_bundle_name(const void *a, const void *b){
1157 const BundleEmitter * rA = (const BundleEmitter*)a;
1158 const BundleEmitter * rB = (const BundleEmitter*)b;
1159 return fossil_strcmp(rA->zName, rB->zName);
1160 }
1161
1162 /*
1163 ** Internal helper for /builtin/FILENAME for dispatching "bundles"
1164 ** of amalgamated text (primarily JS) code.
1165 **
1166 ** Returns true if it finds a bundle matcing the given name, else
1167 ** false. On success it outputs the amalgamated bundle without any
1168 ** sort of wrapper, e.g. SCRIPT tag
1169 */
1170 static int page_builtin_text_bundle(const char * zFilename){
1171 const BundleEmitter * pBH;
1172 BundleEmitter needle = {zFilename, 0};
1173
1174 pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters,
1175 count(BundleEmitters),
1176 sizeof BundleEmitters[0],
1177 cmp_builtin_bundle_name);
1178 if(pBH!=0){
1179 pBH->xEmit();
1180 }
1181 return pBH!=0;
1182 }
1183
1184 /*
1185 ** WEBPAGE: builtin
1186 ** URL: builtin/FILENAME
1187 **
1188 ** Return the built-in text given by FILENAME. This is used internally
1189 ** by many Fossil web pages to load built-in javascript files.
1190 **
1191 ** If the id= parameter is present, then Fossil assumes that the
1192 ** result is immutable and sets a very large cache retention time (1
1193 ** year).
1194 */
1195 void page_builtin_text(void){
1196 Blob out;
1197 const char *zName = P("name");
1198 const char *zTxt = 0;
1199 const char *zId = P("id");
1200 int nId;
1201 int isBundle = 0;
1202
1203 if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
1204 g.isConst = 1;
1205 }else{
1206 etag_check(0,0)/*might not return*/;
1207 }
1208 if( zName ){
1209 if( sqlite3_strglob("*.js", zName)==0 ){
1210 cgi_set_content_type("application/javascript");
1211 }else{
1212 cgi_set_content_type("text/plain");
1213 }
1214 if(':'==zName[0]){
1215 isBundle = 1;
1216 zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL;
1217 }else{
1218 zTxt = builtin_text(zName);
1219 }
1220 }
1221 if( zTxt==0 ){
1222 cgi_set_content_type("text/html");
1223 cgi_set_status(404, "Not Found");
1224 @ File "%h(zName)" not found
1225 }else if(isBundle==0){
1226 blob_init(&out, zTxt, -1);
1227 cgi_set_content(&out);
1228 }
1229 }
1230
1231 /*
1232 ** All possible capabilities
1233 */
1234 static const char allCap[] =
1235 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
@@ -1605,21 +1430,18 @@
1605 ** 1) window.fossil core object, some of which depends on C-lelel
1606 ** runtime data. That part of the script is always emitted inline. If
1607 ** addScripTag is true then it is wrapped in its own SCRIPT tag, else
1608 ** it is assumed that the caller already opened a tag.
1609 **
1610 ** 2) Emits the static fossil.bootstrap.js. If asInline is true then
1611 ** it is emitted inline with the components from (1), else it is
1612 ** emitted as a separate SCRIPT tag with
1613 ** src=/builtin/fossil.bootstrap.js (so causes another HTTP request).
1614 */
1615 void style_emit_script_fossil_bootstrap(int asInline){
1616 static int once = 0;
1617 if(0==once++){
1618 /* Set up the generic/app-agnostic parts of window.fossil
1619 ** which require C-level state... */
1620 if(asInline==0){
1621 style_emit_script_tag(0,0);
1622 }
1623 CX("(function(){\n"
1624 "if(!window.fossil) window.fossil={};\n"
1625 "window.fossil.version = %!j;\n"
@@ -1646,18 +1468,16 @@
1646 */
1647 CX("window.fossil.page = {"
1648 "name:\"%T\""
1649 "};\n", g.zPath);
1650 CX("})();\n");
1651 /* The remaining fossil object bootstrap code is not dependent on
1652 ** C-runtime state... */
1653 if(asInline!=0){
1654 CX("%s\n", builtin_text("fossil.bootstrap.js"));
1655 }else{
1656 style_emit_script_tag(1,0);
1657 style_emit_script_builtin(0,1,"fossil.bootstrap.js");
1658 }
 
 
 
1659 }
1660 }
1661
1662 /*
1663 ** If passed 0 as its first argument, it emits a script opener tag
@@ -1688,116 +1508,33 @@
1688 CX("</script>\n");
1689 }
1690 }
1691
1692 /*
1693 ** Emits a script tag which uses content from a builtin script file.
1694 **
1695 ** If asInline is false, the script is emitted as a SCRIPT tag with a
1696 ** src attribute of /builtin/zName and the 2nd parameter is
1697 ** ignored. If asInline is true then the contents of the script are
1698 ** emitted directly, with a wrapping SCRIPT tag if addScripTag is
1699 ** true, else no wrapping script tag..
1700 **
1701 ** If it is false, a script tag loading it via
1702 ** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a
1703 ** build-time-dependent cache-buster value.
1704 */
1705 void style_emit_script_builtin(int asInline, int addScripTag,
1706 char const * zName){
1707 if(asInline){
1708 if(addScripTag){
1709 style_emit_script_tag(0,0);
1710 }
1711 CX("%s", builtin_text(zName));
1712 if(addScripTag){
1713 style_emit_script_tag(1,0);
1714 }
1715 }else{
1716 char * zFullName = mprintf("builtin/%s",zName);
1717 const char * zHash = fossil_exe_id();
1718 CX("<script src='%R/%T?cache=%.8s'></script>\n",
1719 zFullName, zHash);
1720 fossil_free(zFullName);
1721 }
1722 }
1723
1724 /*
1725 ** A convenience wrapper arond style_emit_script_builtin() which
1726 ** prepends a ':' to zName and passes (0,0,newName) to that
1727 ** function. i.e. it emits a SCRIPT tag with
1728 ** src=.../builtin/:${zName}?cache=.... The given name is assumed to
1729 ** have been added to the style.c:BundleEmitters map.
1730 */
1731 void style_emit_script_bundle(char const * zName){
1732 char *zBundle = mprintf(":%s", zName);
1733 style_emit_script_builtin(0, 0, zBundle);
1734 fossil_free(zBundle);
1735 }
1736
1737 /*
1738 ** The first time this is called it emits the JS code from the
1739 ** built-in file fossil.fossil.js. Subsequent calls are no-ops.
1740 **
1741 ** If passed a true first argument, it emits the contents directly
1742 ** to the page output, else it emits a script tag with a
1743 ** src=builtin/... to load the script.
1744 **
1745 ** If asInline is true and addScripTag is true then the contents
1746 ** are emitted directly but wrapped in a SCRIPT tag. If asInline
1747 ** is false, addScriptTag is ignored.
1748 **
1749 ** Note that this code relies on that loaded via
1750 ** style_emit_script_fossil_bootstrap() but it does not call that
1751 ** routine.
1752 */
1753 void style_emit_script_fetch(int asInline, int addScripTag){
1754 static int once = 0;
1755 if(0==once++){
1756 style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js");
1757 }
1758 }
1759
1760 /*
1761 ** The first time this is called it emits the JS code from the
1762 ** built-in file fossil.dom.js. Subsequent calls are no-ops.
1763 **
1764 ** If passed a true first argument, it emits the contents directly
1765 ** to the page output, else it emits a script tag with a
1766 ** src=builtin/... to load the script.
1767 **
1768 ** If asInline is true and addScripTag is true then the contents
1769 ** are emitted directly but wrapped in a SCRIPT tag. If asInline
1770 ** is false, addScriptTag is ignored.
1771 **
1772 ** Note that this code relies on that loaded via
1773 ** style_emit_script_fossil_bootstrap(), but it does not call that
1774 ** routine.
1775 */
1776 void style_emit_script_dom(int asInline, int addScripTag){
1777 static int once = 0;
1778 if(0==once++){
1779 style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js");
1780 }
1781 }
1782
1783 /*
1784 ** The fossil.tabs.js counterpart of style_emit_script_fetch().
1785 ** Also emits fossil.dom.js.
1786 */
1787 void style_emit_script_tabs(int asInline, int addScripTag){
1788 static int once = 0;
1789 if(0==once++){
1790 style_emit_script_dom(asInline, addScripTag);
1791 style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js");
1792 }
1793 }
1794
1795 /*
1796 ** The fossil.confirmer.js counterpart of style_emit_script_fetch().
1797 */
1798 void style_emit_script_confirmer(int asInline, int addScripTag){
1799 static int once = 0;
1800 if(0==once++){
1801 style_emit_script_builtin(asInline, 0, "fossil.confirmer.js");
1802 }
1803 }
1804
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
88
89 /*
90 ** Flags for various javascript files needed prior to </body>
91 */
92 static int needHrefJs = 0; /* href.js */
 
 
 
 
93
94 /*
95 ** Extra JS added to the end of the file.
96 */
97 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
480 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
481 zTargetId,zText,zTargetId,zTargetId,cchLength);
482 }
483 }
484 free(zText);
485 builtin_request_js("copybtn.js");
486 return zResult;
487 }
488
489 /*
490 ** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
690
691 /*
692 ** Indicate that the table-sorting javascript is needed.
693 */
694 void style_table_sorter(void){
695 builtin_request_js("sorttable.js");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696 }
697
698 /*
699 ** Generate code to load all required javascript files.
700 */
701 static void style_load_all_js_files(void){
 
702 if( needHrefJs ){
703 int nDelay = db_get_int("auto-hyperlink-delay",0);
704 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
705 @ <script id='href-data' type='application/json'>\
706 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
709 @ function debugMsg(msg){
710 @ var n = document.getElementById("debugMsg");
711 @ if(n){n.textContent=msg;}
712 @ }
713 if( needHrefJs ){
714 @ /* href.js */
715 cgi_append_content(builtin_text("href.js"),-1);
716 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
717 if( blob_size(&blobOnLoad)>0 ){
718 @ window.onload = function(){
719 cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
720 cgi_append_content("\n}\n", -1);
721 }
722 @ </script>
723 builtin_fulfill_js_requests();
 
 
 
 
 
 
 
 
 
724 }
725
726 /*
727 ** Draw the footer at the bottom of the page.
728 */
@@ -916,11 +840,11 @@
840 @ </div>
841 if( nSubmenuCtrl ){
842 cgi_query_parameters_to_hidden();
843 cgi_tag_query_parameter(0);
844 @ </form>
845 builtin_request_js("menu.js");
846 }
847 }
848
849 zAd = style_adunit_text(&mAdFlags);
850 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1127,109 +1051,10 @@
1051
1052 /* Tell CGI that the content returned by this page is considered cacheable */
1053 g.isConst = 1;
1054 }
1055
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1056 /*
1057 ** All possible capabilities
1058 */
1059 static const char allCap[] =
1060 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
@@ -1605,21 +1430,18 @@
1430 ** 1) window.fossil core object, some of which depends on C-lelel
1431 ** runtime data. That part of the script is always emitted inline. If
1432 ** addScripTag is true then it is wrapped in its own SCRIPT tag, else
1433 ** it is assumed that the caller already opened a tag.
1434 **
1435 ** 2) Emits the static fossil.bootstrap.js using builtin_request_js().
 
 
 
1436 */
1437 void style_emit_script_fossil_bootstrap(int addScriptTag){
1438 static int once = 0;
1439 if(0==once++){
1440 /* Set up the generic/app-agnostic parts of window.fossil
1441 ** which require C-level state... */
1442 if(addScriptTag!=0){
1443 style_emit_script_tag(0,0);
1444 }
1445 CX("(function(){\n"
1446 "if(!window.fossil) window.fossil={};\n"
1447 "window.fossil.version = %!j;\n"
@@ -1646,18 +1468,16 @@
1468 */
1469 CX("window.fossil.page = {"
1470 "name:\"%T\""
1471 "};\n", g.zPath);
1472 CX("})();\n");
1473 if(addScriptTag!=0){
 
 
 
 
1474 style_emit_script_tag(1,0);
 
1475 }
1476 /* The remaining window.fossil bootstrap code is not dependent on
1477 ** C-runtime state... */
1478 builtin_request_js("fossil.bootstrap.js");
1479 }
1480 }
1481
1482 /*
1483 ** If passed 0 as its first argument, it emits a script opener tag
@@ -1688,116 +1508,33 @@
1508 CX("</script>\n");
1509 }
1510 }
1511
1512 /*
1513 ** Convenience wrapper which calls builtin_request_js() for a series
1514 ** of builtin scripts named fossil.NAME.js. The first time it is
1515 ** called, it also calls style_emit_script_fossil_bootstrap() to
1516 ** initialize the window.fossil JS API. The first argument is a
1517 ** no-meaning dummy required by the va_start() interface. All
1518 ** subsequent arguments must be strings of the NAME part of
1519 ** fossil.NAME.js, followed by a NULL argument to terminate the list.
1520 **
1521 ** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3
1522 ** APIs. Do not forget the trailing 0!
1523 */
1524 void style_emit_fossil_js_apis( int dummy, ... ) {
1525 static int once = 0;
1526 const char *zArg;
1527 char * zName;
1528 va_list vargs;
1529
1530 if(0==once++){
1531 style_emit_script_fossil_bootstrap(1);
1532 }
1533 va_start(vargs,dummy);
1534 while( (zArg = va_arg (vargs, const char *))!=0 ){
1535 zName = mprintf("fossil.%s.js", zArg);
1536 builtin_request_js(zName);
1537 fossil_free(zName);
1538 }
1539 va_end(vargs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1540 }
1541
+39 -302
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
8888
8989
/*
9090
** Flags for various javascript files needed prior to </body>
9191
*/
9292
static int needHrefJs = 0; /* href.js */
93
-static int needSortJs = 0; /* sorttable.js */
94
-static int needGraphJs = 0; /* graph.js */
95
-static int needCopyBtnJs = 0; /* copybtn.js */
96
-static int needAccordionJs = 0; /* accordion.js */
9793
9894
/*
9995
** Extra JS added to the end of the file.
10096
*/
10197
static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
484480
zBtnFmt/*works-like:"%h%s%h%h%d"*/,
485481
zTargetId,zText,zTargetId,zTargetId,cchLength);
486482
}
487483
}
488484
free(zText);
489
- style_copybutton_control();
485
+ builtin_request_js("copybtn.js");
490486
return zResult;
491487
}
492488
493489
/*
494490
** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
694690
695691
/*
696692
** Indicate that the table-sorting javascript is needed.
697693
*/
698694
void style_table_sorter(void){
699
- needSortJs = 1;
700
-}
701
-
702
-/*
703
-** Indicate that the accordion javascript is needed.
704
-*/
705
-void style_accordion(void){
706
- needAccordionJs = 1;
707
-}
708
-
709
-/*
710
-** Indicate that the timeline graph javascript is needed.
711
-*/
712
-void style_graph_generator(void){
713
- needGraphJs = 1;
714
-}
715
-
716
-/*
717
-** Indicate that the copy button javascript is needed.
718
-*/
719
-void style_copybutton_control(void){
720
- needCopyBtnJs = 1;
721
-}
722
-
723
-/*
724
-** Generate code to load a single javascript file
725
-*/
726
-void style_load_one_js_file(const char *zFile){
727
- @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
728
-}
729
-
730
-/*
731
-** All extra JS files to load.
732
-*/
733
-static const char *azJsToLoad[4];
734
-static int nJsToLoad = 0;
735
-
736
-/*
737
-** Register a new JS file to load at the end of the document.
738
-*/
739
-void style_load_js(const char *zName){
740
- int i;
741
- for(i=0; i<nJsToLoad; i++){
742
- if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return;
743
- }
744
- if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){
745
- fossil_panic("too many JS files");
746
- }
747
- azJsToLoad[nJsToLoad++] = zName;
695
+ builtin_request_js("sorttable.js");
748696
}
749697
750698
/*
751699
** Generate code to load all required javascript files.
752700
*/
753701
static void style_load_all_js_files(void){
754
- int i;
755702
if( needHrefJs ){
756703
int nDelay = db_get_int("auto-hyperlink-delay",0);
757704
int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
758705
@ <script id='href-data' type='application/json'>\
759706
@ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
762709
@ function debugMsg(msg){
763710
@ var n = document.getElementById("debugMsg");
764711
@ if(n){n.textContent=msg;}
765712
@ }
766713
if( needHrefJs ){
714
+ @ /* href.js */
767715
cgi_append_content(builtin_text("href.js"),-1);
768716
}
769
- if( needSortJs ){
770
- cgi_append_content(builtin_text("sorttable.js"),-1);
771
- }
772
- if( needGraphJs ){
773
- cgi_append_content(builtin_text("graph.js"),-1);
774
- }
775
- if( needCopyBtnJs ){
776
- cgi_append_content(builtin_text("copybtn.js"),-1);
777
- }
778
- if( needAccordionJs ){
779
- cgi_append_content(builtin_text("accordion.js"),-1);
780
- }
781
- for(i=0; i<nJsToLoad; i++){
782
- cgi_append_content(builtin_text(azJsToLoad[i]),-1);
783
- }
784717
if( blob_size(&blobOnLoad)>0 ){
785718
@ window.onload = function(){
786719
cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
787720
cgi_append_content("\n}\n", -1);
788721
}
789722
@ </script>
790
-}
791
-
792
-/*
793
-** Extra JS to run after all content is loaded.
794
-*/
795
-void style_js_onload(const char *zFormat, ...){
796
- va_list ap;
797
- va_start(ap, zFormat);
798
- blob_vappendf(&blobOnLoad, zFormat, ap);
799
- va_end(ap);
723
+ builtin_fulfill_js_requests();
800724
}
801725
802726
/*
803727
** Draw the footer at the bottom of the page.
804728
*/
@@ -916,11 +840,11 @@
916840
@ </div>
917841
if( nSubmenuCtrl ){
918842
cgi_query_parameters_to_hidden();
919843
cgi_tag_query_parameter(0);
920844
@ </form>
921
- style_load_one_js_file("menu.js");
845
+ builtin_request_js("menu.js");
922846
}
923847
}
924848
925849
zAd = style_adunit_text(&mAdFlags);
926850
if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1127,109 +1051,10 @@
11271051
11281052
/* Tell CGI that the content returned by this page is considered cacheable */
11291053
g.isConst = 1;
11301054
}
11311055
1132
-/*
1133
-** Maps a "bundle" name to a callback which emits the text of that
1134
-** bundle. For use in consolidating scripts for certain pages into a
1135
-** single cacheable request.
1136
-*/
1137
-typedef struct {
1138
- const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */
1139
- void (*xEmit)(void); /* Emits amalgamated text output for this
1140
- bundle */
1141
-} BundleEmitter;
1142
-/*
1143
-** Map each required bundle here...
1144
-*/
1145
-static const BundleEmitter BundleEmitters[] = {
1146
-/* Keep these sorted for bsearch() */
1147
-{"fileedit.js", fileedit_emit_js_bundle},
1148
-{"forum.js", forumpost_emit_js_bundle},
1149
-{"wikiedit.js", wikiedit_emit_js_bundle}
1150
-};
1151
-
1152
-/*
1153
-** Comparison function for bsearch() for searching a BundleEmitter
1154
-** list for a matching name.
1155
-*/
1156
-static int cmp_builtin_bundle_name(const void *a, const void *b){
1157
- const BundleEmitter * rA = (const BundleEmitter*)a;
1158
- const BundleEmitter * rB = (const BundleEmitter*)b;
1159
- return fossil_strcmp(rA->zName, rB->zName);
1160
-}
1161
-
1162
-/*
1163
-** Internal helper for /builtin/FILENAME for dispatching "bundles"
1164
-** of amalgamated text (primarily JS) code.
1165
-**
1166
-** Returns true if it finds a bundle matcing the given name, else
1167
-** false. On success it outputs the amalgamated bundle without any
1168
-** sort of wrapper, e.g. SCRIPT tag
1169
-*/
1170
-static int page_builtin_text_bundle(const char * zFilename){
1171
- const BundleEmitter * pBH;
1172
- BundleEmitter needle = {zFilename, 0};
1173
-
1174
- pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters,
1175
- count(BundleEmitters),
1176
- sizeof BundleEmitters[0],
1177
- cmp_builtin_bundle_name);
1178
- if(pBH!=0){
1179
- pBH->xEmit();
1180
- }
1181
- return pBH!=0;
1182
-}
1183
-
1184
-/*
1185
-** WEBPAGE: builtin
1186
-** URL: builtin/FILENAME
1187
-**
1188
-** Return the built-in text given by FILENAME. This is used internally
1189
-** by many Fossil web pages to load built-in javascript files.
1190
-**
1191
-** If the id= parameter is present, then Fossil assumes that the
1192
-** result is immutable and sets a very large cache retention time (1
1193
-** year).
1194
-*/
1195
-void page_builtin_text(void){
1196
- Blob out;
1197
- const char *zName = P("name");
1198
- const char *zTxt = 0;
1199
- const char *zId = P("id");
1200
- int nId;
1201
- int isBundle = 0;
1202
-
1203
- if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
1204
- g.isConst = 1;
1205
- }else{
1206
- etag_check(0,0)/*might not return*/;
1207
- }
1208
- if( zName ){
1209
- if( sqlite3_strglob("*.js", zName)==0 ){
1210
- cgi_set_content_type("application/javascript");
1211
- }else{
1212
- cgi_set_content_type("text/plain");
1213
- }
1214
- if(':'==zName[0]){
1215
- isBundle = 1;
1216
- zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL;
1217
- }else{
1218
- zTxt = builtin_text(zName);
1219
- }
1220
- }
1221
- if( zTxt==0 ){
1222
- cgi_set_content_type("text/html");
1223
- cgi_set_status(404, "Not Found");
1224
- @ File "%h(zName)" not found
1225
- }else if(isBundle==0){
1226
- blob_init(&out, zTxt, -1);
1227
- cgi_set_content(&out);
1228
- }
1229
-}
1230
-
12311056
/*
12321057
** All possible capabilities
12331058
*/
12341059
static const char allCap[] =
12351060
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
@@ -1605,21 +1430,18 @@
16051430
** 1) window.fossil core object, some of which depends on C-lelel
16061431
** runtime data. That part of the script is always emitted inline. If
16071432
** addScripTag is true then it is wrapped in its own SCRIPT tag, else
16081433
** it is assumed that the caller already opened a tag.
16091434
**
1610
-** 2) Emits the static fossil.bootstrap.js. If asInline is true then
1611
-** it is emitted inline with the components from (1), else it is
1612
-** emitted as a separate SCRIPT tag with
1613
-** src=/builtin/fossil.bootstrap.js (so causes another HTTP request).
1435
+** 2) Emits the static fossil.bootstrap.js using builtin_request_js().
16141436
*/
1615
-void style_emit_script_fossil_bootstrap(int asInline){
1437
+void style_emit_script_fossil_bootstrap(int addScriptTag){
16161438
static int once = 0;
16171439
if(0==once++){
16181440
/* Set up the generic/app-agnostic parts of window.fossil
16191441
** which require C-level state... */
1620
- if(asInline==0){
1442
+ if(addScriptTag!=0){
16211443
style_emit_script_tag(0,0);
16221444
}
16231445
CX("(function(){\n"
16241446
"if(!window.fossil) window.fossil={};\n"
16251447
"window.fossil.version = %!j;\n"
@@ -1646,18 +1468,16 @@
16461468
*/
16471469
CX("window.fossil.page = {"
16481470
"name:\"%T\""
16491471
"};\n", g.zPath);
16501472
CX("})();\n");
1651
- /* The remaining fossil object bootstrap code is not dependent on
1652
- ** C-runtime state... */
1653
- if(asInline!=0){
1654
- CX("%s\n", builtin_text("fossil.bootstrap.js"));
1655
- }else{
1473
+ if(addScriptTag!=0){
16561474
style_emit_script_tag(1,0);
1657
- style_emit_script_builtin(0,1,"fossil.bootstrap.js");
16581475
}
1476
+ /* The remaining window.fossil bootstrap code is not dependent on
1477
+ ** C-runtime state... */
1478
+ builtin_request_js("fossil.bootstrap.js");
16591479
}
16601480
}
16611481
16621482
/*
16631483
** If passed 0 as its first argument, it emits a script opener tag
@@ -1688,116 +1508,33 @@
16881508
CX("</script>\n");
16891509
}
16901510
}
16911511
16921512
/*
1693
-** Emits a script tag which uses content from a builtin script file.
1694
-**
1695
-** If asInline is false, the script is emitted as a SCRIPT tag with a
1696
-** src attribute of /builtin/zName and the 2nd parameter is
1697
-** ignored. If asInline is true then the contents of the script are
1698
-** emitted directly, with a wrapping SCRIPT tag if addScripTag is
1699
-** true, else no wrapping script tag..
1700
-**
1701
-** If it is false, a script tag loading it via
1702
-** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a
1703
-** build-time-dependent cache-buster value.
1704
-*/
1705
-void style_emit_script_builtin(int asInline, int addScripTag,
1706
- char const * zName){
1707
- if(asInline){
1708
- if(addScripTag){
1709
- style_emit_script_tag(0,0);
1710
- }
1711
- CX("%s", builtin_text(zName));
1712
- if(addScripTag){
1713
- style_emit_script_tag(1,0);
1714
- }
1715
- }else{
1716
- char * zFullName = mprintf("builtin/%s",zName);
1717
- const char * zHash = fossil_exe_id();
1718
- CX("<script src='%R/%T?cache=%.8s'></script>\n",
1719
- zFullName, zHash);
1720
- fossil_free(zFullName);
1721
- }
1722
-}
1723
-
1724
-/*
1725
-** A convenience wrapper arond style_emit_script_builtin() which
1726
-** prepends a ':' to zName and passes (0,0,newName) to that
1727
-** function. i.e. it emits a SCRIPT tag with
1728
-** src=.../builtin/:${zName}?cache=.... The given name is assumed to
1729
-** have been added to the style.c:BundleEmitters map.
1730
-*/
1731
-void style_emit_script_bundle(char const * zName){
1732
- char *zBundle = mprintf(":%s", zName);
1733
- style_emit_script_builtin(0, 0, zBundle);
1734
- fossil_free(zBundle);
1735
-}
1736
-
1737
-/*
1738
-** The first time this is called it emits the JS code from the
1739
-** built-in file fossil.fossil.js. Subsequent calls are no-ops.
1740
-**
1741
-** If passed a true first argument, it emits the contents directly
1742
-** to the page output, else it emits a script tag with a
1743
-** src=builtin/... to load the script.
1744
-**
1745
-** If asInline is true and addScripTag is true then the contents
1746
-** are emitted directly but wrapped in a SCRIPT tag. If asInline
1747
-** is false, addScriptTag is ignored.
1748
-**
1749
-** Note that this code relies on that loaded via
1750
-** style_emit_script_fossil_bootstrap() but it does not call that
1751
-** routine.
1752
-*/
1753
-void style_emit_script_fetch(int asInline, int addScripTag){
1754
- static int once = 0;
1755
- if(0==once++){
1756
- style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js");
1757
- }
1758
-}
1759
-
1760
-/*
1761
-** The first time this is called it emits the JS code from the
1762
-** built-in file fossil.dom.js. Subsequent calls are no-ops.
1763
-**
1764
-** If passed a true first argument, it emits the contents directly
1765
-** to the page output, else it emits a script tag with a
1766
-** src=builtin/... to load the script.
1767
-**
1768
-** If asInline is true and addScripTag is true then the contents
1769
-** are emitted directly but wrapped in a SCRIPT tag. If asInline
1770
-** is false, addScriptTag is ignored.
1771
-**
1772
-** Note that this code relies on that loaded via
1773
-** style_emit_script_fossil_bootstrap(), but it does not call that
1774
-** routine.
1775
-*/
1776
-void style_emit_script_dom(int asInline, int addScripTag){
1777
- static int once = 0;
1778
- if(0==once++){
1779
- style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js");
1780
- }
1781
-}
1782
-
1783
-/*
1784
-** The fossil.tabs.js counterpart of style_emit_script_fetch().
1785
-** Also emits fossil.dom.js.
1786
-*/
1787
-void style_emit_script_tabs(int asInline, int addScripTag){
1788
- static int once = 0;
1789
- if(0==once++){
1790
- style_emit_script_dom(asInline, addScripTag);
1791
- style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js");
1792
- }
1793
-}
1794
-
1795
-/*
1796
-** The fossil.confirmer.js counterpart of style_emit_script_fetch().
1797
-*/
1798
-void style_emit_script_confirmer(int asInline, int addScripTag){
1799
- static int once = 0;
1800
- if(0==once++){
1801
- style_emit_script_builtin(asInline, 0, "fossil.confirmer.js");
1802
- }
1513
+** Convenience wrapper which calls builtin_request_js() for a series
1514
+** of builtin scripts named fossil.NAME.js. The first time it is
1515
+** called, it also calls style_emit_script_fossil_bootstrap() to
1516
+** initialize the window.fossil JS API. The first argument is a
1517
+** no-meaning dummy required by the va_start() interface. All
1518
+** subsequent arguments must be strings of the NAME part of
1519
+** fossil.NAME.js, followed by a NULL argument to terminate the list.
1520
+**
1521
+** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3
1522
+** APIs. Do not forget the trailing 0!
1523
+*/
1524
+void style_emit_fossil_js_apis( int dummy, ... ) {
1525
+ static int once = 0;
1526
+ const char *zArg;
1527
+ char * zName;
1528
+ va_list vargs;
1529
+
1530
+ if(0==once++){
1531
+ style_emit_script_fossil_bootstrap(1);
1532
+ }
1533
+ va_start(vargs,dummy);
1534
+ while( (zArg = va_arg (vargs, const char *))!=0 ){
1535
+ zName = mprintf("fossil.%s.js", zArg);
1536
+ builtin_request_js(zName);
1537
+ fossil_free(zName);
1538
+ }
1539
+ va_end(vargs);
18031540
}
18041541
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
88
89 /*
90 ** Flags for various javascript files needed prior to </body>
91 */
92 static int needHrefJs = 0; /* href.js */
93 static int needSortJs = 0; /* sorttable.js */
94 static int needGraphJs = 0; /* graph.js */
95 static int needCopyBtnJs = 0; /* copybtn.js */
96 static int needAccordionJs = 0; /* accordion.js */
97
98 /*
99 ** Extra JS added to the end of the file.
100 */
101 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
484 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
485 zTargetId,zText,zTargetId,zTargetId,cchLength);
486 }
487 }
488 free(zText);
489 style_copybutton_control();
490 return zResult;
491 }
492
493 /*
494 ** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
694
695 /*
696 ** Indicate that the table-sorting javascript is needed.
697 */
698 void style_table_sorter(void){
699 needSortJs = 1;
700 }
701
702 /*
703 ** Indicate that the accordion javascript is needed.
704 */
705 void style_accordion(void){
706 needAccordionJs = 1;
707 }
708
709 /*
710 ** Indicate that the timeline graph javascript is needed.
711 */
712 void style_graph_generator(void){
713 needGraphJs = 1;
714 }
715
716 /*
717 ** Indicate that the copy button javascript is needed.
718 */
719 void style_copybutton_control(void){
720 needCopyBtnJs = 1;
721 }
722
723 /*
724 ** Generate code to load a single javascript file
725 */
726 void style_load_one_js_file(const char *zFile){
727 @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
728 }
729
730 /*
731 ** All extra JS files to load.
732 */
733 static const char *azJsToLoad[4];
734 static int nJsToLoad = 0;
735
736 /*
737 ** Register a new JS file to load at the end of the document.
738 */
739 void style_load_js(const char *zName){
740 int i;
741 for(i=0; i<nJsToLoad; i++){
742 if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return;
743 }
744 if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){
745 fossil_panic("too many JS files");
746 }
747 azJsToLoad[nJsToLoad++] = zName;
748 }
749
750 /*
751 ** Generate code to load all required javascript files.
752 */
753 static void style_load_all_js_files(void){
754 int i;
755 if( needHrefJs ){
756 int nDelay = db_get_int("auto-hyperlink-delay",0);
757 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
758 @ <script id='href-data' type='application/json'>\
759 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
762 @ function debugMsg(msg){
763 @ var n = document.getElementById("debugMsg");
764 @ if(n){n.textContent=msg;}
765 @ }
766 if( needHrefJs ){
 
767 cgi_append_content(builtin_text("href.js"),-1);
768 }
769 if( needSortJs ){
770 cgi_append_content(builtin_text("sorttable.js"),-1);
771 }
772 if( needGraphJs ){
773 cgi_append_content(builtin_text("graph.js"),-1);
774 }
775 if( needCopyBtnJs ){
776 cgi_append_content(builtin_text("copybtn.js"),-1);
777 }
778 if( needAccordionJs ){
779 cgi_append_content(builtin_text("accordion.js"),-1);
780 }
781 for(i=0; i<nJsToLoad; i++){
782 cgi_append_content(builtin_text(azJsToLoad[i]),-1);
783 }
784 if( blob_size(&blobOnLoad)>0 ){
785 @ window.onload = function(){
786 cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
787 cgi_append_content("\n}\n", -1);
788 }
789 @ </script>
790 }
791
792 /*
793 ** Extra JS to run after all content is loaded.
794 */
795 void style_js_onload(const char *zFormat, ...){
796 va_list ap;
797 va_start(ap, zFormat);
798 blob_vappendf(&blobOnLoad, zFormat, ap);
799 va_end(ap);
800 }
801
802 /*
803 ** Draw the footer at the bottom of the page.
804 */
@@ -916,11 +840,11 @@
916 @ </div>
917 if( nSubmenuCtrl ){
918 cgi_query_parameters_to_hidden();
919 cgi_tag_query_parameter(0);
920 @ </form>
921 style_load_one_js_file("menu.js");
922 }
923 }
924
925 zAd = style_adunit_text(&mAdFlags);
926 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1127,109 +1051,10 @@
1127
1128 /* Tell CGI that the content returned by this page is considered cacheable */
1129 g.isConst = 1;
1130 }
1131
1132 /*
1133 ** Maps a "bundle" name to a callback which emits the text of that
1134 ** bundle. For use in consolidating scripts for certain pages into a
1135 ** single cacheable request.
1136 */
1137 typedef struct {
1138 const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */
1139 void (*xEmit)(void); /* Emits amalgamated text output for this
1140 bundle */
1141 } BundleEmitter;
1142 /*
1143 ** Map each required bundle here...
1144 */
1145 static const BundleEmitter BundleEmitters[] = {
1146 /* Keep these sorted for bsearch() */
1147 {"fileedit.js", fileedit_emit_js_bundle},
1148 {"forum.js", forumpost_emit_js_bundle},
1149 {"wikiedit.js", wikiedit_emit_js_bundle}
1150 };
1151
1152 /*
1153 ** Comparison function for bsearch() for searching a BundleEmitter
1154 ** list for a matching name.
1155 */
1156 static int cmp_builtin_bundle_name(const void *a, const void *b){
1157 const BundleEmitter * rA = (const BundleEmitter*)a;
1158 const BundleEmitter * rB = (const BundleEmitter*)b;
1159 return fossil_strcmp(rA->zName, rB->zName);
1160 }
1161
1162 /*
1163 ** Internal helper for /builtin/FILENAME for dispatching "bundles"
1164 ** of amalgamated text (primarily JS) code.
1165 **
1166 ** Returns true if it finds a bundle matcing the given name, else
1167 ** false. On success it outputs the amalgamated bundle without any
1168 ** sort of wrapper, e.g. SCRIPT tag
1169 */
1170 static int page_builtin_text_bundle(const char * zFilename){
1171 const BundleEmitter * pBH;
1172 BundleEmitter needle = {zFilename, 0};
1173
1174 pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters,
1175 count(BundleEmitters),
1176 sizeof BundleEmitters[0],
1177 cmp_builtin_bundle_name);
1178 if(pBH!=0){
1179 pBH->xEmit();
1180 }
1181 return pBH!=0;
1182 }
1183
1184 /*
1185 ** WEBPAGE: builtin
1186 ** URL: builtin/FILENAME
1187 **
1188 ** Return the built-in text given by FILENAME. This is used internally
1189 ** by many Fossil web pages to load built-in javascript files.
1190 **
1191 ** If the id= parameter is present, then Fossil assumes that the
1192 ** result is immutable and sets a very large cache retention time (1
1193 ** year).
1194 */
1195 void page_builtin_text(void){
1196 Blob out;
1197 const char *zName = P("name");
1198 const char *zTxt = 0;
1199 const char *zId = P("id");
1200 int nId;
1201 int isBundle = 0;
1202
1203 if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
1204 g.isConst = 1;
1205 }else{
1206 etag_check(0,0)/*might not return*/;
1207 }
1208 if( zName ){
1209 if( sqlite3_strglob("*.js", zName)==0 ){
1210 cgi_set_content_type("application/javascript");
1211 }else{
1212 cgi_set_content_type("text/plain");
1213 }
1214 if(':'==zName[0]){
1215 isBundle = 1;
1216 zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL;
1217 }else{
1218 zTxt = builtin_text(zName);
1219 }
1220 }
1221 if( zTxt==0 ){
1222 cgi_set_content_type("text/html");
1223 cgi_set_status(404, "Not Found");
1224 @ File "%h(zName)" not found
1225 }else if(isBundle==0){
1226 blob_init(&out, zTxt, -1);
1227 cgi_set_content(&out);
1228 }
1229 }
1230
1231 /*
1232 ** All possible capabilities
1233 */
1234 static const char allCap[] =
1235 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
@@ -1605,21 +1430,18 @@
1605 ** 1) window.fossil core object, some of which depends on C-lelel
1606 ** runtime data. That part of the script is always emitted inline. If
1607 ** addScripTag is true then it is wrapped in its own SCRIPT tag, else
1608 ** it is assumed that the caller already opened a tag.
1609 **
1610 ** 2) Emits the static fossil.bootstrap.js. If asInline is true then
1611 ** it is emitted inline with the components from (1), else it is
1612 ** emitted as a separate SCRIPT tag with
1613 ** src=/builtin/fossil.bootstrap.js (so causes another HTTP request).
1614 */
1615 void style_emit_script_fossil_bootstrap(int asInline){
1616 static int once = 0;
1617 if(0==once++){
1618 /* Set up the generic/app-agnostic parts of window.fossil
1619 ** which require C-level state... */
1620 if(asInline==0){
1621 style_emit_script_tag(0,0);
1622 }
1623 CX("(function(){\n"
1624 "if(!window.fossil) window.fossil={};\n"
1625 "window.fossil.version = %!j;\n"
@@ -1646,18 +1468,16 @@
1646 */
1647 CX("window.fossil.page = {"
1648 "name:\"%T\""
1649 "};\n", g.zPath);
1650 CX("})();\n");
1651 /* The remaining fossil object bootstrap code is not dependent on
1652 ** C-runtime state... */
1653 if(asInline!=0){
1654 CX("%s\n", builtin_text("fossil.bootstrap.js"));
1655 }else{
1656 style_emit_script_tag(1,0);
1657 style_emit_script_builtin(0,1,"fossil.bootstrap.js");
1658 }
 
 
 
1659 }
1660 }
1661
1662 /*
1663 ** If passed 0 as its first argument, it emits a script opener tag
@@ -1688,116 +1508,33 @@
1688 CX("</script>\n");
1689 }
1690 }
1691
1692 /*
1693 ** Emits a script tag which uses content from a builtin script file.
1694 **
1695 ** If asInline is false, the script is emitted as a SCRIPT tag with a
1696 ** src attribute of /builtin/zName and the 2nd parameter is
1697 ** ignored. If asInline is true then the contents of the script are
1698 ** emitted directly, with a wrapping SCRIPT tag if addScripTag is
1699 ** true, else no wrapping script tag..
1700 **
1701 ** If it is false, a script tag loading it via
1702 ** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a
1703 ** build-time-dependent cache-buster value.
1704 */
1705 void style_emit_script_builtin(int asInline, int addScripTag,
1706 char const * zName){
1707 if(asInline){
1708 if(addScripTag){
1709 style_emit_script_tag(0,0);
1710 }
1711 CX("%s", builtin_text(zName));
1712 if(addScripTag){
1713 style_emit_script_tag(1,0);
1714 }
1715 }else{
1716 char * zFullName = mprintf("builtin/%s",zName);
1717 const char * zHash = fossil_exe_id();
1718 CX("<script src='%R/%T?cache=%.8s'></script>\n",
1719 zFullName, zHash);
1720 fossil_free(zFullName);
1721 }
1722 }
1723
1724 /*
1725 ** A convenience wrapper arond style_emit_script_builtin() which
1726 ** prepends a ':' to zName and passes (0,0,newName) to that
1727 ** function. i.e. it emits a SCRIPT tag with
1728 ** src=.../builtin/:${zName}?cache=.... The given name is assumed to
1729 ** have been added to the style.c:BundleEmitters map.
1730 */
1731 void style_emit_script_bundle(char const * zName){
1732 char *zBundle = mprintf(":%s", zName);
1733 style_emit_script_builtin(0, 0, zBundle);
1734 fossil_free(zBundle);
1735 }
1736
1737 /*
1738 ** The first time this is called it emits the JS code from the
1739 ** built-in file fossil.fossil.js. Subsequent calls are no-ops.
1740 **
1741 ** If passed a true first argument, it emits the contents directly
1742 ** to the page output, else it emits a script tag with a
1743 ** src=builtin/... to load the script.
1744 **
1745 ** If asInline is true and addScripTag is true then the contents
1746 ** are emitted directly but wrapped in a SCRIPT tag. If asInline
1747 ** is false, addScriptTag is ignored.
1748 **
1749 ** Note that this code relies on that loaded via
1750 ** style_emit_script_fossil_bootstrap() but it does not call that
1751 ** routine.
1752 */
1753 void style_emit_script_fetch(int asInline, int addScripTag){
1754 static int once = 0;
1755 if(0==once++){
1756 style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js");
1757 }
1758 }
1759
1760 /*
1761 ** The first time this is called it emits the JS code from the
1762 ** built-in file fossil.dom.js. Subsequent calls are no-ops.
1763 **
1764 ** If passed a true first argument, it emits the contents directly
1765 ** to the page output, else it emits a script tag with a
1766 ** src=builtin/... to load the script.
1767 **
1768 ** If asInline is true and addScripTag is true then the contents
1769 ** are emitted directly but wrapped in a SCRIPT tag. If asInline
1770 ** is false, addScriptTag is ignored.
1771 **
1772 ** Note that this code relies on that loaded via
1773 ** style_emit_script_fossil_bootstrap(), but it does not call that
1774 ** routine.
1775 */
1776 void style_emit_script_dom(int asInline, int addScripTag){
1777 static int once = 0;
1778 if(0==once++){
1779 style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js");
1780 }
1781 }
1782
1783 /*
1784 ** The fossil.tabs.js counterpart of style_emit_script_fetch().
1785 ** Also emits fossil.dom.js.
1786 */
1787 void style_emit_script_tabs(int asInline, int addScripTag){
1788 static int once = 0;
1789 if(0==once++){
1790 style_emit_script_dom(asInline, addScripTag);
1791 style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js");
1792 }
1793 }
1794
1795 /*
1796 ** The fossil.confirmer.js counterpart of style_emit_script_fetch().
1797 */
1798 void style_emit_script_confirmer(int asInline, int addScripTag){
1799 static int once = 0;
1800 if(0==once++){
1801 style_emit_script_builtin(asInline, 0, "fossil.confirmer.js");
1802 }
1803 }
1804
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
88
89 /*
90 ** Flags for various javascript files needed prior to </body>
91 */
92 static int needHrefJs = 0; /* href.js */
 
 
 
 
93
94 /*
95 ** Extra JS added to the end of the file.
96 */
97 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
480 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
481 zTargetId,zText,zTargetId,zTargetId,cchLength);
482 }
483 }
484 free(zText);
485 builtin_request_js("copybtn.js");
486 return zResult;
487 }
488
489 /*
490 ** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
690
691 /*
692 ** Indicate that the table-sorting javascript is needed.
693 */
694 void style_table_sorter(void){
695 builtin_request_js("sorttable.js");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696 }
697
698 /*
699 ** Generate code to load all required javascript files.
700 */
701 static void style_load_all_js_files(void){
 
702 if( needHrefJs ){
703 int nDelay = db_get_int("auto-hyperlink-delay",0);
704 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
705 @ <script id='href-data' type='application/json'>\
706 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
709 @ function debugMsg(msg){
710 @ var n = document.getElementById("debugMsg");
711 @ if(n){n.textContent=msg;}
712 @ }
713 if( needHrefJs ){
714 @ /* href.js */
715 cgi_append_content(builtin_text("href.js"),-1);
716 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
717 if( blob_size(&blobOnLoad)>0 ){
718 @ window.onload = function(){
719 cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
720 cgi_append_content("\n}\n", -1);
721 }
722 @ </script>
723 builtin_fulfill_js_requests();
 
 
 
 
 
 
 
 
 
724 }
725
726 /*
727 ** Draw the footer at the bottom of the page.
728 */
@@ -916,11 +840,11 @@
840 @ </div>
841 if( nSubmenuCtrl ){
842 cgi_query_parameters_to_hidden();
843 cgi_tag_query_parameter(0);
844 @ </form>
845 builtin_request_js("menu.js");
846 }
847 }
848
849 zAd = style_adunit_text(&mAdFlags);
850 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1127,109 +1051,10 @@
1051
1052 /* Tell CGI that the content returned by this page is considered cacheable */
1053 g.isConst = 1;
1054 }
1055
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1056 /*
1057 ** All possible capabilities
1058 */
1059 static const char allCap[] =
1060 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
@@ -1605,21 +1430,18 @@
1430 ** 1) window.fossil core object, some of which depends on C-lelel
1431 ** runtime data. That part of the script is always emitted inline. If
1432 ** addScripTag is true then it is wrapped in its own SCRIPT tag, else
1433 ** it is assumed that the caller already opened a tag.
1434 **
1435 ** 2) Emits the static fossil.bootstrap.js using builtin_request_js().
 
 
 
1436 */
1437 void style_emit_script_fossil_bootstrap(int addScriptTag){
1438 static int once = 0;
1439 if(0==once++){
1440 /* Set up the generic/app-agnostic parts of window.fossil
1441 ** which require C-level state... */
1442 if(addScriptTag!=0){
1443 style_emit_script_tag(0,0);
1444 }
1445 CX("(function(){\n"
1446 "if(!window.fossil) window.fossil={};\n"
1447 "window.fossil.version = %!j;\n"
@@ -1646,18 +1468,16 @@
1468 */
1469 CX("window.fossil.page = {"
1470 "name:\"%T\""
1471 "};\n", g.zPath);
1472 CX("})();\n");
1473 if(addScriptTag!=0){
 
 
 
 
1474 style_emit_script_tag(1,0);
 
1475 }
1476 /* The remaining window.fossil bootstrap code is not dependent on
1477 ** C-runtime state... */
1478 builtin_request_js("fossil.bootstrap.js");
1479 }
1480 }
1481
1482 /*
1483 ** If passed 0 as its first argument, it emits a script opener tag
@@ -1688,116 +1508,33 @@
1508 CX("</script>\n");
1509 }
1510 }
1511
1512 /*
1513 ** Convenience wrapper which calls builtin_request_js() for a series
1514 ** of builtin scripts named fossil.NAME.js. The first time it is
1515 ** called, it also calls style_emit_script_fossil_bootstrap() to
1516 ** initialize the window.fossil JS API. The first argument is a
1517 ** no-meaning dummy required by the va_start() interface. All
1518 ** subsequent arguments must be strings of the NAME part of
1519 ** fossil.NAME.js, followed by a NULL argument to terminate the list.
1520 **
1521 ** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3
1522 ** APIs. Do not forget the trailing 0!
1523 */
1524 void style_emit_fossil_js_apis( int dummy, ... ) {
1525 static int once = 0;
1526 const char *zArg;
1527 char * zName;
1528 va_list vargs;
1529
1530 if(0==once++){
1531 style_emit_script_fossil_bootstrap(1);
1532 }
1533 va_start(vargs,dummy);
1534 while( (zArg = va_arg (vargs, const char *))!=0 ){
1535 zName = mprintf("fossil.%s.js", zArg);
1536 builtin_request_js(zName);
1537 fossil_free(zName);
1538 }
1539 va_end(vargs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1540 }
1541
+6 -2
--- src/timeline.c
+++ src/timeline.c
@@ -1083,12 +1083,12 @@
10831083
cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : "");
10841084
cgi_printf("\"h\":\"%!S\"}%s",
10851085
pRow->zUuid, pRow->pNext ? ",\n" : "]\n");
10861086
}
10871087
@ }</script>
1088
- style_graph_generator();
1089
- style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */
1088
+ builtin_request_js("graph.js");
1089
+ builtin_request_js("copybtn.js"); /* Required by graph.js */
10901090
graph_free(pGraph);
10911091
}
10921092
}
10931093
10941094
/*
@@ -1741,10 +1741,14 @@
17411741
}
17421742
}else{
17431743
z = "50";
17441744
nEntry = 50;
17451745
}
1746
+
1747
+ /* Undocumented query parameter to set JS mode */
1748
+ builtin_set_js_delivery_mode(P("jsmode"),1);
1749
+
17461750
secondaryRid = name_to_typed_rid(P("sel2"),"ci");
17471751
selectedRid = name_to_typed_rid(P("sel1"),"ci");
17481752
cgi_replace_query_parameter("n",z);
17491753
cookie_write_parameter("n","n",0);
17501754
tmFlags |= timeline_ss_submenu();
17511755
--- src/timeline.c
+++ src/timeline.c
@@ -1083,12 +1083,12 @@
1083 cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : "");
1084 cgi_printf("\"h\":\"%!S\"}%s",
1085 pRow->zUuid, pRow->pNext ? ",\n" : "]\n");
1086 }
1087 @ }</script>
1088 style_graph_generator();
1089 style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */
1090 graph_free(pGraph);
1091 }
1092 }
1093
1094 /*
@@ -1741,10 +1741,14 @@
1741 }
1742 }else{
1743 z = "50";
1744 nEntry = 50;
1745 }
 
 
 
 
1746 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
1747 selectedRid = name_to_typed_rid(P("sel1"),"ci");
1748 cgi_replace_query_parameter("n",z);
1749 cookie_write_parameter("n","n",0);
1750 tmFlags |= timeline_ss_submenu();
1751
--- src/timeline.c
+++ src/timeline.c
@@ -1083,12 +1083,12 @@
1083 cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : "");
1084 cgi_printf("\"h\":\"%!S\"}%s",
1085 pRow->zUuid, pRow->pNext ? ",\n" : "]\n");
1086 }
1087 @ }</script>
1088 builtin_request_js("graph.js");
1089 builtin_request_js("copybtn.js"); /* Required by graph.js */
1090 graph_free(pGraph);
1091 }
1092 }
1093
1094 /*
@@ -1741,10 +1741,14 @@
1741 }
1742 }else{
1743 z = "50";
1744 nEntry = 50;
1745 }
1746
1747 /* Undocumented query parameter to set JS mode */
1748 builtin_set_js_delivery_mode(P("jsmode"),1);
1749
1750 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
1751 selectedRid = name_to_typed_rid(P("sel1"),"ci");
1752 cgi_replace_query_parameter("n",z);
1753 cookie_write_parameter("n","n",0);
1754 tmFlags |= timeline_ss_submenu();
1755
+8 -20
--- src/wiki.c
+++ src/wiki.c
@@ -1059,24 +1059,10 @@
10591059
return;
10601060
}
10611061
pRoute->xCallback();
10621062
}
10631063
1064
-/*
1065
-** Emits all of the "core" static JS needed by /wikiedit. Intended to
1066
-** be mapped to style.c:BundleEmitters with the name "wikiedit.js".
1067
-*/
1068
-void wikiedit_emit_js_bundle(void){
1069
- style_emit_script_fossil_bootstrap(1);
1070
- style_emit_script_builtin(1,0,"sbsdiff.js");
1071
- style_emit_script_fetch(1, 0);
1072
- style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1073
- style_emit_script_confirmer(1,0);
1074
- style_emit_script_builtin(1, 0, "fossil.storage.js");
1075
- style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js");
1076
-}
1077
-
10781064
/*
10791065
** WEBPAGE: wikiedit
10801066
** URL: /wikedit?name=PAGENAME
10811067
**
10821068
** The main front-end for the Ajax-based wiki editor app. Passing
@@ -1258,20 +1244,20 @@
12581244
CX("<hr><h3>Wiki Name Rules</h3>");
12591245
well_formed_wiki_name_rules();
12601246
CX("</div>"/*#wikiedit-tab-save*/);
12611247
}
12621248
1263
- style_emit_script_bundle("wikiedit.js");
1264
-
1249
+ builtin_request_js("sbsdiff.js");
1250
+ style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1251
+ "storage", "page.wikiedit", 0);
1252
+ builtin_fulfill_js_requests();
12651253
/* Dynamically populate the editor... */
12661254
style_emit_script_tag(0,0);
12671255
CX("\nfossil.onPageLoad(function(){\n");
12681256
CX("const P = fossil.page;\n"
12691257
"try{\n");
1270
- if(found){
1271
- CX("P.loadPage(%!j);\n", zPageName);
1272
- }else if(zPageName && *zPageName){
1258
+ if(!found && zPageName && *zPageName){
12731259
/* For a new page, stick a dummy entry in the JS-side stash
12741260
and "load" it from there. */
12751261
CX("const winfo = {"
12761262
"\"name\": %!j, \"mimetype\": %!j, "
12771263
"\"type\": %!j, "
@@ -1284,10 +1270,12 @@
12841270
copy from the stash, otherwise inject a new stash entry
12851271
for it and load *that* one... */
12861272
CX("if(!P.$stash.getWinfo(winfo)){"
12871273
"P.$stash.updateWinfo(winfo,'');"
12881274
"}\n");
1275
+ }
1276
+ if(zPageName && *zPageName){
12891277
CX("P.loadPage(%!j);\n", zPageName);
12901278
}
12911279
CX("}catch(e){"
12921280
"fossil.error(e); console.error('Exception:',e);"
12931281
"}\n");
@@ -2520,8 +2508,8 @@
25202508
blob_reset(&tail);
25212509
blob_reset(&title);
25222510
blob_reset(&wiki);
25232511
}
25242512
manifest_destroy(pWiki);
2525
- style_accordion();
2513
+ builtin_request_js("accordion.js");
25262514
return 1;
25272515
}
25282516
--- src/wiki.c
+++ src/wiki.c
@@ -1059,24 +1059,10 @@
1059 return;
1060 }
1061 pRoute->xCallback();
1062 }
1063
1064 /*
1065 ** Emits all of the "core" static JS needed by /wikiedit. Intended to
1066 ** be mapped to style.c:BundleEmitters with the name "wikiedit.js".
1067 */
1068 void wikiedit_emit_js_bundle(void){
1069 style_emit_script_fossil_bootstrap(1);
1070 style_emit_script_builtin(1,0,"sbsdiff.js");
1071 style_emit_script_fetch(1, 0);
1072 style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1073 style_emit_script_confirmer(1,0);
1074 style_emit_script_builtin(1, 0, "fossil.storage.js");
1075 style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js");
1076 }
1077
1078 /*
1079 ** WEBPAGE: wikiedit
1080 ** URL: /wikedit?name=PAGENAME
1081 **
1082 ** The main front-end for the Ajax-based wiki editor app. Passing
@@ -1258,20 +1244,20 @@
1258 CX("<hr><h3>Wiki Name Rules</h3>");
1259 well_formed_wiki_name_rules();
1260 CX("</div>"/*#wikiedit-tab-save*/);
1261 }
1262
1263 style_emit_script_bundle("wikiedit.js");
1264
 
 
1265 /* Dynamically populate the editor... */
1266 style_emit_script_tag(0,0);
1267 CX("\nfossil.onPageLoad(function(){\n");
1268 CX("const P = fossil.page;\n"
1269 "try{\n");
1270 if(found){
1271 CX("P.loadPage(%!j);\n", zPageName);
1272 }else if(zPageName && *zPageName){
1273 /* For a new page, stick a dummy entry in the JS-side stash
1274 and "load" it from there. */
1275 CX("const winfo = {"
1276 "\"name\": %!j, \"mimetype\": %!j, "
1277 "\"type\": %!j, "
@@ -1284,10 +1270,12 @@
1284 copy from the stash, otherwise inject a new stash entry
1285 for it and load *that* one... */
1286 CX("if(!P.$stash.getWinfo(winfo)){"
1287 "P.$stash.updateWinfo(winfo,'');"
1288 "}\n");
 
 
1289 CX("P.loadPage(%!j);\n", zPageName);
1290 }
1291 CX("}catch(e){"
1292 "fossil.error(e); console.error('Exception:',e);"
1293 "}\n");
@@ -2520,8 +2508,8 @@
2520 blob_reset(&tail);
2521 blob_reset(&title);
2522 blob_reset(&wiki);
2523 }
2524 manifest_destroy(pWiki);
2525 style_accordion();
2526 return 1;
2527 }
2528
--- src/wiki.c
+++ src/wiki.c
@@ -1059,24 +1059,10 @@
1059 return;
1060 }
1061 pRoute->xCallback();
1062 }
1063
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1064 /*
1065 ** WEBPAGE: wikiedit
1066 ** URL: /wikedit?name=PAGENAME
1067 **
1068 ** The main front-end for the Ajax-based wiki editor app. Passing
@@ -1258,20 +1244,20 @@
1244 CX("<hr><h3>Wiki Name Rules</h3>");
1245 well_formed_wiki_name_rules();
1246 CX("</div>"/*#wikiedit-tab-save*/);
1247 }
1248
1249 builtin_request_js("sbsdiff.js");
1250 style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1251 "storage", "page.wikiedit", 0);
1252 builtin_fulfill_js_requests();
1253 /* Dynamically populate the editor... */
1254 style_emit_script_tag(0,0);
1255 CX("\nfossil.onPageLoad(function(){\n");
1256 CX("const P = fossil.page;\n"
1257 "try{\n");
1258 if(!found && zPageName && *zPageName){
 
 
1259 /* For a new page, stick a dummy entry in the JS-side stash
1260 and "load" it from there. */
1261 CX("const winfo = {"
1262 "\"name\": %!j, \"mimetype\": %!j, "
1263 "\"type\": %!j, "
@@ -1284,10 +1270,12 @@
1270 copy from the stash, otherwise inject a new stash entry
1271 for it and load *that* one... */
1272 CX("if(!P.$stash.getWinfo(winfo)){"
1273 "P.$stash.updateWinfo(winfo,'');"
1274 "}\n");
1275 }
1276 if(zPageName && *zPageName){
1277 CX("P.loadPage(%!j);\n", zPageName);
1278 }
1279 CX("}catch(e){"
1280 "fossil.error(e); console.error('Exception:',e);"
1281 "}\n");
@@ -2520,8 +2508,8 @@
2508 blob_reset(&tail);
2509 blob_reset(&title);
2510 blob_reset(&wiki);
2511 }
2512 manifest_destroy(pWiki);
2513 builtin_request_js("accordion.js");
2514 return 1;
2515 }
2516
+8 -20
--- src/wiki.c
+++ src/wiki.c
@@ -1059,24 +1059,10 @@
10591059
return;
10601060
}
10611061
pRoute->xCallback();
10621062
}
10631063
1064
-/*
1065
-** Emits all of the "core" static JS needed by /wikiedit. Intended to
1066
-** be mapped to style.c:BundleEmitters with the name "wikiedit.js".
1067
-*/
1068
-void wikiedit_emit_js_bundle(void){
1069
- style_emit_script_fossil_bootstrap(1);
1070
- style_emit_script_builtin(1,0,"sbsdiff.js");
1071
- style_emit_script_fetch(1, 0);
1072
- style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1073
- style_emit_script_confirmer(1,0);
1074
- style_emit_script_builtin(1, 0, "fossil.storage.js");
1075
- style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js");
1076
-}
1077
-
10781064
/*
10791065
** WEBPAGE: wikiedit
10801066
** URL: /wikedit?name=PAGENAME
10811067
**
10821068
** The main front-end for the Ajax-based wiki editor app. Passing
@@ -1258,20 +1244,20 @@
12581244
CX("<hr><h3>Wiki Name Rules</h3>");
12591245
well_formed_wiki_name_rules();
12601246
CX("</div>"/*#wikiedit-tab-save*/);
12611247
}
12621248
1263
- style_emit_script_bundle("wikiedit.js");
1264
-
1249
+ builtin_request_js("sbsdiff.js");
1250
+ style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1251
+ "storage", "page.wikiedit", 0);
1252
+ builtin_fulfill_js_requests();
12651253
/* Dynamically populate the editor... */
12661254
style_emit_script_tag(0,0);
12671255
CX("\nfossil.onPageLoad(function(){\n");
12681256
CX("const P = fossil.page;\n"
12691257
"try{\n");
1270
- if(found){
1271
- CX("P.loadPage(%!j);\n", zPageName);
1272
- }else if(zPageName && *zPageName){
1258
+ if(!found && zPageName && *zPageName){
12731259
/* For a new page, stick a dummy entry in the JS-side stash
12741260
and "load" it from there. */
12751261
CX("const winfo = {"
12761262
"\"name\": %!j, \"mimetype\": %!j, "
12771263
"\"type\": %!j, "
@@ -1284,10 +1270,12 @@
12841270
copy from the stash, otherwise inject a new stash entry
12851271
for it and load *that* one... */
12861272
CX("if(!P.$stash.getWinfo(winfo)){"
12871273
"P.$stash.updateWinfo(winfo,'');"
12881274
"}\n");
1275
+ }
1276
+ if(zPageName && *zPageName){
12891277
CX("P.loadPage(%!j);\n", zPageName);
12901278
}
12911279
CX("}catch(e){"
12921280
"fossil.error(e); console.error('Exception:',e);"
12931281
"}\n");
@@ -2520,8 +2508,8 @@
25202508
blob_reset(&tail);
25212509
blob_reset(&title);
25222510
blob_reset(&wiki);
25232511
}
25242512
manifest_destroy(pWiki);
2525
- style_accordion();
2513
+ builtin_request_js("accordion.js");
25262514
return 1;
25272515
}
25282516
--- src/wiki.c
+++ src/wiki.c
@@ -1059,24 +1059,10 @@
1059 return;
1060 }
1061 pRoute->xCallback();
1062 }
1063
1064 /*
1065 ** Emits all of the "core" static JS needed by /wikiedit. Intended to
1066 ** be mapped to style.c:BundleEmitters with the name "wikiedit.js".
1067 */
1068 void wikiedit_emit_js_bundle(void){
1069 style_emit_script_fossil_bootstrap(1);
1070 style_emit_script_builtin(1,0,"sbsdiff.js");
1071 style_emit_script_fetch(1, 0);
1072 style_emit_script_tabs(1,0)/*also emits fossil.dom*/;
1073 style_emit_script_confirmer(1,0);
1074 style_emit_script_builtin(1, 0, "fossil.storage.js");
1075 style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js");
1076 }
1077
1078 /*
1079 ** WEBPAGE: wikiedit
1080 ** URL: /wikedit?name=PAGENAME
1081 **
1082 ** The main front-end for the Ajax-based wiki editor app. Passing
@@ -1258,20 +1244,20 @@
1258 CX("<hr><h3>Wiki Name Rules</h3>");
1259 well_formed_wiki_name_rules();
1260 CX("</div>"/*#wikiedit-tab-save*/);
1261 }
1262
1263 style_emit_script_bundle("wikiedit.js");
1264
 
 
1265 /* Dynamically populate the editor... */
1266 style_emit_script_tag(0,0);
1267 CX("\nfossil.onPageLoad(function(){\n");
1268 CX("const P = fossil.page;\n"
1269 "try{\n");
1270 if(found){
1271 CX("P.loadPage(%!j);\n", zPageName);
1272 }else if(zPageName && *zPageName){
1273 /* For a new page, stick a dummy entry in the JS-side stash
1274 and "load" it from there. */
1275 CX("const winfo = {"
1276 "\"name\": %!j, \"mimetype\": %!j, "
1277 "\"type\": %!j, "
@@ -1284,10 +1270,12 @@
1284 copy from the stash, otherwise inject a new stash entry
1285 for it and load *that* one... */
1286 CX("if(!P.$stash.getWinfo(winfo)){"
1287 "P.$stash.updateWinfo(winfo,'');"
1288 "}\n");
 
 
1289 CX("P.loadPage(%!j);\n", zPageName);
1290 }
1291 CX("}catch(e){"
1292 "fossil.error(e); console.error('Exception:',e);"
1293 "}\n");
@@ -2520,8 +2508,8 @@
2520 blob_reset(&tail);
2521 blob_reset(&title);
2522 blob_reset(&wiki);
2523 }
2524 manifest_destroy(pWiki);
2525 style_accordion();
2526 return 1;
2527 }
2528
--- src/wiki.c
+++ src/wiki.c
@@ -1059,24 +1059,10 @@
1059 return;
1060 }
1061 pRoute->xCallback();
1062 }
1063
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1064 /*
1065 ** WEBPAGE: wikiedit
1066 ** URL: /wikedit?name=PAGENAME
1067 **
1068 ** The main front-end for the Ajax-based wiki editor app. Passing
@@ -1258,20 +1244,20 @@
1244 CX("<hr><h3>Wiki Name Rules</h3>");
1245 well_formed_wiki_name_rules();
1246 CX("</div>"/*#wikiedit-tab-save*/);
1247 }
1248
1249 builtin_request_js("sbsdiff.js");
1250 style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer",
1251 "storage", "page.wikiedit", 0);
1252 builtin_fulfill_js_requests();
1253 /* Dynamically populate the editor... */
1254 style_emit_script_tag(0,0);
1255 CX("\nfossil.onPageLoad(function(){\n");
1256 CX("const P = fossil.page;\n"
1257 "try{\n");
1258 if(!found && zPageName && *zPageName){
 
 
1259 /* For a new page, stick a dummy entry in the JS-side stash
1260 and "load" it from there. */
1261 CX("const winfo = {"
1262 "\"name\": %!j, \"mimetype\": %!j, "
1263 "\"type\": %!j, "
@@ -1284,10 +1270,12 @@
1270 copy from the stash, otherwise inject a new stash entry
1271 for it and load *that* one... */
1272 CX("if(!P.$stash.getWinfo(winfo)){"
1273 "P.$stash.updateWinfo(winfo,'');"
1274 "}\n");
1275 }
1276 if(zPageName && *zPageName){
1277 CX("P.loadPage(%!j);\n", zPageName);
1278 }
1279 CX("}catch(e){"
1280 "fossil.error(e); console.error('Exception:',e);"
1281 "}\n");
@@ -2520,8 +2508,8 @@
2508 blob_reset(&tail);
2509 blob_reset(&title);
2510 blob_reset(&wiki);
2511 }
2512 manifest_destroy(pWiki);
2513 builtin_request_js("accordion.js");
2514 return 1;
2515 }
2516
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1063,13 +1063,16 @@
10631063
# build is done from, i.e. the checkout belongs to. Do not sync/push
10641064
# the repository after running the tests.
10651065
test: $(OBJDIR) $(APPNAME)
10661066
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
10671067
1068
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
1068
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
10691069
$(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
10701070
1071
+$(OBJDIR)/phony.h:
1072
+ # Force rebuild of VERSION.h every time "make" is run
1073
+
10711074
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
10721075
# to 1. If it is set to 1, then there is no need to build or link
10731076
# the sqlite3.o object. Instead, the system SQLite will be linked
10741077
# using -lsqlite3.
10751078
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
10761079
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1063,13 +1063,16 @@
1063 # build is done from, i.e. the checkout belongs to. Do not sync/push
1064 # the repository after running the tests.
1065 test: $(OBJDIR) $(APPNAME)
1066 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
1067
1068 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
1069 $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
1070
 
 
 
1071 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
1072 # to 1. If it is set to 1, then there is no need to build or link
1073 # the sqlite3.o object. Instead, the system SQLite will be linked
1074 # using -lsqlite3.
1075 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
1076
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1063,13 +1063,16 @@
1063 # build is done from, i.e. the checkout belongs to. Do not sync/push
1064 # the repository after running the tests.
1065 test: $(OBJDIR) $(APPNAME)
1066 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
1067
1068 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
1069 $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
1070
1071 $(OBJDIR)/phony.h:
1072 # Force rebuild of VERSION.h every time "make" is run
1073
1074 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
1075 # to 1. If it is set to 1, then there is no need to build or link
1076 # the sqlite3.o object. Instead, the system SQLite will be linked
1077 # using -lsqlite3.
1078 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
1079
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1063,13 +1063,16 @@
10631063
# build is done from, i.e. the checkout belongs to. Do not sync/push
10641064
# the repository after running the tests.
10651065
test: $(OBJDIR) $(APPNAME)
10661066
$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
10671067
1068
-$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
1068
+$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
10691069
$(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
10701070
1071
+$(OBJDIR)/phony.h:
1072
+ # Force rebuild of VERSION.h every time "make" is run
1073
+
10711074
# The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
10721075
# to 1. If it is set to 1, then there is no need to build or link
10731076
# the sqlite3.o object. Instead, the system SQLite will be linked
10741077
# using -lsqlite3.
10751078
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
10761079
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1063,13 +1063,16 @@
1063 # build is done from, i.e. the checkout belongs to. Do not sync/push
1064 # the repository after running the tests.
1065 test: $(OBJDIR) $(APPNAME)
1066 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
1067
1068 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION)
1069 $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
1070
 
 
 
1071 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
1072 # to 1. If it is set to 1, then there is no need to build or link
1073 # the sqlite3.o object. Instead, the system SQLite will be linked
1074 # using -lsqlite3.
1075 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
1076
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1063,13 +1063,16 @@
1063 # build is done from, i.e. the checkout belongs to. Do not sync/push
1064 # the repository after running the tests.
1065 test: $(OBJDIR) $(APPNAME)
1066 $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)
1067
1068 $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h
1069 $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@
1070
1071 $(OBJDIR)/phony.h:
1072 # Force rebuild of VERSION.h every time "make" is run
1073
1074 # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set
1075 # to 1. If it is set to 1, then there is no need to build or link
1076 # the sqlite3.o object. Instead, the system SQLite will be linked
1077 # using -lsqlite3.
1078 SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
1079
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -1024,12 +1024,15 @@
10241024
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10251025
10261026
"$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
10271027
$(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
10281028
1029
-"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION"
1030
- $** > $@
1029
+"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1030
+ "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1031
+
1032
+"$(B)\phony.h" :
1033
+ rem Force rebuild of VERSION.h whenever nmake is run
10311034
10321035
"$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
10331036
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10341037
10351038
"$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
10361039
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -1024,12 +1024,15 @@
1024 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1025
1026 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1027 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1028
1029 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION"
1030 $** > $@
 
 
 
1031
1032 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1033 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1034
1035 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1036
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -1024,12 +1024,15 @@
1024 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1025
1026 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1027 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1028
1029 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1030 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1031
1032 "$(B)\phony.h" :
1033 rem Force rebuild of VERSION.h whenever nmake is run
1034
1035 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1036 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1037
1038 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1039
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -1024,12 +1024,15 @@
10241024
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10251025
10261026
"$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
10271027
$(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
10281028
1029
-"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION"
1030
- $** > $@
1029
+"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1030
+ "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1031
+
1032
+"$(B)\phony.h" :
1033
+ rem Force rebuild of VERSION.h whenever nmake is run
10311034
10321035
"$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
10331036
$(TCC) /Fo$@ /Fd$(@D)\ -c $**
10341037
10351038
"$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
10361039
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -1024,12 +1024,15 @@
1024 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1025
1026 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1027 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1028
1029 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION"
1030 $** > $@
 
 
 
1031
1032 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1033 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1034
1035 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1036
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -1024,12 +1024,15 @@
1024 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1025
1026 "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c"
1027 $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $**
1028
1029 "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h"
1030 "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@
1031
1032 "$(B)\phony.h" :
1033 rem Force rebuild of VERSION.h whenever nmake is run
1034
1035 "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c"
1036 $(TCC) /Fo$@ /Fd$(@D)\ -c $**
1037
1038 "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC)
1039

Keyboard Shortcuts

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