Fossil SCM

merge trunk

jan.nijtmans 2015-02-06 10:02 mistake merge
Commit bddc40ced26df1b8e5e520103527c26267db8f73
246 files changed +55 -4 +1 -1 +9 -13 +35 -36 +35 -36 +58 -31 +17 +1 -1 +166 -20 +60 +121 -112 +1 -1 +25 -8 +1 -1 +1 -1 +1 -1
~ .dockerignore ~ .project ~ .settings/org.eclipse.core.resources.prefs ~ .settings/org.eclipse.core.runtime.prefs ~ BUILD.txt ~ COPYRIGHT-BSD2.txt ~ Dockerfile ~ Makefile.classic ~ Makefile.in ~ VERSION ~ ajax/README ~ ajax/index.html ~ ajax/wiki-editor.html ~ art/CollRev1.dia ~ art/CollRev2.dia ~ art/CollRev3.dia ~ art/CollRev4.dia ~ art/branching.odp ~ art/concept1.dia ~ art/concept2.dia ~ art/delta1.dia ~ art/delta2.dia ~ art/delta3.dia ~ art/delta4.dia ~ art/delta5.dia ~ art/delta6.dia ~ art/encode1.tex ~ art/encode10.dia ~ art/encode2.tex ~ art/encode3.tex ~ art/encode4.tex ~ art/encode5.tex ~ art/encode6.tex ~ art/encode7.tex ~ art/encode8.tex ~ art/encode9.tex ~ auto.def ~ autosetup/LICENSE ~ autosetup/README.autosetup ~ autosetup/cc-db.tcl ~ autosetup/cc-lib.tcl ~ autosetup/cc-shared.tcl ~ autosetup/cc.tcl ~ autosetup/default.auto ~ autosetup/jimsh0.c ~ autosetup/local.tcl ~ autosetup/system.tcl ~ autosetup/test-tclsh ~ debian/makedeb.sh ~ setup/fossil.iss ~ setup/fossil.nsi ~ skins/README.md ~ src/Makefile ~ src/builtin.c ~ src/bundle.c ~ src/cache.c ~ src/cgi.c ~ src/codecheck1.c ~ src/comformat.c ~ src/config.h ~ src/cson_amalgamation.h ~ src/cygsup.h ~ src/diff.tcl ~ src/doc.c ~ src/event.c ~ src/foci.c ~ src/fusefs.c ~ src/import.c ~ src/import.c ~ src/json_detail.h ~ src/loadctrl.c ~ src/lookslike.c ~ src/main.mk ~ src/makeheaders.html ~ src/makemake.tcl ~ src/markdown.md ~ src/miniz.c ~ src/mkbuiltin.c ~ src/publish.c ~ src/purge.c ~ src/schema.c ~ src/search.c ~ src/setup.c ~ src/shell.c ~ src/sitemap.c ~ src/sqlite3.h ~ src/statrep.c ~ src/style.c ~ src/th.h ~ src/th_main.c ~ src/timeline.c ~ src/tkt.c ~ src/unicode.c ~ src/url.c ~ src/wiki.c ~ src/winfile.c ~ src/wysiwyg.c ~ test/Greek-Lipsum-1.txt ~ test/Greek-Lipsum-2.txt ~ test/cmdline.test ~ test/comment.test ~ test/delta1.test ~ test/diff-test-1.wiki ~ test/file1.test ~ test/glob.test ~ test/graph-test-1.wiki ~ test/many-www.tcl ~ test/markdown-test1.md ~ test/merge1.test ~ test/merge2.test ~ test/merge3.test ~ test/merge4.test ~ test/merge5.test ~ test/merge5_repo.sql ~ test/merge6.test ~ test/merge_renames.test ~ test/release-checklist.wiki ~ test/revert.test ~ test/test-page++.wiki ~ test/tester.tcl ~ test/th1-hooks-input.txt ~ test/th1-hooks.test ~ test/th1-tcl1.txt ~ test/th1-tcl2.txt ~ test/th1-tcl3.txt ~ test/th1-tcl4.txt ~ test/th1-tcl5.txt ~ test/th1-tcl6.txt ~ test/th1-tcl7.txt ~ test/th1-tcl8.txt ~ test/th1-tcl9.txt ~ test/th1.test ~ test/update-test-1.sh ~ test/update-test-2.sh ~ test/utf.test ~ test/utf16be.txt ~ test/utf16le.txt ~ test/valgrind-www.tcl ~ tools/encode_math.sh ~ tools/fossil-autocomplete.bash ~ tools/fossil_chat.tcl ~ win/Makefile.PellesCGMake ~ win/Makefile.dmc ~ win/Makefile.mingw ~ win/Makefile.mingw.mistachkin ~ win/Makefile.msc ~ win/buildmsvc.bat ~ win/fossil.exe.manifest ~ win/fossil.ico ~ win/fossil.rc ~ www/CollRev1.gif ~ www/CollRev2.gif ~ www/CollRev3.gif ~ www/CollRev4.gif ~ www/adding_code.wiki ~ www/antibot.wiki ~ www/apple-touch-icon.png ~ www/background.jpg ~ www/branch01.gif ~ www/branch02.gif ~ www/branch03.gif ~ www/branch04.gif ~ www/branch05.gif ~ www/branching.wiki ~ www/bugtheory.wiki ~ www/build.wiki ~ www/changes.wiki ~ www/checkin.wiki ~ www/checkin_names.wiki ~ www/cmd_.wiki-template ~ www/concept1.gif ~ www/concept2.gif ~ www/concepts.wiki ~ www/contribute.wiki ~ www/copyright-release.html ~ www/copyright-release.pdf ~ www/custom_ticket.wiki ~ www/delta1.gif ~ www/delta2.gif ~ www/delta3.gif ~ www/delta4.gif ~ www/delta5.gif ~ www/delta6.gif ~ www/delta_encoder_algorithm.wiki ~ www/delta_format.wiki ~ www/embeddeddoc.wiki ~ www/encode1.gif ~ www/encode10.gif ~ www/encode2.gif ~ www/encode3.gif ~ www/encode4.gif ~ www/encode5.gif ~ www/encode6.gif ~ www/encode7.gif ~ www/encode8.gif ~ www/encode9.gif ~ www/event.wiki ~ www/faq.tcl ~ www/faq.wiki ~ www/fileformat.wiki ~ www/fiveminutes.wiki ~ www/foss-cklist.wiki ~ www/fossil-from-msvc.wiki ~ www/fossil-v-git.wiki ~ www/fossil.eps ~ www/fossil.gif ~ www/fossil2.eps ~ www/fossil2.gif ~ www/fossil3.gif ~ www/fossil_logo_small.gif ~ www/fossil_logo_small2.gif ~ www/fossil_logo_small3.gif ~ www/fossil_prompt.sh ~ www/fossil_prompt.wiki ~ www/hacker-howto.wiki ~ www/hints.wiki ~ www/index.wiki ~ www/inout.wiki ~ www/makefile.wiki ~ www/mkdownload.tcl ~ www/mkindex.tcl ~ www/newrepo.wiki ~ www/password.wiki ~ www/permutedindex.html ~ www/pop.wiki ~ www/private.wiki ~ www/qandc.wiki ~ www/quickstart.wiki ~ www/quotes.wiki ~ www/reviews.wiki ~ www/scgi.wiki ~ www/selfcheck.wiki ~ www/selfhost.wiki ~ www/server.wiki ~ www/settings.wiki ~ www/shunning.wiki ~ www/ssl.wiki ~ www/stats.wiki ~ www/style.wiki ~ www/sync.wiki ~ www/tech_overview.wiki ~ www/theory1.wiki ~ www/tickets.wiki ~ www/uitest.html ~ www/webui.wiki ~ www/wikitheory.wiki

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

Binary file

Binary file

Binary file

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

+55 -4
--- src/cgi.c
+++ src/cgi.c
@@ -52,10 +52,11 @@
5252
*/
5353
#define P(x) cgi_parameter((x),0)
5454
#define PD(x,y) cgi_parameter((x),(y))
5555
#define PT(x) cgi_parameter_trimmed((x),0)
5656
#define PDT(x,y) cgi_parameter_trimmed((x),(y))
57
+#define PB(x) cgi_parameter_boolean(x)
5758
5859
5960
/*
6061
** Destinations for output text.
6162
*/
@@ -436,11 +437,12 @@
436437
static int seqQP = 0; /* Sequence numbers */
437438
static struct QParam { /* One entry for each query parameter or cookie */
438439
const char *zName; /* Parameter or cookie name */
439440
const char *zValue; /* Value of the query parameter or cookie */
440441
int seq; /* Order of insertion */
441
- int isQP; /* True for query parameters */
442
+ char isQP; /* True for query parameters */
443
+ char cTag; /* Tag on query parameters */
442444
} *aParamQP; /* An array of all parameters and cookies */
443445
444446
/*
445447
** Add another query parameter or cookie to the parameter set.
446448
** zName is the name of the query parameter or cookie and zValue
@@ -490,10 +492,21 @@
490492
aParamQP[i].zValue = zValue;
491493
return;
492494
}
493495
}
494496
cgi_set_parameter_nocopy(zName, zValue, 0);
497
+}
498
+void cgi_replace_query_parameter(const char *zName, const char *zValue){
499
+ int i;
500
+ for(i=0; i<nUsedQP; i++){
501
+ if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){
502
+ aParamQP[i].zValue = zValue;
503
+ assert( aParamQP[i].isQP );
504
+ return;
505
+ }
506
+ }
507
+ cgi_set_parameter_nocopy(zName, zValue, 1);
495508
}
496509
497510
/*
498511
** Add a query parameter. The zName portion is fixed but a copy
499512
** must be made of zValue.
@@ -1064,10 +1077,20 @@
10641077
zOut = fossil_strdup(zIn);
10651078
for(i=0; zOut[i]; i++){}
10661079
while( i>0 && fossil_isspace(zOut[i-1]) ) zOut[--i] = 0;
10671080
return zOut;
10681081
}
1082
+
1083
+/*
1084
+** Return true if the CGI parameter zName exists and is not equal to 0,
1085
+** or "no" or "off".
1086
+*/
1087
+int cgi_parameter_boolean(const char *zName){
1088
+ const char *zIn = cgi_parameter(zName, 0);
1089
+ if( zIn==0 ) return 0;
1090
+ return zIn[0]==0 || is_truth(zIn);
1091
+}
10691092
10701093
/*
10711094
** Return the name of the i-th CGI parameter. Return NULL if there
10721095
** are fewer than i registered CGI parameters.
10731096
*/
@@ -1142,23 +1165,51 @@
11421165
cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue);
11431166
}
11441167
}
11451168
11461169
/*
1147
-** Export all query parameters (but not cookies or environment variables)
1148
-** as hidden values of a form.
1170
+** Export all untagged query parameters (but not cookies or environment
1171
+** variables) as hidden values of a form.
11491172
*/
11501173
void cgi_query_parameters_to_hidden(void){
11511174
int i;
11521175
const char *zN, *zV;
11531176
for(i=0; i<nUsedQP; i++){
1154
- if( aParamQP[i].isQP==0 ) continue;
1177
+ if( aParamQP[i].isQP==0 || aParamQP[i].cTag ) continue;
11551178
zN = aParamQP[i].zName;
11561179
zV = aParamQP[i].zValue;
11571180
@ <input type="hidden" name="%h(zN)" value="%h(zV)">
11581181
}
11591182
}
1183
+
1184
+/*
1185
+** Export all untagged query parameters (but not cookies or environment
1186
+** variables) to the HQuery object.
1187
+*/
1188
+void cgi_query_parameters_to_url(HQuery *p){
1189
+ int i;
1190
+ for(i=0; i<nUsedQP; i++){
1191
+ if( aParamQP[i].isQP==0 || aParamQP[i].cTag ) continue;
1192
+ url_add_parameter(p, aParamQP[i].zName, aParamQP[i].zValue);
1193
+ }
1194
+}
1195
+
1196
+/*
1197
+** Tag query parameter zName so that it is not exported by
1198
+** cgi_query_parameters_to_hidden(). Or if zName==0, then
1199
+** untag all query parameters.
1200
+*/
1201
+void cgi_tag_query_parameter(const char *zName){
1202
+ int i;
1203
+ if( zName==0 ){
1204
+ for(i=0; i<nUsedQP; i++) aParamQP[i].cTag = 0;
1205
+ }else{
1206
+ for(i=0; i<nUsedQP; i++){
1207
+ if( strcmp(zName,aParamQP[i].zName)==0 ) aParamQP[i].cTag = 1;
1208
+ }
1209
+ }
1210
+}
11601211
11611212
/*
11621213
** This routine works like "printf" except that it has the
11631214
** extra formatting capabilities such as %h and %t.
11641215
*/
11651216
--- src/cgi.c
+++ src/cgi.c
@@ -52,10 +52,11 @@
52 */
53 #define P(x) cgi_parameter((x),0)
54 #define PD(x,y) cgi_parameter((x),(y))
55 #define PT(x) cgi_parameter_trimmed((x),0)
56 #define PDT(x,y) cgi_parameter_trimmed((x),(y))
 
57
58
59 /*
60 ** Destinations for output text.
61 */
@@ -436,11 +437,12 @@
436 static int seqQP = 0; /* Sequence numbers */
437 static struct QParam { /* One entry for each query parameter or cookie */
438 const char *zName; /* Parameter or cookie name */
439 const char *zValue; /* Value of the query parameter or cookie */
440 int seq; /* Order of insertion */
441 int isQP; /* True for query parameters */
 
442 } *aParamQP; /* An array of all parameters and cookies */
443
444 /*
445 ** Add another query parameter or cookie to the parameter set.
446 ** zName is the name of the query parameter or cookie and zValue
@@ -490,10 +492,21 @@
490 aParamQP[i].zValue = zValue;
491 return;
492 }
493 }
494 cgi_set_parameter_nocopy(zName, zValue, 0);
 
 
 
 
 
 
 
 
 
 
 
495 }
496
497 /*
498 ** Add a query parameter. The zName portion is fixed but a copy
499 ** must be made of zValue.
@@ -1064,10 +1077,20 @@
1064 zOut = fossil_strdup(zIn);
1065 for(i=0; zOut[i]; i++){}
1066 while( i>0 && fossil_isspace(zOut[i-1]) ) zOut[--i] = 0;
1067 return zOut;
1068 }
 
 
 
 
 
 
 
 
 
 
1069
1070 /*
1071 ** Return the name of the i-th CGI parameter. Return NULL if there
1072 ** are fewer than i registered CGI parameters.
1073 */
@@ -1142,23 +1165,51 @@
1142 cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue);
1143 }
1144 }
1145
1146 /*
1147 ** Export all query parameters (but not cookies or environment variables)
1148 ** as hidden values of a form.
1149 */
1150 void cgi_query_parameters_to_hidden(void){
1151 int i;
1152 const char *zN, *zV;
1153 for(i=0; i<nUsedQP; i++){
1154 if( aParamQP[i].isQP==0 ) continue;
1155 zN = aParamQP[i].zName;
1156 zV = aParamQP[i].zValue;
1157 @ <input type="hidden" name="%h(zN)" value="%h(zV)">
1158 }
1159 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1160
1161 /*
1162 ** This routine works like "printf" except that it has the
1163 ** extra formatting capabilities such as %h and %t.
1164 */
1165
--- src/cgi.c
+++ src/cgi.c
@@ -52,10 +52,11 @@
52 */
53 #define P(x) cgi_parameter((x),0)
54 #define PD(x,y) cgi_parameter((x),(y))
55 #define PT(x) cgi_parameter_trimmed((x),0)
56 #define PDT(x,y) cgi_parameter_trimmed((x),(y))
57 #define PB(x) cgi_parameter_boolean(x)
58
59
60 /*
61 ** Destinations for output text.
62 */
@@ -436,11 +437,12 @@
437 static int seqQP = 0; /* Sequence numbers */
438 static struct QParam { /* One entry for each query parameter or cookie */
439 const char *zName; /* Parameter or cookie name */
440 const char *zValue; /* Value of the query parameter or cookie */
441 int seq; /* Order of insertion */
442 char isQP; /* True for query parameters */
443 char cTag; /* Tag on query parameters */
444 } *aParamQP; /* An array of all parameters and cookies */
445
446 /*
447 ** Add another query parameter or cookie to the parameter set.
448 ** zName is the name of the query parameter or cookie and zValue
@@ -490,10 +492,21 @@
492 aParamQP[i].zValue = zValue;
493 return;
494 }
495 }
496 cgi_set_parameter_nocopy(zName, zValue, 0);
497 }
498 void cgi_replace_query_parameter(const char *zName, const char *zValue){
499 int i;
500 for(i=0; i<nUsedQP; i++){
501 if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){
502 aParamQP[i].zValue = zValue;
503 assert( aParamQP[i].isQP );
504 return;
505 }
506 }
507 cgi_set_parameter_nocopy(zName, zValue, 1);
508 }
509
510 /*
511 ** Add a query parameter. The zName portion is fixed but a copy
512 ** must be made of zValue.
@@ -1064,10 +1077,20 @@
1077 zOut = fossil_strdup(zIn);
1078 for(i=0; zOut[i]; i++){}
1079 while( i>0 && fossil_isspace(zOut[i-1]) ) zOut[--i] = 0;
1080 return zOut;
1081 }
1082
1083 /*
1084 ** Return true if the CGI parameter zName exists and is not equal to 0,
1085 ** or "no" or "off".
1086 */
1087 int cgi_parameter_boolean(const char *zName){
1088 const char *zIn = cgi_parameter(zName, 0);
1089 if( zIn==0 ) return 0;
1090 return zIn[0]==0 || is_truth(zIn);
1091 }
1092
1093 /*
1094 ** Return the name of the i-th CGI parameter. Return NULL if there
1095 ** are fewer than i registered CGI parameters.
1096 */
@@ -1142,23 +1165,51 @@
1165 cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue);
1166 }
1167 }
1168
1169 /*
1170 ** Export all untagged query parameters (but not cookies or environment
1171 ** variables) as hidden values of a form.
1172 */
1173 void cgi_query_parameters_to_hidden(void){
1174 int i;
1175 const char *zN, *zV;
1176 for(i=0; i<nUsedQP; i++){
1177 if( aParamQP[i].isQP==0 || aParamQP[i].cTag ) continue;
1178 zN = aParamQP[i].zName;
1179 zV = aParamQP[i].zValue;
1180 @ <input type="hidden" name="%h(zN)" value="%h(zV)">
1181 }
1182 }
1183
1184 /*
1185 ** Export all untagged query parameters (but not cookies or environment
1186 ** variables) to the HQuery object.
1187 */
1188 void cgi_query_parameters_to_url(HQuery *p){
1189 int i;
1190 for(i=0; i<nUsedQP; i++){
1191 if( aParamQP[i].isQP==0 || aParamQP[i].cTag ) continue;
1192 url_add_parameter(p, aParamQP[i].zName, aParamQP[i].zValue);
1193 }
1194 }
1195
1196 /*
1197 ** Tag query parameter zName so that it is not exported by
1198 ** cgi_query_parameters_to_hidden(). Or if zName==0, then
1199 ** untag all query parameters.
1200 */
1201 void cgi_tag_query_parameter(const char *zName){
1202 int i;
1203 if( zName==0 ){
1204 for(i=0; i<nUsedQP; i++) aParamQP[i].cTag = 0;
1205 }else{
1206 for(i=0; i<nUsedQP; i++){
1207 if( strcmp(zName,aParamQP[i].zName)==0 ) aParamQP[i].cTag = 1;
1208 }
1209 }
1210 }
1211
1212 /*
1213 ** This routine works like "printf" except that it has the
1214 ** extra formatting capabilities such as %h and %t.
1215 */
1216

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

+1 -1
--- src/doc.c
+++ src/doc.c
@@ -785,8 +785,8 @@
785785
** Search for documents that match a user-supplied pattern.
786786
*/
787787
void doc_search_page(void){
788788
login_check_credentials();
789789
style_header("Document Search");
790
- search_screen(SRCH_DOC, "docsrch");
790
+ search_screen(SRCH_DOC, 0);
791791
style_footer();
792792
}
793793
--- src/doc.c
+++ src/doc.c
@@ -785,8 +785,8 @@
785 ** Search for documents that match a user-supplied pattern.
786 */
787 void doc_search_page(void){
788 login_check_credentials();
789 style_header("Document Search");
790 search_screen(SRCH_DOC, "docsrch");
791 style_footer();
792 }
793
--- src/doc.c
+++ src/doc.c
@@ -785,8 +785,8 @@
785 ** Search for documents that match a user-supplied pattern.
786 */
787 void doc_search_page(void){
788 login_check_credentials();
789 style_header("Document Search");
790 search_screen(SRCH_DOC, 0);
791 style_footer();
792 }
793
+9 -13
--- src/event.c
+++ src/event.c
@@ -129,36 +129,32 @@
129129
if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
130130
style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
131131
g.zTop, zEventId);
132132
}
133133
zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
134
- style_submenu_element("Context", "Context", "%s/timeline?c=%T",
135
- g.zTop, zETime);
134
+ style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zEventId);
136135
if( g.perm.Hyperlink ){
137136
if( verboseFlag ){
138
- style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s",
139
- g.zTop, zEventId, zUuid);
137
+ style_submenu_element("Plain", 0, "%R/event?name=%.20s&aid=%s",
138
+ zEventId, zUuid);
140139
if( nextRid ){
141140
char *zNext;
142141
zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
143
- style_submenu_element("Next", "Next",
144
- "%s/event?name=%s&aid=%s&v",
145
- g.zTop, zEventId, zNext);
142
+ style_submenu_element("Next", 0,"%R/event?name=%.20s&aid=%s&v",
143
+ zEventId, zNext);
146144
free(zNext);
147145
}
148146
if( prevRid ){
149147
char *zPrev;
150148
zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
151
- style_submenu_element("Prev", "Prev",
152
- "%s/event?name=%s&aid=%s&v",
153
- g.zTop, zEventId, zPrev);
149
+ style_submenu_element("Prev", 0, "%R/event?name=%s&aid=%s&v",
150
+ zEventId, zPrev);
154151
free(zPrev);
155152
}
156153
}else{
157
- style_submenu_element("Detail", "Detail",
158
- "%s/event?name=%s&aid=%s&v",
159
- g.zTop, zEventId, zUuid);
154
+ style_submenu_element("Detail", 0, "%R/event?name=%.20s&aid=%s&v",
155
+ zEventId, zUuid);
160156
}
161157
}
162158
163159
if( verboseFlag && g.perm.Hyperlink ){
164160
int i;
165161
--- src/event.c
+++ src/event.c
@@ -129,36 +129,32 @@
129 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
130 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
131 g.zTop, zEventId);
132 }
133 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
134 style_submenu_element("Context", "Context", "%s/timeline?c=%T",
135 g.zTop, zETime);
136 if( g.perm.Hyperlink ){
137 if( verboseFlag ){
138 style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s",
139 g.zTop, zEventId, zUuid);
140 if( nextRid ){
141 char *zNext;
142 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
143 style_submenu_element("Next", "Next",
144 "%s/event?name=%s&aid=%s&v",
145 g.zTop, zEventId, zNext);
146 free(zNext);
147 }
148 if( prevRid ){
149 char *zPrev;
150 zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
151 style_submenu_element("Prev", "Prev",
152 "%s/event?name=%s&aid=%s&v",
153 g.zTop, zEventId, zPrev);
154 free(zPrev);
155 }
156 }else{
157 style_submenu_element("Detail", "Detail",
158 "%s/event?name=%s&aid=%s&v",
159 g.zTop, zEventId, zUuid);
160 }
161 }
162
163 if( verboseFlag && g.perm.Hyperlink ){
164 int i;
165
--- src/event.c
+++ src/event.c
@@ -129,36 +129,32 @@
129 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
130 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
131 g.zTop, zEventId);
132 }
133 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
134 style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zEventId);
 
135 if( g.perm.Hyperlink ){
136 if( verboseFlag ){
137 style_submenu_element("Plain", 0, "%R/event?name=%.20s&aid=%s",
138 zEventId, zUuid);
139 if( nextRid ){
140 char *zNext;
141 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
142 style_submenu_element("Next", 0,"%R/event?name=%.20s&aid=%s&v",
143 zEventId, zNext);
 
144 free(zNext);
145 }
146 if( prevRid ){
147 char *zPrev;
148 zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
149 style_submenu_element("Prev", 0, "%R/event?name=%s&aid=%s&v",
150 zEventId, zPrev);
 
151 free(zPrev);
152 }
153 }else{
154 style_submenu_element("Detail", 0, "%R/event?name=%.20s&aid=%s&v",
155 zEventId, zUuid);
 
156 }
157 }
158
159 if( verboseFlag && g.perm.Hyperlink ){
160 int i;
161

No diff available

No diff available

+35 -36
--- src/import.c
+++ src/import.c
@@ -1515,46 +1515,10 @@
15151515
db_open_config(0);
15161516
15171517
db_begin_transaction();
15181518
if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
15191519
1520
- if( strncmp(g.argv[2], "git", 3)==0 ){
1521
- /* The following temp-tables are used to hold information needed for
1522
- ** the import.
1523
- **
1524
- ** The XMARK table provides a mapping from fast-import "marks" and symbols
1525
- ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1526
- ** Given any valid fast-import symbol, the corresponding fossil rid and
1527
- ** uuid can found by searching against the xmark.tname field.
1528
- **
1529
- ** The XBRANCH table maps commit marks and symbols into the branch those
1530
- ** commits belong to. If xbranch.tname is a fast-import symbol for a
1531
- ** checkin then xbranch.brnm is the branch that checkin is part of.
1532
- **
1533
- ** The XTAG table records information about tags that need to be applied
1534
- ** to various branches after the import finishes. The xtag.tcontent field
1535
- ** contains the text of an artifact that will add a tag to a check-in.
1536
- ** The git-fast-export file format might specify the same tag multiple
1537
- ** times but only the last tag should be used. And we do not know which
1538
- ** occurrence of the tag is the last until the import finishes.
1539
- */
1540
- db_multi_exec(
1541
- "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1542
- "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1543
- "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1544
- );
1545
-
1546
- git_fast_import(pIn);
1547
- db_prepare(&q, "SELECT tcontent FROM xtag");
1548
- while( db_step(&q)==SQLITE_ROW ){
1549
- Blob record;
1550
- db_ephemeral_blob(&q, 0, &record);
1551
- fast_insert_content(&record, 0, 0);
1552
- import_reset(0);
1553
- }
1554
- db_finalize(&q);
1555
- }else
15561520
if( strncmp(g.argv[2], "svn", 3)==0 ){
15571521
db_multi_exec(
15581522
"CREATE TEMP TABLE xrevisions("
15591523
" trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
15601524
" UNIQUE(tbranch, trev)"
@@ -1605,10 +1569,45 @@
16051569
gsvn.zTags = mprintf("%s/", gsvn.zTags);
16061570
gsvn.lenTags++;
16071571
}
16081572
}
16091573
svn_dump_import(pIn);
1574
+ }else if( strncmp(g.argv[2], "git", 3)==0 ){
1575
+ /* The following temp-tables are used to hold information needed for
1576
+ ** the import.
1577
+ **
1578
+ ** The XMARK table provides a mapping from fast-import "marks" and symbols
1579
+ ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1580
+ ** Given any valid fast-import symbol, the corresponding fossil rid and
1581
+ ** uuid can found by searching against the xmark.tname field.
1582
+ **
1583
+ ** The XBRANCH table maps commit marks and symbols into the branch those
1584
+ ** commits belong to. If xbranch.tname is a fast-import symbol for a
1585
+ ** checkin then xbranch.brnm is the branch that checkin is part of.
1586
+ **
1587
+ ** The XTAG table records information about tags that need to be applied
1588
+ ** to various branches after the import finishes. The xtag.tcontent field
1589
+ ** contains the text of an artifact that will add a tag to a check-in.
1590
+ ** The git-fast-export file format might specify the same tag multiple
1591
+ ** times but only the last tag should be used. And we do not know which
1592
+ ** occurrence of the tag is the last until the import finishes.
1593
+ */
1594
+ db_multi_exec(
1595
+ "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1596
+ "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1597
+ "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1598
+ );
1599
+
1600
+ git_fast_import(pIn);
1601
+ db_prepare(&q, "SELECT tcontent FROM xtag");
1602
+ while( db_step(&q)==SQLITE_ROW ){
1603
+ Blob record;
1604
+ db_ephemeral_blob(&q, 0, &record);
1605
+ fast_insert_content(&record, 0, 0);
1606
+ import_reset(0);
1607
+ }
1608
+ db_finalize(&q);
16101609
}
16111610
16121611
verify_cancel();
16131612
db_end_transaction(0);
16141613
db_begin_transaction();
16151614
--- src/import.c
+++ src/import.c
@@ -1515,46 +1515,10 @@
1515 db_open_config(0);
1516
1517 db_begin_transaction();
1518 if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
1519
1520 if( strncmp(g.argv[2], "git", 3)==0 ){
1521 /* The following temp-tables are used to hold information needed for
1522 ** the import.
1523 **
1524 ** The XMARK table provides a mapping from fast-import "marks" and symbols
1525 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1526 ** Given any valid fast-import symbol, the corresponding fossil rid and
1527 ** uuid can found by searching against the xmark.tname field.
1528 **
1529 ** The XBRANCH table maps commit marks and symbols into the branch those
1530 ** commits belong to. If xbranch.tname is a fast-import symbol for a
1531 ** checkin then xbranch.brnm is the branch that checkin is part of.
1532 **
1533 ** The XTAG table records information about tags that need to be applied
1534 ** to various branches after the import finishes. The xtag.tcontent field
1535 ** contains the text of an artifact that will add a tag to a check-in.
1536 ** The git-fast-export file format might specify the same tag multiple
1537 ** times but only the last tag should be used. And we do not know which
1538 ** occurrence of the tag is the last until the import finishes.
1539 */
1540 db_multi_exec(
1541 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1542 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1543 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1544 );
1545
1546 git_fast_import(pIn);
1547 db_prepare(&q, "SELECT tcontent FROM xtag");
1548 while( db_step(&q)==SQLITE_ROW ){
1549 Blob record;
1550 db_ephemeral_blob(&q, 0, &record);
1551 fast_insert_content(&record, 0, 0);
1552 import_reset(0);
1553 }
1554 db_finalize(&q);
1555 }else
1556 if( strncmp(g.argv[2], "svn", 3)==0 ){
1557 db_multi_exec(
1558 "CREATE TEMP TABLE xrevisions("
1559 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1560 " UNIQUE(tbranch, trev)"
@@ -1605,10 +1569,45 @@
1605 gsvn.zTags = mprintf("%s/", gsvn.zTags);
1606 gsvn.lenTags++;
1607 }
1608 }
1609 svn_dump_import(pIn);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1610 }
1611
1612 verify_cancel();
1613 db_end_transaction(0);
1614 db_begin_transaction();
1615
--- src/import.c
+++ src/import.c
@@ -1515,46 +1515,10 @@
1515 db_open_config(0);
1516
1517 db_begin_transaction();
1518 if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
1519
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1520 if( strncmp(g.argv[2], "svn", 3)==0 ){
1521 db_multi_exec(
1522 "CREATE TEMP TABLE xrevisions("
1523 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1524 " UNIQUE(tbranch, trev)"
@@ -1605,10 +1569,45 @@
1569 gsvn.zTags = mprintf("%s/", gsvn.zTags);
1570 gsvn.lenTags++;
1571 }
1572 }
1573 svn_dump_import(pIn);
1574 }else if( strncmp(g.argv[2], "git", 3)==0 ){
1575 /* The following temp-tables are used to hold information needed for
1576 ** the import.
1577 **
1578 ** The XMARK table provides a mapping from fast-import "marks" and symbols
1579 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1580 ** Given any valid fast-import symbol, the corresponding fossil rid and
1581 ** uuid can found by searching against the xmark.tname field.
1582 **
1583 ** The XBRANCH table maps commit marks and symbols into the branch those
1584 ** commits belong to. If xbranch.tname is a fast-import symbol for a
1585 ** checkin then xbranch.brnm is the branch that checkin is part of.
1586 **
1587 ** The XTAG table records information about tags that need to be applied
1588 ** to various branches after the import finishes. The xtag.tcontent field
1589 ** contains the text of an artifact that will add a tag to a check-in.
1590 ** The git-fast-export file format might specify the same tag multiple
1591 ** times but only the last tag should be used. And we do not know which
1592 ** occurrence of the tag is the last until the import finishes.
1593 */
1594 db_multi_exec(
1595 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1596 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1597 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1598 );
1599
1600 git_fast_import(pIn);
1601 db_prepare(&q, "SELECT tcontent FROM xtag");
1602 while( db_step(&q)==SQLITE_ROW ){
1603 Blob record;
1604 db_ephemeral_blob(&q, 0, &record);
1605 fast_insert_content(&record, 0, 0);
1606 import_reset(0);
1607 }
1608 db_finalize(&q);
1609 }
1610
1611 verify_cancel();
1612 db_end_transaction(0);
1613 db_begin_transaction();
1614
+35 -36
--- src/import.c
+++ src/import.c
@@ -1515,46 +1515,10 @@
15151515
db_open_config(0);
15161516
15171517
db_begin_transaction();
15181518
if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
15191519
1520
- if( strncmp(g.argv[2], "git", 3)==0 ){
1521
- /* The following temp-tables are used to hold information needed for
1522
- ** the import.
1523
- **
1524
- ** The XMARK table provides a mapping from fast-import "marks" and symbols
1525
- ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1526
- ** Given any valid fast-import symbol, the corresponding fossil rid and
1527
- ** uuid can found by searching against the xmark.tname field.
1528
- **
1529
- ** The XBRANCH table maps commit marks and symbols into the branch those
1530
- ** commits belong to. If xbranch.tname is a fast-import symbol for a
1531
- ** checkin then xbranch.brnm is the branch that checkin is part of.
1532
- **
1533
- ** The XTAG table records information about tags that need to be applied
1534
- ** to various branches after the import finishes. The xtag.tcontent field
1535
- ** contains the text of an artifact that will add a tag to a check-in.
1536
- ** The git-fast-export file format might specify the same tag multiple
1537
- ** times but only the last tag should be used. And we do not know which
1538
- ** occurrence of the tag is the last until the import finishes.
1539
- */
1540
- db_multi_exec(
1541
- "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1542
- "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1543
- "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1544
- );
1545
-
1546
- git_fast_import(pIn);
1547
- db_prepare(&q, "SELECT tcontent FROM xtag");
1548
- while( db_step(&q)==SQLITE_ROW ){
1549
- Blob record;
1550
- db_ephemeral_blob(&q, 0, &record);
1551
- fast_insert_content(&record, 0, 0);
1552
- import_reset(0);
1553
- }
1554
- db_finalize(&q);
1555
- }else
15561520
if( strncmp(g.argv[2], "svn", 3)==0 ){
15571521
db_multi_exec(
15581522
"CREATE TEMP TABLE xrevisions("
15591523
" trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
15601524
" UNIQUE(tbranch, trev)"
@@ -1605,10 +1569,45 @@
16051569
gsvn.zTags = mprintf("%s/", gsvn.zTags);
16061570
gsvn.lenTags++;
16071571
}
16081572
}
16091573
svn_dump_import(pIn);
1574
+ }else if( strncmp(g.argv[2], "git", 3)==0 ){
1575
+ /* The following temp-tables are used to hold information needed for
1576
+ ** the import.
1577
+ **
1578
+ ** The XMARK table provides a mapping from fast-import "marks" and symbols
1579
+ ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1580
+ ** Given any valid fast-import symbol, the corresponding fossil rid and
1581
+ ** uuid can found by searching against the xmark.tname field.
1582
+ **
1583
+ ** The XBRANCH table maps commit marks and symbols into the branch those
1584
+ ** commits belong to. If xbranch.tname is a fast-import symbol for a
1585
+ ** checkin then xbranch.brnm is the branch that checkin is part of.
1586
+ **
1587
+ ** The XTAG table records information about tags that need to be applied
1588
+ ** to various branches after the import finishes. The xtag.tcontent field
1589
+ ** contains the text of an artifact that will add a tag to a check-in.
1590
+ ** The git-fast-export file format might specify the same tag multiple
1591
+ ** times but only the last tag should be used. And we do not know which
1592
+ ** occurrence of the tag is the last until the import finishes.
1593
+ */
1594
+ db_multi_exec(
1595
+ "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1596
+ "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1597
+ "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1598
+ );
1599
+
1600
+ git_fast_import(pIn);
1601
+ db_prepare(&q, "SELECT tcontent FROM xtag");
1602
+ while( db_step(&q)==SQLITE_ROW ){
1603
+ Blob record;
1604
+ db_ephemeral_blob(&q, 0, &record);
1605
+ fast_insert_content(&record, 0, 0);
1606
+ import_reset(0);
1607
+ }
1608
+ db_finalize(&q);
16101609
}
16111610
16121611
verify_cancel();
16131612
db_end_transaction(0);
16141613
db_begin_transaction();
16151614
--- src/import.c
+++ src/import.c
@@ -1515,46 +1515,10 @@
1515 db_open_config(0);
1516
1517 db_begin_transaction();
1518 if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
1519
1520 if( strncmp(g.argv[2], "git", 3)==0 ){
1521 /* The following temp-tables are used to hold information needed for
1522 ** the import.
1523 **
1524 ** The XMARK table provides a mapping from fast-import "marks" and symbols
1525 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1526 ** Given any valid fast-import symbol, the corresponding fossil rid and
1527 ** uuid can found by searching against the xmark.tname field.
1528 **
1529 ** The XBRANCH table maps commit marks and symbols into the branch those
1530 ** commits belong to. If xbranch.tname is a fast-import symbol for a
1531 ** checkin then xbranch.brnm is the branch that checkin is part of.
1532 **
1533 ** The XTAG table records information about tags that need to be applied
1534 ** to various branches after the import finishes. The xtag.tcontent field
1535 ** contains the text of an artifact that will add a tag to a check-in.
1536 ** The git-fast-export file format might specify the same tag multiple
1537 ** times but only the last tag should be used. And we do not know which
1538 ** occurrence of the tag is the last until the import finishes.
1539 */
1540 db_multi_exec(
1541 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1542 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1543 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1544 );
1545
1546 git_fast_import(pIn);
1547 db_prepare(&q, "SELECT tcontent FROM xtag");
1548 while( db_step(&q)==SQLITE_ROW ){
1549 Blob record;
1550 db_ephemeral_blob(&q, 0, &record);
1551 fast_insert_content(&record, 0, 0);
1552 import_reset(0);
1553 }
1554 db_finalize(&q);
1555 }else
1556 if( strncmp(g.argv[2], "svn", 3)==0 ){
1557 db_multi_exec(
1558 "CREATE TEMP TABLE xrevisions("
1559 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1560 " UNIQUE(tbranch, trev)"
@@ -1605,10 +1569,45 @@
1605 gsvn.zTags = mprintf("%s/", gsvn.zTags);
1606 gsvn.lenTags++;
1607 }
1608 }
1609 svn_dump_import(pIn);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1610 }
1611
1612 verify_cancel();
1613 db_end_transaction(0);
1614 db_begin_transaction();
1615
--- src/import.c
+++ src/import.c
@@ -1515,46 +1515,10 @@
1515 db_open_config(0);
1516
1517 db_begin_transaction();
1518 if( !incrFlag ) db_initial_setup(0, 0, 0, 1);
1519
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1520 if( strncmp(g.argv[2], "svn", 3)==0 ){
1521 db_multi_exec(
1522 "CREATE TEMP TABLE xrevisions("
1523 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1524 " UNIQUE(tbranch, trev)"
@@ -1605,10 +1569,45 @@
1569 gsvn.zTags = mprintf("%s/", gsvn.zTags);
1570 gsvn.lenTags++;
1571 }
1572 }
1573 svn_dump_import(pIn);
1574 }else if( strncmp(g.argv[2], "git", 3)==0 ){
1575 /* The following temp-tables are used to hold information needed for
1576 ** the import.
1577 **
1578 ** The XMARK table provides a mapping from fast-import "marks" and symbols
1579 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
1580 ** Given any valid fast-import symbol, the corresponding fossil rid and
1581 ** uuid can found by searching against the xmark.tname field.
1582 **
1583 ** The XBRANCH table maps commit marks and symbols into the branch those
1584 ** commits belong to. If xbranch.tname is a fast-import symbol for a
1585 ** checkin then xbranch.brnm is the branch that checkin is part of.
1586 **
1587 ** The XTAG table records information about tags that need to be applied
1588 ** to various branches after the import finishes. The xtag.tcontent field
1589 ** contains the text of an artifact that will add a tag to a check-in.
1590 ** The git-fast-export file format might specify the same tag multiple
1591 ** times but only the last tag should be used. And we do not know which
1592 ** occurrence of the tag is the last until the import finishes.
1593 */
1594 db_multi_exec(
1595 "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);"
1596 "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);"
1597 "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);"
1598 );
1599
1600 git_fast_import(pIn);
1601 db_prepare(&q, "SELECT tcontent FROM xtag");
1602 while( db_step(&q)==SQLITE_ROW ){
1603 Blob record;
1604 db_ephemeral_blob(&q, 0, &record);
1605 fast_insert_content(&record, 0, 0);
1606 import_reset(0);
1607 }
1608 db_finalize(&q);
1609 }
1610
1611 verify_cancel();
1612 db_end_transaction(0);
1613 db_begin_transaction();
1614

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

+58 -31
--- src/search.c
+++ src/search.c
@@ -567,26 +567,33 @@
567567
/*
568568
** Remove bits from srchFlags which are disallowed by either the
569569
** current server configuration or by user permissions.
570570
*/
571571
unsigned int search_restrict(unsigned int srchFlags){
572
+ static unsigned int knownGood = 0;
573
+ static unsigned int knownBad = 0;
574
+ static const struct { unsigned m; const char *zKey; } aSetng[] = {
575
+ { SRCH_CKIN, "search-ci" },
576
+ { SRCH_DOC, "search-doc" },
577
+ { SRCH_TKT, "search-tkt" },
578
+ { SRCH_WIKI, "search-wiki" },
579
+ };
580
+ int i;
572581
if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC);
573582
if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT);
574583
if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI);
575
- if( (srchFlags & SRCH_CKIN)!=0 && db_get_boolean("search-ci",0)==0 ){
576
- srchFlags &= ~SRCH_CKIN;
577
- }
578
- if( (srchFlags & SRCH_DOC)!=0 && db_get_boolean("search-doc",0)==0 ){
579
- srchFlags &= ~SRCH_DOC;
580
- }
581
- if( (srchFlags & SRCH_TKT)!=0 && db_get_boolean("search-tkt",0)==0 ){
582
- srchFlags &= ~SRCH_TKT;
583
- }
584
- if( (srchFlags & SRCH_WIKI)!=0 && db_get_boolean("search-wiki",0)==0 ){
585
- srchFlags &= ~SRCH_WIKI;
586
- }
587
- return srchFlags;
584
+ for(i=0; i<ArraySize(aSetng); i++){
585
+ unsigned int m = aSetng[i].m;
586
+ if( (srchFlags & m)==0 ) continue;
587
+ if( ((knownGood|knownBad) & m)!=0 ) continue;
588
+ if( db_get_boolean(aSetng[i].zKey,0) ){
589
+ knownGood |= m;
590
+ }else{
591
+ knownBad |= m;
592
+ }
593
+ }
594
+ return srchFlags & ~knownBad;
588595
}
589596
590597
/*
591598
** When this routine is called, there already exists a table
592599
**
@@ -875,46 +882,75 @@
875882
/*
876883
** Generate some HTML for doing search. At a minimum include the
877884
** Search-Text entry form. If the "s" query parameter is present, also
878885
** show search results.
879886
**
880
-** The srchFlags parameter is used to customize some of the text of the
881
-** form and the results. srchFlags should be either a single search
882
-** category or all categories. Any srchFlags with two or more bits set
887
+** The srchFlags parameter restricts the set of documents to be searched.
888
+** srchFlags should normally be either a single search category or all
889
+** categories. Any srchFlags with two or more bits set
883890
** is treated like SRCH_ALL for display purposes.
884891
**
885
-** The entry box is shown disabled if srchFlags is 0.
892
+** This routine automatically restricts srchFlag according to user
893
+** permissions and the server configuration. The entry box is shown
894
+** disabled if srchFlags is 0 after these restrictions are applied.
895
+**
896
+** If useYparam is true, then this routine also looks at the y= query
897
+** parameter for further search restrictions.
886898
*/
887
-void search_screen(unsigned srchFlags, const char *zAction){
899
+void search_screen(unsigned srchFlags, int useYparam){
888900
const char *zType = 0;
889901
const char *zClass = 0;
890902
const char *zDisable1;
891903
const char *zDisable2;
892904
const char *zPattern;
905
+ srchFlags = search_restrict(srchFlags);
893906
switch( srchFlags ){
894907
case SRCH_CKIN: zType = " Check-ins"; zClass = "Ckin"; break;
895908
case SRCH_DOC: zType = " Docs"; zClass = "Doc"; break;
896909
case SRCH_TKT: zType = " Tickets"; zClass = "Tkt"; break;
897910
case SRCH_WIKI: zType = " Wiki"; zClass = "Wiki"; break;
898911
}
899
- srchFlags = search_restrict(srchFlags);
900912
if( srchFlags==0 ){
901913
zDisable1 = " disabled";
902914
zDisable2 = " disabled";
903915
zPattern = "";
904916
}else{
905917
zDisable1 = " autofocus";
906918
zDisable2 = "";
907919
zPattern = PD("s","");
908920
}
909
- @ <form method='GET' action='%s(zAction)'>
921
+ @ <form method='GET' action='%R/%t(g.zPath)'>
910922
if( zClass ){
911923
@ <div class='searchForm searchForm%s(zClass)'>
912924
}else{
913925
@ <div class='searchForm'>
914926
}
915927
@ <input type="text" name="s" size="40" value="%h(zPattern)"%s(zDisable1)>
928
+ if( useYparam && (srchFlags & (srchFlags-1))!=0 && useYparam ){
929
+ static const struct { char *z; char *zNm; unsigned m; } aY[] = {
930
+ { "all", "All", SRCH_ALL },
931
+ { "c", "Check-ins", SRCH_CKIN },
932
+ { "d", "Docs", SRCH_DOC },
933
+ { "t", "Tickets", SRCH_TKT },
934
+ { "w", "Wiki", SRCH_WIKI },
935
+ };
936
+ const char *zY = PD("y","all");
937
+ unsigned newFlags = srchFlags;
938
+ int i;
939
+ @ <select size='1' name='y'>
940
+ for(i=0; i<ArraySize(aY); i++){
941
+ if( (aY[i].m & srchFlags)==0 ) continue;
942
+ cgi_printf("<option value='%s'", aY[i].z);
943
+ if( fossil_strcmp(zY,aY[i].z)==0 ){
944
+ newFlags &= aY[i].m;
945
+ cgi_printf(" selected");
946
+ }
947
+ cgi_printf(">%s</option>\n", aY[i].zNm);
948
+ }
949
+ @ </select>
950
+ srchFlags = newFlags;
951
+ }
916952
@ <input type="submit" value="Search%s(zType)"%s(zDisable2)>
917953
if( srchFlags==0 ){
918954
@ <p class="generalError">Search is disabled</p>
919955
}
920956
@ </div></form>
@@ -937,22 +973,13 @@
937973
**
938974
** Search for check-in comments, documents, tickets, or wiki that
939975
** match a user-supplied pattern.
940976
*/
941977
void search_page(void){
942
- unsigned srchFlags = SRCH_ALL;
943
- const char *zOnly = P("only");
944
-
945978
login_check_credentials();
946
- if( zOnly ){
947
- if( strchr(zOnly,'c') ) srchFlags &= SRCH_CKIN;
948
- if( strchr(zOnly,'d') ) srchFlags &= SRCH_DOC;
949
- if( strchr(zOnly,'t') ) srchFlags &= SRCH_TKT;
950
- if( strchr(zOnly,'w') ) srchFlags &= SRCH_WIKI;
951
- }
952979
style_header("Search");
953
- search_screen(srchFlags, "search");
980
+ search_screen(SRCH_ALL, 1);
954981
style_footer();
955982
}
956983
957984
958985
/*
@@ -1295,11 +1322,11 @@
12951322
);
12961323
db_multi_exec(
12971324
"REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
12981325
" SELECT ftsdocs.rowid, 1, 'c', ftsdocs.rid, NULL,"
12991326
" printf('Check-in [%%.16s] on %%s',blob.uuid,datetime(event.mtime)),"
1300
- " printf('/timeline?y=ci&n=9&c=%%.20s',blob.uuid),"
1327
+ " printf('/timeline?y=ci&c=%%.20s',blob.uuid),"
13011328
" event.mtime"
13021329
" FROM ftsdocs, event, blob"
13031330
" WHERE ftsdocs.type='c' AND NOT ftsdocs.idxed"
13041331
" AND event.objid=ftsdocs.rid"
13051332
" AND blob.rid=ftsdocs.rid"
13061333
--- src/search.c
+++ src/search.c
@@ -567,26 +567,33 @@
567 /*
568 ** Remove bits from srchFlags which are disallowed by either the
569 ** current server configuration or by user permissions.
570 */
571 unsigned int search_restrict(unsigned int srchFlags){
 
 
 
 
 
 
 
 
 
572 if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC);
573 if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT);
574 if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI);
575 if( (srchFlags & SRCH_CKIN)!=0 && db_get_boolean("search-ci",0)==0 ){
576 srchFlags &= ~SRCH_CKIN;
577 }
578 if( (srchFlags & SRCH_DOC)!=0 && db_get_boolean("search-doc",0)==0 ){
579 srchFlags &= ~SRCH_DOC;
580 }
581 if( (srchFlags & SRCH_TKT)!=0 && db_get_boolean("search-tkt",0)==0 ){
582 srchFlags &= ~SRCH_TKT;
583 }
584 if( (srchFlags & SRCH_WIKI)!=0 && db_get_boolean("search-wiki",0)==0 ){
585 srchFlags &= ~SRCH_WIKI;
586 }
587 return srchFlags;
588 }
589
590 /*
591 ** When this routine is called, there already exists a table
592 **
@@ -875,46 +882,75 @@
875 /*
876 ** Generate some HTML for doing search. At a minimum include the
877 ** Search-Text entry form. If the "s" query parameter is present, also
878 ** show search results.
879 **
880 ** The srchFlags parameter is used to customize some of the text of the
881 ** form and the results. srchFlags should be either a single search
882 ** category or all categories. Any srchFlags with two or more bits set
883 ** is treated like SRCH_ALL for display purposes.
884 **
885 ** The entry box is shown disabled if srchFlags is 0.
 
 
 
 
 
886 */
887 void search_screen(unsigned srchFlags, const char *zAction){
888 const char *zType = 0;
889 const char *zClass = 0;
890 const char *zDisable1;
891 const char *zDisable2;
892 const char *zPattern;
 
893 switch( srchFlags ){
894 case SRCH_CKIN: zType = " Check-ins"; zClass = "Ckin"; break;
895 case SRCH_DOC: zType = " Docs"; zClass = "Doc"; break;
896 case SRCH_TKT: zType = " Tickets"; zClass = "Tkt"; break;
897 case SRCH_WIKI: zType = " Wiki"; zClass = "Wiki"; break;
898 }
899 srchFlags = search_restrict(srchFlags);
900 if( srchFlags==0 ){
901 zDisable1 = " disabled";
902 zDisable2 = " disabled";
903 zPattern = "";
904 }else{
905 zDisable1 = " autofocus";
906 zDisable2 = "";
907 zPattern = PD("s","");
908 }
909 @ <form method='GET' action='%s(zAction)'>
910 if( zClass ){
911 @ <div class='searchForm searchForm%s(zClass)'>
912 }else{
913 @ <div class='searchForm'>
914 }
915 @ <input type="text" name="s" size="40" value="%h(zPattern)"%s(zDisable1)>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
916 @ <input type="submit" value="Search%s(zType)"%s(zDisable2)>
917 if( srchFlags==0 ){
918 @ <p class="generalError">Search is disabled</p>
919 }
920 @ </div></form>
@@ -937,22 +973,13 @@
937 **
938 ** Search for check-in comments, documents, tickets, or wiki that
939 ** match a user-supplied pattern.
940 */
941 void search_page(void){
942 unsigned srchFlags = SRCH_ALL;
943 const char *zOnly = P("only");
944
945 login_check_credentials();
946 if( zOnly ){
947 if( strchr(zOnly,'c') ) srchFlags &= SRCH_CKIN;
948 if( strchr(zOnly,'d') ) srchFlags &= SRCH_DOC;
949 if( strchr(zOnly,'t') ) srchFlags &= SRCH_TKT;
950 if( strchr(zOnly,'w') ) srchFlags &= SRCH_WIKI;
951 }
952 style_header("Search");
953 search_screen(srchFlags, "search");
954 style_footer();
955 }
956
957
958 /*
@@ -1295,11 +1322,11 @@
1295 );
1296 db_multi_exec(
1297 "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1298 " SELECT ftsdocs.rowid, 1, 'c', ftsdocs.rid, NULL,"
1299 " printf('Check-in [%%.16s] on %%s',blob.uuid,datetime(event.mtime)),"
1300 " printf('/timeline?y=ci&n=9&c=%%.20s',blob.uuid),"
1301 " event.mtime"
1302 " FROM ftsdocs, event, blob"
1303 " WHERE ftsdocs.type='c' AND NOT ftsdocs.idxed"
1304 " AND event.objid=ftsdocs.rid"
1305 " AND blob.rid=ftsdocs.rid"
1306
--- src/search.c
+++ src/search.c
@@ -567,26 +567,33 @@
567 /*
568 ** Remove bits from srchFlags which are disallowed by either the
569 ** current server configuration or by user permissions.
570 */
571 unsigned int search_restrict(unsigned int srchFlags){
572 static unsigned int knownGood = 0;
573 static unsigned int knownBad = 0;
574 static const struct { unsigned m; const char *zKey; } aSetng[] = {
575 { SRCH_CKIN, "search-ci" },
576 { SRCH_DOC, "search-doc" },
577 { SRCH_TKT, "search-tkt" },
578 { SRCH_WIKI, "search-wiki" },
579 };
580 int i;
581 if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC);
582 if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT);
583 if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI);
584 for(i=0; i<ArraySize(aSetng); i++){
585 unsigned int m = aSetng[i].m;
586 if( (srchFlags & m)==0 ) continue;
587 if( ((knownGood|knownBad) & m)!=0 ) continue;
588 if( db_get_boolean(aSetng[i].zKey,0) ){
589 knownGood |= m;
590 }else{
591 knownBad |= m;
592 }
593 }
594 return srchFlags & ~knownBad;
 
 
595 }
596
597 /*
598 ** When this routine is called, there already exists a table
599 **
@@ -875,46 +882,75 @@
882 /*
883 ** Generate some HTML for doing search. At a minimum include the
884 ** Search-Text entry form. If the "s" query parameter is present, also
885 ** show search results.
886 **
887 ** The srchFlags parameter restricts the set of documents to be searched.
888 ** srchFlags should normally be either a single search category or all
889 ** categories. Any srchFlags with two or more bits set
890 ** is treated like SRCH_ALL for display purposes.
891 **
892 ** This routine automatically restricts srchFlag according to user
893 ** permissions and the server configuration. The entry box is shown
894 ** disabled if srchFlags is 0 after these restrictions are applied.
895 **
896 ** If useYparam is true, then this routine also looks at the y= query
897 ** parameter for further search restrictions.
898 */
899 void search_screen(unsigned srchFlags, int useYparam){
900 const char *zType = 0;
901 const char *zClass = 0;
902 const char *zDisable1;
903 const char *zDisable2;
904 const char *zPattern;
905 srchFlags = search_restrict(srchFlags);
906 switch( srchFlags ){
907 case SRCH_CKIN: zType = " Check-ins"; zClass = "Ckin"; break;
908 case SRCH_DOC: zType = " Docs"; zClass = "Doc"; break;
909 case SRCH_TKT: zType = " Tickets"; zClass = "Tkt"; break;
910 case SRCH_WIKI: zType = " Wiki"; zClass = "Wiki"; break;
911 }
 
912 if( srchFlags==0 ){
913 zDisable1 = " disabled";
914 zDisable2 = " disabled";
915 zPattern = "";
916 }else{
917 zDisable1 = " autofocus";
918 zDisable2 = "";
919 zPattern = PD("s","");
920 }
921 @ <form method='GET' action='%R/%t(g.zPath)'>
922 if( zClass ){
923 @ <div class='searchForm searchForm%s(zClass)'>
924 }else{
925 @ <div class='searchForm'>
926 }
927 @ <input type="text" name="s" size="40" value="%h(zPattern)"%s(zDisable1)>
928 if( useYparam && (srchFlags & (srchFlags-1))!=0 && useYparam ){
929 static const struct { char *z; char *zNm; unsigned m; } aY[] = {
930 { "all", "All", SRCH_ALL },
931 { "c", "Check-ins", SRCH_CKIN },
932 { "d", "Docs", SRCH_DOC },
933 { "t", "Tickets", SRCH_TKT },
934 { "w", "Wiki", SRCH_WIKI },
935 };
936 const char *zY = PD("y","all");
937 unsigned newFlags = srchFlags;
938 int i;
939 @ <select size='1' name='y'>
940 for(i=0; i<ArraySize(aY); i++){
941 if( (aY[i].m & srchFlags)==0 ) continue;
942 cgi_printf("<option value='%s'", aY[i].z);
943 if( fossil_strcmp(zY,aY[i].z)==0 ){
944 newFlags &= aY[i].m;
945 cgi_printf(" selected");
946 }
947 cgi_printf(">%s</option>\n", aY[i].zNm);
948 }
949 @ </select>
950 srchFlags = newFlags;
951 }
952 @ <input type="submit" value="Search%s(zType)"%s(zDisable2)>
953 if( srchFlags==0 ){
954 @ <p class="generalError">Search is disabled</p>
955 }
956 @ </div></form>
@@ -937,22 +973,13 @@
973 **
974 ** Search for check-in comments, documents, tickets, or wiki that
975 ** match a user-supplied pattern.
976 */
977 void search_page(void){
 
 
 
978 login_check_credentials();
 
 
 
 
 
 
979 style_header("Search");
980 search_screen(SRCH_ALL, 1);
981 style_footer();
982 }
983
984
985 /*
@@ -1295,11 +1322,11 @@
1322 );
1323 db_multi_exec(
1324 "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1325 " SELECT ftsdocs.rowid, 1, 'c', ftsdocs.rid, NULL,"
1326 " printf('Check-in [%%.16s] on %%s',blob.uuid,datetime(event.mtime)),"
1327 " printf('/timeline?y=ci&c=%%.20s',blob.uuid),"
1328 " event.mtime"
1329 " FROM ftsdocs, event, blob"
1330 " WHERE ftsdocs.type='c' AND NOT ftsdocs.idxed"
1331 " AND event.objid=ftsdocs.rid"
1332 " AND blob.rid=ftsdocs.rid"
1333
+17
--- src/setup.c
+++ src/setup.c
@@ -1263,10 +1263,27 @@
12631263
@ <p><form action="%s(g.zTop)/setup_login_group" method="post"><div>
12641264
login_insert_csrf_secret();
12651265
@ To leave this login group press
12661266
@ <input type="submit" value="Leave Login Group" name="leave">
12671267
@ </form></p>
1268
+ @ <hr><h2>Implementation Details</h2>
1269
+ @ <p>The following are fields from the CONFIG table related to login-groups,
1270
+ @ provided here for instructional and debugging purposes:</p>
1271
+ @ <table border='1' id='configTab'>
1272
+ @ <thead><tr><th>Config.Name<th>Config.Value<th>Config.mtime</tr></thead><tbody>
1273
+ db_prepare(&q, "SELECT name, value, datetime(mtime,'unixepoch') FROM config"
1274
+ " WHERE name GLOB 'peer-*'"
1275
+ " OR name GLOB 'project-*'"
1276
+ " ORDER BY name");
1277
+ while( db_step(&q)==SQLITE_ROW ){
1278
+ @ <tr><td>%h(db_column_text(&q,0))</td>
1279
+ @ <td>%h(db_column_text(&q,1))</td>
1280
+ @ <td>%h(db_column_text(&q,2))</td></tr>
1281
+ }
1282
+ db_finalize(&q);
1283
+ @ </tbody></table>
1284
+ output_table_sorting_javascript("configTab","ttt",1);
12681285
}
12691286
style_footer();
12701287
}
12711288
12721289
/*
12731290
--- src/setup.c
+++ src/setup.c
@@ -1263,10 +1263,27 @@
1263 @ <p><form action="%s(g.zTop)/setup_login_group" method="post"><div>
1264 login_insert_csrf_secret();
1265 @ To leave this login group press
1266 @ <input type="submit" value="Leave Login Group" name="leave">
1267 @ </form></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1268 }
1269 style_footer();
1270 }
1271
1272 /*
1273
--- src/setup.c
+++ src/setup.c
@@ -1263,10 +1263,27 @@
1263 @ <p><form action="%s(g.zTop)/setup_login_group" method="post"><div>
1264 login_insert_csrf_secret();
1265 @ To leave this login group press
1266 @ <input type="submit" value="Leave Login Group" name="leave">
1267 @ </form></p>
1268 @ <hr><h2>Implementation Details</h2>
1269 @ <p>The following are fields from the CONFIG table related to login-groups,
1270 @ provided here for instructional and debugging purposes:</p>
1271 @ <table border='1' id='configTab'>
1272 @ <thead><tr><th>Config.Name<th>Config.Value<th>Config.mtime</tr></thead><tbody>
1273 db_prepare(&q, "SELECT name, value, datetime(mtime,'unixepoch') FROM config"
1274 " WHERE name GLOB 'peer-*'"
1275 " OR name GLOB 'project-*'"
1276 " ORDER BY name");
1277 while( db_step(&q)==SQLITE_ROW ){
1278 @ <tr><td>%h(db_column_text(&q,0))</td>
1279 @ <td>%h(db_column_text(&q,1))</td>
1280 @ <td>%h(db_column_text(&q,2))</td></tr>
1281 }
1282 db_finalize(&q);
1283 @ </tbody></table>
1284 output_table_sorting_javascript("configTab","ttt",1);
1285 }
1286 style_footer();
1287 }
1288
1289 /*
1290

No diff available

+1 -1
--- src/sitemap.c
+++ src/sitemap.c
@@ -44,11 +44,11 @@
4444
@ <li>%z(href("%R/fileage?name=trunk"))File ages for Trunk</a></li>
4545
@ </ul>
4646
@ <li>%z(href("%R/timeline?n=200"))Project Timeline</a></li>
4747
@ <ul>
4848
@ <li>%z(href("%R/timeline?a=1970-01-01&y=ci&n=10"))First 10 checkins</a></li>
49
- @ <li>%z(href("%R/timeline?n=0&namechng"))All checkins with file name
49
+ @ <li>%z(href("%R/timeline?n=all&namechng"))All checkins with file name
5050
@ changes</a></li>
5151
@ <li>%z(href("%R/reports"))Activity Reports</a></li>
5252
@ </ul>
5353
@ <li>Branches and Tags</a>
5454
@ <ul>
5555
--- src/sitemap.c
+++ src/sitemap.c
@@ -44,11 +44,11 @@
44 @ <li>%z(href("%R/fileage?name=trunk"))File ages for Trunk</a></li>
45 @ </ul>
46 @ <li>%z(href("%R/timeline?n=200"))Project Timeline</a></li>
47 @ <ul>
48 @ <li>%z(href("%R/timeline?a=1970-01-01&y=ci&n=10"))First 10 checkins</a></li>
49 @ <li>%z(href("%R/timeline?n=0&namechng"))All checkins with file name
50 @ changes</a></li>
51 @ <li>%z(href("%R/reports"))Activity Reports</a></li>
52 @ </ul>
53 @ <li>Branches and Tags</a>
54 @ <ul>
55
--- src/sitemap.c
+++ src/sitemap.c
@@ -44,11 +44,11 @@
44 @ <li>%z(href("%R/fileage?name=trunk"))File ages for Trunk</a></li>
45 @ </ul>
46 @ <li>%z(href("%R/timeline?n=200"))Project Timeline</a></li>
47 @ <ul>
48 @ <li>%z(href("%R/timeline?a=1970-01-01&y=ci&n=10"))First 10 checkins</a></li>
49 @ <li>%z(href("%R/timeline?n=all&namechng"))All checkins with file name
50 @ changes</a></li>
51 @ <li>%z(href("%R/reports"))Activity Reports</a></li>
52 @ </ul>
53 @ <li>Branches and Tags</a>
54 @ <ul>
55

No diff available

No diff available

+166 -20
--- src/style.c
+++ src/style.c
@@ -23,21 +23,42 @@
2323
#include "style.h"
2424
2525
2626
/*
2727
** Elements of the submenu are collected into the following
28
-** structure and displayed below the main menu by style_header().
28
+** structure and displayed below the main menu.
29
+**
30
+** Populate these structure with calls to
31
+**
32
+** style_submenu_element()
33
+** style_submenu_entry()
34
+** style_submenu_checkbox()
35
+** style_submenu_multichoice()
2936
**
30
-** Populate this structure with calls to style_submenu_element()
31
-** prior to calling style_header().
37
+** prior to calling style_footer(). The style_footer() routine
38
+** will generate the appropriate HTML text just below the main
39
+** menu.
3240
*/
3341
static struct Submenu {
34
- const char *zLabel;
42
+ const char *zLabel; /* Button label */
3543
const char *zTitle;
36
- const char *zLink;
44
+ const char *zLink; /* Jump to this link when button is pressed */
3745
} aSubmenu[30];
38
-static int nSubmenu = 0;
46
+static int nSubmenu = 0; /* Number of buttons */
47
+static struct SubmenuCtrl {
48
+ const char *zName; /* Form query parameter */
49
+ const char *zLabel; /* Label. Might be NULL for FF_MULTI */
50
+ int eType; /* FF_ENTRY, FF_CKBOX, FF_MULTI */
51
+ int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
52
+ const char **azChoice; /* value/display pairs for FF_MULTI */
53
+ const char *zFalse; /* FF_BINARY label when false */
54
+} aSubmenuCtrl[20];
55
+static int nSubmenuCtrl = 0;
56
+#define FF_ENTRY 1
57
+#define FF_CKBOX 2
58
+#define FF_MULTI 3
59
+#define FF_BINARY 4
3960
4061
/*
4162
** Remember that the header has been generated. The footer is omitted
4263
** if an error occurs before the header.
4364
*/
@@ -216,16 +237,63 @@
216237
...
217238
){
218239
va_list ap;
219240
assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) );
220241
aSubmenu[nSubmenu].zLabel = zLabel;
221
- aSubmenu[nSubmenu].zTitle = zTitle;
242
+ aSubmenu[nSubmenu].zTitle = zTitle ? zTitle : zLabel;
222243
va_start(ap, zLink);
223244
aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap);
224245
va_end(ap);
225246
nSubmenu++;
226247
}
248
+void style_submenu_entry(
249
+ const char *zName, /* Query parameter name */
250
+ const char *zLabel, /* Label before the entry box */
251
+ int iSize /* Size of the entry box */
252
+){
253
+ assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
254
+ aSubmenuCtrl[nSubmenuCtrl].zName = zName;
255
+ aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
256
+ aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
257
+ aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
258
+ nSubmenuCtrl++;
259
+}
260
+void style_submenu_checkbox(
261
+ const char *zName, /* Query parameter name */
262
+ const char *zLabel /* Label before the checkbox */
263
+){
264
+ assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
265
+ aSubmenuCtrl[nSubmenuCtrl].zName = zName;
266
+ aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
267
+ aSubmenuCtrl[nSubmenuCtrl].eType = FF_CKBOX;
268
+ nSubmenuCtrl++;
269
+}
270
+void style_submenu_binary(
271
+ const char *zName, /* Query parameter name */
272
+ const char *zTrue, /* Label to show when parameter is true */
273
+ const char *zFalse /* Label to show when the parameter is false */
274
+){
275
+ assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
276
+ aSubmenuCtrl[nSubmenuCtrl].zName = zName;
277
+ aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
278
+ aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
279
+ aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
280
+ nSubmenuCtrl++;
281
+}
282
+void style_submenu_multichoice(
283
+ const char *zName, /* Query parameter name */
284
+ int nChoice, /* Number of options */
285
+ const char **azChoice /* value/display pairs. 2*nChoice entries */
286
+){
287
+ assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
288
+ aSubmenuCtrl[nSubmenuCtrl].zName = zName;
289
+ aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
290
+ aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
291
+ aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
292
+ nSubmenuCtrl++;
293
+}
294
+
227295
228296
/*
229297
** Compare two submenu items for sorting purposes
230298
*/
231299
static int submenuCompare(const void *a, const void *b){
@@ -411,23 +479,102 @@
411479
/* Go back and put the submenu at the top of the page. We delay the
412480
** creation of the submenu until the end so that we can add elements
413481
** to the submenu while generating page text.
414482
*/
415483
cgi_destination(CGI_HEADER);
416
- if( nSubmenu>0 ){
484
+ if( nSubmenu+nSubmenuCtrl>0 ){
417485
int i;
486
+ if( nSubmenuCtrl ){
487
+ cgi_printf("<form id='f01' method='GET' action='%R/%s'>", g.zPath);
488
+ }
418489
@ <div class="submenu">
419
- qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
420
- for(i=0; i<nSubmenu; i++){
421
- struct Submenu *p = &aSubmenu[i];
422
- if( p->zLink==0 ){
423
- @ <span class="label">%h(p->zLabel)</span>
424
- }else{
425
- @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
490
+ if( nSubmenu>0 ){
491
+ qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
492
+ for(i=0; i<nSubmenu; i++){
493
+ struct Submenu *p = &aSubmenu[i];
494
+ if( p->zLink==0 ){
495
+ @ <span class="label">%h(p->zLabel)</span>
496
+ }else{
497
+ @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
498
+ }
499
+ }
500
+ }
501
+ if( nSubmenuCtrl>0 ){
502
+ for(i=0; i<nSubmenuCtrl; i++){
503
+ const char *zQPN = aSubmenuCtrl[i].zName;
504
+ cgi_tag_query_parameter(zQPN);
505
+ switch( aSubmenuCtrl[i].eType ){
506
+ case FF_ENTRY: {
507
+ cgi_printf(
508
+ "<span class='submenuctrl'>"
509
+ "%h:&nbsp;<input type='text' name='%s' size='%d' "
510
+ "value='%h'></span>\n",
511
+ aSubmenuCtrl[i].zLabel,
512
+ zQPN,
513
+ aSubmenuCtrl[i].iSize,
514
+ PD(zQPN,"")
515
+ );
516
+ break;
517
+ }
518
+ case FF_CKBOX: {
519
+ cgi_printf(
520
+ "<span class='submenuctrl'>"
521
+ "%h:&nbsp;<input type='checkbox' name='%s'%s "
522
+ "onchange='gebi(\"f01\").submit();'></span>\n",
523
+ aSubmenuCtrl[i].zLabel,
524
+ zQPN,
525
+ PB(zQPN) ? " checked":""
526
+ );
527
+ break;
528
+ }
529
+ case FF_MULTI: {
530
+ int j;
531
+ const char *zVal = P(zQPN);
532
+ cgi_printf(
533
+ "<select class='submenuctrl' size='1' name='%s' "
534
+ "onchange='gebi(\"f01\").submit();'>\n",
535
+ zQPN
536
+ );
537
+ for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){
538
+ const char *zQPV = aSubmenuCtrl[i].azChoice[j];
539
+ cgi_printf(
540
+ "<option value='%h'%s>%h</option>\n",
541
+ zQPV,
542
+ fossil_strcmp(zVal,zQPV)==0 ? " selected" : "",
543
+ aSubmenuCtrl[i].azChoice[j+1]
544
+ );
545
+ }
546
+ @ </select>
547
+ break;
548
+ }
549
+ case FF_BINARY: {
550
+ int isTrue = PB(zQPN);
551
+ cgi_printf(
552
+ "<select class='submenuctrl' size='1' name='%s' "
553
+ "onchange='gebi(\"f01\").submit();'>\n",
554
+ zQPN
555
+ );
556
+ cgi_printf(
557
+ "<option value='1'%s>%h</option>\n",
558
+ isTrue ? " selected":"", aSubmenuCtrl[i].zLabel
559
+ );
560
+ cgi_printf(
561
+ "<option value='0'%s>%h</option>\n",
562
+ (!isTrue) ? " selected":"", aSubmenuCtrl[i].zFalse
563
+ );
564
+ @ </select>
565
+ break;
566
+ }
567
+ }
426568
}
427569
}
428570
@ </div>
571
+ if( nSubmenuCtrl ){
572
+ cgi_query_parameters_to_hidden();
573
+ cgi_tag_query_parameter(0);
574
+ @ </form>
575
+ }
429576
}
430577
431578
zAd = style_adunit_text(&mAdFlags);
432579
if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
433580
@ <div class="content adunit_right_container">
@@ -1183,11 +1330,11 @@
11831330
}
11841331
zHaystack = z + n;
11851332
}
11861333
return 0;
11871334
}
1188
-
1335
+
11891336
11901337
/*
11911338
** WEBPAGE: style.css
11921339
*/
11931340
void page_style_css(void){
@@ -1246,22 +1393,21 @@
12461393
}
12471394
for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
12481395
style_header("Environment Test");
12491396
showAll = atoi(PD("showall","0"));
12501397
if( !showAll ){
1251
- style_submenu_element("Show Cookies", "Show Cookies",
1252
- "%s/test_env?showall=1", g.zTop);
1398
+ style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1");
12531399
}else{
1254
- style_submenu_element("Hide Cookies", "Hide Cookies",
1255
- "%s/test_env", g.zTop);
1400
+ style_submenu_element("Hide Cookies", 0, "%R/test_env");
12561401
}
12571402
#if !defined(_WIN32)
12581403
@ uid=%d(getuid()), gid=%d(getgid())<br />
12591404
#endif
12601405
@ g.zBaseURL = %h(g.zBaseURL)<br />
12611406
@ g.zHttpsURL = %h(g.zHttpsURL)<br />
12621407
@ g.zTop = %h(g.zTop)<br />
1408
+ @ g.zPath = %h(g.zPath)<br />
12631409
for(i=0, c='a'; c<='z'; c++){
12641410
if( login_has_capability(&c, 1) ) zCap[i++] = c;
12651411
}
12661412
zCap[i] = 0;
12671413
@ g.userUid = %d(g.userUid)<br />
12681414
--- src/style.c
+++ src/style.c
@@ -23,21 +23,42 @@
23 #include "style.h"
24
25
26 /*
27 ** Elements of the submenu are collected into the following
28 ** structure and displayed below the main menu by style_header().
 
 
 
 
 
 
 
29 **
30 ** Populate this structure with calls to style_submenu_element()
31 ** prior to calling style_header().
 
32 */
33 static struct Submenu {
34 const char *zLabel;
35 const char *zTitle;
36 const char *zLink;
37 } aSubmenu[30];
38 static int nSubmenu = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
39
40 /*
41 ** Remember that the header has been generated. The footer is omitted
42 ** if an error occurs before the header.
43 */
@@ -216,16 +237,63 @@
216 ...
217 ){
218 va_list ap;
219 assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) );
220 aSubmenu[nSubmenu].zLabel = zLabel;
221 aSubmenu[nSubmenu].zTitle = zTitle;
222 va_start(ap, zLink);
223 aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap);
224 va_end(ap);
225 nSubmenu++;
226 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
228 /*
229 ** Compare two submenu items for sorting purposes
230 */
231 static int submenuCompare(const void *a, const void *b){
@@ -411,23 +479,102 @@
411 /* Go back and put the submenu at the top of the page. We delay the
412 ** creation of the submenu until the end so that we can add elements
413 ** to the submenu while generating page text.
414 */
415 cgi_destination(CGI_HEADER);
416 if( nSubmenu>0 ){
417 int i;
 
 
 
418 @ <div class="submenu">
419 qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
420 for(i=0; i<nSubmenu; i++){
421 struct Submenu *p = &aSubmenu[i];
422 if( p->zLink==0 ){
423 @ <span class="label">%h(p->zLabel)</span>
424 }else{
425 @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426 }
427 }
428 @ </div>
 
 
 
 
 
429 }
430
431 zAd = style_adunit_text(&mAdFlags);
432 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
433 @ <div class="content adunit_right_container">
@@ -1183,11 +1330,11 @@
1183 }
1184 zHaystack = z + n;
1185 }
1186 return 0;
1187 }
1188
1189
1190 /*
1191 ** WEBPAGE: style.css
1192 */
1193 void page_style_css(void){
@@ -1246,22 +1393,21 @@
1246 }
1247 for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
1248 style_header("Environment Test");
1249 showAll = atoi(PD("showall","0"));
1250 if( !showAll ){
1251 style_submenu_element("Show Cookies", "Show Cookies",
1252 "%s/test_env?showall=1", g.zTop);
1253 }else{
1254 style_submenu_element("Hide Cookies", "Hide Cookies",
1255 "%s/test_env", g.zTop);
1256 }
1257 #if !defined(_WIN32)
1258 @ uid=%d(getuid()), gid=%d(getgid())<br />
1259 #endif
1260 @ g.zBaseURL = %h(g.zBaseURL)<br />
1261 @ g.zHttpsURL = %h(g.zHttpsURL)<br />
1262 @ g.zTop = %h(g.zTop)<br />
 
1263 for(i=0, c='a'; c<='z'; c++){
1264 if( login_has_capability(&c, 1) ) zCap[i++] = c;
1265 }
1266 zCap[i] = 0;
1267 @ g.userUid = %d(g.userUid)<br />
1268
--- src/style.c
+++ src/style.c
@@ -23,21 +23,42 @@
23 #include "style.h"
24
25
26 /*
27 ** Elements of the submenu are collected into the following
28 ** structure and displayed below the main menu.
29 **
30 ** Populate these structure with calls to
31 **
32 ** style_submenu_element()
33 ** style_submenu_entry()
34 ** style_submenu_checkbox()
35 ** style_submenu_multichoice()
36 **
37 ** prior to calling style_footer(). The style_footer() routine
38 ** will generate the appropriate HTML text just below the main
39 ** menu.
40 */
41 static struct Submenu {
42 const char *zLabel; /* Button label */
43 const char *zTitle;
44 const char *zLink; /* Jump to this link when button is pressed */
45 } aSubmenu[30];
46 static int nSubmenu = 0; /* Number of buttons */
47 static struct SubmenuCtrl {
48 const char *zName; /* Form query parameter */
49 const char *zLabel; /* Label. Might be NULL for FF_MULTI */
50 int eType; /* FF_ENTRY, FF_CKBOX, FF_MULTI */
51 int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
52 const char **azChoice; /* value/display pairs for FF_MULTI */
53 const char *zFalse; /* FF_BINARY label when false */
54 } aSubmenuCtrl[20];
55 static int nSubmenuCtrl = 0;
56 #define FF_ENTRY 1
57 #define FF_CKBOX 2
58 #define FF_MULTI 3
59 #define FF_BINARY 4
60
61 /*
62 ** Remember that the header has been generated. The footer is omitted
63 ** if an error occurs before the header.
64 */
@@ -216,16 +237,63 @@
237 ...
238 ){
239 va_list ap;
240 assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) );
241 aSubmenu[nSubmenu].zLabel = zLabel;
242 aSubmenu[nSubmenu].zTitle = zTitle ? zTitle : zLabel;
243 va_start(ap, zLink);
244 aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap);
245 va_end(ap);
246 nSubmenu++;
247 }
248 void style_submenu_entry(
249 const char *zName, /* Query parameter name */
250 const char *zLabel, /* Label before the entry box */
251 int iSize /* Size of the entry box */
252 ){
253 assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
254 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
255 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
256 aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
257 aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
258 nSubmenuCtrl++;
259 }
260 void style_submenu_checkbox(
261 const char *zName, /* Query parameter name */
262 const char *zLabel /* Label before the checkbox */
263 ){
264 assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
265 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
266 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
267 aSubmenuCtrl[nSubmenuCtrl].eType = FF_CKBOX;
268 nSubmenuCtrl++;
269 }
270 void style_submenu_binary(
271 const char *zName, /* Query parameter name */
272 const char *zTrue, /* Label to show when parameter is true */
273 const char *zFalse /* Label to show when the parameter is false */
274 ){
275 assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
276 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
277 aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
278 aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
279 aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
280 nSubmenuCtrl++;
281 }
282 void style_submenu_multichoice(
283 const char *zName, /* Query parameter name */
284 int nChoice, /* Number of options */
285 const char **azChoice /* value/display pairs. 2*nChoice entries */
286 ){
287 assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) );
288 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
289 aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
290 aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
291 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
292 nSubmenuCtrl++;
293 }
294
295
296 /*
297 ** Compare two submenu items for sorting purposes
298 */
299 static int submenuCompare(const void *a, const void *b){
@@ -411,23 +479,102 @@
479 /* Go back and put the submenu at the top of the page. We delay the
480 ** creation of the submenu until the end so that we can add elements
481 ** to the submenu while generating page text.
482 */
483 cgi_destination(CGI_HEADER);
484 if( nSubmenu+nSubmenuCtrl>0 ){
485 int i;
486 if( nSubmenuCtrl ){
487 cgi_printf("<form id='f01' method='GET' action='%R/%s'>", g.zPath);
488 }
489 @ <div class="submenu">
490 if( nSubmenu>0 ){
491 qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
492 for(i=0; i<nSubmenu; i++){
493 struct Submenu *p = &aSubmenu[i];
494 if( p->zLink==0 ){
495 @ <span class="label">%h(p->zLabel)</span>
496 }else{
497 @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
498 }
499 }
500 }
501 if( nSubmenuCtrl>0 ){
502 for(i=0; i<nSubmenuCtrl; i++){
503 const char *zQPN = aSubmenuCtrl[i].zName;
504 cgi_tag_query_parameter(zQPN);
505 switch( aSubmenuCtrl[i].eType ){
506 case FF_ENTRY: {
507 cgi_printf(
508 "<span class='submenuctrl'>"
509 "%h:&nbsp;<input type='text' name='%s' size='%d' "
510 "value='%h'></span>\n",
511 aSubmenuCtrl[i].zLabel,
512 zQPN,
513 aSubmenuCtrl[i].iSize,
514 PD(zQPN,"")
515 );
516 break;
517 }
518 case FF_CKBOX: {
519 cgi_printf(
520 "<span class='submenuctrl'>"
521 "%h:&nbsp;<input type='checkbox' name='%s'%s "
522 "onchange='gebi(\"f01\").submit();'></span>\n",
523 aSubmenuCtrl[i].zLabel,
524 zQPN,
525 PB(zQPN) ? " checked":""
526 );
527 break;
528 }
529 case FF_MULTI: {
530 int j;
531 const char *zVal = P(zQPN);
532 cgi_printf(
533 "<select class='submenuctrl' size='1' name='%s' "
534 "onchange='gebi(\"f01\").submit();'>\n",
535 zQPN
536 );
537 for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){
538 const char *zQPV = aSubmenuCtrl[i].azChoice[j];
539 cgi_printf(
540 "<option value='%h'%s>%h</option>\n",
541 zQPV,
542 fossil_strcmp(zVal,zQPV)==0 ? " selected" : "",
543 aSubmenuCtrl[i].azChoice[j+1]
544 );
545 }
546 @ </select>
547 break;
548 }
549 case FF_BINARY: {
550 int isTrue = PB(zQPN);
551 cgi_printf(
552 "<select class='submenuctrl' size='1' name='%s' "
553 "onchange='gebi(\"f01\").submit();'>\n",
554 zQPN
555 );
556 cgi_printf(
557 "<option value='1'%s>%h</option>\n",
558 isTrue ? " selected":"", aSubmenuCtrl[i].zLabel
559 );
560 cgi_printf(
561 "<option value='0'%s>%h</option>\n",
562 (!isTrue) ? " selected":"", aSubmenuCtrl[i].zFalse
563 );
564 @ </select>
565 break;
566 }
567 }
568 }
569 }
570 @ </div>
571 if( nSubmenuCtrl ){
572 cgi_query_parameters_to_hidden();
573 cgi_tag_query_parameter(0);
574 @ </form>
575 }
576 }
577
578 zAd = style_adunit_text(&mAdFlags);
579 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
580 @ <div class="content adunit_right_container">
@@ -1183,11 +1330,11 @@
1330 }
1331 zHaystack = z + n;
1332 }
1333 return 0;
1334 }
1335
1336
1337 /*
1338 ** WEBPAGE: style.css
1339 */
1340 void page_style_css(void){
@@ -1246,22 +1393,21 @@
1393 }
1394 for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]);
1395 style_header("Environment Test");
1396 showAll = atoi(PD("showall","0"));
1397 if( !showAll ){
1398 style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1");
 
1399 }else{
1400 style_submenu_element("Hide Cookies", 0, "%R/test_env");
 
1401 }
1402 #if !defined(_WIN32)
1403 @ uid=%d(getuid()), gid=%d(getgid())<br />
1404 #endif
1405 @ g.zBaseURL = %h(g.zBaseURL)<br />
1406 @ g.zHttpsURL = %h(g.zHttpsURL)<br />
1407 @ g.zTop = %h(g.zTop)<br />
1408 @ g.zPath = %h(g.zPath)<br />
1409 for(i=0, c='a'; c<='z'; c++){
1410 if( login_has_capability(&c, 1) ) zCap[i++] = c;
1411 }
1412 zCap[i] = 0;
1413 @ g.userUid = %d(g.userUid)<br />
1414

No diff available

--- src/th_main.c
+++ src/th_main.c
@@ -365,10 +365,69 @@
365365
Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
366366
}
367367
Th_SetResultInt(interp, rc);
368368
return TH_OK;
369369
}
370
+
371
+/*
372
+** TH1 command: searchable STRING...
373
+**
374
+** Return true if searching in any of the document classes identified
375
+** by STRING is enabled for the repository and user has the necessary
376
+** capabilities to perform the search.
377
+**
378
+** Document classes:
379
+**
380
+** c Check-in comments
381
+** d Embedded documentation
382
+** t Tickets
383
+** w Wiki
384
+**
385
+** To be clear, only one of the document classes identified by each STRING
386
+** needs to be searchable in order for that argument to be true. But
387
+** all arguments must be true for this routine to return true. Hence, to
388
+** see if ALL document classes are searchable:
389
+**
390
+** if {[searchable c d t w]} {...}
391
+**
392
+** But to see if ANY document class is searchable:
393
+**
394
+** if {[searchable cdtw]} {...}
395
+**
396
+** This command is useful for enabling or disabling a "Search" entry
397
+** on the menu bar.
398
+*/
399
+static int searchableCmd(
400
+ Th_Interp *interp,
401
+ void *p,
402
+ int argc,
403
+ const char **argv,
404
+ int *argl
405
+){
406
+ int rc = 1, i, j;
407
+ unsigned int searchCap = search_restrict(SRCH_ALL);
408
+ if( argc<2 ){
409
+ return Th_WrongNumArgs(interp, "hascap STRING ...");
410
+ }
411
+ for(i=1; i<argc && rc; i++){
412
+ int match = 0;
413
+ for(j=0; j<argl[i]; j++){
414
+ switch( argv[i][j] ){
415
+ case 'c': match |= searchCap & SRCH_CKIN; break;
416
+ case 'd': match |= searchCap & SRCH_DOC; break;
417
+ case 't': match |= searchCap & SRCH_TKT; break;
418
+ case 'w': match |= searchCap & SRCH_WIKI; break;
419
+ }
420
+ }
421
+ if( !match ) rc = 0;
422
+ }
423
+ if( g.thTrace ){
424
+ Th_Trace("[searchable %#h] => %d<br />\n", argl[1], argv[1], rc);
425
+ }
426
+ Th_SetResultInt(interp, rc);
427
+ return TH_OK;
428
+}
370429
371430
/*
372431
** TH1 command: hasfeature STRING
373432
**
374433
** Return true if the fossil binary has the given compile-time feature
@@ -1419,10 +1478,11 @@
14191478
{"randhex", randhexCmd, 0},
14201479
{"regexp", regexpCmd, 0},
14211480
{"reinitialize", reinitializeCmd, 0},
14221481
{"render", renderCmd, 0},
14231482
{"repository", repositoryCmd, 0},
1483
+ {"searchable", searchableCmd, 0},
14241484
{"setParameter", setParameterCmd, 0},
14251485
{"setting", settingCmd, 0},
14261486
{"styleHeader", styleHeaderCmd, 0},
14271487
{"styleFooter", styleFooterCmd, 0},
14281488
{"tclReady", tclReadyCmd, 0},
14291489
--- src/th_main.c
+++ src/th_main.c
@@ -365,10 +365,69 @@
365 Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
366 }
367 Th_SetResultInt(interp, rc);
368 return TH_OK;
369 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
371 /*
372 ** TH1 command: hasfeature STRING
373 **
374 ** Return true if the fossil binary has the given compile-time feature
@@ -1419,10 +1478,11 @@
1419 {"randhex", randhexCmd, 0},
1420 {"regexp", regexpCmd, 0},
1421 {"reinitialize", reinitializeCmd, 0},
1422 {"render", renderCmd, 0},
1423 {"repository", repositoryCmd, 0},
 
1424 {"setParameter", setParameterCmd, 0},
1425 {"setting", settingCmd, 0},
1426 {"styleHeader", styleHeaderCmd, 0},
1427 {"styleFooter", styleFooterCmd, 0},
1428 {"tclReady", tclReadyCmd, 0},
1429
--- src/th_main.c
+++ src/th_main.c
@@ -365,10 +365,69 @@
365 Th_Trace("[hascap %#h] => %d<br />\n", argl[1], argv[1], rc);
366 }
367 Th_SetResultInt(interp, rc);
368 return TH_OK;
369 }
370
371 /*
372 ** TH1 command: searchable STRING...
373 **
374 ** Return true if searching in any of the document classes identified
375 ** by STRING is enabled for the repository and user has the necessary
376 ** capabilities to perform the search.
377 **
378 ** Document classes:
379 **
380 ** c Check-in comments
381 ** d Embedded documentation
382 ** t Tickets
383 ** w Wiki
384 **
385 ** To be clear, only one of the document classes identified by each STRING
386 ** needs to be searchable in order for that argument to be true. But
387 ** all arguments must be true for this routine to return true. Hence, to
388 ** see if ALL document classes are searchable:
389 **
390 ** if {[searchable c d t w]} {...}
391 **
392 ** But to see if ANY document class is searchable:
393 **
394 ** if {[searchable cdtw]} {...}
395 **
396 ** This command is useful for enabling or disabling a "Search" entry
397 ** on the menu bar.
398 */
399 static int searchableCmd(
400 Th_Interp *interp,
401 void *p,
402 int argc,
403 const char **argv,
404 int *argl
405 ){
406 int rc = 1, i, j;
407 unsigned int searchCap = search_restrict(SRCH_ALL);
408 if( argc<2 ){
409 return Th_WrongNumArgs(interp, "hascap STRING ...");
410 }
411 for(i=1; i<argc && rc; i++){
412 int match = 0;
413 for(j=0; j<argl[i]; j++){
414 switch( argv[i][j] ){
415 case 'c': match |= searchCap & SRCH_CKIN; break;
416 case 'd': match |= searchCap & SRCH_DOC; break;
417 case 't': match |= searchCap & SRCH_TKT; break;
418 case 'w': match |= searchCap & SRCH_WIKI; break;
419 }
420 }
421 if( !match ) rc = 0;
422 }
423 if( g.thTrace ){
424 Th_Trace("[searchable %#h] => %d<br />\n", argl[1], argv[1], rc);
425 }
426 Th_SetResultInt(interp, rc);
427 return TH_OK;
428 }
429
430 /*
431 ** TH1 command: hasfeature STRING
432 **
433 ** Return true if the fossil binary has the given compile-time feature
@@ -1419,10 +1478,11 @@
1478 {"randhex", randhexCmd, 0},
1479 {"regexp", regexpCmd, 0},
1480 {"reinitialize", reinitializeCmd, 0},
1481 {"render", renderCmd, 0},
1482 {"repository", repositoryCmd, 0},
1483 {"searchable", searchableCmd, 0},
1484 {"setParameter", setParameterCmd, 0},
1485 {"setting", settingCmd, 0},
1486 {"styleHeader", styleHeaderCmd, 0},
1487 {"styleFooter", styleFooterCmd, 0},
1488 {"tclReady", tclReadyCmd, 0},
1489
+121 -112
--- src/timeline.c
+++ src/timeline.c
@@ -494,10 +494,11 @@
494494
" (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
495495
" FROM mlink"
496496
" WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
497497
" AND (fid>0 OR"
498498
" fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))"
499
+ " AND NOT mlink.isaux"
499500
" ORDER BY 3 /*sort*/"
500501
);
501502
fchngQueryInit = 1;
502503
}
503504
db_bind_int(&fchngQuery, ":mid", rid);
@@ -666,16 +667,16 @@
666667
if( cSep=='[' ) cgi_printf("[");
667668
cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n");
668669
}
669670
cgi_printf("var nrail = %d\n", pGraph->mxRail+1);
670671
graph_free(pGraph);
671
- @ var canvasDiv = gebi("canvas");
672
- @ var canvasStyle = window.getComputedStyle && window.getComputedStyle(canvasDiv,null);
673
- @ var lineColor = (canvasStyle && canvasStyle.getPropertyValue('color')) || 'black';
674
- @ var bgColor = (canvasStyle && canvasStyle.getPropertyValue('background-color')) || 'white';
675
- @ if( bgColor=='transparent' ) bgColor = 'white';
676
- @ var boxColor = lineColor;
672
+ @ var cDiv = gebi("canvas");
673
+ @ var csty = window.getComputedStyle && window.getComputedStyle(cDiv,null);
674
+ @ var lineClr = (csty && csty.getPropertyValue('color')) || 'black';
675
+ @ var bgClr = (csty && csty.getPropertyValue('background-color')) ||'white';
676
+ @ if( bgClr=='transparent' ) bgClr = 'white';
677
+ @ var boxColor = lineClr;
677678
@ function drawBox(color,x0,y0,x1,y1){
678679
@ var n = document.createElement("div");
679680
@ if( x0>x1 ){ var t=x0; x0=x1; x1=t; }
680681
@ if( y0>y1 ){ var t=y0; y0=y1; y1=t; }
681682
@ var w = x1-x0+1;
@@ -685,11 +686,11 @@
685686
@ n.style.left = x0+"px";
686687
@ n.style.top = y0+"px";
687688
@ n.style.width = w+"px";
688689
@ n.style.height = h+"px";
689690
@ n.style.backgroundColor = color;
690
- @ canvasDiv.appendChild(n);
691
+ @ cDiv.appendChild(n);
691692
@ return n;
692693
@ }
693694
@ function absoluteY(id){
694695
@ var obj = gebi(id);
695696
@ if( !obj ) return;
@@ -711,39 +712,39 @@
711712
@ }while( obj = obj.offsetParent );
712713
@ }
713714
@ return left;
714715
@ }
715716
@ function drawUpArrow(x,y0,y1){
716
- @ drawBox(lineColor,x,y0,x+1,y1);
717
+ @ drawBox(lineClr,x,y0,x+1,y1);
717718
@ if( y0+10>=y1 ){
718
- @ drawBox(lineColor,x-1,y0+1,x+2,y0+2);
719
- @ drawBox(lineColor,x-2,y0+3,x+3,y0+4);
719
+ @ drawBox(lineClr,x-1,y0+1,x+2,y0+2);
720
+ @ drawBox(lineClr,x-2,y0+3,x+3,y0+4);
720721
@ }else{
721
- @ drawBox(lineColor,x-1,y0+2,x+2,y0+4);
722
- @ drawBox(lineColor,x-2,y0+5,x+3,y0+7);
722
+ @ drawBox(lineClr,x-1,y0+2,x+2,y0+4);
723
+ @ drawBox(lineClr,x-2,y0+5,x+3,y0+7);
723724
@ }
724725
@ }
725726
@ function drawThinArrow(y,xFrom,xTo){
726727
@ if( xFrom<xTo ){
727
- @ drawBox(lineColor,xFrom,y,xTo,y);
728
- @ drawBox(lineColor,xTo-3,y-1,xTo-2,y+1);
729
- @ drawBox(lineColor,xTo-4,y-2,xTo-4,y+2);
728
+ @ drawBox(lineClr,xFrom,y,xTo,y);
729
+ @ drawBox(lineClr,xTo-3,y-1,xTo-2,y+1);
730
+ @ drawBox(lineClr,xTo-4,y-2,xTo-4,y+2);
730731
@ }else{
731
- @ drawBox(lineColor,xTo,y,xFrom,y);
732
- @ drawBox(lineColor,xTo+2,y-1,xTo+3,y+1);
733
- @ drawBox(lineColor,xTo+4,y-2,xTo+4,y+2);
732
+ @ drawBox(lineClr,xTo,y,xFrom,y);
733
+ @ drawBox(lineClr,xTo+2,y-1,xTo+3,y+1);
734
+ @ drawBox(lineClr,xTo+4,y-2,xTo+4,y+2);
734735
@ }
735736
@ }
736737
@ function drawThinLine(x0,y0,x1,y1){
737
- @ drawBox(lineColor,x0,y0,x1,y1);
738
+ @ drawBox(lineClr,x0,y0,x1,y1);
738739
@ }
739740
@ function drawNodeBox(color,x0,y0,x1,y1){
740741
@ drawBox(color,x0,y0,x1,y1).style.cursor = "pointer";
741742
@ }
742743
@ function drawNode(p, left, btm){
743744
@ drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6);
744
- @ drawNodeBox(p.bg||bgColor,p.x-4,p.y-4,p.x+5,p.y+5);
745
+ @ drawNodeBox(p.bg||bgClr,p.x-4,p.y-4,p.x+5,p.y+5);
745746
@ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
746747
@ if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2);
747748
if( !omitDescenders ){
748749
@ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
749750
@ if( p.d ) drawUpArrow(p.x, p.y+6, btm);
@@ -765,11 +766,11 @@
765766
@ for(var i=0; i<n; i+=2){
766767
@ var x1 = p.au[i]*railPitch + left;
767768
@ var x0 = x1>p.x ? p.x+7 : p.x-6;
768769
@ var u = rowinfo[p.au[i+1]-1];
769770
@ if(u.id<p.id){
770
- @ drawBox(lineColor,x0,p.y,x1,p.y+1);
771
+ @ drawBox(lineClr,x0,p.y,x1,p.y+1);
771772
@ drawUpArrow(x1, u.y+6, p.y);
772773
@ }else{
773774
@ drawBox("#600000",x0,p.y,x1,p.y+1);
774775
@ drawBox("#600000",x1-1,p.y,x1,u.y+1);
775776
@ drawBox("#600000",x1,u.y,u.x-6,u.y+1);
@@ -952,13 +953,22 @@
952953
if( z==0 ) return -1.0;
953954
if( fossil_isdate(z) ){
954955
mtime = db_double(0.0, "SELECT julianday(%Q,'utc')", z);
955956
if( mtime>0.0 ) return mtime;
956957
}
957
- rid = symbolic_name_to_rid(z, "ci");
958
- if( rid==0 ) return -1.0;
959
- mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
958
+ rid = symbolic_name_to_rid(z, "*");
959
+ if( rid ){
960
+ mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
961
+ }else{
962
+ mtime = db_double(-1.0,
963
+ "SELECT max(event.mtime) FROM event, tag, tagxref"
964
+ " WHERE tag.tagname GLOB 'event-%q*'"
965
+ " AND tagxref.tagid=tag.tagid AND tagxref.tagtype"
966
+ " AND event.objid=tagxref.rid",
967
+ z
968
+ );
969
+ }
960970
return mtime;
961971
}
962972
963973
/*
964974
** The value of one second in julianday notation
@@ -1011,10 +1021,47 @@
10111021
}
10121022
db_finalize(&q);
10131023
return blob_str(&out);
10141024
}
10151025
1026
+
1027
+/*
1028
+** Add the select/option box to the timeline submenu that is used to
1029
+** set the y= parameter that determines which elements to display
1030
+** on the timeline.
1031
+*/
1032
+static void timeline_y_submenu(void){
1033
+ static int i = 0;
1034
+ static const char *az[12];
1035
+ if( i==0 ){
1036
+ az[0] = "all";
1037
+ az[1] = "All Types";
1038
+ i = 2;
1039
+ if( g.perm.Read ){
1040
+ az[i++] = "ci";
1041
+ az[i++] = "Check-ins";
1042
+ az[i++] = "g";
1043
+ az[i++] = "Tags";
1044
+ }
1045
+ if( g.perm.RdWiki ){
1046
+ az[i++] = "e";
1047
+ az[i++] = "Tech Notes";
1048
+ }
1049
+ if( g.perm.RdTkt ){
1050
+ az[i++] = "t";
1051
+ az[i++] = "Tickets";
1052
+ }
1053
+ if( g.perm.RdWiki ){
1054
+ az[i++] = "w";
1055
+ az[i++] = "Wiki";
1056
+ }
1057
+ assert( i<=ArraySize(az) );
1058
+ }
1059
+ if( i>2 ){
1060
+ style_submenu_multichoice("y", i/2, az);
1061
+ }
1062
+}
10161063
10171064
/*
10181065
** WEBPAGE: timeline
10191066
**
10201067
** Query parameters:
@@ -1055,11 +1102,11 @@
10551102
*/
10561103
void page_timeline(void){
10571104
Stmt q; /* Query used to generate the timeline */
10581105
Blob sql; /* text of SQL used to generate timeline */
10591106
Blob desc; /* Description of the timeline */
1060
- int nEntry = atoi(PD("n","20")); /* Max number of entries on timeline */
1107
+ int nEntry; /* Max number of entries on timeline */
10611108
int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
10621109
int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
10631110
int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
10641111
const char *zUser = P("u"); /* All entries by this user if not NULL */
10651112
const char *zType = PD("y","all"); /* Type of events. All if NULL */
@@ -1069,11 +1116,11 @@
10691116
const char *zTagName = P("t"); /* Show events with this tag */
10701117
const char *zBrName = P("r"); /* Show events related to this tag */
10711118
const char *zSearch = P("s"); /* Search string */
10721119
const char *zUses = P("uf"); /* Only show checkins hold this file */
10731120
const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
1074
- const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/
1121
+ const char *zYearWeek = P("yw"); /* Checkins for YYYY-WW (week-of-year) */
10751122
int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
10761123
int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
10771124
int tagid; /* Tag ID */
10781125
int tmFlags = 0; /* Timeline flags */
10791126
const char *zThisTag = 0; /* Suppress links to this tag */
@@ -1084,10 +1131,32 @@
10841131
int noMerge = P("shortest")==0; /* Follow merge links if shorter */
10851132
int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
10861133
int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
10871134
int pd_rid;
10881135
double rBefore, rAfter, rCirca; /* Boundary times */
1136
+ const char *z;
1137
+ char *zOlderButton = 0; /* URL for Older button at the bottom */
1138
+
1139
+ /* Set number of rows to display */
1140
+ z = P("n");
1141
+ if( z ){
1142
+ if( fossil_strcmp(z,"all")==0 ){
1143
+ nEntry = 0;
1144
+ }else{
1145
+ nEntry = atoi(z);
1146
+ if( nEntry<=0 ){
1147
+ cgi_replace_query_parameter("n","10");
1148
+ nEntry = 10;
1149
+ }
1150
+ }
1151
+ }else if( zCirca ){
1152
+ cgi_replace_query_parameter("n","11");
1153
+ nEntry = 11;
1154
+ }else{
1155
+ cgi_replace_query_parameter("n","50");
1156
+ nEntry = 50;
1157
+ }
10891158
10901159
/* To view the timeline, must have permission to read project data.
10911160
*/
10921161
pd_rid = name_to_typed_rid(P("dp"),"ci");
10931162
if( pd_rid ){
@@ -1097,20 +1166,21 @@
10971166
if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
10981167
login_needed();
10991168
return;
11001169
}
11011170
url_initialize(&url, "timeline");
1171
+ cgi_query_parameters_to_url(&url);
11021172
if( zTagName && g.perm.Read ){
11031173
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
11041174
zThisTag = zTagName;
11051175
}else if( zBrName && g.perm.Read ){
11061176
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
11071177
zThisTag = zBrName;
11081178
}else{
11091179
tagid = 0;
11101180
}
1111
- if( tagid>0
1181
+ if( tagid>0
11121182
&& db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry
11131183
){
11141184
zCirca = zBefore = zAfter = 0;
11151185
nEntry = -1;
11161186
}
@@ -1117,32 +1187,26 @@
11171187
if( zType[0]=='a' ){
11181188
tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH;
11191189
}else{
11201190
tmFlags |= TIMELINE_GRAPH;
11211191
}
1122
- if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry));
1123
- if( P("ng")!=0 || zSearch!=0 ){
1192
+ if( PB("ng") || zSearch!=0 ){
11241193
tmFlags &= ~TIMELINE_GRAPH;
1125
- url_add_parameter(&url, "ng", 0);
11261194
}
1127
- if( P("brbg")!=0 ){
1195
+ if( PB("brbg") ){
11281196
tmFlags |= TIMELINE_BRCOLOR;
1129
- url_add_parameter(&url, "brbg", 0);
11301197
}
1131
- if( P("unhide")!=0 ){
1198
+ if( PB("unhide") ){
11321199
tmFlags |= TIMELINE_UNHIDE;
1133
- url_add_parameter(&url, "unhide", 0);
11341200
}
1135
- if( P("ubg")!=0 ){
1201
+ if( PB("ubg") ){
11361202
tmFlags |= TIMELINE_UCOLOR;
1137
- url_add_parameter(&url, "ubg", 0);
11381203
}
11391204
if( zUses!=0 ){
11401205
int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses);
11411206
if( ufid ){
11421207
zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid);
1143
- url_add_parameter(&url, "uf", zUses);
11441208
db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)");
11451209
compute_uses_file("usesfile", ufid, 0);
11461210
zType = "ci";
11471211
}else{
11481212
zUses = 0;
@@ -1161,22 +1225,20 @@
11611225
timeline_temp_table();
11621226
blob_zero(&sql);
11631227
blob_zero(&desc);
11641228
blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
11651229
blob_append(&sql, timeline_query_for_www(), -1);
1166
- if( P("fc")!=0 || P("v")!=0 || P("detail")!=0 ){
1230
+ if( PB("fc") || PB("v") || PB("detail") ){
11671231
tmFlags |= TIMELINE_FCHANGES;
1168
- url_add_parameter(&url, "v", 0);
11691232
}
11701233
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
11711234
blob_append_sql(&sql,
11721235
" AND NOT EXISTS(SELECT 1 FROM tagxref"
11731236
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)",
11741237
TAG_HIDDEN
11751238
);
11761239
}
1177
- if( !useDividers ) url_add_parameter(&url, "nd", 0);
11781240
if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
11791241
/* If from= and to= are present, display all nodes on a path connecting
11801242
** the two */
11811243
PathNode *p = 0;
11821244
const char *zFrom = 0;
@@ -1241,34 +1303,19 @@
12411303
}
12421304
if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
12431305
}
12441306
blob_appendf(&desc, " of %z[%S]</a>",
12451307
href("%R/info/%s", zUuid), zUuid);
1246
- if( p_rid ){
1247
- url_add_parameter(&url, "p", zUuid);
1248
- }
12491308
if( d_rid ){
12501309
if( p_rid ){
12511310
/* If both p= and d= are set, we don't have the uuid of d yet. */
12521311
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
12531312
}
1254
- url_add_parameter(&url, "d", zUuid);
1255
- }
1256
- if( nEntry>20 ){
1257
- timeline_submenu(&url, "20 Entries", "n", "20", 0);
1258
- }
1259
- if( nEntry<200 && nEntry>0 ){
1260
- timeline_submenu(&url, "200 Entries", "n", "200", 0);
1261
- }
1262
- if( tmFlags & TIMELINE_FCHANGES ){
1263
- timeline_submenu(&url, "Hide Files", "v", 0, 0);
1264
- }else{
1265
- timeline_submenu(&url, "Show Files", "v", "", 0);
1266
- }
1267
- if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1268
- timeline_submenu(&url, "Unhide", "unhide", "", 0);
1269
- }
1313
+ }
1314
+ style_submenu_binary("v","With Files","Without Files");
1315
+ style_submenu_entry("n","Lines",1);
1316
+ timeline_y_submenu();
12701317
}else if( f_rid && g.perm.Read ){
12711318
/* If f= is present, ignore all other parameters other than n= */
12721319
char *zUuid;
12731320
db_multi_exec(
12741321
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1282,16 +1329,11 @@
12821329
if( useDividers ) timeline_add_dividers(0, f_rid);
12831330
blob_appendf(&desc, "Parents and children of check-in ");
12841331
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
12851332
blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%s", zUuid), zUuid);
12861333
tmFlags |= TIMELINE_DISJOINT;
1287
- url_add_parameter(&url, "f", zUuid);
1288
- if( tmFlags & TIMELINE_FCHANGES ){
1289
- timeline_submenu(&url, "Hide Files", "v", 0, 0);
1290
- }else{
1291
- timeline_submenu(&url, "Show Files", "v", "", 0);
1292
- }
1334
+ style_submenu_binary("v","With Files","Without Files");
12931335
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
12941336
timeline_submenu(&url, "Unhide", "unhide", "", 0);
12951337
}
12961338
}else{
12971339
/* Otherwise, a timeline based on a span of time */
@@ -1316,11 +1358,10 @@
13161358
blob_append_sql(&sql,
13171359
"AND (EXISTS(SELECT 1 FROM tagxref"
13181360
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
13191361
13201362
if( zBrName ){
1321
- url_add_parameter(&url, "r", zBrName);
13221363
/* The next two blob_appendf() calls add SQL that causes checkins that
13231364
** are not part of the branch which are parents or children of the
13241365
** branch to be included in the report. This related check-ins are
13251366
** useful in helping to visualize what has happened on a quiescent
13261367
** branch that is infrequently merged with a much more activate branch.
@@ -1342,21 +1383,17 @@
13421383
" OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid"
13431384
" WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
13441385
tagid
13451386
);
13461387
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1347
- blob_append_sql(&sql,
1388
+ blob_append_sql(&sql,
13481389
" AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid"
13491390
" WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
13501391
TAG_HIDDEN
13511392
);
13521393
}
1353
- }else{
1354
- url_add_parameter(&url, "mionly", "1");
13551394
}
1356
- }else{
1357
- url_add_parameter(&url, "t", zTagName);
13581395
}
13591396
blob_append_sql(&sql, ")");
13601397
}
13611398
if( (zType[0]=='w' && !g.perm.RdWiki)
13621399
|| (zType[0]=='t' && !g.perm.RdTkt)
@@ -1384,11 +1421,10 @@
13841421
}
13851422
blob_append_sql(&sql, ")");
13861423
}
13871424
}else{ /* zType!="all" */
13881425
blob_append_sql(&sql, " AND event.type=%Q", zType);
1389
- url_add_parameter(&url, "y", zType);
13901426
if( zType[0]=='c' ){
13911427
zEType = "checkin";
13921428
}else if( zType[0]=='w' ){
13931429
zEType = "wiki edit";
13941430
}else if( zType[0]=='t' ){
@@ -1406,41 +1442,35 @@
14061442
zCirca = zBefore = zAfter = 0;
14071443
nEntry = -1;
14081444
}
14091445
blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)",
14101446
zUser, zUser);
1411
- url_add_parameter(&url, "u", zUser);
14121447
zThisUser = zUser;
14131448
}
14141449
if( zSearch ){
14151450
blob_append_sql(&sql,
14161451
" AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
14171452
zSearch, zSearch);
1418
- url_add_parameter(&url, "s", zSearch);
14191453
}
14201454
rBefore = symbolic_name_to_mtime(zBefore);
14211455
rAfter = symbolic_name_to_mtime(zAfter);
14221456
rCirca = symbolic_name_to_mtime(zCirca);
14231457
if( rAfter>0.0 ){
14241458
if( rBefore>0.0 ){
14251459
blob_append_sql(&sql,
14261460
" AND event.mtime>=%.17g AND event.mtime<=%.17g"
14271461
" ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND);
1428
- url_add_parameter(&url, "a", zAfter);
1429
- url_add_parameter(&url, "b", zBefore);
14301462
nEntry = -1;
14311463
}else{
14321464
blob_append_sql(&sql,
14331465
" AND event.mtime>=%.17g ORDER BY event.mtime ASC",
14341466
rAfter-ONE_SECOND);
1435
- url_add_parameter(&url, "a", zAfter);
14361467
}
14371468
}else if( rBefore>0.0 ){
14381469
blob_append_sql(&sql,
14391470
" AND event.mtime<=%.17g ORDER BY event.mtime DESC",
14401471
rBefore+ONE_SECOND);
1441
- url_add_parameter(&url, "b", zBefore);
14421472
}else if( rCirca>0.0 ){
14431473
Blob sql2;
14441474
blob_init(&sql2, blob_sql_text(&sql), -1);
14451475
blob_append_sql(&sql2,
14461476
" AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d",
@@ -1452,11 +1482,10 @@
14521482
" AND event.mtime>=%f ORDER BY event.mtime ASC",
14531483
rCirca
14541484
);
14551485
nEntry -= (nEntry+1)/2;
14561486
if( useDividers ) timeline_add_dividers(rCirca, 0);
1457
- url_add_parameter(&url, "c", zCirca);
14581487
}else{
14591488
blob_append_sql(&sql, " ORDER BY event.mtime DESC");
14601489
}
14611490
if( nEntry>0 ) blob_append_sql(&sql, " LIMIT %d", nEntry);
14621491
db_multi_exec("%s", blob_sql_text(&sql));
@@ -1509,64 +1538,44 @@
15091538
}
15101539
if( g.perm.Hyperlink ){
15111540
if( zAfter || n==nEntry ){
15121541
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
15131542
timeline_submenu(&url, "Older", "b", zDate, "a");
1543
+ zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
15141544
free(zDate);
15151545
}
15161546
if( zBefore || (zAfter && n==nEntry) ){
15171547
zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
15181548
timeline_submenu(&url, "Newer", "a", zDate, "b");
15191549
free(zDate);
1520
- }else if( tagid==0 && zUses==0 ){
1521
- if( zType[0]!='a' ){
1522
- timeline_submenu(&url, "All Types", "y", "all", 0);
1523
- }
1524
- if( zType[0]!='w' && g.perm.RdWiki ){
1525
- timeline_submenu(&url, "Wiki Only", "y", "w", 0);
1526
- }
1527
- if( zType[0]!='c' && g.perm.Read ){
1528
- timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
1529
- }
1530
- if( zType[0]!='t' && g.perm.RdTkt ){
1531
- timeline_submenu(&url, "Tickets Only", "y", "t", 0);
1532
- }
1533
- if( zType[0]!='e' && g.perm.RdWiki ){
1534
- timeline_submenu(&url, "Events Only", "y", "e", 0);
1535
- }
1536
- if( zType[0]!='g' && g.perm.Read ){
1537
- timeline_submenu(&url, "Tags Only", "y", "g", 0);
1538
- }
1539
- }
1540
- if( nEntry>20 ){
1541
- timeline_submenu(&url, "20 Entries", "n", "20", 0);
1542
- }
1543
- if( nEntry<200 && nEntry>0 ){
1544
- timeline_submenu(&url, "200 Entries", "n", "200", 0);
15451550
}
15461551
if( zType[0]=='a' || zType[0]=='c' ){
1547
- if( tmFlags & TIMELINE_FCHANGES ){
1548
- timeline_submenu(&url, "Hide Files", "v", 0, 0);
1549
- }else{
1550
- timeline_submenu(&url, "Show Files", "v", "", 0);
1551
- }
15521552
if( (tmFlags & TIMELINE_UNHIDE)==0 ){
15531553
timeline_submenu(&url, "Unhide", "unhide", "", 0);
15541554
}
15551555
}
1556
+ style_submenu_binary("v","With Files","Without Files");
1557
+ if( zUses==0 ) timeline_y_submenu();
1558
+ style_submenu_entry("n","Lines",1);
15561559
}
15571560
}
15581561
if( P("showsql") ){
15591562
@ <blockquote>%h(blob_sql_text(&sql))</blockquote>
15601563
}
1564
+ if( search_restrict(SRCH_CKIN)!=0 ){
1565
+ style_submenu_element("Search", 0, "%R/search?y=c");
1566
+ }
15611567
if( P("showid") ) tmFlags |= TIMELINE_SHOWRID;
15621568
blob_zero(&sql);
15631569
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
15641570
@ <h2>%b(&desc)</h2>
15651571
blob_reset(&desc);
15661572
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
15671573
db_finalize(&q);
1574
+ if( zOlderButton ){
1575
+ @ %z(xhref("class='button'","%z",zOlderButton))Older</a>
1576
+ }
15681577
style_footer();
15691578
}
15701579
15711580
/*
15721581
** The input query q selects various records. Print a human-readable
@@ -1771,11 +1780,11 @@
17711780
** for the current version or "now" for the current time.
17721781
**
17731782
** Options:
17741783
** -n|--limit N Output the first N entries (default 20 lines).
17751784
** N=0 means no limit.
1776
-** -p|--path PATH Output items affecting PATH only.
1785
+** -p|--path PATH Output items affecting PATH only.
17771786
** PATH can be a file or a sub directory.
17781787
** --offset P skip P changes
17791788
** -t|--type TYPE Output items from the given types only, such as:
17801789
** ci = file commits only
17811790
** e = events only
@@ -1893,11 +1902,11 @@
18931902
if( mode==0 ){
18941903
if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
18951904
}
18961905
zDate = mprintf("(SELECT julianday(%Q%s, 'utc'))", zOrigin, zShift);
18971906
}
1898
-
1907
+
18991908
if( zFilePattern ){
19001909
if( zType==0 ){
19011910
/* When zFilePattern is specified and type is not specified, only show
19021911
* file checkins */
19031912
zType="ci";
@@ -2041,10 +2050,10 @@
20412050
" AND blob.rid=c.cid"
20422051
);
20432052
while( db_step(&q)==SQLITE_ROW ){
20442053
const char *zUuid = db_column_text(&q, 0);
20452054
@ <li>
2046
- @ <a href="%s(g.zTop)/timeline?p=%s(zUuid)&amp;d=%s(zUuid)&amp;unhide">%S(zUuid)</a>
2055
+ @ <a href="%s(g.zTop)/timeline?dp=%s(zUuid)&amp;unhide">%S(zUuid)</a>
20472056
}
20482057
db_finalize(&q);
20492058
style_footer();
20502059
}
20512060
--- src/timeline.c
+++ src/timeline.c
@@ -494,10 +494,11 @@
494 " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
495 " FROM mlink"
496 " WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
497 " AND (fid>0 OR"
498 " fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))"
 
499 " ORDER BY 3 /*sort*/"
500 );
501 fchngQueryInit = 1;
502 }
503 db_bind_int(&fchngQuery, ":mid", rid);
@@ -666,16 +667,16 @@
666 if( cSep=='[' ) cgi_printf("[");
667 cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n");
668 }
669 cgi_printf("var nrail = %d\n", pGraph->mxRail+1);
670 graph_free(pGraph);
671 @ var canvasDiv = gebi("canvas");
672 @ var canvasStyle = window.getComputedStyle && window.getComputedStyle(canvasDiv,null);
673 @ var lineColor = (canvasStyle && canvasStyle.getPropertyValue('color')) || 'black';
674 @ var bgColor = (canvasStyle && canvasStyle.getPropertyValue('background-color')) || 'white';
675 @ if( bgColor=='transparent' ) bgColor = 'white';
676 @ var boxColor = lineColor;
677 @ function drawBox(color,x0,y0,x1,y1){
678 @ var n = document.createElement("div");
679 @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; }
680 @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; }
681 @ var w = x1-x0+1;
@@ -685,11 +686,11 @@
685 @ n.style.left = x0+"px";
686 @ n.style.top = y0+"px";
687 @ n.style.width = w+"px";
688 @ n.style.height = h+"px";
689 @ n.style.backgroundColor = color;
690 @ canvasDiv.appendChild(n);
691 @ return n;
692 @ }
693 @ function absoluteY(id){
694 @ var obj = gebi(id);
695 @ if( !obj ) return;
@@ -711,39 +712,39 @@
711 @ }while( obj = obj.offsetParent );
712 @ }
713 @ return left;
714 @ }
715 @ function drawUpArrow(x,y0,y1){
716 @ drawBox(lineColor,x,y0,x+1,y1);
717 @ if( y0+10>=y1 ){
718 @ drawBox(lineColor,x-1,y0+1,x+2,y0+2);
719 @ drawBox(lineColor,x-2,y0+3,x+3,y0+4);
720 @ }else{
721 @ drawBox(lineColor,x-1,y0+2,x+2,y0+4);
722 @ drawBox(lineColor,x-2,y0+5,x+3,y0+7);
723 @ }
724 @ }
725 @ function drawThinArrow(y,xFrom,xTo){
726 @ if( xFrom<xTo ){
727 @ drawBox(lineColor,xFrom,y,xTo,y);
728 @ drawBox(lineColor,xTo-3,y-1,xTo-2,y+1);
729 @ drawBox(lineColor,xTo-4,y-2,xTo-4,y+2);
730 @ }else{
731 @ drawBox(lineColor,xTo,y,xFrom,y);
732 @ drawBox(lineColor,xTo+2,y-1,xTo+3,y+1);
733 @ drawBox(lineColor,xTo+4,y-2,xTo+4,y+2);
734 @ }
735 @ }
736 @ function drawThinLine(x0,y0,x1,y1){
737 @ drawBox(lineColor,x0,y0,x1,y1);
738 @ }
739 @ function drawNodeBox(color,x0,y0,x1,y1){
740 @ drawBox(color,x0,y0,x1,y1).style.cursor = "pointer";
741 @ }
742 @ function drawNode(p, left, btm){
743 @ drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6);
744 @ drawNodeBox(p.bg||bgColor,p.x-4,p.y-4,p.x+5,p.y+5);
745 @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
746 @ if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2);
747 if( !omitDescenders ){
748 @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
749 @ if( p.d ) drawUpArrow(p.x, p.y+6, btm);
@@ -765,11 +766,11 @@
765 @ for(var i=0; i<n; i+=2){
766 @ var x1 = p.au[i]*railPitch + left;
767 @ var x0 = x1>p.x ? p.x+7 : p.x-6;
768 @ var u = rowinfo[p.au[i+1]-1];
769 @ if(u.id<p.id){
770 @ drawBox(lineColor,x0,p.y,x1,p.y+1);
771 @ drawUpArrow(x1, u.y+6, p.y);
772 @ }else{
773 @ drawBox("#600000",x0,p.y,x1,p.y+1);
774 @ drawBox("#600000",x1-1,p.y,x1,u.y+1);
775 @ drawBox("#600000",x1,u.y,u.x-6,u.y+1);
@@ -952,13 +953,22 @@
952 if( z==0 ) return -1.0;
953 if( fossil_isdate(z) ){
954 mtime = db_double(0.0, "SELECT julianday(%Q,'utc')", z);
955 if( mtime>0.0 ) return mtime;
956 }
957 rid = symbolic_name_to_rid(z, "ci");
958 if( rid==0 ) return -1.0;
959 mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
 
 
 
 
 
 
 
 
 
960 return mtime;
961 }
962
963 /*
964 ** The value of one second in julianday notation
@@ -1011,10 +1021,47 @@
1011 }
1012 db_finalize(&q);
1013 return blob_str(&out);
1014 }
1015
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1016
1017 /*
1018 ** WEBPAGE: timeline
1019 **
1020 ** Query parameters:
@@ -1055,11 +1102,11 @@
1055 */
1056 void page_timeline(void){
1057 Stmt q; /* Query used to generate the timeline */
1058 Blob sql; /* text of SQL used to generate timeline */
1059 Blob desc; /* Description of the timeline */
1060 int nEntry = atoi(PD("n","20")); /* Max number of entries on timeline */
1061 int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
1062 int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
1063 int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
1064 const char *zUser = P("u"); /* All entries by this user if not NULL */
1065 const char *zType = PD("y","all"); /* Type of events. All if NULL */
@@ -1069,11 +1116,11 @@
1069 const char *zTagName = P("t"); /* Show events with this tag */
1070 const char *zBrName = P("r"); /* Show events related to this tag */
1071 const char *zSearch = P("s"); /* Search string */
1072 const char *zUses = P("uf"); /* Only show checkins hold this file */
1073 const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
1074 const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/
1075 int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
1076 int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
1077 int tagid; /* Tag ID */
1078 int tmFlags = 0; /* Timeline flags */
1079 const char *zThisTag = 0; /* Suppress links to this tag */
@@ -1084,10 +1131,32 @@
1084 int noMerge = P("shortest")==0; /* Follow merge links if shorter */
1085 int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
1086 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
1087 int pd_rid;
1088 double rBefore, rAfter, rCirca; /* Boundary times */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1089
1090 /* To view the timeline, must have permission to read project data.
1091 */
1092 pd_rid = name_to_typed_rid(P("dp"),"ci");
1093 if( pd_rid ){
@@ -1097,20 +1166,21 @@
1097 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
1098 login_needed();
1099 return;
1100 }
1101 url_initialize(&url, "timeline");
 
1102 if( zTagName && g.perm.Read ){
1103 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
1104 zThisTag = zTagName;
1105 }else if( zBrName && g.perm.Read ){
1106 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
1107 zThisTag = zBrName;
1108 }else{
1109 tagid = 0;
1110 }
1111 if( tagid>0
1112 && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry
1113 ){
1114 zCirca = zBefore = zAfter = 0;
1115 nEntry = -1;
1116 }
@@ -1117,32 +1187,26 @@
1117 if( zType[0]=='a' ){
1118 tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH;
1119 }else{
1120 tmFlags |= TIMELINE_GRAPH;
1121 }
1122 if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry));
1123 if( P("ng")!=0 || zSearch!=0 ){
1124 tmFlags &= ~TIMELINE_GRAPH;
1125 url_add_parameter(&url, "ng", 0);
1126 }
1127 if( P("brbg")!=0 ){
1128 tmFlags |= TIMELINE_BRCOLOR;
1129 url_add_parameter(&url, "brbg", 0);
1130 }
1131 if( P("unhide")!=0 ){
1132 tmFlags |= TIMELINE_UNHIDE;
1133 url_add_parameter(&url, "unhide", 0);
1134 }
1135 if( P("ubg")!=0 ){
1136 tmFlags |= TIMELINE_UCOLOR;
1137 url_add_parameter(&url, "ubg", 0);
1138 }
1139 if( zUses!=0 ){
1140 int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses);
1141 if( ufid ){
1142 zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid);
1143 url_add_parameter(&url, "uf", zUses);
1144 db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)");
1145 compute_uses_file("usesfile", ufid, 0);
1146 zType = "ci";
1147 }else{
1148 zUses = 0;
@@ -1161,22 +1225,20 @@
1161 timeline_temp_table();
1162 blob_zero(&sql);
1163 blob_zero(&desc);
1164 blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
1165 blob_append(&sql, timeline_query_for_www(), -1);
1166 if( P("fc")!=0 || P("v")!=0 || P("detail")!=0 ){
1167 tmFlags |= TIMELINE_FCHANGES;
1168 url_add_parameter(&url, "v", 0);
1169 }
1170 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1171 blob_append_sql(&sql,
1172 " AND NOT EXISTS(SELECT 1 FROM tagxref"
1173 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)",
1174 TAG_HIDDEN
1175 );
1176 }
1177 if( !useDividers ) url_add_parameter(&url, "nd", 0);
1178 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
1179 /* If from= and to= are present, display all nodes on a path connecting
1180 ** the two */
1181 PathNode *p = 0;
1182 const char *zFrom = 0;
@@ -1241,34 +1303,19 @@
1241 }
1242 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
1243 }
1244 blob_appendf(&desc, " of %z[%S]</a>",
1245 href("%R/info/%s", zUuid), zUuid);
1246 if( p_rid ){
1247 url_add_parameter(&url, "p", zUuid);
1248 }
1249 if( d_rid ){
1250 if( p_rid ){
1251 /* If both p= and d= are set, we don't have the uuid of d yet. */
1252 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
1253 }
1254 url_add_parameter(&url, "d", zUuid);
1255 }
1256 if( nEntry>20 ){
1257 timeline_submenu(&url, "20 Entries", "n", "20", 0);
1258 }
1259 if( nEntry<200 && nEntry>0 ){
1260 timeline_submenu(&url, "200 Entries", "n", "200", 0);
1261 }
1262 if( tmFlags & TIMELINE_FCHANGES ){
1263 timeline_submenu(&url, "Hide Files", "v", 0, 0);
1264 }else{
1265 timeline_submenu(&url, "Show Files", "v", "", 0);
1266 }
1267 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1268 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1269 }
1270 }else if( f_rid && g.perm.Read ){
1271 /* If f= is present, ignore all other parameters other than n= */
1272 char *zUuid;
1273 db_multi_exec(
1274 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1282,16 +1329,11 @@
1282 if( useDividers ) timeline_add_dividers(0, f_rid);
1283 blob_appendf(&desc, "Parents and children of check-in ");
1284 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1285 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%s", zUuid), zUuid);
1286 tmFlags |= TIMELINE_DISJOINT;
1287 url_add_parameter(&url, "f", zUuid);
1288 if( tmFlags & TIMELINE_FCHANGES ){
1289 timeline_submenu(&url, "Hide Files", "v", 0, 0);
1290 }else{
1291 timeline_submenu(&url, "Show Files", "v", "", 0);
1292 }
1293 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1294 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1295 }
1296 }else{
1297 /* Otherwise, a timeline based on a span of time */
@@ -1316,11 +1358,10 @@
1316 blob_append_sql(&sql,
1317 "AND (EXISTS(SELECT 1 FROM tagxref"
1318 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
1319
1320 if( zBrName ){
1321 url_add_parameter(&url, "r", zBrName);
1322 /* The next two blob_appendf() calls add SQL that causes checkins that
1323 ** are not part of the branch which are parents or children of the
1324 ** branch to be included in the report. This related check-ins are
1325 ** useful in helping to visualize what has happened on a quiescent
1326 ** branch that is infrequently merged with a much more activate branch.
@@ -1342,21 +1383,17 @@
1342 " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid"
1343 " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
1344 tagid
1345 );
1346 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1347 blob_append_sql(&sql,
1348 " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid"
1349 " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
1350 TAG_HIDDEN
1351 );
1352 }
1353 }else{
1354 url_add_parameter(&url, "mionly", "1");
1355 }
1356 }else{
1357 url_add_parameter(&url, "t", zTagName);
1358 }
1359 blob_append_sql(&sql, ")");
1360 }
1361 if( (zType[0]=='w' && !g.perm.RdWiki)
1362 || (zType[0]=='t' && !g.perm.RdTkt)
@@ -1384,11 +1421,10 @@
1384 }
1385 blob_append_sql(&sql, ")");
1386 }
1387 }else{ /* zType!="all" */
1388 blob_append_sql(&sql, " AND event.type=%Q", zType);
1389 url_add_parameter(&url, "y", zType);
1390 if( zType[0]=='c' ){
1391 zEType = "checkin";
1392 }else if( zType[0]=='w' ){
1393 zEType = "wiki edit";
1394 }else if( zType[0]=='t' ){
@@ -1406,41 +1442,35 @@
1406 zCirca = zBefore = zAfter = 0;
1407 nEntry = -1;
1408 }
1409 blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1410 zUser, zUser);
1411 url_add_parameter(&url, "u", zUser);
1412 zThisUser = zUser;
1413 }
1414 if( zSearch ){
1415 blob_append_sql(&sql,
1416 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
1417 zSearch, zSearch);
1418 url_add_parameter(&url, "s", zSearch);
1419 }
1420 rBefore = symbolic_name_to_mtime(zBefore);
1421 rAfter = symbolic_name_to_mtime(zAfter);
1422 rCirca = symbolic_name_to_mtime(zCirca);
1423 if( rAfter>0.0 ){
1424 if( rBefore>0.0 ){
1425 blob_append_sql(&sql,
1426 " AND event.mtime>=%.17g AND event.mtime<=%.17g"
1427 " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND);
1428 url_add_parameter(&url, "a", zAfter);
1429 url_add_parameter(&url, "b", zBefore);
1430 nEntry = -1;
1431 }else{
1432 blob_append_sql(&sql,
1433 " AND event.mtime>=%.17g ORDER BY event.mtime ASC",
1434 rAfter-ONE_SECOND);
1435 url_add_parameter(&url, "a", zAfter);
1436 }
1437 }else if( rBefore>0.0 ){
1438 blob_append_sql(&sql,
1439 " AND event.mtime<=%.17g ORDER BY event.mtime DESC",
1440 rBefore+ONE_SECOND);
1441 url_add_parameter(&url, "b", zBefore);
1442 }else if( rCirca>0.0 ){
1443 Blob sql2;
1444 blob_init(&sql2, blob_sql_text(&sql), -1);
1445 blob_append_sql(&sql2,
1446 " AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d",
@@ -1452,11 +1482,10 @@
1452 " AND event.mtime>=%f ORDER BY event.mtime ASC",
1453 rCirca
1454 );
1455 nEntry -= (nEntry+1)/2;
1456 if( useDividers ) timeline_add_dividers(rCirca, 0);
1457 url_add_parameter(&url, "c", zCirca);
1458 }else{
1459 blob_append_sql(&sql, " ORDER BY event.mtime DESC");
1460 }
1461 if( nEntry>0 ) blob_append_sql(&sql, " LIMIT %d", nEntry);
1462 db_multi_exec("%s", blob_sql_text(&sql));
@@ -1509,64 +1538,44 @@
1509 }
1510 if( g.perm.Hyperlink ){
1511 if( zAfter || n==nEntry ){
1512 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1513 timeline_submenu(&url, "Older", "b", zDate, "a");
 
1514 free(zDate);
1515 }
1516 if( zBefore || (zAfter && n==nEntry) ){
1517 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1518 timeline_submenu(&url, "Newer", "a", zDate, "b");
1519 free(zDate);
1520 }else if( tagid==0 && zUses==0 ){
1521 if( zType[0]!='a' ){
1522 timeline_submenu(&url, "All Types", "y", "all", 0);
1523 }
1524 if( zType[0]!='w' && g.perm.RdWiki ){
1525 timeline_submenu(&url, "Wiki Only", "y", "w", 0);
1526 }
1527 if( zType[0]!='c' && g.perm.Read ){
1528 timeline_submenu(&url, "Checkins Only", "y", "ci", 0);
1529 }
1530 if( zType[0]!='t' && g.perm.RdTkt ){
1531 timeline_submenu(&url, "Tickets Only", "y", "t", 0);
1532 }
1533 if( zType[0]!='e' && g.perm.RdWiki ){
1534 timeline_submenu(&url, "Events Only", "y", "e", 0);
1535 }
1536 if( zType[0]!='g' && g.perm.Read ){
1537 timeline_submenu(&url, "Tags Only", "y", "g", 0);
1538 }
1539 }
1540 if( nEntry>20 ){
1541 timeline_submenu(&url, "20 Entries", "n", "20", 0);
1542 }
1543 if( nEntry<200 && nEntry>0 ){
1544 timeline_submenu(&url, "200 Entries", "n", "200", 0);
1545 }
1546 if( zType[0]=='a' || zType[0]=='c' ){
1547 if( tmFlags & TIMELINE_FCHANGES ){
1548 timeline_submenu(&url, "Hide Files", "v", 0, 0);
1549 }else{
1550 timeline_submenu(&url, "Show Files", "v", "", 0);
1551 }
1552 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1553 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1554 }
1555 }
 
 
 
1556 }
1557 }
1558 if( P("showsql") ){
1559 @ <blockquote>%h(blob_sql_text(&sql))</blockquote>
1560 }
 
 
 
1561 if( P("showid") ) tmFlags |= TIMELINE_SHOWRID;
1562 blob_zero(&sql);
1563 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
1564 @ <h2>%b(&desc)</h2>
1565 blob_reset(&desc);
1566 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
1567 db_finalize(&q);
 
 
 
1568 style_footer();
1569 }
1570
1571 /*
1572 ** The input query q selects various records. Print a human-readable
@@ -1771,11 +1780,11 @@
1771 ** for the current version or "now" for the current time.
1772 **
1773 ** Options:
1774 ** -n|--limit N Output the first N entries (default 20 lines).
1775 ** N=0 means no limit.
1776 ** -p|--path PATH Output items affecting PATH only.
1777 ** PATH can be a file or a sub directory.
1778 ** --offset P skip P changes
1779 ** -t|--type TYPE Output items from the given types only, such as:
1780 ** ci = file commits only
1781 ** e = events only
@@ -1893,11 +1902,11 @@
1893 if( mode==0 ){
1894 if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
1895 }
1896 zDate = mprintf("(SELECT julianday(%Q%s, 'utc'))", zOrigin, zShift);
1897 }
1898
1899 if( zFilePattern ){
1900 if( zType==0 ){
1901 /* When zFilePattern is specified and type is not specified, only show
1902 * file checkins */
1903 zType="ci";
@@ -2041,10 +2050,10 @@
2041 " AND blob.rid=c.cid"
2042 );
2043 while( db_step(&q)==SQLITE_ROW ){
2044 const char *zUuid = db_column_text(&q, 0);
2045 @ <li>
2046 @ <a href="%s(g.zTop)/timeline?p=%s(zUuid)&amp;d=%s(zUuid)&amp;unhide">%S(zUuid)</a>
2047 }
2048 db_finalize(&q);
2049 style_footer();
2050 }
2051
--- src/timeline.c
+++ src/timeline.c
@@ -494,10 +494,11 @@
494 " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm"
495 " FROM mlink"
496 " WHERE mid=:mid AND (pid!=fid OR pfnid>0)"
497 " AND (fid>0 OR"
498 " fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))"
499 " AND NOT mlink.isaux"
500 " ORDER BY 3 /*sort*/"
501 );
502 fchngQueryInit = 1;
503 }
504 db_bind_int(&fchngQuery, ":mid", rid);
@@ -666,16 +667,16 @@
667 if( cSep=='[' ) cgi_printf("[");
668 cgi_printf("],h:\"%s\"}%s", pRow->zUuid, pRow->pNext ? ",\n" : "];\n");
669 }
670 cgi_printf("var nrail = %d\n", pGraph->mxRail+1);
671 graph_free(pGraph);
672 @ var cDiv = gebi("canvas");
673 @ var csty = window.getComputedStyle && window.getComputedStyle(cDiv,null);
674 @ var lineClr = (csty && csty.getPropertyValue('color')) || 'black';
675 @ var bgClr = (csty && csty.getPropertyValue('background-color')) ||'white';
676 @ if( bgClr=='transparent' ) bgClr = 'white';
677 @ var boxColor = lineClr;
678 @ function drawBox(color,x0,y0,x1,y1){
679 @ var n = document.createElement("div");
680 @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; }
681 @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; }
682 @ var w = x1-x0+1;
@@ -685,11 +686,11 @@
686 @ n.style.left = x0+"px";
687 @ n.style.top = y0+"px";
688 @ n.style.width = w+"px";
689 @ n.style.height = h+"px";
690 @ n.style.backgroundColor = color;
691 @ cDiv.appendChild(n);
692 @ return n;
693 @ }
694 @ function absoluteY(id){
695 @ var obj = gebi(id);
696 @ if( !obj ) return;
@@ -711,39 +712,39 @@
712 @ }while( obj = obj.offsetParent );
713 @ }
714 @ return left;
715 @ }
716 @ function drawUpArrow(x,y0,y1){
717 @ drawBox(lineClr,x,y0,x+1,y1);
718 @ if( y0+10>=y1 ){
719 @ drawBox(lineClr,x-1,y0+1,x+2,y0+2);
720 @ drawBox(lineClr,x-2,y0+3,x+3,y0+4);
721 @ }else{
722 @ drawBox(lineClr,x-1,y0+2,x+2,y0+4);
723 @ drawBox(lineClr,x-2,y0+5,x+3,y0+7);
724 @ }
725 @ }
726 @ function drawThinArrow(y,xFrom,xTo){
727 @ if( xFrom<xTo ){
728 @ drawBox(lineClr,xFrom,y,xTo,y);
729 @ drawBox(lineClr,xTo-3,y-1,xTo-2,y+1);
730 @ drawBox(lineClr,xTo-4,y-2,xTo-4,y+2);
731 @ }else{
732 @ drawBox(lineClr,xTo,y,xFrom,y);
733 @ drawBox(lineClr,xTo+2,y-1,xTo+3,y+1);
734 @ drawBox(lineClr,xTo+4,y-2,xTo+4,y+2);
735 @ }
736 @ }
737 @ function drawThinLine(x0,y0,x1,y1){
738 @ drawBox(lineClr,x0,y0,x1,y1);
739 @ }
740 @ function drawNodeBox(color,x0,y0,x1,y1){
741 @ drawBox(color,x0,y0,x1,y1).style.cursor = "pointer";
742 @ }
743 @ function drawNode(p, left, btm){
744 @ drawNodeBox(boxColor,p.x-5,p.y-5,p.x+6,p.y+6);
745 @ drawNodeBox(p.bg||bgClr,p.x-4,p.y-4,p.x+5,p.y+5);
746 @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
747 @ if( p.f&1 ) drawNodeBox(boxColor,p.x-1,p.y-1,p.x+2,p.y+2);
748 if( !omitDescenders ){
749 @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
750 @ if( p.d ) drawUpArrow(p.x, p.y+6, btm);
@@ -765,11 +766,11 @@
766 @ for(var i=0; i<n; i+=2){
767 @ var x1 = p.au[i]*railPitch + left;
768 @ var x0 = x1>p.x ? p.x+7 : p.x-6;
769 @ var u = rowinfo[p.au[i+1]-1];
770 @ if(u.id<p.id){
771 @ drawBox(lineClr,x0,p.y,x1,p.y+1);
772 @ drawUpArrow(x1, u.y+6, p.y);
773 @ }else{
774 @ drawBox("#600000",x0,p.y,x1,p.y+1);
775 @ drawBox("#600000",x1-1,p.y,x1,u.y+1);
776 @ drawBox("#600000",x1,u.y,u.x-6,u.y+1);
@@ -952,13 +953,22 @@
953 if( z==0 ) return -1.0;
954 if( fossil_isdate(z) ){
955 mtime = db_double(0.0, "SELECT julianday(%Q,'utc')", z);
956 if( mtime>0.0 ) return mtime;
957 }
958 rid = symbolic_name_to_rid(z, "*");
959 if( rid ){
960 mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
961 }else{
962 mtime = db_double(-1.0,
963 "SELECT max(event.mtime) FROM event, tag, tagxref"
964 " WHERE tag.tagname GLOB 'event-%q*'"
965 " AND tagxref.tagid=tag.tagid AND tagxref.tagtype"
966 " AND event.objid=tagxref.rid",
967 z
968 );
969 }
970 return mtime;
971 }
972
973 /*
974 ** The value of one second in julianday notation
@@ -1011,10 +1021,47 @@
1021 }
1022 db_finalize(&q);
1023 return blob_str(&out);
1024 }
1025
1026
1027 /*
1028 ** Add the select/option box to the timeline submenu that is used to
1029 ** set the y= parameter that determines which elements to display
1030 ** on the timeline.
1031 */
1032 static void timeline_y_submenu(void){
1033 static int i = 0;
1034 static const char *az[12];
1035 if( i==0 ){
1036 az[0] = "all";
1037 az[1] = "All Types";
1038 i = 2;
1039 if( g.perm.Read ){
1040 az[i++] = "ci";
1041 az[i++] = "Check-ins";
1042 az[i++] = "g";
1043 az[i++] = "Tags";
1044 }
1045 if( g.perm.RdWiki ){
1046 az[i++] = "e";
1047 az[i++] = "Tech Notes";
1048 }
1049 if( g.perm.RdTkt ){
1050 az[i++] = "t";
1051 az[i++] = "Tickets";
1052 }
1053 if( g.perm.RdWiki ){
1054 az[i++] = "w";
1055 az[i++] = "Wiki";
1056 }
1057 assert( i<=ArraySize(az) );
1058 }
1059 if( i>2 ){
1060 style_submenu_multichoice("y", i/2, az);
1061 }
1062 }
1063
1064 /*
1065 ** WEBPAGE: timeline
1066 **
1067 ** Query parameters:
@@ -1055,11 +1102,11 @@
1102 */
1103 void page_timeline(void){
1104 Stmt q; /* Query used to generate the timeline */
1105 Blob sql; /* text of SQL used to generate timeline */
1106 Blob desc; /* Description of the timeline */
1107 int nEntry; /* Max number of entries on timeline */
1108 int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
1109 int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
1110 int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
1111 const char *zUser = P("u"); /* All entries by this user if not NULL */
1112 const char *zType = PD("y","all"); /* Type of events. All if NULL */
@@ -1069,11 +1116,11 @@
1116 const char *zTagName = P("t"); /* Show events with this tag */
1117 const char *zBrName = P("r"); /* Show events related to this tag */
1118 const char *zSearch = P("s"); /* Search string */
1119 const char *zUses = P("uf"); /* Only show checkins hold this file */
1120 const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */
1121 const char *zYearWeek = P("yw"); /* Checkins for YYYY-WW (week-of-year) */
1122 int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */
1123 int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */
1124 int tagid; /* Tag ID */
1125 int tmFlags = 0; /* Timeline flags */
1126 const char *zThisTag = 0; /* Suppress links to this tag */
@@ -1084,10 +1131,32 @@
1131 int noMerge = P("shortest")==0; /* Follow merge links if shorter */
1132 int me_rid = name_to_typed_rid(P("me"),"ci"); /* me= for common ancestory */
1133 int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */
1134 int pd_rid;
1135 double rBefore, rAfter, rCirca; /* Boundary times */
1136 const char *z;
1137 char *zOlderButton = 0; /* URL for Older button at the bottom */
1138
1139 /* Set number of rows to display */
1140 z = P("n");
1141 if( z ){
1142 if( fossil_strcmp(z,"all")==0 ){
1143 nEntry = 0;
1144 }else{
1145 nEntry = atoi(z);
1146 if( nEntry<=0 ){
1147 cgi_replace_query_parameter("n","10");
1148 nEntry = 10;
1149 }
1150 }
1151 }else if( zCirca ){
1152 cgi_replace_query_parameter("n","11");
1153 nEntry = 11;
1154 }else{
1155 cgi_replace_query_parameter("n","50");
1156 nEntry = 50;
1157 }
1158
1159 /* To view the timeline, must have permission to read project data.
1160 */
1161 pd_rid = name_to_typed_rid(P("dp"),"ci");
1162 if( pd_rid ){
@@ -1097,20 +1166,21 @@
1166 if( !g.perm.Read && !g.perm.RdTkt && !g.perm.RdWiki ){
1167 login_needed();
1168 return;
1169 }
1170 url_initialize(&url, "timeline");
1171 cgi_query_parameters_to_url(&url);
1172 if( zTagName && g.perm.Read ){
1173 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
1174 zThisTag = zTagName;
1175 }else if( zBrName && g.perm.Read ){
1176 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName);
1177 zThisTag = zBrName;
1178 }else{
1179 tagid = 0;
1180 }
1181 if( tagid>0
1182 && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry
1183 ){
1184 zCirca = zBefore = zAfter = 0;
1185 nEntry = -1;
1186 }
@@ -1117,32 +1187,26 @@
1187 if( zType[0]=='a' ){
1188 tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH;
1189 }else{
1190 tmFlags |= TIMELINE_GRAPH;
1191 }
1192 if( PB("ng") || zSearch!=0 ){
 
1193 tmFlags &= ~TIMELINE_GRAPH;
 
1194 }
1195 if( PB("brbg") ){
1196 tmFlags |= TIMELINE_BRCOLOR;
 
1197 }
1198 if( PB("unhide") ){
1199 tmFlags |= TIMELINE_UNHIDE;
 
1200 }
1201 if( PB("ubg") ){
1202 tmFlags |= TIMELINE_UCOLOR;
 
1203 }
1204 if( zUses!=0 ){
1205 int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses);
1206 if( ufid ){
1207 zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid);
 
1208 db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)");
1209 compute_uses_file("usesfile", ufid, 0);
1210 zType = "ci";
1211 }else{
1212 zUses = 0;
@@ -1161,22 +1225,20 @@
1225 timeline_temp_table();
1226 blob_zero(&sql);
1227 blob_zero(&desc);
1228 blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
1229 blob_append(&sql, timeline_query_for_www(), -1);
1230 if( PB("fc") || PB("v") || PB("detail") ){
1231 tmFlags |= TIMELINE_FCHANGES;
 
1232 }
1233 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1234 blob_append_sql(&sql,
1235 " AND NOT EXISTS(SELECT 1 FROM tagxref"
1236 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)",
1237 TAG_HIDDEN
1238 );
1239 }
 
1240 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){
1241 /* If from= and to= are present, display all nodes on a path connecting
1242 ** the two */
1243 PathNode *p = 0;
1244 const char *zFrom = 0;
@@ -1241,34 +1303,19 @@
1303 }
1304 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
1305 }
1306 blob_appendf(&desc, " of %z[%S]</a>",
1307 href("%R/info/%s", zUuid), zUuid);
 
 
 
1308 if( d_rid ){
1309 if( p_rid ){
1310 /* If both p= and d= are set, we don't have the uuid of d yet. */
1311 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
1312 }
1313 }
1314 style_submenu_binary("v","With Files","Without Files");
1315 style_submenu_entry("n","Lines",1);
1316 timeline_y_submenu();
 
 
 
 
 
 
 
 
 
 
 
 
1317 }else if( f_rid && g.perm.Read ){
1318 /* If f= is present, ignore all other parameters other than n= */
1319 char *zUuid;
1320 db_multi_exec(
1321 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1282,16 +1329,11 @@
1329 if( useDividers ) timeline_add_dividers(0, f_rid);
1330 blob_appendf(&desc, "Parents and children of check-in ");
1331 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1332 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%s", zUuid), zUuid);
1333 tmFlags |= TIMELINE_DISJOINT;
1334 style_submenu_binary("v","With Files","Without Files");
 
 
 
 
 
1335 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1336 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1337 }
1338 }else{
1339 /* Otherwise, a timeline based on a span of time */
@@ -1316,11 +1358,10 @@
1358 blob_append_sql(&sql,
1359 "AND (EXISTS(SELECT 1 FROM tagxref"
1360 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid);
1361
1362 if( zBrName ){
 
1363 /* The next two blob_appendf() calls add SQL that causes checkins that
1364 ** are not part of the branch which are parents or children of the
1365 ** branch to be included in the report. This related check-ins are
1366 ** useful in helping to visualize what has happened on a quiescent
1367 ** branch that is infrequently merged with a much more activate branch.
@@ -1342,21 +1383,17 @@
1383 " OR EXISTS(SELECT 1 FROM plink CROSS JOIN tagxref ON rid=pid"
1384 " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
1385 tagid
1386 );
1387 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1388 blob_append_sql(&sql,
1389 " AND NOT EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=pid"
1390 " WHERE tagid=%d AND tagtype>0 AND cid=blob.rid)",
1391 TAG_HIDDEN
1392 );
1393 }
 
 
1394 }
 
 
1395 }
1396 blob_append_sql(&sql, ")");
1397 }
1398 if( (zType[0]=='w' && !g.perm.RdWiki)
1399 || (zType[0]=='t' && !g.perm.RdTkt)
@@ -1384,11 +1421,10 @@
1421 }
1422 blob_append_sql(&sql, ")");
1423 }
1424 }else{ /* zType!="all" */
1425 blob_append_sql(&sql, " AND event.type=%Q", zType);
 
1426 if( zType[0]=='c' ){
1427 zEType = "checkin";
1428 }else if( zType[0]=='w' ){
1429 zEType = "wiki edit";
1430 }else if( zType[0]=='t' ){
@@ -1406,41 +1442,35 @@
1442 zCirca = zBefore = zAfter = 0;
1443 nEntry = -1;
1444 }
1445 blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)",
1446 zUser, zUser);
 
1447 zThisUser = zUser;
1448 }
1449 if( zSearch ){
1450 blob_append_sql(&sql,
1451 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
1452 zSearch, zSearch);
 
1453 }
1454 rBefore = symbolic_name_to_mtime(zBefore);
1455 rAfter = symbolic_name_to_mtime(zAfter);
1456 rCirca = symbolic_name_to_mtime(zCirca);
1457 if( rAfter>0.0 ){
1458 if( rBefore>0.0 ){
1459 blob_append_sql(&sql,
1460 " AND event.mtime>=%.17g AND event.mtime<=%.17g"
1461 " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND);
 
 
1462 nEntry = -1;
1463 }else{
1464 blob_append_sql(&sql,
1465 " AND event.mtime>=%.17g ORDER BY event.mtime ASC",
1466 rAfter-ONE_SECOND);
 
1467 }
1468 }else if( rBefore>0.0 ){
1469 blob_append_sql(&sql,
1470 " AND event.mtime<=%.17g ORDER BY event.mtime DESC",
1471 rBefore+ONE_SECOND);
 
1472 }else if( rCirca>0.0 ){
1473 Blob sql2;
1474 blob_init(&sql2, blob_sql_text(&sql), -1);
1475 blob_append_sql(&sql2,
1476 " AND event.mtime<=%f ORDER BY event.mtime DESC LIMIT %d",
@@ -1452,11 +1482,10 @@
1482 " AND event.mtime>=%f ORDER BY event.mtime ASC",
1483 rCirca
1484 );
1485 nEntry -= (nEntry+1)/2;
1486 if( useDividers ) timeline_add_dividers(rCirca, 0);
 
1487 }else{
1488 blob_append_sql(&sql, " ORDER BY event.mtime DESC");
1489 }
1490 if( nEntry>0 ) blob_append_sql(&sql, " LIMIT %d", nEntry);
1491 db_multi_exec("%s", blob_sql_text(&sql));
@@ -1509,64 +1538,44 @@
1538 }
1539 if( g.perm.Hyperlink ){
1540 if( zAfter || n==nEntry ){
1541 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1542 timeline_submenu(&url, "Older", "b", zDate, "a");
1543 zOlderButton = fossil_strdup(url_render(&url, "b", zDate, "a", 0));
1544 free(zDate);
1545 }
1546 if( zBefore || (zAfter && n==nEntry) ){
1547 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
1548 timeline_submenu(&url, "Newer", "a", zDate, "b");
1549 free(zDate);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1550 }
1551 if( zType[0]=='a' || zType[0]=='c' ){
 
 
 
 
 
1552 if( (tmFlags & TIMELINE_UNHIDE)==0 ){
1553 timeline_submenu(&url, "Unhide", "unhide", "", 0);
1554 }
1555 }
1556 style_submenu_binary("v","With Files","Without Files");
1557 if( zUses==0 ) timeline_y_submenu();
1558 style_submenu_entry("n","Lines",1);
1559 }
1560 }
1561 if( P("showsql") ){
1562 @ <blockquote>%h(blob_sql_text(&sql))</blockquote>
1563 }
1564 if( search_restrict(SRCH_CKIN)!=0 ){
1565 style_submenu_element("Search", 0, "%R/search?y=c");
1566 }
1567 if( P("showid") ) tmFlags |= TIMELINE_SHOWRID;
1568 blob_zero(&sql);
1569 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
1570 @ <h2>%b(&desc)</h2>
1571 blob_reset(&desc);
1572 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
1573 db_finalize(&q);
1574 if( zOlderButton ){
1575 @ %z(xhref("class='button'","%z",zOlderButton))Older</a>
1576 }
1577 style_footer();
1578 }
1579
1580 /*
1581 ** The input query q selects various records. Print a human-readable
@@ -1771,11 +1780,11 @@
1780 ** for the current version or "now" for the current time.
1781 **
1782 ** Options:
1783 ** -n|--limit N Output the first N entries (default 20 lines).
1784 ** N=0 means no limit.
1785 ** -p|--path PATH Output items affecting PATH only.
1786 ** PATH can be a file or a sub directory.
1787 ** --offset P skip P changes
1788 ** -t|--type TYPE Output items from the given types only, such as:
1789 ** ci = file commits only
1790 ** e = events only
@@ -1893,11 +1902,11 @@
1902 if( mode==0 ){
1903 if( isIsoDate(zOrigin) ) zShift = ",'+1 day'";
1904 }
1905 zDate = mprintf("(SELECT julianday(%Q%s, 'utc'))", zOrigin, zShift);
1906 }
1907
1908 if( zFilePattern ){
1909 if( zType==0 ){
1910 /* When zFilePattern is specified and type is not specified, only show
1911 * file checkins */
1912 zType="ci";
@@ -2041,10 +2050,10 @@
2050 " AND blob.rid=c.cid"
2051 );
2052 while( db_step(&q)==SQLITE_ROW ){
2053 const char *zUuid = db_column_text(&q, 0);
2054 @ <li>
2055 @ <a href="%s(g.zTop)/timeline?dp=%s(zUuid)&amp;unhide">%S(zUuid)</a>
2056 }
2057 db_finalize(&q);
2058 style_footer();
2059 }
2060
+1 -1
--- src/tkt.c
+++ src/tkt.c
@@ -1434,8 +1434,8 @@
14341434
*/
14351435
void tkt_srchpage(void){
14361436
login_check_credentials();
14371437
style_header("Ticket Search");
14381438
ticket_standard_submenu(T_ALL_BUT(T_SRCH));
1439
- search_screen(SRCH_TKT, "tktsrch");
1439
+ search_screen(SRCH_TKT, 0);
14401440
style_footer();
14411441
}
14421442
--- src/tkt.c
+++ src/tkt.c
@@ -1434,8 +1434,8 @@
1434 */
1435 void tkt_srchpage(void){
1436 login_check_credentials();
1437 style_header("Ticket Search");
1438 ticket_standard_submenu(T_ALL_BUT(T_SRCH));
1439 search_screen(SRCH_TKT, "tktsrch");
1440 style_footer();
1441 }
1442
--- src/tkt.c
+++ src/tkt.c
@@ -1434,8 +1434,8 @@
1434 */
1435 void tkt_srchpage(void){
1436 login_check_credentials();
1437 style_header("Ticket Search");
1438 ticket_standard_submenu(T_ALL_BUT(T_SRCH));
1439 search_screen(SRCH_TKT, 0);
1440 style_footer();
1441 }
1442

No diff available

+25 -8
--- src/url.c
+++ src/url.c
@@ -432,47 +432,64 @@
432432
** An instance of this object is used to build a URL with query parameters.
433433
*/
434434
struct HQuery {
435435
Blob url; /* The URL */
436436
const char *zBase; /* The base URL */
437
- int nParam; /* Number of parameters. Max 10 */
438
- const char *azName[15]; /* Parameter names */
439
- const char *azValue[15]; /* Parameter values */
437
+ int nParam; /* Number of parameters. */
438
+ int nAlloc; /* Number of allocated slots */
439
+ const char **azName; /* Parameter names */
440
+ const char **azValue; /* Parameter values */
440441
};
441442
#endif
442443
443444
/*
444445
** Initialize the URL object.
445446
*/
446447
void url_initialize(HQuery *p, const char *zBase){
448
+ memset(p, 0, sizeof(*p));
447449
blob_zero(&p->url);
448450
p->zBase = zBase;
449
- p->nParam = 0;
450451
}
451452
452453
/*
453454
** Resets the given URL object, deallocating any memory
454455
** it uses.
455456
*/
456457
void url_reset(HQuery *p){
457458
blob_reset(&p->url);
459
+ fossil_free(p->azName);
460
+ fossil_free(p->azValue);
458461
url_initialize(p, p->zBase);
459462
}
460463
461464
/*
462465
** Add a fixed parameter to an HQuery.
463466
*/
464467
void url_add_parameter(HQuery *p, const char *zName, const char *zValue){
465
- assert( p->nParam < count(p->azName) );
466
- assert( p->nParam < count(p->azValue) );
467
- p->azName[p->nParam] = zName;
468
- p->azValue[p->nParam] = zValue;
468
+ int i;
469
+ for(i=0; i<p->nParam; i++){
470
+ if( fossil_strcmp(p->azName[i],zName)==0 ){
471
+ p->azValue[i] = zValue;
472
+ return;
473
+ }
474
+ }
475
+ assert( i==p->nParam );
476
+ if( i>=p->nAlloc ){
477
+ p->nAlloc = p->nAlloc*2 + 10;
478
+ p->azName = fossil_realloc(p->azName, sizeof(p->azName[0])*p->nAlloc);
479
+ p->azValue = fossil_realloc(p->azValue, sizeof(p->azValue[0])*p->nAlloc);
480
+ }
481
+ p->azName[i] = zName;
482
+ p->azValue[i] = zValue;
469483
p->nParam++;
470484
}
471485
472486
/*
473487
** Render the URL with a parameter override.
488
+**
489
+** Returned memory is transient and is overwritten on the next call to this
490
+** routine for the same HQuery, or until the HQuery object is destroyed.
474491
*/
475492
char *url_render(
476493
HQuery *p, /* Base URL */
477494
const char *zName1, /* First override */
478495
const char *zValue1, /* First override value */
479496
--- src/url.c
+++ src/url.c
@@ -432,47 +432,64 @@
432 ** An instance of this object is used to build a URL with query parameters.
433 */
434 struct HQuery {
435 Blob url; /* The URL */
436 const char *zBase; /* The base URL */
437 int nParam; /* Number of parameters. Max 10 */
438 const char *azName[15]; /* Parameter names */
439 const char *azValue[15]; /* Parameter values */
 
440 };
441 #endif
442
443 /*
444 ** Initialize the URL object.
445 */
446 void url_initialize(HQuery *p, const char *zBase){
 
447 blob_zero(&p->url);
448 p->zBase = zBase;
449 p->nParam = 0;
450 }
451
452 /*
453 ** Resets the given URL object, deallocating any memory
454 ** it uses.
455 */
456 void url_reset(HQuery *p){
457 blob_reset(&p->url);
 
 
458 url_initialize(p, p->zBase);
459 }
460
461 /*
462 ** Add a fixed parameter to an HQuery.
463 */
464 void url_add_parameter(HQuery *p, const char *zName, const char *zValue){
465 assert( p->nParam < count(p->azName) );
466 assert( p->nParam < count(p->azValue) );
467 p->azName[p->nParam] = zName;
468 p->azValue[p->nParam] = zValue;
 
 
 
 
 
 
 
 
 
 
 
469 p->nParam++;
470 }
471
472 /*
473 ** Render the URL with a parameter override.
 
 
 
474 */
475 char *url_render(
476 HQuery *p, /* Base URL */
477 const char *zName1, /* First override */
478 const char *zValue1, /* First override value */
479
--- src/url.c
+++ src/url.c
@@ -432,47 +432,64 @@
432 ** An instance of this object is used to build a URL with query parameters.
433 */
434 struct HQuery {
435 Blob url; /* The URL */
436 const char *zBase; /* The base URL */
437 int nParam; /* Number of parameters. */
438 int nAlloc; /* Number of allocated slots */
439 const char **azName; /* Parameter names */
440 const char **azValue; /* Parameter values */
441 };
442 #endif
443
444 /*
445 ** Initialize the URL object.
446 */
447 void url_initialize(HQuery *p, const char *zBase){
448 memset(p, 0, sizeof(*p));
449 blob_zero(&p->url);
450 p->zBase = zBase;
 
451 }
452
453 /*
454 ** Resets the given URL object, deallocating any memory
455 ** it uses.
456 */
457 void url_reset(HQuery *p){
458 blob_reset(&p->url);
459 fossil_free(p->azName);
460 fossil_free(p->azValue);
461 url_initialize(p, p->zBase);
462 }
463
464 /*
465 ** Add a fixed parameter to an HQuery.
466 */
467 void url_add_parameter(HQuery *p, const char *zName, const char *zValue){
468 int i;
469 for(i=0; i<p->nParam; i++){
470 if( fossil_strcmp(p->azName[i],zName)==0 ){
471 p->azValue[i] = zValue;
472 return;
473 }
474 }
475 assert( i==p->nParam );
476 if( i>=p->nAlloc ){
477 p->nAlloc = p->nAlloc*2 + 10;
478 p->azName = fossil_realloc(p->azName, sizeof(p->azName[0])*p->nAlloc);
479 p->azValue = fossil_realloc(p->azValue, sizeof(p->azValue[0])*p->nAlloc);
480 }
481 p->azName[i] = zName;
482 p->azValue[i] = zValue;
483 p->nParam++;
484 }
485
486 /*
487 ** Render the URL with a parameter override.
488 **
489 ** Returned memory is transient and is overwritten on the next call to this
490 ** routine for the same HQuery, or until the HQuery object is destroyed.
491 */
492 char *url_render(
493 HQuery *p, /* Base URL */
494 const char *zName1, /* First override */
495 const char *zValue1, /* First override value */
496
+1 -1
--- src/wiki.c
+++ src/wiki.c
@@ -291,11 +291,11 @@
291291
*/
292292
void wiki_srchpage(void){
293293
login_check_credentials();
294294
style_header("Wiki Search");
295295
wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX);
296
- search_screen(SRCH_WIKI, "wikisrch");
296
+ search_screen(SRCH_WIKI, 0);
297297
style_footer();
298298
}
299299
300300
/*
301301
** WEBPAGE: wiki
302302
--- src/wiki.c
+++ src/wiki.c
@@ -291,11 +291,11 @@
291 */
292 void wiki_srchpage(void){
293 login_check_credentials();
294 style_header("Wiki Search");
295 wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX);
296 search_screen(SRCH_WIKI, "wikisrch");
297 style_footer();
298 }
299
300 /*
301 ** WEBPAGE: wiki
302
--- src/wiki.c
+++ src/wiki.c
@@ -291,11 +291,11 @@
291 */
292 void wiki_srchpage(void){
293 login_check_credentials();
294 style_header("Wiki Search");
295 wiki_standard_submenu(W_HELP|W_LIST|W_SANDBOX);
296 search_screen(SRCH_WIKI, 0);
297 style_footer();
298 }
299
300 /*
301 ** WEBPAGE: wiki
302

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

Binary file

Binary file

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

Binary file

No diff available

Binary file

Binary file

Binary file

Binary file

No diff available

No diff available

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

Binary file

Binary file

No diff available

No diff available

No diff available

No diff available

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

No diff available

No diff available

No diff available

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

Binary file

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

Binary file

No diff available

Binary file

Binary file

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

+1 -1
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -96,11 +96,11 @@
9696
<li> <a href='faq.wiki'>FAQ</a>
9797
<li> <a href='build.wiki'>Compiling and installing Fossil</a>
9898
<li> <a href='COPYRIGHT-BSD2.txt'>License</a>
9999
<li> <a href='http://www.fossil-scm.org/schimpf-book/home'>Jim Schimpf's
100100
book</a>
101
-<li> <a href='../../help'>Command-line help</a>
101
+<li> <a href='../../../help'>Command-line help</a>
102102
</ul>
103103
<a name="pindex"></a>
104104
<h2>Permuted Index:</h2>
105105
<ul>}
106106
foreach entry $permindex {
107107
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -96,11 +96,11 @@
96 <li> <a href='faq.wiki'>FAQ</a>
97 <li> <a href='build.wiki'>Compiling and installing Fossil</a>
98 <li> <a href='COPYRIGHT-BSD2.txt'>License</a>
99 <li> <a href='http://www.fossil-scm.org/schimpf-book/home'>Jim Schimpf's
100 book</a>
101 <li> <a href='../../help'>Command-line help</a>
102 </ul>
103 <a name="pindex"></a>
104 <h2>Permuted Index:</h2>
105 <ul>}
106 foreach entry $permindex {
107
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -96,11 +96,11 @@
96 <li> <a href='faq.wiki'>FAQ</a>
97 <li> <a href='build.wiki'>Compiling and installing Fossil</a>
98 <li> <a href='COPYRIGHT-BSD2.txt'>License</a>
99 <li> <a href='http://www.fossil-scm.org/schimpf-book/home'>Jim Schimpf's
100 book</a>
101 <li> <a href='../../../help'>Command-line help</a>
102 </ul>
103 <a name="pindex"></a>
104 <h2>Permuted Index:</h2>
105 <ul>}
106 foreach entry $permindex {
107

No diff available

No diff available

--- www/permutedindex.html
+++ www/permutedindex.html
@@ -12,11 +12,11 @@
1212
<li> <a href='faq.wiki'>FAQ</a>
1313
<li> <a href='build.wiki'>Compiling and installing Fossil</a>
1414
<li> <a href='COPYRIGHT-BSD2.txt'>License</a>
1515
<li> <a href='http://www.fossil-scm.org/schimpf-book/home'>Jim Schimpf's
1616
book</a>
17
-<li> <a href='../../help'>Command-line help</a>
17
+<li> <a href='../../../help'>Command-line help</a>
1818
</ul>
1919
<a name="pindex"></a>
2020
<h2>Permuted Index:</h2>
2121
<ul>
2222
<li><a href="fiveminutes.wiki">5 Minutes as a Single User &mdash; Update and Running in</a></li>
2323
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -12,11 +12,11 @@
12 <li> <a href='faq.wiki'>FAQ</a>
13 <li> <a href='build.wiki'>Compiling and installing Fossil</a>
14 <li> <a href='COPYRIGHT-BSD2.txt'>License</a>
15 <li> <a href='http://www.fossil-scm.org/schimpf-book/home'>Jim Schimpf's
16 book</a>
17 <li> <a href='../../help'>Command-line help</a>
18 </ul>
19 <a name="pindex"></a>
20 <h2>Permuted Index:</h2>
21 <ul>
22 <li><a href="fiveminutes.wiki">5 Minutes as a Single User &mdash; Update and Running in</a></li>
23
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -12,11 +12,11 @@
12 <li> <a href='faq.wiki'>FAQ</a>
13 <li> <a href='build.wiki'>Compiling and installing Fossil</a>
14 <li> <a href='COPYRIGHT-BSD2.txt'>License</a>
15 <li> <a href='http://www.fossil-scm.org/schimpf-book/home'>Jim Schimpf's
16 book</a>
17 <li> <a href='../../../help'>Command-line help</a>
18 </ul>
19 <a name="pindex"></a>
20 <h2>Permuted Index:</h2>
21 <ul>
22 <li><a href="fiveminutes.wiki">5 Minutes as a Single User &mdash; Update and Running in</a></li>
23

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

No diff available

Keyboard Shortcuts

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