Fossil SCM

merge [trunk]

bch 2020-04-09 20:16 NULLSeparated merge
Commit 0b63227882a8342c415c5292f25fae748d52c6facb1fe9997a1dbe50bc542554
--- a/src/accordion.js
+++ b/src/accordion.js
@@ -0,0 +1,27 @@
1
+/* Attach appropriate javascript to each ".accordion" button so that
2
+** it expands and contracts when clicked.
3
+**ntracts when clicked.
4
+**
5
+** The uncompressed source code for the SV
6
+** wiki page "branch/accordion-experiments" window to a smaller
7
+** width, causing vertical growth.)
8
+**
9
+** Ano"+"/"+"ttach appropriate javascript to each ".accordion" button so that
10
+** it expands and contracts when clicked.
11
+**ntracts when clicked.
12
+**
13
+** The uncompressed source code for the SV
14
+** wiki page "branch/accordion-experiments" window to a smaller
15
+** width, causing vertical growth.)
16
+**
17
+** Another problem is that `scrollHeight' used to calculate the expanded height
18
+** while still in the contracted state may return values with small errors on
19
+** some browsers, especially for large elements, presumably due to omitting the
20
+** space required by the vertical scrollbar that may become necessary, causing
21
+** additional horizontal shrinking and consequently more vertical growth than
22
+** calculated. That's why se/* Attach appropriate javascript to each ".accordion" button so that
23
+** it expands and contracts when clicked.
24
+**ntracts when clicked.
25
+**
26
+** The uncompressed source code for the SV
27
+** wiki page "branch/accordion-experiments" window to a smvar p = a[i].nextElementSibli
--- a/src/accordion.js
+++ b/src/accordion.js
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/accordion.js
+++ b/src/accordion.js
@@ -0,0 +1,27 @@
1 /* Attach appropriate javascript to each ".accordion" button so that
2 ** it expands and contracts when clicked.
3 **ntracts when clicked.
4 **
5 ** The uncompressed source code for the SV
6 ** wiki page "branch/accordion-experiments" window to a smaller
7 ** width, causing vertical growth.)
8 **
9 ** Ano"+"/"+"ttach appropriate javascript to each ".accordion" button so that
10 ** it expands and contracts when clicked.
11 **ntracts when clicked.
12 **
13 ** The uncompressed source code for the SV
14 ** wiki page "branch/accordion-experiments" window to a smaller
15 ** width, causing vertical growth.)
16 **
17 ** Another problem is that `scrollHeight' used to calculate the expanded height
18 ** while still in the contracted state may return values with small errors on
19 ** some browsers, especially for large elements, presumably due to omitting the
20 ** space required by the vertical scrollbar that may become necessary, causing
21 ** additional horizontal shrinking and consequently more vertical growth than
22 ** calculated. That's why se/* Attach appropriate javascript to each ".accordion" button so that
23 ** it expands and contracts when clicked.
24 **ntracts when clicked.
25 **
26 ** The uncompressed source code for the SV
27 ** wiki page "branch/accordion-experiments" window to a smvar p = a[i].nextElementSibli
+1 -1
--- src/attach.c
+++ src/attach.c
@@ -545,11 +545,11 @@
545545
cgi_redirectf("%R/wiki?name=%t", zWikiName);
546546
}
547547
return;
548548
}
549549
if( strcmp(zModAction,"approve")==0 ){
550
- moderation_approve(rid);
550
+ moderation_approve('a', rid);
551551
}
552552
}
553553
style_header("Attachment Details");
554554
style_submenu_element("Raw", "%R/artifact/%s", zUuid);
555555
if(fShowContent){
556556
--- src/attach.c
+++ src/attach.c
@@ -545,11 +545,11 @@
545 cgi_redirectf("%R/wiki?name=%t", zWikiName);
546 }
547 return;
548 }
549 if( strcmp(zModAction,"approve")==0 ){
550 moderation_approve(rid);
551 }
552 }
553 style_header("Attachment Details");
554 style_submenu_element("Raw", "%R/artifact/%s", zUuid);
555 if(fShowContent){
556
--- src/attach.c
+++ src/attach.c
@@ -545,11 +545,11 @@
545 cgi_redirectf("%R/wiki?name=%t", zWikiName);
546 }
547 return;
548 }
549 if( strcmp(zModAction,"approve")==0 ){
550 moderation_approve('a', rid);
551 }
552 }
553 style_header("Attachment Details");
554 style_submenu_element("Raw", "%R/artifact/%s", zUuid);
555 if(fShowContent){
556
--- src/default_css.txt
+++ src/default_css.txt
@@ -745,10 +745,12 @@
745745
}
746746
div.forumTimeline {
747747
border: 1px solid black;
748748
padding-left: 1ex;
749749
padding-right: 1ex;
750
+ max-width: 50em;
751
+ overflow: auto;
750752
}
751753
div.forumTimeline code {
752754
white-space: pre-wrap;
753755
}
754756
div.markdown code {
@@ -757,10 +759,14 @@
757759
div.forumHier, div.forumTime {
758760
border: 1px solid black;
759761
padding-left: 1ex;
760762
padding-right: 1ex;
761763
margin-top: 1ex;
764
+}
765
+div.forumPostBody {
766
+ max-height: 40em;
767
+ overflow: auto;
762768
}
763769
div.forumSel {
764770
background-color: #cef;
765771
}
766772
div.forumObs {
@@ -810,5 +816,30 @@
810816
margin-right: 0;
811817
}
812818
.nobr {
813819
white-space: nowrap;
814820
}
821
+.accordion {
822
+ cursor: pointer;
823
+}
824
+.accordion_btn {
825
+ display: inline-block;
826
+ width: 16px;
827
+ height: 16px;
828
+ margin-right: .5em;
829
+ vertical-align: middle;
830
+}
831
+// Note: the order of the next 3 entries should be
832
+// maintained for the hierarchical cascade to work.
833
+.accordion > .accordion_btn_plus {
834
+ display: none;
835
+}
836
+.accordion_closed > .accordion_btn_minus {
837
+ display: none;
838
+}
839
+.accordion_closed > .accordion_btn_plus {
840
+ display: inline-block;
841
+}
842
+.accordion_panel {
843
+ overflow: hidden;
844
+ transition: max-height 0.25s ease-out;
845
+}
815846
--- src/default_css.txt
+++ src/default_css.txt
@@ -745,10 +745,12 @@
745 }
746 div.forumTimeline {
747 border: 1px solid black;
748 padding-left: 1ex;
749 padding-right: 1ex;
 
 
750 }
751 div.forumTimeline code {
752 white-space: pre-wrap;
753 }
754 div.markdown code {
@@ -757,10 +759,14 @@
757 div.forumHier, div.forumTime {
758 border: 1px solid black;
759 padding-left: 1ex;
760 padding-right: 1ex;
761 margin-top: 1ex;
 
 
 
 
762 }
763 div.forumSel {
764 background-color: #cef;
765 }
766 div.forumObs {
@@ -810,5 +816,30 @@
810 margin-right: 0;
811 }
812 .nobr {
813 white-space: nowrap;
814 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
--- src/default_css.txt
+++ src/default_css.txt
@@ -745,10 +745,12 @@
745 }
746 div.forumTimeline {
747 border: 1px solid black;
748 padding-left: 1ex;
749 padding-right: 1ex;
750 max-width: 50em;
751 overflow: auto;
752 }
753 div.forumTimeline code {
754 white-space: pre-wrap;
755 }
756 div.markdown code {
@@ -757,10 +759,14 @@
759 div.forumHier, div.forumTime {
760 border: 1px solid black;
761 padding-left: 1ex;
762 padding-right: 1ex;
763 margin-top: 1ex;
764 }
765 div.forumPostBody {
766 max-height: 40em;
767 overflow: auto;
768 }
769 div.forumSel {
770 background-color: #cef;
771 }
772 div.forumObs {
@@ -810,5 +816,30 @@
816 margin-right: 0;
817 }
818 .nobr {
819 white-space: nowrap;
820 }
821 .accordion {
822 cursor: pointer;
823 }
824 .accordion_btn {
825 display: inline-block;
826 width: 16px;
827 height: 16px;
828 margin-right: .5em;
829 vertical-align: middle;
830 }
831 // Note: the order of the next 3 entries should be
832 // maintained for the hierarchical cascade to work.
833 .accordion > .accordion_btn_plus {
834 display: none;
835 }
836 .accordion_closed > .accordion_btn_minus {
837 display: none;
838 }
839 .accordion_closed > .accordion_btn_plus {
840 display: inline-block;
841 }
842 .accordion_panel {
843 overflow: hidden;
844 transition: max-height 0.25s ease-out;
845 }
846
+2 -1
--- src/file.c
+++ src/file.c
@@ -1126,10 +1126,11 @@
11261126
memset(&testFileStat, 0, sizeof(struct fossilStat));
11271127
rc = fossil_stat(zPath, &testFileStat, 0);
11281128
fossil_print(" stat_rc = %d\n", rc);
11291129
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_size);
11301130
fossil_print(" stat_size = %s\n", zBuf);
1131
+ if( g.db==0 ) sqlite3_open(":memory:", &g.db);
11311132
z = db_text(0, "SELECT datetime(%lld, 'unixepoch')", testFileStat.st_mtime);
11321133
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld (%s)", testFileStat.st_mtime, z);
11331134
fossil_free(z);
11341135
fossil_print(" stat_mtime = %s\n", zBuf);
11351136
fossil_print(" stat_mode = 0%o\n", testFileStat.st_mode);
@@ -1192,11 +1193,11 @@
11921193
int resetFlag = find_option("reset",0,0)!=0;
11931194
const char *zAllow = find_option("allow-symlinks",0,1);
11941195
if( find_option("open-config", 0, 0)!=0 ){
11951196
Th_OpenConfig(1);
11961197
}
1197
- db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1198
+ db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
11981199
fossil_print("filenames_are_case_sensitive() = %d\n",
11991200
filenames_are_case_sensitive());
12001201
fossil_print("db_allow_symlinks_by_default() = %d\n",
12011202
db_allow_symlinks_by_default());
12021203
if( zAllow ){
12031204
--- src/file.c
+++ src/file.c
@@ -1126,10 +1126,11 @@
1126 memset(&testFileStat, 0, sizeof(struct fossilStat));
1127 rc = fossil_stat(zPath, &testFileStat, 0);
1128 fossil_print(" stat_rc = %d\n", rc);
1129 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_size);
1130 fossil_print(" stat_size = %s\n", zBuf);
 
1131 z = db_text(0, "SELECT datetime(%lld, 'unixepoch')", testFileStat.st_mtime);
1132 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld (%s)", testFileStat.st_mtime, z);
1133 fossil_free(z);
1134 fossil_print(" stat_mtime = %s\n", zBuf);
1135 fossil_print(" stat_mode = 0%o\n", testFileStat.st_mode);
@@ -1192,11 +1193,11 @@
1192 int resetFlag = find_option("reset",0,0)!=0;
1193 const char *zAllow = find_option("allow-symlinks",0,1);
1194 if( find_option("open-config", 0, 0)!=0 ){
1195 Th_OpenConfig(1);
1196 }
1197 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1198 fossil_print("filenames_are_case_sensitive() = %d\n",
1199 filenames_are_case_sensitive());
1200 fossil_print("db_allow_symlinks_by_default() = %d\n",
1201 db_allow_symlinks_by_default());
1202 if( zAllow ){
1203
--- src/file.c
+++ src/file.c
@@ -1126,10 +1126,11 @@
1126 memset(&testFileStat, 0, sizeof(struct fossilStat));
1127 rc = fossil_stat(zPath, &testFileStat, 0);
1128 fossil_print(" stat_rc = %d\n", rc);
1129 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_size);
1130 fossil_print(" stat_size = %s\n", zBuf);
1131 if( g.db==0 ) sqlite3_open(":memory:", &g.db);
1132 z = db_text(0, "SELECT datetime(%lld, 'unixepoch')", testFileStat.st_mtime);
1133 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld (%s)", testFileStat.st_mtime, z);
1134 fossil_free(z);
1135 fossil_print(" stat_mtime = %s\n", zBuf);
1136 fossil_print(" stat_mode = 0%o\n", testFileStat.st_mode);
@@ -1192,11 +1193,11 @@
1193 int resetFlag = find_option("reset",0,0)!=0;
1194 const char *zAllow = find_option("allow-symlinks",0,1);
1195 if( find_option("open-config", 0, 0)!=0 ){
1196 Th_OpenConfig(1);
1197 }
1198 db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
1199 fossil_print("filenames_are_case_sensitive() = %d\n",
1200 filenames_are_case_sensitive());
1201 fossil_print("db_allow_symlinks_by_default() = %d\n",
1202 db_allow_symlinks_by_default());
1203 if( zAllow ){
1204
+22 -16
--- src/forum.c
+++ src/forum.c
@@ -309,11 +309,12 @@
309309
*/
310310
void forum_render(
311311
const char *zTitle, /* The title. Might be NULL for no title */
312312
const char *zMimetype, /* Mimetype of the message */
313313
const char *zContent, /* Content of the message */
314
- const char *zClass /* Put in a <div> if not NULL */
314
+ const char *zClass, /* Put in a <div> if not NULL */
315
+ int bScroll /* Large message content scrolls if true */
315316
){
316317
if( zClass ){
317318
@ <div class='%s(zClass)'>
318319
}
319320
if( zTitle ){
@@ -323,14 +324,20 @@
323324
@ <h1><i>Deleted</i></h1>
324325
}
325326
}
326327
if( zContent && zContent[0] ){
327328
Blob x;
329
+ if( bScroll ){
330
+ @ <div class='forumPostBody'>
331
+ }else{
332
+ @ <div class='forumPostFullBody'>
333
+ }
328334
blob_init(&x, 0, 0);
329335
blob_append(&x, zContent, -1);
330336
wiki_render_by_mimetype(&x, zMimetype);
331337
blob_reset(&x);
338
+ @ </div>
332339
}else{
333340
@ <i>Deleted</i>
334341
}
335342
if( zClass ){
336343
@ </div>
@@ -444,20 +451,21 @@
444451
zUuid = p->pLeaf->zUuid;
445452
}
446453
if( p->fpid!=target ){
447454
@ %z(href("%R/forumpost/%S?t=%c",zUuid,cMode))[link]</a>
448455
}
449
- if( !bRawMode && fossil_strcmp(pPost->zMimetype,"text/plain")!=0 ){
456
+ if( !bRawMode ){
450457
@ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
451458
}
452459
isPrivate = content_is_private(p->fpid);
453460
sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
454461
@ </h3>
455462
if( isPrivate && !g.perm.ModForum && !sameUser ){
456463
@ <p><span class="modpending">Awaiting Moderator Approval</span></p>
457464
}else{
458
- forum_render(0, bRawMode?"text/plain":pPost->zMimetype, pPost->zWiki, 0);
465
+ forum_render(0, bRawMode?"text/plain":pPost->zMimetype, pPost->zWiki,
466
+ 0, 1);
459467
}
460468
if( g.perm.WrForum && p->pLeaf==0 ){
461469
int sameUser = login_is_individual()
462470
&& fossil_strcmp(pPost->zUser, g.zLogin)==0;
463471
@ <p><form action="%R/forumedit" method="POST">
@@ -565,13 +573,11 @@
565573
manifest_destroy(pOPost);
566574
}
567575
if( fpid!=target ){
568576
@ %z(href("%R/forumpost/%S",zUuid))[link]</a>
569577
}
570
- if( fossil_strcmp(pPost->zMimetype,"text/plain")!=0 ){
571
- @ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
572
- }
578
+ @ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
573579
if( p->firt ){
574580
ForumEntry *pIrt = p->pPrev;
575581
while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev;
576582
if( pIrt ){
577583
@ in reply to %z(href("%R/forumpost/%S?t=h",pIrt->zUuid))\
@@ -582,11 +588,11 @@
582588
isPrivate = content_is_private(fpid);
583589
sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
584590
if( isPrivate && !g.perm.ModForum && !sameUser ){
585591
@ <p><span class="modpending">Awaiting Moderator Approval</span></p>
586592
}else{
587
- forum_render(0, pPost->zMimetype, pPost->zWiki, 0);
593
+ forum_render(0, pPost->zMimetype, pPost->zWiki, 0, 1);
588594
}
589595
if( g.perm.WrForum ){
590596
@ <p><form action="%R/forumedit" method="POST">
591597
@ <input type="hidden" name="fpid" value="%s(zUuid)">
592598
if( !isPrivate ){
@@ -717,11 +723,11 @@
717723
int notAnon = login_is_individual();
718724
int sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
719725
if( isPrivate && !g.perm.ModForum && !sameUser ){
720726
@ <p><span class="modpending">Awaiting Moderator Approval</span></p>
721727
}else{
722
- forum_render(0, "text/plain", pPost->zWiki, 0);
728
+ forum_render(0, "text/plain", pPost->zWiki, 0, 0);
723729
}
724730
manifest_destroy(pPost);
725731
}
726732
}else if( zMode[0]=='c' ){
727733
style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
@@ -949,11 +955,11 @@
949955
if( P("submit") ){
950956
if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
951957
}
952958
if( P("preview") ){
953959
@ <h1>Preview:</h1>
954
- forum_render(zTitle, zMimetype, zContent, "forumEdit");
960
+ forum_render(zTitle, zMimetype, zContent, "forumEdit", 1);
955961
}
956962
style_header("New Forum Thread");
957963
@ <form action="%R/forume1" method="POST">
958964
@ <h1>New Thread:</h1>
959965
forum_from_line();
@@ -1018,11 +1024,11 @@
10181024
}
10191025
isCsrfSafe = cgi_csrf_safe(1);
10201026
if( g.perm.ModForum && isCsrfSafe ){
10211027
if( P("approve") ){
10221028
const char *zUserToTrust;
1023
- moderation_approve(fpid);
1029
+ moderation_approve('f', fpid);
10241030
if( g.perm.AdminForum
10251031
&& PB("trust")
10261032
&& (zUserToTrust = P("trustuser"))!=0
10271033
){
10281034
db_multi_exec("UPDATE user SET cap=cap||'4' "
@@ -1067,13 +1073,13 @@
10671073
zContent = "";
10681074
if( pPost->zThreadTitle ) zTitle = "";
10691075
style_header("Delete %s", zTitle ? "Post" : "Reply");
10701076
@ <h1>Original Post:</h1>
10711077
forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
1072
- "forumEdit");
1078
+ "forumEdit", 1);
10731079
@ <h1>Change Into:</h1>
1074
- forum_render(zTitle, zMimetype, zContent,"forumEdit");
1080
+ forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
10751081
@ <form action="%R/forume2" method="POST">
10761082
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
10771083
@ <input type="hidden" name="nullout" value="1">
10781084
@ <input type="hidden" name="mimetype" value="%h(zMimetype)">
10791085
@ <input type="hidden" name="content" value="%h(zContent)">
@@ -1091,14 +1097,14 @@
10911097
zTitle = fossil_strdup(pPost->zThreadTitle);
10921098
}
10931099
style_header("Edit %s", zTitle ? "Post" : "Reply");
10941100
@ <h2>Original Post:</h2>
10951101
forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
1096
- "forumEdit");
1102
+ "forumEdit", 1);
10971103
if( P("preview") ){
10981104
@ <h2>Preview of Edited Post:</h2>
1099
- forum_render(zTitle, zMimetype, zContent,"forumEdit");
1105
+ forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
11001106
}
11011107
@ <h2>Revised Message:</h2>
11021108
@ <form action="%R/forume2" method="POST">
11031109
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
11041110
@ <input type="hidden" name="edit" value="1">
@@ -1117,14 +1123,14 @@
11171123
zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
11181124
zDisplayName = display_name_from_login(pPost->zUser);
11191125
@ <h3 class='forumPostHdr'>By %h(zDisplayName) on %h(zDate)</h3>
11201126
fossil_free(zDisplayName);
11211127
fossil_free(zDate);
1122
- forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit");
1128
+ forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit", 1);
11231129
if( P("preview") ){
11241130
@ <h2>Preview:</h2>
1125
- forum_render(0, zMimetype,zContent, "forumEdit");
1131
+ forum_render(0, zMimetype,zContent, "forumEdit", 1);
11261132
}
11271133
@ <h2>Enter Reply:</h2>
11281134
@ <form action="%R/forume2" method="POST">
11291135
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
11301136
@ <input type="hidden" name="reply" value="1">
11311137
--- src/forum.c
+++ src/forum.c
@@ -309,11 +309,12 @@
309 */
310 void forum_render(
311 const char *zTitle, /* The title. Might be NULL for no title */
312 const char *zMimetype, /* Mimetype of the message */
313 const char *zContent, /* Content of the message */
314 const char *zClass /* Put in a <div> if not NULL */
 
315 ){
316 if( zClass ){
317 @ <div class='%s(zClass)'>
318 }
319 if( zTitle ){
@@ -323,14 +324,20 @@
323 @ <h1><i>Deleted</i></h1>
324 }
325 }
326 if( zContent && zContent[0] ){
327 Blob x;
 
 
 
 
 
328 blob_init(&x, 0, 0);
329 blob_append(&x, zContent, -1);
330 wiki_render_by_mimetype(&x, zMimetype);
331 blob_reset(&x);
 
332 }else{
333 @ <i>Deleted</i>
334 }
335 if( zClass ){
336 @ </div>
@@ -444,20 +451,21 @@
444 zUuid = p->pLeaf->zUuid;
445 }
446 if( p->fpid!=target ){
447 @ %z(href("%R/forumpost/%S?t=%c",zUuid,cMode))[link]</a>
448 }
449 if( !bRawMode && fossil_strcmp(pPost->zMimetype,"text/plain")!=0 ){
450 @ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
451 }
452 isPrivate = content_is_private(p->fpid);
453 sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
454 @ </h3>
455 if( isPrivate && !g.perm.ModForum && !sameUser ){
456 @ <p><span class="modpending">Awaiting Moderator Approval</span></p>
457 }else{
458 forum_render(0, bRawMode?"text/plain":pPost->zMimetype, pPost->zWiki, 0);
 
459 }
460 if( g.perm.WrForum && p->pLeaf==0 ){
461 int sameUser = login_is_individual()
462 && fossil_strcmp(pPost->zUser, g.zLogin)==0;
463 @ <p><form action="%R/forumedit" method="POST">
@@ -565,13 +573,11 @@
565 manifest_destroy(pOPost);
566 }
567 if( fpid!=target ){
568 @ %z(href("%R/forumpost/%S",zUuid))[link]</a>
569 }
570 if( fossil_strcmp(pPost->zMimetype,"text/plain")!=0 ){
571 @ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
572 }
573 if( p->firt ){
574 ForumEntry *pIrt = p->pPrev;
575 while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev;
576 if( pIrt ){
577 @ in reply to %z(href("%R/forumpost/%S?t=h",pIrt->zUuid))\
@@ -582,11 +588,11 @@
582 isPrivate = content_is_private(fpid);
583 sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
584 if( isPrivate && !g.perm.ModForum && !sameUser ){
585 @ <p><span class="modpending">Awaiting Moderator Approval</span></p>
586 }else{
587 forum_render(0, pPost->zMimetype, pPost->zWiki, 0);
588 }
589 if( g.perm.WrForum ){
590 @ <p><form action="%R/forumedit" method="POST">
591 @ <input type="hidden" name="fpid" value="%s(zUuid)">
592 if( !isPrivate ){
@@ -717,11 +723,11 @@
717 int notAnon = login_is_individual();
718 int sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
719 if( isPrivate && !g.perm.ModForum && !sameUser ){
720 @ <p><span class="modpending">Awaiting Moderator Approval</span></p>
721 }else{
722 forum_render(0, "text/plain", pPost->zWiki, 0);
723 }
724 manifest_destroy(pPost);
725 }
726 }else if( zMode[0]=='c' ){
727 style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
@@ -949,11 +955,11 @@
949 if( P("submit") ){
950 if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
951 }
952 if( P("preview") ){
953 @ <h1>Preview:</h1>
954 forum_render(zTitle, zMimetype, zContent, "forumEdit");
955 }
956 style_header("New Forum Thread");
957 @ <form action="%R/forume1" method="POST">
958 @ <h1>New Thread:</h1>
959 forum_from_line();
@@ -1018,11 +1024,11 @@
1018 }
1019 isCsrfSafe = cgi_csrf_safe(1);
1020 if( g.perm.ModForum && isCsrfSafe ){
1021 if( P("approve") ){
1022 const char *zUserToTrust;
1023 moderation_approve(fpid);
1024 if( g.perm.AdminForum
1025 && PB("trust")
1026 && (zUserToTrust = P("trustuser"))!=0
1027 ){
1028 db_multi_exec("UPDATE user SET cap=cap||'4' "
@@ -1067,13 +1073,13 @@
1067 zContent = "";
1068 if( pPost->zThreadTitle ) zTitle = "";
1069 style_header("Delete %s", zTitle ? "Post" : "Reply");
1070 @ <h1>Original Post:</h1>
1071 forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
1072 "forumEdit");
1073 @ <h1>Change Into:</h1>
1074 forum_render(zTitle, zMimetype, zContent,"forumEdit");
1075 @ <form action="%R/forume2" method="POST">
1076 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1077 @ <input type="hidden" name="nullout" value="1">
1078 @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
1079 @ <input type="hidden" name="content" value="%h(zContent)">
@@ -1091,14 +1097,14 @@
1091 zTitle = fossil_strdup(pPost->zThreadTitle);
1092 }
1093 style_header("Edit %s", zTitle ? "Post" : "Reply");
1094 @ <h2>Original Post:</h2>
1095 forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
1096 "forumEdit");
1097 if( P("preview") ){
1098 @ <h2>Preview of Edited Post:</h2>
1099 forum_render(zTitle, zMimetype, zContent,"forumEdit");
1100 }
1101 @ <h2>Revised Message:</h2>
1102 @ <form action="%R/forume2" method="POST">
1103 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1104 @ <input type="hidden" name="edit" value="1">
@@ -1117,14 +1123,14 @@
1117 zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
1118 zDisplayName = display_name_from_login(pPost->zUser);
1119 @ <h3 class='forumPostHdr'>By %h(zDisplayName) on %h(zDate)</h3>
1120 fossil_free(zDisplayName);
1121 fossil_free(zDate);
1122 forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit");
1123 if( P("preview") ){
1124 @ <h2>Preview:</h2>
1125 forum_render(0, zMimetype,zContent, "forumEdit");
1126 }
1127 @ <h2>Enter Reply:</h2>
1128 @ <form action="%R/forume2" method="POST">
1129 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1130 @ <input type="hidden" name="reply" value="1">
1131
--- src/forum.c
+++ src/forum.c
@@ -309,11 +309,12 @@
309 */
310 void forum_render(
311 const char *zTitle, /* The title. Might be NULL for no title */
312 const char *zMimetype, /* Mimetype of the message */
313 const char *zContent, /* Content of the message */
314 const char *zClass, /* Put in a <div> if not NULL */
315 int bScroll /* Large message content scrolls if true */
316 ){
317 if( zClass ){
318 @ <div class='%s(zClass)'>
319 }
320 if( zTitle ){
@@ -323,14 +324,20 @@
324 @ <h1><i>Deleted</i></h1>
325 }
326 }
327 if( zContent && zContent[0] ){
328 Blob x;
329 if( bScroll ){
330 @ <div class='forumPostBody'>
331 }else{
332 @ <div class='forumPostFullBody'>
333 }
334 blob_init(&x, 0, 0);
335 blob_append(&x, zContent, -1);
336 wiki_render_by_mimetype(&x, zMimetype);
337 blob_reset(&x);
338 @ </div>
339 }else{
340 @ <i>Deleted</i>
341 }
342 if( zClass ){
343 @ </div>
@@ -444,20 +451,21 @@
451 zUuid = p->pLeaf->zUuid;
452 }
453 if( p->fpid!=target ){
454 @ %z(href("%R/forumpost/%S?t=%c",zUuid,cMode))[link]</a>
455 }
456 if( !bRawMode ){
457 @ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
458 }
459 isPrivate = content_is_private(p->fpid);
460 sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
461 @ </h3>
462 if( isPrivate && !g.perm.ModForum && !sameUser ){
463 @ <p><span class="modpending">Awaiting Moderator Approval</span></p>
464 }else{
465 forum_render(0, bRawMode?"text/plain":pPost->zMimetype, pPost->zWiki,
466 0, 1);
467 }
468 if( g.perm.WrForum && p->pLeaf==0 ){
469 int sameUser = login_is_individual()
470 && fossil_strcmp(pPost->zUser, g.zLogin)==0;
471 @ <p><form action="%R/forumedit" method="POST">
@@ -565,13 +573,11 @@
573 manifest_destroy(pOPost);
574 }
575 if( fpid!=target ){
576 @ %z(href("%R/forumpost/%S",zUuid))[link]</a>
577 }
578 @ %z(href("%R/forumpost/%S?raw",zUuid))[source]</a>
 
 
579 if( p->firt ){
580 ForumEntry *pIrt = p->pPrev;
581 while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev;
582 if( pIrt ){
583 @ in reply to %z(href("%R/forumpost/%S?t=h",pIrt->zUuid))\
@@ -582,11 +588,11 @@
588 isPrivate = content_is_private(fpid);
589 sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
590 if( isPrivate && !g.perm.ModForum && !sameUser ){
591 @ <p><span class="modpending">Awaiting Moderator Approval</span></p>
592 }else{
593 forum_render(0, pPost->zMimetype, pPost->zWiki, 0, 1);
594 }
595 if( g.perm.WrForum ){
596 @ <p><form action="%R/forumedit" method="POST">
597 @ <input type="hidden" name="fpid" value="%s(zUuid)">
598 if( !isPrivate ){
@@ -717,11 +723,11 @@
723 int notAnon = login_is_individual();
724 int sameUser = notAnon && fossil_strcmp(pPost->zUser, g.zLogin)==0;
725 if( isPrivate && !g.perm.ModForum && !sameUser ){
726 @ <p><span class="modpending">Awaiting Moderator Approval</span></p>
727 }else{
728 forum_render(0, "text/plain", pPost->zWiki, 0, 0);
729 }
730 manifest_destroy(pPost);
731 }
732 }else if( zMode[0]=='c' ){
733 style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
@@ -949,11 +955,11 @@
955 if( P("submit") ){
956 if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
957 }
958 if( P("preview") ){
959 @ <h1>Preview:</h1>
960 forum_render(zTitle, zMimetype, zContent, "forumEdit", 1);
961 }
962 style_header("New Forum Thread");
963 @ <form action="%R/forume1" method="POST">
964 @ <h1>New Thread:</h1>
965 forum_from_line();
@@ -1018,11 +1024,11 @@
1024 }
1025 isCsrfSafe = cgi_csrf_safe(1);
1026 if( g.perm.ModForum && isCsrfSafe ){
1027 if( P("approve") ){
1028 const char *zUserToTrust;
1029 moderation_approve('f', fpid);
1030 if( g.perm.AdminForum
1031 && PB("trust")
1032 && (zUserToTrust = P("trustuser"))!=0
1033 ){
1034 db_multi_exec("UPDATE user SET cap=cap||'4' "
@@ -1067,13 +1073,13 @@
1073 zContent = "";
1074 if( pPost->zThreadTitle ) zTitle = "";
1075 style_header("Delete %s", zTitle ? "Post" : "Reply");
1076 @ <h1>Original Post:</h1>
1077 forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
1078 "forumEdit", 1);
1079 @ <h1>Change Into:</h1>
1080 forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
1081 @ <form action="%R/forume2" method="POST">
1082 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1083 @ <input type="hidden" name="nullout" value="1">
1084 @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
1085 @ <input type="hidden" name="content" value="%h(zContent)">
@@ -1091,14 +1097,14 @@
1097 zTitle = fossil_strdup(pPost->zThreadTitle);
1098 }
1099 style_header("Edit %s", zTitle ? "Post" : "Reply");
1100 @ <h2>Original Post:</h2>
1101 forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
1102 "forumEdit", 1);
1103 if( P("preview") ){
1104 @ <h2>Preview of Edited Post:</h2>
1105 forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
1106 }
1107 @ <h2>Revised Message:</h2>
1108 @ <form action="%R/forume2" method="POST">
1109 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1110 @ <input type="hidden" name="edit" value="1">
@@ -1117,14 +1123,14 @@
1123 zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
1124 zDisplayName = display_name_from_login(pPost->zUser);
1125 @ <h3 class='forumPostHdr'>By %h(zDisplayName) on %h(zDate)</h3>
1126 fossil_free(zDisplayName);
1127 fossil_free(zDate);
1128 forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit", 1);
1129 if( P("preview") ){
1130 @ <h2>Preview:</h2>
1131 forum_render(0, zMimetype,zContent, "forumEdit", 1);
1132 }
1133 @ <h2>Enter Reply:</h2>
1134 @ <form action="%R/forume2" method="POST">
1135 @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
1136 @ <input type="hidden" name="reply" value="1">
1137
+4 -1
--- src/fshell.c
+++ src/fshell.c
@@ -57,16 +57,18 @@
5757
int n, i;
5858
char **azArg = 0;
5959
int fDebug;
6060
pid_t childPid;
6161
char *zLine = 0;
62
+ char *zPrompt = 0;
6263
fDebug = find_option("debug", 0, 0)!=0;
6364
db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
65
+ zPrompt = mprintf("fossil (%z)> ", db_get("project-name","no repo"));
6466
db_close(0);
6567
sqlite3_shutdown();
6668
linenoiseSetMultiLine(1);
67
- while( (free(zLine), zLine = linenoise("fossil> ")) ){
69
+ while( (free(zLine), zLine = linenoise(zPrompt)) ){
6870
/* Remember shell history within the current session */
6971
linenoiseHistoryAdd(zLine);
7072
7173
/* Parse the line of input */
7274
n = (int)strlen(zLine);
@@ -117,7 +119,8 @@
117119
/* The parent process */
118120
int status;
119121
waitpid(childPid, &status, 0);
120122
}
121123
}
124
+ free(zPrompt);
122125
#endif
123126
}
124127
--- src/fshell.c
+++ src/fshell.c
@@ -57,16 +57,18 @@
57 int n, i;
58 char **azArg = 0;
59 int fDebug;
60 pid_t childPid;
61 char *zLine = 0;
 
62 fDebug = find_option("debug", 0, 0)!=0;
63 db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
 
64 db_close(0);
65 sqlite3_shutdown();
66 linenoiseSetMultiLine(1);
67 while( (free(zLine), zLine = linenoise("fossil> ")) ){
68 /* Remember shell history within the current session */
69 linenoiseHistoryAdd(zLine);
70
71 /* Parse the line of input */
72 n = (int)strlen(zLine);
@@ -117,7 +119,8 @@
117 /* The parent process */
118 int status;
119 waitpid(childPid, &status, 0);
120 }
121 }
 
122 #endif
123 }
124
--- src/fshell.c
+++ src/fshell.c
@@ -57,16 +57,18 @@
57 int n, i;
58 char **azArg = 0;
59 int fDebug;
60 pid_t childPid;
61 char *zLine = 0;
62 char *zPrompt = 0;
63 fDebug = find_option("debug", 0, 0)!=0;
64 db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0);
65 zPrompt = mprintf("fossil (%z)> ", db_get("project-name","no repo"));
66 db_close(0);
67 sqlite3_shutdown();
68 linenoiseSetMultiLine(1);
69 while( (free(zLine), zLine = linenoise(zPrompt)) ){
70 /* Remember shell history within the current session */
71 linenoiseHistoryAdd(zLine);
72
73 /* Parse the line of input */
74 n = (int)strlen(zLine);
@@ -117,7 +119,8 @@
119 /* The parent process */
120 int status;
121 waitpid(childPid, &status, 0);
122 }
123 }
124 free(zPrompt);
125 #endif
126 }
127
+2 -2
--- src/info.c
+++ src/info.c
@@ -1022,11 +1022,11 @@
10221022
cgi_redirectf("%R/modreq");
10231023
/*NOTREACHED*/
10241024
}
10251025
}
10261026
if( strcmp(zModAction,"approve")==0 ){
1027
- moderation_approve(rid);
1027
+ moderation_approve('w', rid);
10281028
}
10291029
}
10301030
style_header("Update of \"%h\"", pWiki->zWikiTitle);
10311031
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
10321032
zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
@@ -2423,11 +2423,11 @@
24232423
cgi_redirectf("%R/modreq");
24242424
/*NOTREACHED*/
24252425
}
24262426
}
24272427
if( strcmp(zModAction,"approve")==0 ){
2428
- moderation_approve(rid);
2428
+ moderation_approve('t', rid);
24292429
}
24302430
}
24312431
zTktTitle = db_table_has_column("repository", "ticket", "title" )
24322432
? db_text("(No title)",
24332433
"SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
24342434
--- src/info.c
+++ src/info.c
@@ -1022,11 +1022,11 @@
1022 cgi_redirectf("%R/modreq");
1023 /*NOTREACHED*/
1024 }
1025 }
1026 if( strcmp(zModAction,"approve")==0 ){
1027 moderation_approve(rid);
1028 }
1029 }
1030 style_header("Update of \"%h\"", pWiki->zWikiTitle);
1031 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1032 zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
@@ -2423,11 +2423,11 @@
2423 cgi_redirectf("%R/modreq");
2424 /*NOTREACHED*/
2425 }
2426 }
2427 if( strcmp(zModAction,"approve")==0 ){
2428 moderation_approve(rid);
2429 }
2430 }
2431 zTktTitle = db_table_has_column("repository", "ticket", "title" )
2432 ? db_text("(No title)",
2433 "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
2434
--- src/info.c
+++ src/info.c
@@ -1022,11 +1022,11 @@
1022 cgi_redirectf("%R/modreq");
1023 /*NOTREACHED*/
1024 }
1025 }
1026 if( strcmp(zModAction,"approve")==0 ){
1027 moderation_approve('w', rid);
1028 }
1029 }
1030 style_header("Update of \"%h\"", pWiki->zWikiTitle);
1031 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1032 zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
@@ -2423,11 +2423,11 @@
2423 cgi_redirectf("%R/modreq");
2424 /*NOTREACHED*/
2425 }
2426 }
2427 if( strcmp(zModAction,"approve")==0 ){
2428 moderation_approve('t', rid);
2429 }
2430 }
2431 zTktTitle = db_table_has_column("repository", "ticket", "title" )
2432 ? db_text("(No title)",
2433 "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
2434
--- src/main.mk
+++ src/main.mk
@@ -211,10 +211,11 @@
211211
$(SRCDIR)/../skins/rounded1/header.txt \
212212
$(SRCDIR)/../skins/xekri/css.txt \
213213
$(SRCDIR)/../skins/xekri/details.txt \
214214
$(SRCDIR)/../skins/xekri/footer.txt \
215215
$(SRCDIR)/../skins/xekri/header.txt \
216
+ $(SRCDIR)/accordion.js \
216217
$(SRCDIR)/ci_edit.js \
217218
$(SRCDIR)/copybtn.js \
218219
$(SRCDIR)/diff.tcl \
219220
$(SRCDIR)/forum.js \
220221
$(SRCDIR)/graph.js \
221222
--- src/main.mk
+++ src/main.mk
@@ -211,10 +211,11 @@
211 $(SRCDIR)/../skins/rounded1/header.txt \
212 $(SRCDIR)/../skins/xekri/css.txt \
213 $(SRCDIR)/../skins/xekri/details.txt \
214 $(SRCDIR)/../skins/xekri/footer.txt \
215 $(SRCDIR)/../skins/xekri/header.txt \
 
216 $(SRCDIR)/ci_edit.js \
217 $(SRCDIR)/copybtn.js \
218 $(SRCDIR)/diff.tcl \
219 $(SRCDIR)/forum.js \
220 $(SRCDIR)/graph.js \
221
--- src/main.mk
+++ src/main.mk
@@ -211,10 +211,11 @@
211 $(SRCDIR)/../skins/rounded1/header.txt \
212 $(SRCDIR)/../skins/xekri/css.txt \
213 $(SRCDIR)/../skins/xekri/details.txt \
214 $(SRCDIR)/../skins/xekri/footer.txt \
215 $(SRCDIR)/../skins/xekri/header.txt \
216 $(SRCDIR)/accordion.js \
217 $(SRCDIR)/ci_edit.js \
218 $(SRCDIR)/copybtn.js \
219 $(SRCDIR)/diff.tcl \
220 $(SRCDIR)/forum.js \
221 $(SRCDIR)/graph.js \
222
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -713,11 +713,11 @@
713713
#### The directories where the OpenSSL include and library files are located.
714714
# The recommended usage here is to use the Sysinternals junction tool
715715
# to create a hard link between an "openssl-1.x" sub-directory of the
716716
# Fossil source code directory and the target OpenSSL source directory.
717717
#
718
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1e
718
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1f
719719
OPENSSLINCDIR = $(OPENSSLDIR)/include
720720
OPENSSLLIBDIR = $(OPENSSLDIR)
721721
722722
#### Either the directory where the Tcl library is installed or the Tcl
723723
# source code directory resides (depending on the value of the macro
@@ -1570,11 +1570,11 @@
15701570
!ifndef USE_SEE
15711571
USE_SEE = 0
15721572
!endif
15731573
15741574
!if $(FOSSIL_ENABLE_SSL)!=0
1575
-SSLDIR = $(B)\compat\openssl-1.1.1e
1575
+SSLDIR = $(B)\compat\openssl-1.1.1f
15761576
SSLINCDIR = $(SSLDIR)\include
15771577
!if $(FOSSIL_DYNAMIC_BUILD)!=0
15781578
SSLLIBDIR = $(SSLDIR)
15791579
!else
15801580
SSLLIBDIR = $(SSLDIR)
15811581
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -713,11 +713,11 @@
713 #### The directories where the OpenSSL include and library files are located.
714 # The recommended usage here is to use the Sysinternals junction tool
715 # to create a hard link between an "openssl-1.x" sub-directory of the
716 # Fossil source code directory and the target OpenSSL source directory.
717 #
718 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1e
719 OPENSSLINCDIR = $(OPENSSLDIR)/include
720 OPENSSLLIBDIR = $(OPENSSLDIR)
721
722 #### Either the directory where the Tcl library is installed or the Tcl
723 # source code directory resides (depending on the value of the macro
@@ -1570,11 +1570,11 @@
1570 !ifndef USE_SEE
1571 USE_SEE = 0
1572 !endif
1573
1574 !if $(FOSSIL_ENABLE_SSL)!=0
1575 SSLDIR = $(B)\compat\openssl-1.1.1e
1576 SSLINCDIR = $(SSLDIR)\include
1577 !if $(FOSSIL_DYNAMIC_BUILD)!=0
1578 SSLLIBDIR = $(SSLDIR)
1579 !else
1580 SSLLIBDIR = $(SSLDIR)
1581
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -713,11 +713,11 @@
713 #### The directories where the OpenSSL include and library files are located.
714 # The recommended usage here is to use the Sysinternals junction tool
715 # to create a hard link between an "openssl-1.x" sub-directory of the
716 # Fossil source code directory and the target OpenSSL source directory.
717 #
718 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1f
719 OPENSSLINCDIR = $(OPENSSLDIR)/include
720 OPENSSLLIBDIR = $(OPENSSLDIR)
721
722 #### Either the directory where the Tcl library is installed or the Tcl
723 # source code directory resides (depending on the value of the macro
@@ -1570,11 +1570,11 @@
1570 !ifndef USE_SEE
1571 USE_SEE = 0
1572 !endif
1573
1574 !if $(FOSSIL_ENABLE_SSL)!=0
1575 SSLDIR = $(B)\compat\openssl-1.1.1f
1576 SSLINCDIR = $(SSLDIR)\include
1577 !if $(FOSSIL_DYNAMIC_BUILD)!=0
1578 SSLLIBDIR = $(SSLDIR)
1579 !else
1580 SSLLIBDIR = $(SSLDIR)
1581
+3 -1
--- src/manifest.c
+++ src/manifest.c
@@ -2059,19 +2059,20 @@
20592059
return c;
20602060
}
20612061
20622062
/*
20632063
** Scan artifact rid/pContent to see if it is a control artifact of
2064
-** any key:
2064
+** any type:
20652065
**
20662066
** * Manifest
20672067
** * Control
20682068
** * Wiki Page
20692069
** * Ticket Change
20702070
** * Cluster
20712071
** * Attachment
20722072
** * Event
2073
+** * Forum post
20732074
**
20742075
** If the input is a control artifact, then make appropriate entries
20752076
** in the auxiliary tables of the database in order to crosslink the
20762077
** artifact.
20772078
**
@@ -2558,10 +2559,11 @@
25582559
if( p->type==CFTYPE_FORUM ){
25592560
int froot, fprev, firt;
25602561
char *zFType;
25612562
char *zTitle;
25622563
schema_forum();
2564
+ search_doc_touch('f', rid, 0);
25632565
froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : rid;
25642566
fprev = p->nParent ? uuid_to_rid(p->azParent[0],1) : 0;
25652567
firt = p->zInReplyTo ? uuid_to_rid(p->zInReplyTo,1) : 0;
25662568
db_multi_exec(
25672569
"REPLACE INTO forumpost(fpid,froot,fprev,firt,fmtime)"
25682570
--- src/manifest.c
+++ src/manifest.c
@@ -2059,19 +2059,20 @@
2059 return c;
2060 }
2061
2062 /*
2063 ** Scan artifact rid/pContent to see if it is a control artifact of
2064 ** any key:
2065 **
2066 ** * Manifest
2067 ** * Control
2068 ** * Wiki Page
2069 ** * Ticket Change
2070 ** * Cluster
2071 ** * Attachment
2072 ** * Event
 
2073 **
2074 ** If the input is a control artifact, then make appropriate entries
2075 ** in the auxiliary tables of the database in order to crosslink the
2076 ** artifact.
2077 **
@@ -2558,10 +2559,11 @@
2558 if( p->type==CFTYPE_FORUM ){
2559 int froot, fprev, firt;
2560 char *zFType;
2561 char *zTitle;
2562 schema_forum();
 
2563 froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : rid;
2564 fprev = p->nParent ? uuid_to_rid(p->azParent[0],1) : 0;
2565 firt = p->zInReplyTo ? uuid_to_rid(p->zInReplyTo,1) : 0;
2566 db_multi_exec(
2567 "REPLACE INTO forumpost(fpid,froot,fprev,firt,fmtime)"
2568
--- src/manifest.c
+++ src/manifest.c
@@ -2059,19 +2059,20 @@
2059 return c;
2060 }
2061
2062 /*
2063 ** Scan artifact rid/pContent to see if it is a control artifact of
2064 ** any type:
2065 **
2066 ** * Manifest
2067 ** * Control
2068 ** * Wiki Page
2069 ** * Ticket Change
2070 ** * Cluster
2071 ** * Attachment
2072 ** * Event
2073 ** * Forum post
2074 **
2075 ** If the input is a control artifact, then make appropriate entries
2076 ** in the auxiliary tables of the database in order to crosslink the
2077 ** artifact.
2078 **
@@ -2558,10 +2559,11 @@
2559 if( p->type==CFTYPE_FORUM ){
2560 int froot, fprev, firt;
2561 char *zFType;
2562 char *zTitle;
2563 schema_forum();
2564 search_doc_touch('f', rid, 0);
2565 froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : rid;
2566 fprev = p->nParent ? uuid_to_rid(p->azParent[0],1) : 0;
2567 firt = p->zInReplyTo ? uuid_to_rid(p->zInReplyTo,1) : 0;
2568 db_multi_exec(
2569 "REPLACE INTO forumpost(fpid,froot,fprev,firt,fmtime)"
2570
+3 -2
--- src/moderate.c
+++ src/moderate.c
@@ -147,21 +147,22 @@
147147
}
148148
149149
/*
150150
** Approve an object held for moderation.
151151
*/
152
-void moderation_approve(int rid){
152
+void moderation_approve(char class, int rid){
153153
if( !moderation_pending(rid) ) return;
154154
db_begin_transaction();
155155
db_multi_exec(
156156
"DELETE FROM private WHERE rid=%d;"
157157
"INSERT OR IGNORE INTO unclustered VALUES(%d);"
158158
"INSERT OR IGNORE INTO unsent VALUES(%d);",
159159
rid, rid, rid
160160
);
161161
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
162
- admin_log("Approved moderation of rid %d.", rid);
162
+ admin_log("Approved moderation of rid %c-%d.", class, rid);
163
+ if( class!='a' ) search_doc_touch(class, rid, 0);
163164
db_end_transaction(0);
164165
}
165166
166167
/*
167168
** WEBPAGE: modreq
168169
--- src/moderate.c
+++ src/moderate.c
@@ -147,21 +147,22 @@
147 }
148
149 /*
150 ** Approve an object held for moderation.
151 */
152 void moderation_approve(int rid){
153 if( !moderation_pending(rid) ) return;
154 db_begin_transaction();
155 db_multi_exec(
156 "DELETE FROM private WHERE rid=%d;"
157 "INSERT OR IGNORE INTO unclustered VALUES(%d);"
158 "INSERT OR IGNORE INTO unsent VALUES(%d);",
159 rid, rid, rid
160 );
161 db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
162 admin_log("Approved moderation of rid %d.", rid);
 
163 db_end_transaction(0);
164 }
165
166 /*
167 ** WEBPAGE: modreq
168
--- src/moderate.c
+++ src/moderate.c
@@ -147,21 +147,22 @@
147 }
148
149 /*
150 ** Approve an object held for moderation.
151 */
152 void moderation_approve(char class, int rid){
153 if( !moderation_pending(rid) ) return;
154 db_begin_transaction();
155 db_multi_exec(
156 "DELETE FROM private WHERE rid=%d;"
157 "INSERT OR IGNORE INTO unclustered VALUES(%d);"
158 "INSERT OR IGNORE INTO unsent VALUES(%d);",
159 rid, rid, rid
160 );
161 db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
162 admin_log("Approved moderation of rid %c-%d.", class, rid);
163 if( class!='a' ) search_doc_touch(class, rid, 0);
164 db_end_transaction(0);
165 }
166
167 /*
168 ** WEBPAGE: modreq
169
+48 -8
--- src/name.c
+++ src/name.c
@@ -105,10 +105,43 @@
105105
}
106106
107107
/* It looks like this may be a date. Return it with punctuation added. */
108108
return zEDate;
109109
}
110
+
111
+/*
112
+** The data-time string in the argument is going to be used as an
113
+** upper bound like this: mtime<=julianday(zDate,'localtime').
114
+** But if the zDate parameter omits the fractional seconds or the
115
+** seconds, or the time, that might mess up the == part of the
116
+** comparison. So add in missing factional seconds or seconds or time.
117
+**
118
+** The returned string is held in a static buffer that is overwritten
119
+** with each call, or else is just a copy of its input if there are
120
+** no changes.
121
+*/
122
+const char *fossil_roundup_date(const char *zDate){
123
+ static char zUp[24];
124
+ int n = (int)strlen(zDate);
125
+ if( n==19 ){ /* YYYY-MM-DD HH:MM:SS */
126
+ memcpy(zUp, zDate, 19);
127
+ memcpy(zUp+19, ".999", 5);
128
+ return zUp;
129
+ }
130
+ if( n==16 ){ /* YYYY-MM-DD HH:MM */
131
+ memcpy(zUp, zDate, 16);
132
+ memcpy(zUp+16, ":59.999", 8);
133
+ return zUp;
134
+ }
135
+ if( n==10 ){ /* YYYY-MM-DD */
136
+ memcpy(zUp, zDate, 10);
137
+ memcpy(zUp+10, " 23:59:59.999", 14);
138
+ return zUp;
139
+ }
140
+ return zDate;
141
+}
142
+
110143
111144
/*
112145
** Return the RID that is the "root" of the branch that contains
113146
** check-in "rid". Details depending on eType:
114147
**
@@ -235,19 +268,19 @@
235268
if( zDate==0 ) zDate = &zTag[5];
236269
rid = db_int(0,
237270
"SELECT objid FROM event"
238271
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
239272
" ORDER BY mtime DESC LIMIT 1",
240
- zDate, zType);
273
+ fossil_roundup_date(zDate), zType);
241274
return rid;
242275
}
243276
if( fossil_isdate(zTag) ){
244277
rid = db_int(0,
245278
"SELECT objid FROM event"
246279
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
247280
" ORDER BY mtime DESC LIMIT 1",
248
- zTag, zType);
281
+ fossil_roundup_date(zTag), zType);
249282
if( rid) return rid;
250283
}
251284
252285
/* Deprecated date & time formats: "local:" + date-time and
253286
** "utc:" + date-time */
@@ -262,11 +295,11 @@
262295
if( memcmp(zTag, "utc:", 4)==0 ){
263296
rid = db_int(0,
264297
"SELECT objid FROM event"
265298
" WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
266299
" ORDER BY mtime DESC LIMIT 1",
267
- &zTag[4], zType);
300
+ fossil_roundup_date(&zTag[4]), zType);
268301
return rid;
269302
}
270303
271304
/* "tag:" + symbolic-name */
272305
if( memcmp(zTag, "tag:", 4)==0 ){
@@ -294,29 +327,36 @@
294327
return start_of_branch(rid, 2);
295328
}
296329
297330
/* symbolic-name ":" date-time */
298331
nTag = strlen(zTag);
299
- for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
300
- if( zTag[i]==':' && fossil_isdate(&zTag[i+1]) ){
332
+ for(i=0; i<nTag-8 && zTag[i]!=':'; i++){}
333
+ if( zTag[i]==':'
334
+ && (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0)!=0)
335
+ ){
301336
char *zDate = mprintf("%s", &zTag[i+1]);
302337
char *zTagBase = mprintf("%.*s", i, zTag);
338
+ char *zXDate;
303339
int nDate = strlen(zDate);
304340
if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
305341
zDate[nDate-3] = 'z';
306342
zDate[nDate-2] = 0;
307343
}
344
+ zXDate = fossil_expand_datetime(zDate,0);
345
+ if( zXDate==0 ) zXDate = zDate;
308346
rid = db_int(0,
309347
"SELECT event.objid, max(event.mtime)"
310348
" FROM tag, tagxref, event"
311349
" WHERE tag.tagname='sym-%q' "
312350
" AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
313351
" AND event.objid=tagxref.rid "
314
- " AND event.mtime<=julianday(%Q)"
352
+ " AND event.mtime<=julianday(%Q,fromLocal())"
315353
" AND event.type GLOB '%q'",
316
- zTagBase, zDate, zType
354
+ zTagBase, fossil_roundup_date(zXDate), zType
317355
);
356
+ fossil_free(zDate);
357
+ fossil_free(zTagBase);
318358
return rid;
319359
}
320360
321361
/* Remove optional [...] */
322362
zXTag = zTag;
@@ -381,11 +421,11 @@
381421
if( zDate ){
382422
rid = db_int(0,
383423
"SELECT objid FROM event"
384424
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
385425
" ORDER BY mtime DESC LIMIT 1",
386
- zDate, zType);
426
+ fossil_roundup_date(zDate), zType);
387427
if( rid) return rid;
388428
}
389429
390430
391431
/* Undocumented: numeric tags get translated directly into the RID */
392432
--- src/name.c
+++ src/name.c
@@ -105,10 +105,43 @@
105 }
106
107 /* It looks like this may be a date. Return it with punctuation added. */
108 return zEDate;
109 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid". Details depending on eType:
114 **
@@ -235,19 +268,19 @@
235 if( zDate==0 ) zDate = &zTag[5];
236 rid = db_int(0,
237 "SELECT objid FROM event"
238 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
239 " ORDER BY mtime DESC LIMIT 1",
240 zDate, zType);
241 return rid;
242 }
243 if( fossil_isdate(zTag) ){
244 rid = db_int(0,
245 "SELECT objid FROM event"
246 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
247 " ORDER BY mtime DESC LIMIT 1",
248 zTag, zType);
249 if( rid) return rid;
250 }
251
252 /* Deprecated date & time formats: "local:" + date-time and
253 ** "utc:" + date-time */
@@ -262,11 +295,11 @@
262 if( memcmp(zTag, "utc:", 4)==0 ){
263 rid = db_int(0,
264 "SELECT objid FROM event"
265 " WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
266 " ORDER BY mtime DESC LIMIT 1",
267 &zTag[4], zType);
268 return rid;
269 }
270
271 /* "tag:" + symbolic-name */
272 if( memcmp(zTag, "tag:", 4)==0 ){
@@ -294,29 +327,36 @@
294 return start_of_branch(rid, 2);
295 }
296
297 /* symbolic-name ":" date-time */
298 nTag = strlen(zTag);
299 for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
300 if( zTag[i]==':' && fossil_isdate(&zTag[i+1]) ){
 
 
301 char *zDate = mprintf("%s", &zTag[i+1]);
302 char *zTagBase = mprintf("%.*s", i, zTag);
 
303 int nDate = strlen(zDate);
304 if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
305 zDate[nDate-3] = 'z';
306 zDate[nDate-2] = 0;
307 }
 
 
308 rid = db_int(0,
309 "SELECT event.objid, max(event.mtime)"
310 " FROM tag, tagxref, event"
311 " WHERE tag.tagname='sym-%q' "
312 " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
313 " AND event.objid=tagxref.rid "
314 " AND event.mtime<=julianday(%Q)"
315 " AND event.type GLOB '%q'",
316 zTagBase, zDate, zType
317 );
 
 
318 return rid;
319 }
320
321 /* Remove optional [...] */
322 zXTag = zTag;
@@ -381,11 +421,11 @@
381 if( zDate ){
382 rid = db_int(0,
383 "SELECT objid FROM event"
384 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
385 " ORDER BY mtime DESC LIMIT 1",
386 zDate, zType);
387 if( rid) return rid;
388 }
389
390
391 /* Undocumented: numeric tags get translated directly into the RID */
392
--- src/name.c
+++ src/name.c
@@ -105,10 +105,43 @@
105 }
106
107 /* It looks like this may be a date. Return it with punctuation added. */
108 return zEDate;
109 }
110
111 /*
112 ** The data-time string in the argument is going to be used as an
113 ** upper bound like this: mtime<=julianday(zDate,'localtime').
114 ** But if the zDate parameter omits the fractional seconds or the
115 ** seconds, or the time, that might mess up the == part of the
116 ** comparison. So add in missing factional seconds or seconds or time.
117 **
118 ** The returned string is held in a static buffer that is overwritten
119 ** with each call, or else is just a copy of its input if there are
120 ** no changes.
121 */
122 const char *fossil_roundup_date(const char *zDate){
123 static char zUp[24];
124 int n = (int)strlen(zDate);
125 if( n==19 ){ /* YYYY-MM-DD HH:MM:SS */
126 memcpy(zUp, zDate, 19);
127 memcpy(zUp+19, ".999", 5);
128 return zUp;
129 }
130 if( n==16 ){ /* YYYY-MM-DD HH:MM */
131 memcpy(zUp, zDate, 16);
132 memcpy(zUp+16, ":59.999", 8);
133 return zUp;
134 }
135 if( n==10 ){ /* YYYY-MM-DD */
136 memcpy(zUp, zDate, 10);
137 memcpy(zUp+10, " 23:59:59.999", 14);
138 return zUp;
139 }
140 return zDate;
141 }
142
143
144 /*
145 ** Return the RID that is the "root" of the branch that contains
146 ** check-in "rid". Details depending on eType:
147 **
@@ -235,19 +268,19 @@
268 if( zDate==0 ) zDate = &zTag[5];
269 rid = db_int(0,
270 "SELECT objid FROM event"
271 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
272 " ORDER BY mtime DESC LIMIT 1",
273 fossil_roundup_date(zDate), zType);
274 return rid;
275 }
276 if( fossil_isdate(zTag) ){
277 rid = db_int(0,
278 "SELECT objid FROM event"
279 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
280 " ORDER BY mtime DESC LIMIT 1",
281 fossil_roundup_date(zTag), zType);
282 if( rid) return rid;
283 }
284
285 /* Deprecated date & time formats: "local:" + date-time and
286 ** "utc:" + date-time */
@@ -262,11 +295,11 @@
295 if( memcmp(zTag, "utc:", 4)==0 ){
296 rid = db_int(0,
297 "SELECT objid FROM event"
298 " WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
299 " ORDER BY mtime DESC LIMIT 1",
300 fossil_roundup_date(&zTag[4]), zType);
301 return rid;
302 }
303
304 /* "tag:" + symbolic-name */
305 if( memcmp(zTag, "tag:", 4)==0 ){
@@ -294,29 +327,36 @@
327 return start_of_branch(rid, 2);
328 }
329
330 /* symbolic-name ":" date-time */
331 nTag = strlen(zTag);
332 for(i=0; i<nTag-8 && zTag[i]!=':'; i++){}
333 if( zTag[i]==':'
334 && (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0)!=0)
335 ){
336 char *zDate = mprintf("%s", &zTag[i+1]);
337 char *zTagBase = mprintf("%.*s", i, zTag);
338 char *zXDate;
339 int nDate = strlen(zDate);
340 if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
341 zDate[nDate-3] = 'z';
342 zDate[nDate-2] = 0;
343 }
344 zXDate = fossil_expand_datetime(zDate,0);
345 if( zXDate==0 ) zXDate = zDate;
346 rid = db_int(0,
347 "SELECT event.objid, max(event.mtime)"
348 " FROM tag, tagxref, event"
349 " WHERE tag.tagname='sym-%q' "
350 " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
351 " AND event.objid=tagxref.rid "
352 " AND event.mtime<=julianday(%Q,fromLocal())"
353 " AND event.type GLOB '%q'",
354 zTagBase, fossil_roundup_date(zXDate), zType
355 );
356 fossil_free(zDate);
357 fossil_free(zTagBase);
358 return rid;
359 }
360
361 /* Remove optional [...] */
362 zXTag = zTag;
@@ -381,11 +421,11 @@
421 if( zDate ){
422 rid = db_int(0,
423 "SELECT objid FROM event"
424 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
425 " ORDER BY mtime DESC LIMIT 1",
426 fossil_roundup_date(zDate), zType);
427 if( rid) return rid;
428 }
429
430
431 /* Undocumented: numeric tags get translated directly into the RID */
432
+89 -20
--- src/search.c
+++ src/search.c
@@ -14,11 +14,12 @@
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code to implement a search functions
19
-** against timeline comments, check-in content, wiki pages, and/or tickets.
19
+** against timeline comments, check-in content, wiki pages, tickets,
20
+** and/or forum posts.
2021
**
2122
** The search can be either a per-query "grep"-like search that scans
2223
** the entire corpus. Or it can use the FTS4 or FTS5 search engine of
2324
** SQLite. The choice is a administrator configuration option.
2425
**
@@ -331,10 +332,18 @@
331332
**
332333
** Usage: %fossil test-match SEARCHSTRING FILE1 FILE2 ...
333334
**
334335
** Run the full-scan search algorithm using SEARCHSTRING against
335336
** the text of the files listed. Output matches and snippets.
337
+**
338
+** Options:
339
+**
340
+** --begin TEXT Text to insert before each match
341
+** --end TEXT Text to insert after each match
342
+** --gap TEXT Text to indicate elided content
343
+** --html Input is HTML
344
+** --static Use the static Search object
336345
*/
337346
void test_match_cmd(void){
338347
Search *p;
339348
int i;
340349
Blob x;
@@ -372,11 +381,12 @@
372381
**
373382
** All arguments are optional. PATTERN is the search pattern. If it
374383
** is omitted, then the global search pattern is reset. BEGIN and END
375384
** and GAP are the strings used to construct snippets. FLAGS is an
376385
** integer bit pattern containing the various SRCH_CKIN, SRCH_DOC,
377
-** SRCH_TKT, or SRCH_ALL bits to determine what is to be searched.
386
+** SRCH_TKT, SRCH_FORUM, or SRCH_ALL bits to determine what is to be
387
+** searched.
378388
*/
379389
static void search_init_sqlfunc(
380390
sqlite3_context *context,
381391
int argc,
382392
sqlite3_value **argv
@@ -407,11 +417,11 @@
407417
408418
/* search_match(TEXT, TEXT, ....)
409419
**
410420
** Using the full-scan search engine created by the most recent call
411421
** to search_init(), match the input the TEXT arguments.
412
-** Remember the results global full-scan search object.
422
+** Remember the results in the global full-scan search object.
413423
** Return non-zero on a match and zero on a miss.
414424
*/
415425
static void search_match_sqlfunc(
416426
sqlite3_context *context,
417427
int argc,
@@ -560,10 +570,15 @@
560570
** Usage: %fossil search [-all|-a] [-limit|-n #] [-width|-W #] pattern...
561571
**
562572
** Search for timeline entries matching all words provided on the
563573
** command line. Whole-word matches scope more highly than partial
564574
** matches.
575
+**
576
+** Note: The command only search the EVENT table. So it will only
577
+** display check-in comments or other comments that appear on an
578
+** unaugmented timeline. It does not search document text or forum
579
+** messages.
565580
**
566581
** Outputs, by default, some top-N fraction of the results. The -all
567582
** option can be used to output all matches, regardless of their search
568583
** score. The -limit option can be used to limit the number of entries
569584
** returned. The -width option can be used to set the output width used
@@ -645,11 +660,12 @@
645660
#define SRCH_ALL 0x003f /* Search over everything */
646661
#endif
647662
648663
/*
649664
** Remove bits from srchFlags which are disallowed by either the
650
-** current server configuration or by user permissions.
665
+** current server configuration or by user permissions. Return
666
+** the revised search flags mask.
651667
*/
652668
unsigned int search_restrict(unsigned int srchFlags){
653669
static unsigned int knownGood = 0;
654670
static unsigned int knownBad = 0;
655671
static const struct { unsigned m; const char *zKey; } aSetng[] = {
@@ -1569,11 +1585,11 @@
15691585
** updated. If the document has already been indexed, then unindex it
15701586
** now while we still have access to the old content. Add the document
15711587
** to the queue of documents that need to be indexed or reindexed.
15721588
*/
15731589
void search_doc_touch(char cType, int rid, const char *zName){
1574
- if( search_index_exists() ){
1590
+ if( search_index_exists() && !content_is_private(rid) ){
15751591
char zType[2];
15761592
zType[0] = cType;
15771593
zType[1] = 0;
15781594
search_sql_setup(g.db);
15791595
db_multi_exec(
@@ -1836,18 +1852,25 @@
18361852
**
18371853
** The current search settings are displayed after any changes are applied.
18381854
** Run this command with no arguments to simply see the settings.
18391855
*/
18401856
void fts_config_cmd(void){
1841
- static const struct { int iCmd; const char *z; } aCmd[] = {
1857
+ static const struct {
1858
+ int iCmd;
1859
+ const char *z;
1860
+ } aCmd[] = {
18421861
{ 1, "reindex" },
18431862
{ 2, "index" },
18441863
{ 3, "disable" },
18451864
{ 4, "enable" },
18461865
{ 5, "stemmer" },
18471866
};
1848
- static const struct { const char *zSetting; const char *zName; const char *zSw; } aSetng[] = {
1867
+ static const struct {
1868
+ const char *zSetting;
1869
+ const char *zName;
1870
+ const char *zSw;
1871
+ } aSetng[] = {
18491872
{ "search-ci", "check-in search:", "c" },
18501873
{ "search-doc", "document search:", "d" },
18511874
{ "search-tkt", "ticket search:", "t" },
18521875
{ "search-wiki", "wiki search:", "w" },
18531876
{ "search-technote", "tech note search:", "e" },
@@ -1937,48 +1960,77 @@
19371960
Stmt q;
19381961
const char *zId = P("id");
19391962
const char *zType = P("y");
19401963
const char *zIdxed = P("ixed");
19411964
int id;
1942
- int cnt = 0;
1965
+ int cnt1 = 0, cnt2 = 0, cnt3 = 0;
19431966
login_check_credentials();
19441967
if( !g.perm.Admin ){ login_needed(0); return; }
19451968
if( !search_index_exists() ){
19461969
@ <p>Indexed search is disabled
19471970
style_footer();
19481971
return;
19491972
}
1973
+ search_sql_setup(g.db);
1974
+ style_submenu_element("Setup","%R/srchsetup");
19501975
if( zId!=0 && (id = atoi(zId))>0 ){
19511976
/* Show information about a single ftsdocs entry */
19521977
style_header("Information about ftsdoc entry %d", id);
1978
+ style_submenu_element("Summary","%R/test-ftsdocs");
19531979
db_prepare(&q,
19541980
"SELECT type||rid, name, idxed, label, url, datetime(mtime)"
19551981
" FROM ftsdocs WHERE rowid=%d", id
19561982
);
19571983
if( db_step(&q)==SQLITE_ROW ){
19581984
const char *zUrl = db_column_text(&q,4);
1985
+ const char *zDocId = db_column_text(&q,0);
1986
+ char *zName;
1987
+ char *z;
19591988
@ <table border=0>
1960
- @ <tr><td align='right'>rowid:<td>&nbsp;&nbsp;<td>%d(id)
1961
- @ <tr><td align='right'>id:<td><td>%s(db_column_text(&q,0))
1989
+ @ <tr><td align='right'>docid:<td>&nbsp;&nbsp;<td>%d(id)
1990
+ @ <tr><td align='right'>id:<td><td>%s(zDocId)
19621991
@ <tr><td align='right'>name:<td><td>%h(db_column_text(&q,1))
19631992
@ <tr><td align='right'>idxed:<td><td>%d(db_column_int(&q,2))
19641993
@ <tr><td align='right'>label:<td><td>%h(db_column_text(&q,3))
19651994
@ <tr><td align='right'>url:<td><td>
19661995
@ <a href='%R%s(zUrl)'>%h(zUrl)</a>
19671996
@ <tr><td align='right'>mtime:<td><td>%s(db_column_text(&q,5))
1997
+ z = db_text(0, "SELECT title FROM ftsidx WHERE docid=%d",id);
1998
+ if( z && z[0] ){
1999
+ @ <tr><td align="right">title:<td><td>%h(z)
2000
+ fossil_free(z);
2001
+ }
2002
+ z = db_text(0, "SELECT body FROM ftsidx WHERE docid=%d",id);
2003
+ if( z && z[0] ){
2004
+ @ <tr><td align="right" valign="top">body:<td><td>%h(z)
2005
+ fossil_free(z);
2006
+ }
19682007
@ </table>
2008
+ zName = mprintf("Indexed '%c' docs",zDocId[0]);
2009
+ style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zDocId[0]);
2010
+ zName = mprintf("Unindexed '%c' docs",zDocId[0]);
2011
+ style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zDocId[0]);
19692012
}
19702013
db_finalize(&q);
19712014
style_footer();
19722015
return;
19732016
}
19742017
if( zType!=0 && zType[0]!=0 && zType[1]==0 &&
19752018
zIdxed!=0 && (zIdxed[0]=='1' || zIdxed[0]=='0') && zIdxed[1]==0
19762019
){
19772020
int ixed = zIdxed[0]=='1';
2021
+ char *zName;
19782022
style_header("List of '%c' documents that are%s indexed",
19792023
zType[0], ixed ? "" : " not");
2024
+ style_submenu_element("Summary","%R/test-ftsdocs");
2025
+ if( ixed==0 ){
2026
+ zName = mprintf("Indexed '%c' docs",zType[0]);
2027
+ style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zType[0]);
2028
+ }else{
2029
+ zName = mprintf("Unindexed '%c' docs",zType[0]);
2030
+ style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zType[0]);
2031
+ }
19802032
db_prepare(&q,
19812033
"SELECT rowid, type||rid ||' '|| coalesce(label,'')"
19822034
" FROM ftsdocs WHERE type='%c' AND %s idxed",
19832035
zType[0], ixed ? "" : "NOT"
19842036
);
@@ -1992,29 +2044,46 @@
19922044
style_footer();
19932045
return;
19942046
}
19952047
style_header("Summary of ftsdocs");
19962048
db_prepare(&q,
1997
- "SELECT type, idxed, count(*) FROM ftsdocs"
1998
- " GROUP BY 1, 2 ORDER BY 3 DESC"
2049
+ "SELECT type, sum(idxed IS TRUE), sum(idxed IS FALSE), count(*)"
2050
+ " FROM ftsdocs"
2051
+ " GROUP BY 1 ORDER BY 4 DESC"
19992052
);
20002053
@ <table border=1 cellpadding=3 cellspacing=0>
20012054
@ <thead>
2002
- @ <tr><th>Type<th>Indexed?<th>Count<th>Link
2055
+ @ <tr><th>Type<th>Indexed<th>Unindexed<th>Total
20032056
@ </thead>
20042057
@ <tbody>
20052058
while( db_step(&q)==SQLITE_ROW ){
20062059
const char *zType = db_column_text(&q,0);
2007
- int idxed = db_column_int(&q,1);
2008
- int n = db_column_int(&q,2);
2009
- @ <tr><td>%h(zType)<td>%d(idxed)
2010
- @ <td>%d(n)
2011
- @ <td><a href='test-ftsdocs?y=%s(zType)&ixed=%d(idxed)'>listing</a>
2060
+ int nIndexed = db_column_int(&q, 1);
2061
+ int nUnindexed = db_column_int(&q, 2);
2062
+ int nTotal = db_column_int(&q, 3);
2063
+ @ <tr><td>%h(zType)
2064
+ if( nIndexed>0 ){
2065
+ @ <td align="right"><a href='%R/test-ftsdocs?y=%s(zType)&ixed=1'>\
2066
+ @ %d(nIndexed)</a>
2067
+ }else{
2068
+ @ <td align="right">0
2069
+ }
2070
+ if( nUnindexed>0 ){
2071
+ @ <td align="right"><a href='%R/test-ftsdocs?y=%s(zType)&ixed=0'>\
2072
+ @ %d(nUnindexed)</a>
2073
+ }else{
2074
+ @ <td align="right">0
2075
+ }
2076
+ @ <td align="right">%d(nTotal)
20122077
@ </tr>
2013
- cnt += n;
2078
+ cnt1 += nIndexed;
2079
+ cnt2 += nUnindexed;
2080
+ cnt3 += nTotal;
20142081
}
2082
+ db_finalize(&q);
20152083
@ </tbody><tfooter>
2016
- @ <tr><th>Total<th><th>%d(cnt)<th>
2084
+ @ <tr><th>Total<th align="right">%d(cnt1)<th align="right">%d(cnt2)
2085
+ @ <th align="right">%d(cnt3)
20172086
@ </tfooter>
20182087
@ </table>
20192088
style_footer();
20202089
}
20212090
--- src/search.c
+++ src/search.c
@@ -14,11 +14,12 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to implement a search functions
19 ** against timeline comments, check-in content, wiki pages, and/or tickets.
 
20 **
21 ** The search can be either a per-query "grep"-like search that scans
22 ** the entire corpus. Or it can use the FTS4 or FTS5 search engine of
23 ** SQLite. The choice is a administrator configuration option.
24 **
@@ -331,10 +332,18 @@
331 **
332 ** Usage: %fossil test-match SEARCHSTRING FILE1 FILE2 ...
333 **
334 ** Run the full-scan search algorithm using SEARCHSTRING against
335 ** the text of the files listed. Output matches and snippets.
 
 
 
 
 
 
 
 
336 */
337 void test_match_cmd(void){
338 Search *p;
339 int i;
340 Blob x;
@@ -372,11 +381,12 @@
372 **
373 ** All arguments are optional. PATTERN is the search pattern. If it
374 ** is omitted, then the global search pattern is reset. BEGIN and END
375 ** and GAP are the strings used to construct snippets. FLAGS is an
376 ** integer bit pattern containing the various SRCH_CKIN, SRCH_DOC,
377 ** SRCH_TKT, or SRCH_ALL bits to determine what is to be searched.
 
378 */
379 static void search_init_sqlfunc(
380 sqlite3_context *context,
381 int argc,
382 sqlite3_value **argv
@@ -407,11 +417,11 @@
407
408 /* search_match(TEXT, TEXT, ....)
409 **
410 ** Using the full-scan search engine created by the most recent call
411 ** to search_init(), match the input the TEXT arguments.
412 ** Remember the results global full-scan search object.
413 ** Return non-zero on a match and zero on a miss.
414 */
415 static void search_match_sqlfunc(
416 sqlite3_context *context,
417 int argc,
@@ -560,10 +570,15 @@
560 ** Usage: %fossil search [-all|-a] [-limit|-n #] [-width|-W #] pattern...
561 **
562 ** Search for timeline entries matching all words provided on the
563 ** command line. Whole-word matches scope more highly than partial
564 ** matches.
 
 
 
 
 
565 **
566 ** Outputs, by default, some top-N fraction of the results. The -all
567 ** option can be used to output all matches, regardless of their search
568 ** score. The -limit option can be used to limit the number of entries
569 ** returned. The -width option can be used to set the output width used
@@ -645,11 +660,12 @@
645 #define SRCH_ALL 0x003f /* Search over everything */
646 #endif
647
648 /*
649 ** Remove bits from srchFlags which are disallowed by either the
650 ** current server configuration or by user permissions.
 
651 */
652 unsigned int search_restrict(unsigned int srchFlags){
653 static unsigned int knownGood = 0;
654 static unsigned int knownBad = 0;
655 static const struct { unsigned m; const char *zKey; } aSetng[] = {
@@ -1569,11 +1585,11 @@
1569 ** updated. If the document has already been indexed, then unindex it
1570 ** now while we still have access to the old content. Add the document
1571 ** to the queue of documents that need to be indexed or reindexed.
1572 */
1573 void search_doc_touch(char cType, int rid, const char *zName){
1574 if( search_index_exists() ){
1575 char zType[2];
1576 zType[0] = cType;
1577 zType[1] = 0;
1578 search_sql_setup(g.db);
1579 db_multi_exec(
@@ -1836,18 +1852,25 @@
1836 **
1837 ** The current search settings are displayed after any changes are applied.
1838 ** Run this command with no arguments to simply see the settings.
1839 */
1840 void fts_config_cmd(void){
1841 static const struct { int iCmd; const char *z; } aCmd[] = {
 
 
 
1842 { 1, "reindex" },
1843 { 2, "index" },
1844 { 3, "disable" },
1845 { 4, "enable" },
1846 { 5, "stemmer" },
1847 };
1848 static const struct { const char *zSetting; const char *zName; const char *zSw; } aSetng[] = {
 
 
 
 
1849 { "search-ci", "check-in search:", "c" },
1850 { "search-doc", "document search:", "d" },
1851 { "search-tkt", "ticket search:", "t" },
1852 { "search-wiki", "wiki search:", "w" },
1853 { "search-technote", "tech note search:", "e" },
@@ -1937,48 +1960,77 @@
1937 Stmt q;
1938 const char *zId = P("id");
1939 const char *zType = P("y");
1940 const char *zIdxed = P("ixed");
1941 int id;
1942 int cnt = 0;
1943 login_check_credentials();
1944 if( !g.perm.Admin ){ login_needed(0); return; }
1945 if( !search_index_exists() ){
1946 @ <p>Indexed search is disabled
1947 style_footer();
1948 return;
1949 }
 
 
1950 if( zId!=0 && (id = atoi(zId))>0 ){
1951 /* Show information about a single ftsdocs entry */
1952 style_header("Information about ftsdoc entry %d", id);
 
1953 db_prepare(&q,
1954 "SELECT type||rid, name, idxed, label, url, datetime(mtime)"
1955 " FROM ftsdocs WHERE rowid=%d", id
1956 );
1957 if( db_step(&q)==SQLITE_ROW ){
1958 const char *zUrl = db_column_text(&q,4);
 
 
 
1959 @ <table border=0>
1960 @ <tr><td align='right'>rowid:<td>&nbsp;&nbsp;<td>%d(id)
1961 @ <tr><td align='right'>id:<td><td>%s(db_column_text(&q,0))
1962 @ <tr><td align='right'>name:<td><td>%h(db_column_text(&q,1))
1963 @ <tr><td align='right'>idxed:<td><td>%d(db_column_int(&q,2))
1964 @ <tr><td align='right'>label:<td><td>%h(db_column_text(&q,3))
1965 @ <tr><td align='right'>url:<td><td>
1966 @ <a href='%R%s(zUrl)'>%h(zUrl)</a>
1967 @ <tr><td align='right'>mtime:<td><td>%s(db_column_text(&q,5))
 
 
 
 
 
 
 
 
 
 
1968 @ </table>
 
 
 
 
1969 }
1970 db_finalize(&q);
1971 style_footer();
1972 return;
1973 }
1974 if( zType!=0 && zType[0]!=0 && zType[1]==0 &&
1975 zIdxed!=0 && (zIdxed[0]=='1' || zIdxed[0]=='0') && zIdxed[1]==0
1976 ){
1977 int ixed = zIdxed[0]=='1';
 
1978 style_header("List of '%c' documents that are%s indexed",
1979 zType[0], ixed ? "" : " not");
 
 
 
 
 
 
 
 
1980 db_prepare(&q,
1981 "SELECT rowid, type||rid ||' '|| coalesce(label,'')"
1982 " FROM ftsdocs WHERE type='%c' AND %s idxed",
1983 zType[0], ixed ? "" : "NOT"
1984 );
@@ -1992,29 +2044,46 @@
1992 style_footer();
1993 return;
1994 }
1995 style_header("Summary of ftsdocs");
1996 db_prepare(&q,
1997 "SELECT type, idxed, count(*) FROM ftsdocs"
1998 " GROUP BY 1, 2 ORDER BY 3 DESC"
 
1999 );
2000 @ <table border=1 cellpadding=3 cellspacing=0>
2001 @ <thead>
2002 @ <tr><th>Type<th>Indexed?<th>Count<th>Link
2003 @ </thead>
2004 @ <tbody>
2005 while( db_step(&q)==SQLITE_ROW ){
2006 const char *zType = db_column_text(&q,0);
2007 int idxed = db_column_int(&q,1);
2008 int n = db_column_int(&q,2);
2009 @ <tr><td>%h(zType)<td>%d(idxed)
2010 @ <td>%d(n)
2011 @ <td><a href='test-ftsdocs?y=%s(zType)&ixed=%d(idxed)'>listing</a>
 
 
 
 
 
 
 
 
 
 
 
 
2012 @ </tr>
2013 cnt += n;
 
 
2014 }
 
2015 @ </tbody><tfooter>
2016 @ <tr><th>Total<th><th>%d(cnt)<th>
 
2017 @ </tfooter>
2018 @ </table>
2019 style_footer();
2020 }
2021
--- src/search.c
+++ src/search.c
@@ -14,11 +14,12 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to implement a search functions
19 ** against timeline comments, check-in content, wiki pages, tickets,
20 ** and/or forum posts.
21 **
22 ** The search can be either a per-query "grep"-like search that scans
23 ** the entire corpus. Or it can use the FTS4 or FTS5 search engine of
24 ** SQLite. The choice is a administrator configuration option.
25 **
@@ -331,10 +332,18 @@
332 **
333 ** Usage: %fossil test-match SEARCHSTRING FILE1 FILE2 ...
334 **
335 ** Run the full-scan search algorithm using SEARCHSTRING against
336 ** the text of the files listed. Output matches and snippets.
337 **
338 ** Options:
339 **
340 ** --begin TEXT Text to insert before each match
341 ** --end TEXT Text to insert after each match
342 ** --gap TEXT Text to indicate elided content
343 ** --html Input is HTML
344 ** --static Use the static Search object
345 */
346 void test_match_cmd(void){
347 Search *p;
348 int i;
349 Blob x;
@@ -372,11 +381,12 @@
381 **
382 ** All arguments are optional. PATTERN is the search pattern. If it
383 ** is omitted, then the global search pattern is reset. BEGIN and END
384 ** and GAP are the strings used to construct snippets. FLAGS is an
385 ** integer bit pattern containing the various SRCH_CKIN, SRCH_DOC,
386 ** SRCH_TKT, SRCH_FORUM, or SRCH_ALL bits to determine what is to be
387 ** searched.
388 */
389 static void search_init_sqlfunc(
390 sqlite3_context *context,
391 int argc,
392 sqlite3_value **argv
@@ -407,11 +417,11 @@
417
418 /* search_match(TEXT, TEXT, ....)
419 **
420 ** Using the full-scan search engine created by the most recent call
421 ** to search_init(), match the input the TEXT arguments.
422 ** Remember the results in the global full-scan search object.
423 ** Return non-zero on a match and zero on a miss.
424 */
425 static void search_match_sqlfunc(
426 sqlite3_context *context,
427 int argc,
@@ -560,10 +570,15 @@
570 ** Usage: %fossil search [-all|-a] [-limit|-n #] [-width|-W #] pattern...
571 **
572 ** Search for timeline entries matching all words provided on the
573 ** command line. Whole-word matches scope more highly than partial
574 ** matches.
575 **
576 ** Note: The command only search the EVENT table. So it will only
577 ** display check-in comments or other comments that appear on an
578 ** unaugmented timeline. It does not search document text or forum
579 ** messages.
580 **
581 ** Outputs, by default, some top-N fraction of the results. The -all
582 ** option can be used to output all matches, regardless of their search
583 ** score. The -limit option can be used to limit the number of entries
584 ** returned. The -width option can be used to set the output width used
@@ -645,11 +660,12 @@
660 #define SRCH_ALL 0x003f /* Search over everything */
661 #endif
662
663 /*
664 ** Remove bits from srchFlags which are disallowed by either the
665 ** current server configuration or by user permissions. Return
666 ** the revised search flags mask.
667 */
668 unsigned int search_restrict(unsigned int srchFlags){
669 static unsigned int knownGood = 0;
670 static unsigned int knownBad = 0;
671 static const struct { unsigned m; const char *zKey; } aSetng[] = {
@@ -1569,11 +1585,11 @@
1585 ** updated. If the document has already been indexed, then unindex it
1586 ** now while we still have access to the old content. Add the document
1587 ** to the queue of documents that need to be indexed or reindexed.
1588 */
1589 void search_doc_touch(char cType, int rid, const char *zName){
1590 if( search_index_exists() && !content_is_private(rid) ){
1591 char zType[2];
1592 zType[0] = cType;
1593 zType[1] = 0;
1594 search_sql_setup(g.db);
1595 db_multi_exec(
@@ -1836,18 +1852,25 @@
1852 **
1853 ** The current search settings are displayed after any changes are applied.
1854 ** Run this command with no arguments to simply see the settings.
1855 */
1856 void fts_config_cmd(void){
1857 static const struct {
1858 int iCmd;
1859 const char *z;
1860 } aCmd[] = {
1861 { 1, "reindex" },
1862 { 2, "index" },
1863 { 3, "disable" },
1864 { 4, "enable" },
1865 { 5, "stemmer" },
1866 };
1867 static const struct {
1868 const char *zSetting;
1869 const char *zName;
1870 const char *zSw;
1871 } aSetng[] = {
1872 { "search-ci", "check-in search:", "c" },
1873 { "search-doc", "document search:", "d" },
1874 { "search-tkt", "ticket search:", "t" },
1875 { "search-wiki", "wiki search:", "w" },
1876 { "search-technote", "tech note search:", "e" },
@@ -1937,48 +1960,77 @@
1960 Stmt q;
1961 const char *zId = P("id");
1962 const char *zType = P("y");
1963 const char *zIdxed = P("ixed");
1964 int id;
1965 int cnt1 = 0, cnt2 = 0, cnt3 = 0;
1966 login_check_credentials();
1967 if( !g.perm.Admin ){ login_needed(0); return; }
1968 if( !search_index_exists() ){
1969 @ <p>Indexed search is disabled
1970 style_footer();
1971 return;
1972 }
1973 search_sql_setup(g.db);
1974 style_submenu_element("Setup","%R/srchsetup");
1975 if( zId!=0 && (id = atoi(zId))>0 ){
1976 /* Show information about a single ftsdocs entry */
1977 style_header("Information about ftsdoc entry %d", id);
1978 style_submenu_element("Summary","%R/test-ftsdocs");
1979 db_prepare(&q,
1980 "SELECT type||rid, name, idxed, label, url, datetime(mtime)"
1981 " FROM ftsdocs WHERE rowid=%d", id
1982 );
1983 if( db_step(&q)==SQLITE_ROW ){
1984 const char *zUrl = db_column_text(&q,4);
1985 const char *zDocId = db_column_text(&q,0);
1986 char *zName;
1987 char *z;
1988 @ <table border=0>
1989 @ <tr><td align='right'>docid:<td>&nbsp;&nbsp;<td>%d(id)
1990 @ <tr><td align='right'>id:<td><td>%s(zDocId)
1991 @ <tr><td align='right'>name:<td><td>%h(db_column_text(&q,1))
1992 @ <tr><td align='right'>idxed:<td><td>%d(db_column_int(&q,2))
1993 @ <tr><td align='right'>label:<td><td>%h(db_column_text(&q,3))
1994 @ <tr><td align='right'>url:<td><td>
1995 @ <a href='%R%s(zUrl)'>%h(zUrl)</a>
1996 @ <tr><td align='right'>mtime:<td><td>%s(db_column_text(&q,5))
1997 z = db_text(0, "SELECT title FROM ftsidx WHERE docid=%d",id);
1998 if( z && z[0] ){
1999 @ <tr><td align="right">title:<td><td>%h(z)
2000 fossil_free(z);
2001 }
2002 z = db_text(0, "SELECT body FROM ftsidx WHERE docid=%d",id);
2003 if( z && z[0] ){
2004 @ <tr><td align="right" valign="top">body:<td><td>%h(z)
2005 fossil_free(z);
2006 }
2007 @ </table>
2008 zName = mprintf("Indexed '%c' docs",zDocId[0]);
2009 style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zDocId[0]);
2010 zName = mprintf("Unindexed '%c' docs",zDocId[0]);
2011 style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zDocId[0]);
2012 }
2013 db_finalize(&q);
2014 style_footer();
2015 return;
2016 }
2017 if( zType!=0 && zType[0]!=0 && zType[1]==0 &&
2018 zIdxed!=0 && (zIdxed[0]=='1' || zIdxed[0]=='0') && zIdxed[1]==0
2019 ){
2020 int ixed = zIdxed[0]=='1';
2021 char *zName;
2022 style_header("List of '%c' documents that are%s indexed",
2023 zType[0], ixed ? "" : " not");
2024 style_submenu_element("Summary","%R/test-ftsdocs");
2025 if( ixed==0 ){
2026 zName = mprintf("Indexed '%c' docs",zType[0]);
2027 style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=1",zType[0]);
2028 }else{
2029 zName = mprintf("Unindexed '%c' docs",zType[0]);
2030 style_submenu_element(zName,"%R/test-ftsdocs?y=%c&ixed=0",zType[0]);
2031 }
2032 db_prepare(&q,
2033 "SELECT rowid, type||rid ||' '|| coalesce(label,'')"
2034 " FROM ftsdocs WHERE type='%c' AND %s idxed",
2035 zType[0], ixed ? "" : "NOT"
2036 );
@@ -1992,29 +2044,46 @@
2044 style_footer();
2045 return;
2046 }
2047 style_header("Summary of ftsdocs");
2048 db_prepare(&q,
2049 "SELECT type, sum(idxed IS TRUE), sum(idxed IS FALSE), count(*)"
2050 " FROM ftsdocs"
2051 " GROUP BY 1 ORDER BY 4 DESC"
2052 );
2053 @ <table border=1 cellpadding=3 cellspacing=0>
2054 @ <thead>
2055 @ <tr><th>Type<th>Indexed<th>Unindexed<th>Total
2056 @ </thead>
2057 @ <tbody>
2058 while( db_step(&q)==SQLITE_ROW ){
2059 const char *zType = db_column_text(&q,0);
2060 int nIndexed = db_column_int(&q, 1);
2061 int nUnindexed = db_column_int(&q, 2);
2062 int nTotal = db_column_int(&q, 3);
2063 @ <tr><td>%h(zType)
2064 if( nIndexed>0 ){
2065 @ <td align="right"><a href='%R/test-ftsdocs?y=%s(zType)&ixed=1'>\
2066 @ %d(nIndexed)</a>
2067 }else{
2068 @ <td align="right">0
2069 }
2070 if( nUnindexed>0 ){
2071 @ <td align="right"><a href='%R/test-ftsdocs?y=%s(zType)&ixed=0'>\
2072 @ %d(nUnindexed)</a>
2073 }else{
2074 @ <td align="right">0
2075 }
2076 @ <td align="right">%d(nTotal)
2077 @ </tr>
2078 cnt1 += nIndexed;
2079 cnt2 += nUnindexed;
2080 cnt3 += nTotal;
2081 }
2082 db_finalize(&q);
2083 @ </tbody><tfooter>
2084 @ <tr><th>Total<th align="right">%d(cnt1)<th align="right">%d(cnt2)
2085 @ <th align="right">%d(cnt3)
2086 @ </tfooter>
2087 @ </table>
2088 style_footer();
2089 }
2090
--- src/setup.c
+++ src/setup.c
@@ -1640,10 +1640,11 @@
16401640
@ <p>Currently using an SQLite FTS4 search index. This makes search
16411641
@ run faster, especially on large repositories, but takes up space.</p>
16421642
onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
16431643
@ <p><input type="submit" name="fts0" value="Delete The Full-Text Index">
16441644
@ <input type="submit" name="fts1" value="Rebuild The Full-Text Index">
1645
+ style_submenu_element("FTS Index Debugging","%R/test-ftsdocs");
16451646
}else{
16461647
@ <p>The SQLite FTS4 search index is disabled. All searching will be
16471648
@ a full-text scan. This usually works fine, but can be slow for
16481649
@ larger repositories.</p>
16491650
onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
16501651
--- src/setup.c
+++ src/setup.c
@@ -1640,10 +1640,11 @@
1640 @ <p>Currently using an SQLite FTS4 search index. This makes search
1641 @ run faster, especially on large repositories, but takes up space.</p>
1642 onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
1643 @ <p><input type="submit" name="fts0" value="Delete The Full-Text Index">
1644 @ <input type="submit" name="fts1" value="Rebuild The Full-Text Index">
 
1645 }else{
1646 @ <p>The SQLite FTS4 search index is disabled. All searching will be
1647 @ a full-text scan. This usually works fine, but can be slow for
1648 @ larger repositories.</p>
1649 onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
1650
--- src/setup.c
+++ src/setup.c
@@ -1640,10 +1640,11 @@
1640 @ <p>Currently using an SQLite FTS4 search index. This makes search
1641 @ run faster, especially on large repositories, but takes up space.</p>
1642 onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
1643 @ <p><input type="submit" name="fts0" value="Delete The Full-Text Index">
1644 @ <input type="submit" name="fts1" value="Rebuild The Full-Text Index">
1645 style_submenu_element("FTS Index Debugging","%R/test-ftsdocs");
1646 }else{
1647 @ <p>The SQLite FTS4 search index is disabled. All searching will be
1648 @ a full-text scan. This usually works fine, but can be slow for
1649 @ larger repositories.</p>
1650 onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
1651
+11
--- src/style.c
+++ src/style.c
@@ -91,10 +91,11 @@
9191
*/
9292
static int needHrefJs = 0; /* href.js */
9393
static int needSortJs = 0; /* sorttable.js */
9494
static int needGraphJs = 0; /* graph.js */
9595
static int needCopyBtnJs = 0; /* copybtn.js */
96
+static int needAccordionJs = 0; /* accordion.js */
9697
9798
/*
9899
** Extra JS added to the end of the file.
99100
*/
100101
static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -680,10 +681,17 @@
680681
** Indicate that the table-sorting javascript is needed.
681682
*/
682683
void style_table_sorter(void){
683684
needSortJs = 1;
684685
}
686
+
687
+/*
688
+** Indicate that the accordion javascript is needed.
689
+*/
690
+void style_accordion(void){
691
+ needAccordionJs = 1;
692
+}
685693
686694
/*
687695
** Indicate that the timeline graph javascript is needed.
688696
*/
689697
void style_graph_generator(void){
@@ -750,10 +758,13 @@
750758
cgi_append_content(builtin_text("graph.js"),-1);
751759
}
752760
if( needCopyBtnJs ){
753761
cgi_append_content(builtin_text("copybtn.js"),-1);
754762
}
763
+ if( needAccordionJs ){
764
+ cgi_append_content(builtin_text("accordion.js"),-1);
765
+ }
755766
for(i=0; i<nJsToLoad; i++){
756767
cgi_append_content(builtin_text(azJsToLoad[i]),-1);
757768
}
758769
if( blob_size(&blobOnLoad)>0 ){
759770
@ window.onload = function(){
760771
--- src/style.c
+++ src/style.c
@@ -91,10 +91,11 @@
91 */
92 static int needHrefJs = 0; /* href.js */
93 static int needSortJs = 0; /* sorttable.js */
94 static int needGraphJs = 0; /* graph.js */
95 static int needCopyBtnJs = 0; /* copybtn.js */
 
96
97 /*
98 ** Extra JS added to the end of the file.
99 */
100 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -680,10 +681,17 @@
680 ** Indicate that the table-sorting javascript is needed.
681 */
682 void style_table_sorter(void){
683 needSortJs = 1;
684 }
 
 
 
 
 
 
 
685
686 /*
687 ** Indicate that the timeline graph javascript is needed.
688 */
689 void style_graph_generator(void){
@@ -750,10 +758,13 @@
750 cgi_append_content(builtin_text("graph.js"),-1);
751 }
752 if( needCopyBtnJs ){
753 cgi_append_content(builtin_text("copybtn.js"),-1);
754 }
 
 
 
755 for(i=0; i<nJsToLoad; i++){
756 cgi_append_content(builtin_text(azJsToLoad[i]),-1);
757 }
758 if( blob_size(&blobOnLoad)>0 ){
759 @ window.onload = function(){
760
--- src/style.c
+++ src/style.c
@@ -91,10 +91,11 @@
91 */
92 static int needHrefJs = 0; /* href.js */
93 static int needSortJs = 0; /* sorttable.js */
94 static int needGraphJs = 0; /* graph.js */
95 static int needCopyBtnJs = 0; /* copybtn.js */
96 static int needAccordionJs = 0; /* accordion.js */
97
98 /*
99 ** Extra JS added to the end of the file.
100 */
101 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -680,10 +681,17 @@
681 ** Indicate that the table-sorting javascript is needed.
682 */
683 void style_table_sorter(void){
684 needSortJs = 1;
685 }
686
687 /*
688 ** Indicate that the accordion javascript is needed.
689 */
690 void style_accordion(void){
691 needAccordionJs = 1;
692 }
693
694 /*
695 ** Indicate that the timeline graph javascript is needed.
696 */
697 void style_graph_generator(void){
@@ -750,10 +758,13 @@
758 cgi_append_content(builtin_text("graph.js"),-1);
759 }
760 if( needCopyBtnJs ){
761 cgi_append_content(builtin_text("copybtn.js"),-1);
762 }
763 if( needAccordionJs ){
764 cgi_append_content(builtin_text("accordion.js"),-1);
765 }
766 for(i=0; i<nJsToLoad; i++){
767 cgi_append_content(builtin_text(azJsToLoad[i]),-1);
768 }
769 if( blob_size(&blobOnLoad)>0 ){
770 @ window.onload = function(){
771
+8 -6
--- src/timeline.c
+++ src/timeline.c
@@ -798,11 +798,11 @@
798798
if( pPost ){
799799
const char *zClass = "forumTimeline";
800800
if( forum_rid_has_been_edited(rid) ){
801801
zClass = "forumTimeline forumObs";
802802
}
803
- forum_render(0, pPost->zMimetype, pPost->zWiki, zClass);
803
+ forum_render(0, pPost->zMimetype, pPost->zWiki, zClass, 1);
804804
manifest_destroy(pPost);
805805
}
806806
}
807807
}
808808
if( suppressCnt ){
@@ -1113,15 +1113,17 @@
11131113
if( fossil_isdate(z) ){
11141114
mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
11151115
if( mtime>0.0 ) return mtime;
11161116
}
11171117
zDate = fossil_expand_datetime(z, 1);
1118
- if( zDate!=0
1119
- && (mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", zDate))>0.0
1120
- ){
1121
- if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
1122
- return mtime;
1118
+ if( zDate!=0 ){
1119
+ mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())",
1120
+ fossil_roundup_date(zDate));
1121
+ if( mtime>0.0 ){
1122
+ if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
1123
+ return mtime;
1124
+ }
11231125
}
11241126
rid = symbolic_name_to_rid(z, "*");
11251127
if( rid ){
11261128
mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
11271129
}else{
11281130
--- src/timeline.c
+++ src/timeline.c
@@ -798,11 +798,11 @@
798 if( pPost ){
799 const char *zClass = "forumTimeline";
800 if( forum_rid_has_been_edited(rid) ){
801 zClass = "forumTimeline forumObs";
802 }
803 forum_render(0, pPost->zMimetype, pPost->zWiki, zClass);
804 manifest_destroy(pPost);
805 }
806 }
807 }
808 if( suppressCnt ){
@@ -1113,15 +1113,17 @@
1113 if( fossil_isdate(z) ){
1114 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
1115 if( mtime>0.0 ) return mtime;
1116 }
1117 zDate = fossil_expand_datetime(z, 1);
1118 if( zDate!=0
1119 && (mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", zDate))>0.0
1120 ){
1121 if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
1122 return mtime;
 
 
1123 }
1124 rid = symbolic_name_to_rid(z, "*");
1125 if( rid ){
1126 mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
1127 }else{
1128
--- src/timeline.c
+++ src/timeline.c
@@ -798,11 +798,11 @@
798 if( pPost ){
799 const char *zClass = "forumTimeline";
800 if( forum_rid_has_been_edited(rid) ){
801 zClass = "forumTimeline forumObs";
802 }
803 forum_render(0, pPost->zMimetype, pPost->zWiki, zClass, 1);
804 manifest_destroy(pPost);
805 }
806 }
807 }
808 if( suppressCnt ){
@@ -1113,15 +1113,17 @@
1113 if( fossil_isdate(z) ){
1114 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
1115 if( mtime>0.0 ) return mtime;
1116 }
1117 zDate = fossil_expand_datetime(z, 1);
1118 if( zDate!=0 ){
1119 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())",
1120 fossil_roundup_date(zDate));
1121 if( mtime>0.0 ){
1122 if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
1123 return mtime;
1124 }
1125 }
1126 rid = symbolic_name_to_rid(z, "*");
1127 if( rid ){
1128 mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
1129 }else{
1130
+2 -1
--- src/update.c
+++ src/update.c
@@ -688,10 +688,11 @@
688688
}else if( !g.localOpen ){
689689
vid = name_to_typed_rid(db_get("main-branch", 0), "ci");
690690
}else{
691691
vid = db_lget_int("checkout", 0);
692692
if( !is_a_version(vid) ){
693
+ if( vid==0 ) return 0;
693694
zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
694695
if( zRevision ){
695696
fossil_fatal("checkout artifact is not a check-in: %s", zRevision);
696697
}else{
697698
fossil_fatal("invalid checkout artifact ID: %d", vid);
@@ -858,11 +859,11 @@
858859
}
859860
while( db_step(&q)==SQLITE_ROW ){
860861
char *zFull;
861862
zFile = db_column_text(&q, 0);
862863
zFull = mprintf("%/%/", g.zLocalRoot, zFile);
863
- pRvFile = manifest_file_find(pRvManifest, zFile);
864
+ pRvFile = pRvManifest? manifest_file_find(pRvManifest, zFile) : 0;
864865
if( !pRvFile ){
865866
if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q",
866867
zFile, zFile)==0 ){
867868
fossil_print("UNMANAGE %s\n", zFile);
868869
}else{
869870
--- src/update.c
+++ src/update.c
@@ -688,10 +688,11 @@
688 }else if( !g.localOpen ){
689 vid = name_to_typed_rid(db_get("main-branch", 0), "ci");
690 }else{
691 vid = db_lget_int("checkout", 0);
692 if( !is_a_version(vid) ){
 
693 zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
694 if( zRevision ){
695 fossil_fatal("checkout artifact is not a check-in: %s", zRevision);
696 }else{
697 fossil_fatal("invalid checkout artifact ID: %d", vid);
@@ -858,11 +859,11 @@
858 }
859 while( db_step(&q)==SQLITE_ROW ){
860 char *zFull;
861 zFile = db_column_text(&q, 0);
862 zFull = mprintf("%/%/", g.zLocalRoot, zFile);
863 pRvFile = manifest_file_find(pRvManifest, zFile);
864 if( !pRvFile ){
865 if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q",
866 zFile, zFile)==0 ){
867 fossil_print("UNMANAGE %s\n", zFile);
868 }else{
869
--- src/update.c
+++ src/update.c
@@ -688,10 +688,11 @@
688 }else if( !g.localOpen ){
689 vid = name_to_typed_rid(db_get("main-branch", 0), "ci");
690 }else{
691 vid = db_lget_int("checkout", 0);
692 if( !is_a_version(vid) ){
693 if( vid==0 ) return 0;
694 zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
695 if( zRevision ){
696 fossil_fatal("checkout artifact is not a check-in: %s", zRevision);
697 }else{
698 fossil_fatal("invalid checkout artifact ID: %d", vid);
@@ -858,11 +859,11 @@
859 }
860 while( db_step(&q)==SQLITE_ROW ){
861 char *zFull;
862 zFile = db_column_text(&q, 0);
863 zFull = mprintf("%/%/", g.zLocalRoot, zFile);
864 pRvFile = pRvManifest? manifest_file_find(pRvManifest, zFile) : 0;
865 if( !pRvFile ){
866 if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q",
867 zFile, zFile)==0 ){
868 fossil_print("UNMANAGE %s\n", zFile);
869 }else{
870
+11 -8
--- src/wiki.c
+++ src/wiki.c
@@ -1713,15 +1713,15 @@
17131713
const char *zPrefix, /* "branch", "tag", or "checkin" */
17141714
const char *zName, /* Name of the object */
17151715
unsigned int mFlags /* Zero or more WIKIASSOC_* flags */
17161716
){
17171717
if( (mFlags & WIKIASSOC_FULL_TITLE)==0 ){
1718
- @ <div class="section">About</div>
1718
+ @ <div class="section accordion">About</div>
17191719
}else if( zPrefix[0]=='c' ){ /* checkin/... */
1720
- @ <div class="section">About checkin %.20h(zName)</div>
1720
+ @ <div class="section accordion">About checkin %.20h(zName)</div>
17211721
}else{
1722
- @ <div class="section">About %s(zPrefix) %h(zName)</div>
1722
+ @ <div class="section accordion">About %s(zPrefix) %h(zName)</div>
17231723
}
17241724
}
17251725
17261726
/*
17271727
** Add an "Wiki" button in a submenu that links to the read-wiki page.
@@ -1775,39 +1775,42 @@
17751775
@ <div class="section">%h(blob_str(&title))</div>
17761776
}else{
17771777
wiki_section_label(zPrefix, zName, mFlags);
17781778
}
17791779
wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1780
+ @ <div class="accordion_panel">
17801781
convert_href_and_output(&tail);
1782
+ @ </div>
17811783
blob_reset(&tail);
17821784
blob_reset(&title);
17831785
blob_reset(&markdown);
17841786
}else if( fossil_strcmp(pWiki->zMimetype, "text/plain")==0 ){
17851787
wiki_section_label(zPrefix, zName, mFlags);
17861788
wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1787
- @ <pre>
1789
+ @ <div class="accordion_panel"><pre>
17881790
@ %h(pWiki->zWiki)
1789
- @ </pre>
1791
+ @ </pre></div>
17901792
}else{
17911793
Blob tail = BLOB_INITIALIZER;
17921794
Blob title = BLOB_INITIALIZER;
17931795
Blob wiki;
17941796
Blob *pBody;
17951797
blob_init(&wiki, pWiki->zWiki, -1);
17961798
if( wiki_find_title(&wiki, &title, &tail) ){
1797
- @ <div class="section">%h(blob_str(&title))</div>
1799
+ @ <div class="section accordion">%h(blob_str(&title))</div>
17981800
pBody = &tail;
17991801
}else{
18001802
wiki_section_label(zPrefix, zName, mFlags);
18011803
pBody = &wiki;
18021804
}
18031805
wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1804
- @ <div class="wiki">
1806
+ @ <div class="accordion_panel"><div class="wiki">
18051807
wiki_convert(pBody, 0, WIKI_BUTTONS);
1806
- @ </div>
1808
+ @ </div></div>
18071809
blob_reset(&tail);
18081810
blob_reset(&title);
18091811
blob_reset(&wiki);
18101812
}
18111813
manifest_destroy(pWiki);
1814
+ style_accordion();
18121815
return 1;
18131816
}
18141817
--- src/wiki.c
+++ src/wiki.c
@@ -1713,15 +1713,15 @@
1713 const char *zPrefix, /* "branch", "tag", or "checkin" */
1714 const char *zName, /* Name of the object */
1715 unsigned int mFlags /* Zero or more WIKIASSOC_* flags */
1716 ){
1717 if( (mFlags & WIKIASSOC_FULL_TITLE)==0 ){
1718 @ <div class="section">About</div>
1719 }else if( zPrefix[0]=='c' ){ /* checkin/... */
1720 @ <div class="section">About checkin %.20h(zName)</div>
1721 }else{
1722 @ <div class="section">About %s(zPrefix) %h(zName)</div>
1723 }
1724 }
1725
1726 /*
1727 ** Add an "Wiki" button in a submenu that links to the read-wiki page.
@@ -1775,39 +1775,42 @@
1775 @ <div class="section">%h(blob_str(&title))</div>
1776 }else{
1777 wiki_section_label(zPrefix, zName, mFlags);
1778 }
1779 wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
 
1780 convert_href_and_output(&tail);
 
1781 blob_reset(&tail);
1782 blob_reset(&title);
1783 blob_reset(&markdown);
1784 }else if( fossil_strcmp(pWiki->zMimetype, "text/plain")==0 ){
1785 wiki_section_label(zPrefix, zName, mFlags);
1786 wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1787 @ <pre>
1788 @ %h(pWiki->zWiki)
1789 @ </pre>
1790 }else{
1791 Blob tail = BLOB_INITIALIZER;
1792 Blob title = BLOB_INITIALIZER;
1793 Blob wiki;
1794 Blob *pBody;
1795 blob_init(&wiki, pWiki->zWiki, -1);
1796 if( wiki_find_title(&wiki, &title, &tail) ){
1797 @ <div class="section">%h(blob_str(&title))</div>
1798 pBody = &tail;
1799 }else{
1800 wiki_section_label(zPrefix, zName, mFlags);
1801 pBody = &wiki;
1802 }
1803 wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1804 @ <div class="wiki">
1805 wiki_convert(pBody, 0, WIKI_BUTTONS);
1806 @ </div>
1807 blob_reset(&tail);
1808 blob_reset(&title);
1809 blob_reset(&wiki);
1810 }
1811 manifest_destroy(pWiki);
 
1812 return 1;
1813 }
1814
--- src/wiki.c
+++ src/wiki.c
@@ -1713,15 +1713,15 @@
1713 const char *zPrefix, /* "branch", "tag", or "checkin" */
1714 const char *zName, /* Name of the object */
1715 unsigned int mFlags /* Zero or more WIKIASSOC_* flags */
1716 ){
1717 if( (mFlags & WIKIASSOC_FULL_TITLE)==0 ){
1718 @ <div class="section accordion">About</div>
1719 }else if( zPrefix[0]=='c' ){ /* checkin/... */
1720 @ <div class="section accordion">About checkin %.20h(zName)</div>
1721 }else{
1722 @ <div class="section accordion">About %s(zPrefix) %h(zName)</div>
1723 }
1724 }
1725
1726 /*
1727 ** Add an "Wiki" button in a submenu that links to the read-wiki page.
@@ -1775,39 +1775,42 @@
1775 @ <div class="section">%h(blob_str(&title))</div>
1776 }else{
1777 wiki_section_label(zPrefix, zName, mFlags);
1778 }
1779 wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1780 @ <div class="accordion_panel">
1781 convert_href_and_output(&tail);
1782 @ </div>
1783 blob_reset(&tail);
1784 blob_reset(&title);
1785 blob_reset(&markdown);
1786 }else if( fossil_strcmp(pWiki->zMimetype, "text/plain")==0 ){
1787 wiki_section_label(zPrefix, zName, mFlags);
1788 wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1789 @ <div class="accordion_panel"><pre>
1790 @ %h(pWiki->zWiki)
1791 @ </pre></div>
1792 }else{
1793 Blob tail = BLOB_INITIALIZER;
1794 Blob title = BLOB_INITIALIZER;
1795 Blob wiki;
1796 Blob *pBody;
1797 blob_init(&wiki, pWiki->zWiki, -1);
1798 if( wiki_find_title(&wiki, &title, &tail) ){
1799 @ <div class="section accordion">%h(blob_str(&title))</div>
1800 pBody = &tail;
1801 }else{
1802 wiki_section_label(zPrefix, zName, mFlags);
1803 pBody = &wiki;
1804 }
1805 wiki_submenu_to_read_wiki(zPrefix, zName, mFlags);
1806 @ <div class="accordion_panel"><div class="wiki">
1807 wiki_convert(pBody, 0, WIKI_BUTTONS);
1808 @ </div></div>
1809 blob_reset(&tail);
1810 blob_reset(&title);
1811 blob_reset(&wiki);
1812 }
1813 manifest_destroy(pWiki);
1814 style_accordion();
1815 return 1;
1816 }
1817
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -174,11 +174,11 @@
174174
#### The directories where the OpenSSL include and library files are located.
175175
# The recommended usage here is to use the Sysinternals junction tool
176176
# to create a hard link between an "openssl-1.x" sub-directory of the
177177
# Fossil source code directory and the target OpenSSL source directory.
178178
#
179
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1e
179
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1f
180180
OPENSSLINCDIR = $(OPENSSLDIR)/include
181181
OPENSSLLIBDIR = $(OPENSSLDIR)
182182
183183
#### Either the directory where the Tcl library is installed or the Tcl
184184
# source code directory resides (depending on the value of the macro
@@ -633,10 +633,11 @@
633633
$(SRCDIR)/../skins/rounded1/header.txt \
634634
$(SRCDIR)/../skins/xekri/css.txt \
635635
$(SRCDIR)/../skins/xekri/details.txt \
636636
$(SRCDIR)/../skins/xekri/footer.txt \
637637
$(SRCDIR)/../skins/xekri/header.txt \
638
+ $(SRCDIR)/accordion.js \
638639
$(SRCDIR)/ci_edit.js \
639640
$(SRCDIR)/copybtn.js \
640641
$(SRCDIR)/diff.tcl \
641642
$(SRCDIR)/forum.js \
642643
$(SRCDIR)/graph.js \
643644
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -174,11 +174,11 @@
174 #### The directories where the OpenSSL include and library files are located.
175 # The recommended usage here is to use the Sysinternals junction tool
176 # to create a hard link between an "openssl-1.x" sub-directory of the
177 # Fossil source code directory and the target OpenSSL source directory.
178 #
179 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1e
180 OPENSSLINCDIR = $(OPENSSLDIR)/include
181 OPENSSLLIBDIR = $(OPENSSLDIR)
182
183 #### Either the directory where the Tcl library is installed or the Tcl
184 # source code directory resides (depending on the value of the macro
@@ -633,10 +633,11 @@
633 $(SRCDIR)/../skins/rounded1/header.txt \
634 $(SRCDIR)/../skins/xekri/css.txt \
635 $(SRCDIR)/../skins/xekri/details.txt \
636 $(SRCDIR)/../skins/xekri/footer.txt \
637 $(SRCDIR)/../skins/xekri/header.txt \
 
638 $(SRCDIR)/ci_edit.js \
639 $(SRCDIR)/copybtn.js \
640 $(SRCDIR)/diff.tcl \
641 $(SRCDIR)/forum.js \
642 $(SRCDIR)/graph.js \
643
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -174,11 +174,11 @@
174 #### The directories where the OpenSSL include and library files are located.
175 # The recommended usage here is to use the Sysinternals junction tool
176 # to create a hard link between an "openssl-1.x" sub-directory of the
177 # Fossil source code directory and the target OpenSSL source directory.
178 #
179 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1f
180 OPENSSLINCDIR = $(OPENSSLDIR)/include
181 OPENSSLLIBDIR = $(OPENSSLDIR)
182
183 #### Either the directory where the Tcl library is installed or the Tcl
184 # source code directory resides (depending on the value of the macro
@@ -633,10 +633,11 @@
633 $(SRCDIR)/../skins/rounded1/header.txt \
634 $(SRCDIR)/../skins/xekri/css.txt \
635 $(SRCDIR)/../skins/xekri/details.txt \
636 $(SRCDIR)/../skins/xekri/footer.txt \
637 $(SRCDIR)/../skins/xekri/header.txt \
638 $(SRCDIR)/accordion.js \
639 $(SRCDIR)/ci_edit.js \
640 $(SRCDIR)/copybtn.js \
641 $(SRCDIR)/diff.tcl \
642 $(SRCDIR)/forum.js \
643 $(SRCDIR)/graph.js \
644
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -174,11 +174,11 @@
174174
#### The directories where the OpenSSL include and library files are located.
175175
# The recommended usage here is to use the Sysinternals junction tool
176176
# to create a hard link between an "openssl-1.x" sub-directory of the
177177
# Fossil source code directory and the target OpenSSL source directory.
178178
#
179
-OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1e
179
+OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1f
180180
OPENSSLINCDIR = $(OPENSSLDIR)/include
181181
OPENSSLLIBDIR = $(OPENSSLDIR)
182182
183183
#### Either the directory where the Tcl library is installed or the Tcl
184184
# source code directory resides (depending on the value of the macro
185185
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -174,11 +174,11 @@
174 #### The directories where the OpenSSL include and library files are located.
175 # The recommended usage here is to use the Sysinternals junction tool
176 # to create a hard link between an "openssl-1.x" sub-directory of the
177 # Fossil source code directory and the target OpenSSL source directory.
178 #
179 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1e
180 OPENSSLINCDIR = $(OPENSSLDIR)/include
181 OPENSSLLIBDIR = $(OPENSSLDIR)
182
183 #### Either the directory where the Tcl library is installed or the Tcl
184 # source code directory resides (depending on the value of the macro
185
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -174,11 +174,11 @@
174 #### The directories where the OpenSSL include and library files are located.
175 # The recommended usage here is to use the Sysinternals junction tool
176 # to create a hard link between an "openssl-1.x" sub-directory of the
177 # Fossil source code directory and the target OpenSSL source directory.
178 #
179 OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.1.1f
180 OPENSSLINCDIR = $(OPENSSLDIR)/include
181 OPENSSLLIBDIR = $(OPENSSLDIR)
182
183 #### Either the directory where the Tcl library is installed or the Tcl
184 # source code directory resides (depending on the value of the macro
185
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -98,11 +98,11 @@
9898
!ifndef USE_SEE
9999
USE_SEE = 0
100100
!endif
101101
102102
!if $(FOSSIL_ENABLE_SSL)!=0
103
-SSLDIR = $(B)\compat\openssl-1.1.1e
103
+SSLDIR = $(B)\compat\openssl-1.1.1f
104104
SSLINCDIR = $(SSLDIR)\include
105105
!if $(FOSSIL_DYNAMIC_BUILD)!=0
106106
SSLLIBDIR = $(SSLDIR)
107107
!else
108108
SSLLIBDIR = $(SSLDIR)
@@ -540,10 +540,11 @@
540540
$(SRCDIR)\..\skins\rounded1\header.txt \
541541
$(SRCDIR)\..\skins\xekri\css.txt \
542542
$(SRCDIR)\..\skins\xekri\details.txt \
543543
$(SRCDIR)\..\skins\xekri\footer.txt \
544544
$(SRCDIR)\..\skins\xekri\header.txt \
545
+ $(SRCDIR)\accordion.js \
545546
$(SRCDIR)\ci_edit.js \
546547
$(SRCDIR)\copybtn.js \
547548
$(SRCDIR)\diff.tcl \
548549
$(SRCDIR)\forum.js \
549550
$(SRCDIR)\graph.js \
550551
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -98,11 +98,11 @@
98 !ifndef USE_SEE
99 USE_SEE = 0
100 !endif
101
102 !if $(FOSSIL_ENABLE_SSL)!=0
103 SSLDIR = $(B)\compat\openssl-1.1.1e
104 SSLINCDIR = $(SSLDIR)\include
105 !if $(FOSSIL_DYNAMIC_BUILD)!=0
106 SSLLIBDIR = $(SSLDIR)
107 !else
108 SSLLIBDIR = $(SSLDIR)
@@ -540,10 +540,11 @@
540 $(SRCDIR)\..\skins\rounded1\header.txt \
541 $(SRCDIR)\..\skins\xekri\css.txt \
542 $(SRCDIR)\..\skins\xekri\details.txt \
543 $(SRCDIR)\..\skins\xekri\footer.txt \
544 $(SRCDIR)\..\skins\xekri\header.txt \
 
545 $(SRCDIR)\ci_edit.js \
546 $(SRCDIR)\copybtn.js \
547 $(SRCDIR)\diff.tcl \
548 $(SRCDIR)\forum.js \
549 $(SRCDIR)\graph.js \
550
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -98,11 +98,11 @@
98 !ifndef USE_SEE
99 USE_SEE = 0
100 !endif
101
102 !if $(FOSSIL_ENABLE_SSL)!=0
103 SSLDIR = $(B)\compat\openssl-1.1.1f
104 SSLINCDIR = $(SSLDIR)\include
105 !if $(FOSSIL_DYNAMIC_BUILD)!=0
106 SSLLIBDIR = $(SSLDIR)
107 !else
108 SSLLIBDIR = $(SSLDIR)
@@ -540,10 +540,11 @@
540 $(SRCDIR)\..\skins\rounded1\header.txt \
541 $(SRCDIR)\..\skins\xekri\css.txt \
542 $(SRCDIR)\..\skins\xekri\details.txt \
543 $(SRCDIR)\..\skins\xekri\footer.txt \
544 $(SRCDIR)\..\skins\xekri\header.txt \
545 $(SRCDIR)\accordion.js \
546 $(SRCDIR)\ci_edit.js \
547 $(SRCDIR)\copybtn.js \
548 $(SRCDIR)\diff.tcl \
549 $(SRCDIR)\forum.js \
550 $(SRCDIR)\graph.js \
551
+1 -1
--- www/build.wiki
+++ www/build.wiki
@@ -161,11 +161,11 @@
161161
the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
162162
first <a href="https://www.openssl.org/source/">download the official
163163
source code for OpenSSL</a> and extract it to an appropriately named
164164
"<b>openssl-X.Y.ZA</b>" subdirectory within the local
165165
[/tree?ci=trunk&name=compat | compat] directory (e.g.
166
-"<b>compat/openssl-1.1.1e</b>"), then make sure that some recent
166
+"<b>compat/openssl-1.1.1f</b>"), then make sure that some recent
167167
<a href="http://www.perl.org/">Perl</a> binaries are installed locally,
168168
and finally run one of the following commands:
169169
<blockquote><pre>
170170
nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
171171
</pre></blockquote>
172172
173173
ADDED www/css-tricks.md
--- www/build.wiki
+++ www/build.wiki
@@ -161,11 +161,11 @@
161 the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
162 first <a href="https://www.openssl.org/source/">download the official
163 source code for OpenSSL</a> and extract it to an appropriately named
164 "<b>openssl-X.Y.ZA</b>" subdirectory within the local
165 [/tree?ci=trunk&name=compat | compat] directory (e.g.
166 "<b>compat/openssl-1.1.1e</b>"), then make sure that some recent
167 <a href="http://www.perl.org/">Perl</a> binaries are installed locally,
168 and finally run one of the following commands:
169 <blockquote><pre>
170 nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
171 </pre></blockquote>
172
173 DDED www/css-tricks.md
--- www/build.wiki
+++ www/build.wiki
@@ -161,11 +161,11 @@
161 the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
162 first <a href="https://www.openssl.org/source/">download the official
163 source code for OpenSSL</a> and extract it to an appropriately named
164 "<b>openssl-X.Y.ZA</b>" subdirectory within the local
165 [/tree?ci=trunk&name=compat | compat] directory (e.g.
166 "<b>compat/openssl-1.1.1f</b>"), then make sure that some recent
167 <a href="http://www.perl.org/">Perl</a> binaries are installed locally,
168 and finally run one of the following commands:
169 <blockquote><pre>
170 nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
171 </pre></blockquote>
172
173 DDED www/css-tricks.md
--- a/www/css-tricks.md
+++ b/www/css-tricks.md
@@ -0,0 +1,35 @@
1
+# Fossil CSS Tips and Tricks
2
+
3
+Many Overriding Default Rules
4
+
5
+One behavior of the skinning system works considerably differently
6
+from the cascading nature of CSS: if a skin appliand Tricks
7
+
8
+Many has a built-in default value, Fossil elides the entire
9
+default definition for that rule. i.e., the skin's definition is the
10
+only one which is applied, rather than cascading the definition from
11
+the default value.
12
+
13
+For example, if Fossil has a default CSS rule which looks like:
14
+
15
+```css
16
+div.foo {
17
+ font-size: 120%;
18
+ margin-left: 1em;
19
+}
20
+```
21
+
22
+And a skin has:
23
+
24
+```css
25
+div.foo {}
26
+```
27
+
28
+Then Fossil will *not* emit its default rule and the user's copy will
29
+become the only definition of that CSS rule. This is different from
30
+normal CSS cascading rules, in which the above sequence would result
31
+in, effectively, the top set of rules being applied because the second
32
+(empty) one does not override anything from the first.
33
+
34
+If a skin applies a given selector more than once, or imports external
35
+style sheets which do, those cascade following CSS's normal rulesr
--- a/www/css-tricks.md
+++ b/www/css-tricks.md
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/css-tricks.md
+++ b/www/css-tricks.md
@@ -0,0 +1,35 @@
1 # Fossil CSS Tips and Tricks
2
3 Many Overriding Default Rules
4
5 One behavior of the skinning system works considerably differently
6 from the cascading nature of CSS: if a skin appliand Tricks
7
8 Many has a built-in default value, Fossil elides the entire
9 default definition for that rule. i.e., the skin's definition is the
10 only one which is applied, rather than cascading the definition from
11 the default value.
12
13 For example, if Fossil has a default CSS rule which looks like:
14
15 ```css
16 div.foo {
17 font-size: 120%;
18 margin-left: 1em;
19 }
20 ```
21
22 And a skin has:
23
24 ```css
25 div.foo {}
26 ```
27
28 Then Fossil will *not* emit its default rule and the user's copy will
29 become the only definition of that CSS rule. This is different from
30 normal CSS cascading rules, in which the above sequence would result
31 in, effectively, the top set of rules being applied because the second
32 (empty) one does not override anything from the first.
33
34 If a skin applies a given selector more than once, or imports external
35 style sheets which do, those cascade following CSS's normal rulesr
+2 -2
--- www/defcsp.md
+++ www/defcsp.md
@@ -319,20 +319,20 @@
319319
320320
The best place to do that is from the [`th1-setup`
321321
script](./th1-hooks.md), which runs before TH1 processing happens during
322322
skin processing:
323323
324
- $ fossil set th1-setup "set default_csp {default-src: 'self'}"
324
+ $ fossil set th1-setup "set default_csp {default-src 'self'}"
325325
326326
This is the cleanest method, allowing you to set a custom CSP without
327327
recompiling Fossil or providing a hand-written `<head>` section in the
328328
Header section of a custom skin.
329329
330330
You can’t remove the CSP entirely with this method, but you can get the
331331
same effect by telling the browser there are no content restrictions:
332332
333
- $ fossil set th1-setup 'set default_csp {default-src: *}'
333
+ $ fossil set th1-setup 'set default_csp {default-src *}'
334334
335335
336336
### <a name="header"></a>Custom Skin Header
337337
338338
Fossil only inserts a CSP into the HTML pages it generates when the
339339
--- www/defcsp.md
+++ www/defcsp.md
@@ -319,20 +319,20 @@
319
320 The best place to do that is from the [`th1-setup`
321 script](./th1-hooks.md), which runs before TH1 processing happens during
322 skin processing:
323
324 $ fossil set th1-setup "set default_csp {default-src: 'self'}"
325
326 This is the cleanest method, allowing you to set a custom CSP without
327 recompiling Fossil or providing a hand-written `<head>` section in the
328 Header section of a custom skin.
329
330 You can’t remove the CSP entirely with this method, but you can get the
331 same effect by telling the browser there are no content restrictions:
332
333 $ fossil set th1-setup 'set default_csp {default-src: *}'
334
335
336 ### <a name="header"></a>Custom Skin Header
337
338 Fossil only inserts a CSP into the HTML pages it generates when the
339
--- www/defcsp.md
+++ www/defcsp.md
@@ -319,20 +319,20 @@
319
320 The best place to do that is from the [`th1-setup`
321 script](./th1-hooks.md), which runs before TH1 processing happens during
322 skin processing:
323
324 $ fossil set th1-setup "set default_csp {default-src 'self'}"
325
326 This is the cleanest method, allowing you to set a custom CSP without
327 recompiling Fossil or providing a hand-written `<head>` section in the
328 Header section of a custom skin.
329
330 You can’t remove the CSP entirely with this method, but you can get the
331 same effect by telling the browser there are no content restrictions:
332
333 $ fossil set th1-setup 'set default_csp {default-src *}'
334
335
336 ### <a name="header"></a>Custom Skin Header
337
338 Fossil only inserts a CSP into the HTML pages it generates when the
339
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -28,10 +28,11 @@
2828
checkin.wiki {Check-in Checklist}
2929
childprojects.wiki {Child Projects}
3030
copyright-release.html {Contributor License Agreement}
3131
concepts.wiki {Fossil Core Concepts}
3232
contribute.wiki {Contributing Code or Documentation To The Fossil Project}
33
+ css-tricks.md {Fossil CSS Tips and Tricks}
3334
customgraph.md {Theming: Customizing the Timeline Graph}
3435
customskin.md {Theming: Customizing The Appearance of Web Pages}
3536
customskin.md {Custom Skins}
3637
custom_ticket.wiki {Customizing The Ticket System}
3738
defcsp.md {The Default Content Security Policy}
3839
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -28,10 +28,11 @@
28 checkin.wiki {Check-in Checklist}
29 childprojects.wiki {Child Projects}
30 copyright-release.html {Contributor License Agreement}
31 concepts.wiki {Fossil Core Concepts}
32 contribute.wiki {Contributing Code or Documentation To The Fossil Project}
 
33 customgraph.md {Theming: Customizing the Timeline Graph}
34 customskin.md {Theming: Customizing The Appearance of Web Pages}
35 customskin.md {Custom Skins}
36 custom_ticket.wiki {Customizing The Ticket System}
37 defcsp.md {The Default Content Security Policy}
38
--- www/mkindex.tcl
+++ www/mkindex.tcl
@@ -28,10 +28,11 @@
28 checkin.wiki {Check-in Checklist}
29 childprojects.wiki {Child Projects}
30 copyright-release.html {Contributor License Agreement}
31 concepts.wiki {Fossil Core Concepts}
32 contribute.wiki {Contributing Code or Documentation To The Fossil Project}
33 css-tricks.md {Fossil CSS Tips and Tricks}
34 customgraph.md {Theming: Customizing the Timeline Graph}
35 customskin.md {Theming: Customizing The Appearance of Web Pages}
36 customskin.md {Custom Skins}
37 custom_ticket.wiki {Customizing The Ticket System}
38 defcsp.md {The Default Content Security Policy}
39
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -76,10 +76,11 @@
7676
<li><a href="whyusefossil.wiki">Control &mdash; Benefits Of Version</a></li>
7777
<li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
7878
<li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; How To</a></li>
7979
<li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li>
8080
<li><a href="qandc.wiki">Criticisms &mdash; Questions And</a></li>
81
+<li><a href="css-tricks.md">CSS Tips and Tricks &mdash; Fossil</a></li>
8182
<li><a href="customskin.md"><b>Custom Skins</b></a></li>
8283
<li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; Theming:</a></li>
8384
<li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li>
8485
<li><a href="customgraph.md">Customizing the Timeline Graph &mdash; Theming:</a></li>
8586
<li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; SQLite</a></li>
@@ -121,10 +122,11 @@
121122
<li><a href="../../../wiki_rules">Formatting Rules &mdash; Wiki</a></li>
122123
<li><a href="forum.wiki">Forums &mdash; Fossil</a></li>
123124
<li><a href="blockchain.md"><b>Fossil As Blockchain</b></a></li>
124125
<li><a href="changes.wiki"><b>Fossil Changelog</b></a></li>
125126
<li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li>
127
+<li><a href="css-tricks.md"><b>Fossil CSS Tips and Tricks</b></a></li>
126128
<li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li>
127129
<li><a href="delta_format.wiki"><b>Fossil Delta Format</b></a></li>
128130
<li><a href="hacker-howto.wiki"><b>Fossil Developers Guide</b></a></li>
129131
<li><a href="fileformat.wiki"><b>Fossil File Format</b></a></li>
130132
<li><a href="forum.wiki"><b>Fossil Forums</b></a></li>
@@ -284,12 +286,14 @@
284286
<li><a href="customgraph.md"><b>Theming: Customizing the Timeline Graph</b></a></li>
285287
<li><a href="theory1.wiki"><b>Thoughts On The Design Of The Fossil DVCS</b></a></li>
286288
<li><a href="custom_ticket.wiki">Ticket System &mdash; Customizing The</a></li>
287289
<li><a href="tickets.wiki">Ticket System &mdash; The Fossil</a></li>
288290
<li><a href="customgraph.md">Timeline Graph &mdash; Theming: Customizing the</a></li>
291
+<li><a href="css-tricks.md">Tips and Tricks &mdash; Fossil CSS</a></li>
289292
<li><a href="hints.wiki">Tips And Usage Hints &mdash; Fossil</a></li>
290293
<li><a href="bugtheory.wiki">Tracking In Fossil &mdash; Bug</a></li>
294
+<li><a href="css-tricks.md">Tricks &mdash; Fossil CSS Tips and</a></li>
291295
<li><a href="unvers.wiki"><b>Unversioned Files</b></a></li>
292296
<li><a href="fiveminutes.wiki"><b>Up and Running in 5 Minutes as a Single User</b></a></li>
293297
<li><a href="hints.wiki">Usage Hints &mdash; Fossil Tips And</a></li>
294298
<li><a href="javascript.md"><b>Use of JavaScript in Fossil</b></a></li>
295299
<li><a href="fiveminutes.wiki">User &mdash; Up and Running in 5 Minutes as a Single</a></li>
296300
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -76,10 +76,11 @@
76 <li><a href="whyusefossil.wiki">Control &mdash; Benefits Of Version</a></li>
77 <li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
78 <li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; How To</a></li>
79 <li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li>
80 <li><a href="qandc.wiki">Criticisms &mdash; Questions And</a></li>
 
81 <li><a href="customskin.md"><b>Custom Skins</b></a></li>
82 <li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; Theming:</a></li>
83 <li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li>
84 <li><a href="customgraph.md">Customizing the Timeline Graph &mdash; Theming:</a></li>
85 <li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; SQLite</a></li>
@@ -121,10 +122,11 @@
121 <li><a href="../../../wiki_rules">Formatting Rules &mdash; Wiki</a></li>
122 <li><a href="forum.wiki">Forums &mdash; Fossil</a></li>
123 <li><a href="blockchain.md"><b>Fossil As Blockchain</b></a></li>
124 <li><a href="changes.wiki"><b>Fossil Changelog</b></a></li>
125 <li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li>
 
126 <li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li>
127 <li><a href="delta_format.wiki"><b>Fossil Delta Format</b></a></li>
128 <li><a href="hacker-howto.wiki"><b>Fossil Developers Guide</b></a></li>
129 <li><a href="fileformat.wiki"><b>Fossil File Format</b></a></li>
130 <li><a href="forum.wiki"><b>Fossil Forums</b></a></li>
@@ -284,12 +286,14 @@
284 <li><a href="customgraph.md"><b>Theming: Customizing the Timeline Graph</b></a></li>
285 <li><a href="theory1.wiki"><b>Thoughts On The Design Of The Fossil DVCS</b></a></li>
286 <li><a href="custom_ticket.wiki">Ticket System &mdash; Customizing The</a></li>
287 <li><a href="tickets.wiki">Ticket System &mdash; The Fossil</a></li>
288 <li><a href="customgraph.md">Timeline Graph &mdash; Theming: Customizing the</a></li>
 
289 <li><a href="hints.wiki">Tips And Usage Hints &mdash; Fossil</a></li>
290 <li><a href="bugtheory.wiki">Tracking In Fossil &mdash; Bug</a></li>
 
291 <li><a href="unvers.wiki"><b>Unversioned Files</b></a></li>
292 <li><a href="fiveminutes.wiki"><b>Up and Running in 5 Minutes as a Single User</b></a></li>
293 <li><a href="hints.wiki">Usage Hints &mdash; Fossil Tips And</a></li>
294 <li><a href="javascript.md"><b>Use of JavaScript in Fossil</b></a></li>
295 <li><a href="fiveminutes.wiki">User &mdash; Up and Running in 5 Minutes as a Single</a></li>
296
--- www/permutedindex.html
+++ www/permutedindex.html
@@ -76,10 +76,11 @@
76 <li><a href="whyusefossil.wiki">Control &mdash; Benefits Of Version</a></li>
77 <li><a href="concepts.wiki">Core Concepts &mdash; Fossil</a></li>
78 <li><a href="newrepo.wiki">Create A New Fossil Repository &mdash; How To</a></li>
79 <li><a href="private.wiki"><b>Creating, Syncing, and Deleting Private Branches</b></a></li>
80 <li><a href="qandc.wiki">Criticisms &mdash; Questions And</a></li>
81 <li><a href="css-tricks.md">CSS Tips and Tricks &mdash; Fossil</a></li>
82 <li><a href="customskin.md"><b>Custom Skins</b></a></li>
83 <li><a href="customskin.md">Customizing The Appearance of Web Pages &mdash; Theming:</a></li>
84 <li><a href="custom_ticket.wiki"><b>Customizing The Ticket System</b></a></li>
85 <li><a href="customgraph.md">Customizing the Timeline Graph &mdash; Theming:</a></li>
86 <li><a href="tech_overview.wiki">Databases Used By Fossil &mdash; SQLite</a></li>
@@ -121,10 +122,11 @@
122 <li><a href="../../../wiki_rules">Formatting Rules &mdash; Wiki</a></li>
123 <li><a href="forum.wiki">Forums &mdash; Fossil</a></li>
124 <li><a href="blockchain.md"><b>Fossil As Blockchain</b></a></li>
125 <li><a href="changes.wiki"><b>Fossil Changelog</b></a></li>
126 <li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li>
127 <li><a href="css-tricks.md"><b>Fossil CSS Tips and Tricks</b></a></li>
128 <li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li>
129 <li><a href="delta_format.wiki"><b>Fossil Delta Format</b></a></li>
130 <li><a href="hacker-howto.wiki"><b>Fossil Developers Guide</b></a></li>
131 <li><a href="fileformat.wiki"><b>Fossil File Format</b></a></li>
132 <li><a href="forum.wiki"><b>Fossil Forums</b></a></li>
@@ -284,12 +286,14 @@
286 <li><a href="customgraph.md"><b>Theming: Customizing the Timeline Graph</b></a></li>
287 <li><a href="theory1.wiki"><b>Thoughts On The Design Of The Fossil DVCS</b></a></li>
288 <li><a href="custom_ticket.wiki">Ticket System &mdash; Customizing The</a></li>
289 <li><a href="tickets.wiki">Ticket System &mdash; The Fossil</a></li>
290 <li><a href="customgraph.md">Timeline Graph &mdash; Theming: Customizing the</a></li>
291 <li><a href="css-tricks.md">Tips and Tricks &mdash; Fossil CSS</a></li>
292 <li><a href="hints.wiki">Tips And Usage Hints &mdash; Fossil</a></li>
293 <li><a href="bugtheory.wiki">Tracking In Fossil &mdash; Bug</a></li>
294 <li><a href="css-tricks.md">Tricks &mdash; Fossil CSS Tips and</a></li>
295 <li><a href="unvers.wiki"><b>Unversioned Files</b></a></li>
296 <li><a href="fiveminutes.wiki"><b>Up and Running in 5 Minutes as a Single User</b></a></li>
297 <li><a href="hints.wiki">Usage Hints &mdash; Fossil Tips And</a></li>
298 <li><a href="javascript.md"><b>Use of JavaScript in Fossil</b></a></li>
299 <li><a href="fiveminutes.wiki">User &mdash; Up and Running in 5 Minutes as a Single</a></li>
300

Keyboard Shortcuts

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