Fossil SCM

A more invasive implementation of the convenience "copy" button before date/time strings that tries to work around objections raised on the Forum.

drh 2026-04-16 19:02 UTC trunk
Commit 68b27378f5f3e80e2819485a68e7a8c516cdd217f8ad22c92d0e236d3b2f8625
+14 -9
--- src/copybtn.js
+++ src/copybtn.js
@@ -18,13 +18,17 @@
1818
** <cchLength>, respectively. Set <cchLength> to "-1" to explicitly remove the
1919
** previous copy length limit.
2020
**
2121
** HTML snippet for statically created buttons:
2222
**
23
-** <button class="copy-button" id="copy-<idTarget>"
24
-** data-copytarget="<idTarget>" data-copylength="<cchLength>">
25
-** <span></span>
23
+** <button
24
+** class="copy-button"
25
+** id="copy-<idTarget>"
26
+** data-copytarget="<idTarget>"
27
+** data-copylength="<cchLength>"
28
+** data-content="<content>">
29
+** <span></span>
2630
** </button>
2731
*/
2832
function makeCopyButton(idTarget,bFlipped,cchLength){
2933
var elButton = document.createElement("button");
3034
elButton.className = "copy-button";
@@ -62,16 +66,17 @@
6266
e.stopPropagation();
6367
if( this.disabled ) return; /* This check is probably redundant. */
6468
var idTarget = this.getAttribute("data-copytarget");
6569
var elTarget = document.getElementById(idTarget);
6670
if( elTarget ){
67
- var text = elTarget.innerText.replace(/^\s+|\s+$/g,"");
68
- var cchLength = parseInt(this.getAttribute("data-copylength"));
69
- if( !isNaN(cchLength) && cchLength>0 ){
70
- text = text.slice(0,cchLength); /* Assume single-byte chars. */
71
- }else if( /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/.test(text) ){
72
- text = text.replace(' ', 'T');
71
+ var text = this.getAttribute("data-content");
72
+ if( !text ){
73
+ text = elTarget.innerText.replace(/^\s+|\s+$/g,"");
74
+ var cchLength = parseInt(this.getAttribute("data-copylength"));
75
+ if( !isNaN(cchLength) && cchLength>0 ){
76
+ text = text.slice(0,cchLength); /* Assume single-byte chars. */
77
+ }
7378
}
7479
copyTextToClipboard(text);
7580
}
7681
}
7782
/* Create a temporary <textarea> element and copy the contents to clipboard. */
7883
--- src/copybtn.js
+++ src/copybtn.js
@@ -18,13 +18,17 @@
18 ** <cchLength>, respectively. Set <cchLength> to "-1" to explicitly remove the
19 ** previous copy length limit.
20 **
21 ** HTML snippet for statically created buttons:
22 **
23 ** <button class="copy-button" id="copy-<idTarget>"
24 ** data-copytarget="<idTarget>" data-copylength="<cchLength>">
25 ** <span></span>
 
 
 
 
26 ** </button>
27 */
28 function makeCopyButton(idTarget,bFlipped,cchLength){
29 var elButton = document.createElement("button");
30 elButton.className = "copy-button";
@@ -62,16 +66,17 @@
62 e.stopPropagation();
63 if( this.disabled ) return; /* This check is probably redundant. */
64 var idTarget = this.getAttribute("data-copytarget");
65 var elTarget = document.getElementById(idTarget);
66 if( elTarget ){
67 var text = elTarget.innerText.replace(/^\s+|\s+$/g,"");
68 var cchLength = parseInt(this.getAttribute("data-copylength"));
69 if( !isNaN(cchLength) && cchLength>0 ){
70 text = text.slice(0,cchLength); /* Assume single-byte chars. */
71 }else if( /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/.test(text) ){
72 text = text.replace(' ', 'T');
 
73 }
74 copyTextToClipboard(text);
75 }
76 }
77 /* Create a temporary <textarea> element and copy the contents to clipboard. */
78
--- src/copybtn.js
+++ src/copybtn.js
@@ -18,13 +18,17 @@
18 ** <cchLength>, respectively. Set <cchLength> to "-1" to explicitly remove the
19 ** previous copy length limit.
20 **
21 ** HTML snippet for statically created buttons:
22 **
23 ** <button
24 ** class="copy-button"
25 ** id="copy-<idTarget>"
26 ** data-copytarget="<idTarget>"
27 ** data-copylength="<cchLength>"
28 ** data-content="<content>">
29 ** <span></span>
30 ** </button>
31 */
32 function makeCopyButton(idTarget,bFlipped,cchLength){
33 var elButton = document.createElement("button");
34 elButton.className = "copy-button";
@@ -62,16 +66,17 @@
66 e.stopPropagation();
67 if( this.disabled ) return; /* This check is probably redundant. */
68 var idTarget = this.getAttribute("data-copytarget");
69 var elTarget = document.getElementById(idTarget);
70 if( elTarget ){
71 var text = this.getAttribute("data-content");
72 if( !text ){
73 text = elTarget.innerText.replace(/^\s+|\s+$/g,"");
74 var cchLength = parseInt(this.getAttribute("data-copylength"));
75 if( !isNaN(cchLength) && cchLength>0 ){
76 text = text.slice(0,cchLength); /* Assume single-byte chars. */
77 }
78 }
79 copyTextToClipboard(text);
80 }
81 }
82 /* Create a temporary <textarea> element and copy the contents to clipboard. */
83
+15 -11
--- src/forum.c
+++ src/forum.c
@@ -763,12 +763,13 @@
763763
char *zQuery /* Common query string */
764764
){
765765
char *zPosterName; /* Name of user who originally made this post */
766766
char *zEditorName; /* Name of user who provided the current edit */
767767
char *zDate; /* The time/date string */
768
- char *zDateTag; /* Tag for the time/date text */
768
+ char *zDateZulu; /* The date/time string in Zulul time */
769769
char *zHist; /* History query string */
770
+ char *z;
770771
Manifest *pManifest; /* Manifest comprising the current post */
771772
int bPrivate; /* True for posts awaiting moderation */
772773
int bSameUser; /* True if author is also the reader */
773774
int iIndent; /* Indent level */
774775
int iClosed; /* True if (sub)thread is closed */
@@ -802,44 +803,47 @@
802803
** varies depending on whether:
803804
** * The post is unedited
804805
** * The post was last edited by the original author
805806
** * The post was last edited by a different person
806807
*/
807
- if( p->pEditHead ){
808
- zDate = db_text(0, "SELECT datetime(%.17g,toLocal())",
809
- p->pEditHead->rDate);
810
- }else{
808
+ if( !p->pEditHead ){
811809
zPosterName = forum_post_display_name(p, pManifest);
812810
zEditorName = zPosterName;
813811
}
814812
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", p->rDate);
815
- zDateTag = mprintf("datetag-%d", p->fpid);
813
+ zDateZulu = db_text(0,
814
+ "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ',%.17g)",
815
+ p->rDate);
816816
if( p->pEditPrev ){
817817
zPosterName = forum_post_display_name(p->pEditHead, 0);
818818
zEditorName = forum_post_display_name(p, pManifest);
819819
zHist = bHist ? "" : zQuery[0]==0 ? "?hist" : "&hist";
820820
@ <h3 class='forumPostHdr'>(%d(p->sid)\
821821
@ .%0*d(fossil_num_digits(p->nEdit))(p->rev))
822822
if( fossil_strcmp(zPosterName, zEditorName)==0 ){
823
- @ By %s(zPosterName) on %h(zDate) edited from \
823
+ @ By %s(zPosterName) on \
824
+ style_copy_button(1, 0, 0, 0, zDateZulu, "%h", zDate);
825
+ @ &#32;edited from \
824826
@ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
825827
@ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
826828
}else{
827829
@ Originally by %s(zPosterName) \
828
- @ with edits by %s(zEditorName) on %h(zDate) from \
830
+ @ with edits by %s(zEditorName) on \
831
+ style_copy_button(1, 0, 0, 0, zDateZulu, "%h", zDate);
832
+ @ &#32;from \
829833
@ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
830834
@ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
831835
}
832836
}else{
833837
zPosterName = forum_post_display_name(p, pManifest);
834838
@ <h3 class='forumPostHdr'>(%d(p->sid))
835839
@ By %s(zPosterName) on \
836
- style_copy_button(1, zDateTag, 0, 0, "%h", zDate);
837
- cgi_printf(" ");
840
+ style_copy_button(1, 0, 0, 0, zDateZulu, "%h", zDate);
841
+ cgi_append_content(" ", 1);
838842
}
839843
fossil_free(zDate);
840
- fossil_free(zDateTag);
844
+ fossil_free(zDateZulu);
841845
842846
843847
/* If debugging is enabled, link to the artifact page. */
844848
if( g.perm.Debug ){
845849
@ <span class="debug">\
846850
--- src/forum.c
+++ src/forum.c
@@ -763,12 +763,13 @@
763 char *zQuery /* Common query string */
764 ){
765 char *zPosterName; /* Name of user who originally made this post */
766 char *zEditorName; /* Name of user who provided the current edit */
767 char *zDate; /* The time/date string */
768 char *zDateTag; /* Tag for the time/date text */
769 char *zHist; /* History query string */
 
770 Manifest *pManifest; /* Manifest comprising the current post */
771 int bPrivate; /* True for posts awaiting moderation */
772 int bSameUser; /* True if author is also the reader */
773 int iIndent; /* Indent level */
774 int iClosed; /* True if (sub)thread is closed */
@@ -802,44 +803,47 @@
802 ** varies depending on whether:
803 ** * The post is unedited
804 ** * The post was last edited by the original author
805 ** * The post was last edited by a different person
806 */
807 if( p->pEditHead ){
808 zDate = db_text(0, "SELECT datetime(%.17g,toLocal())",
809 p->pEditHead->rDate);
810 }else{
811 zPosterName = forum_post_display_name(p, pManifest);
812 zEditorName = zPosterName;
813 }
814 zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", p->rDate);
815 zDateTag = mprintf("datetag-%d", p->fpid);
 
 
816 if( p->pEditPrev ){
817 zPosterName = forum_post_display_name(p->pEditHead, 0);
818 zEditorName = forum_post_display_name(p, pManifest);
819 zHist = bHist ? "" : zQuery[0]==0 ? "?hist" : "&hist";
820 @ <h3 class='forumPostHdr'>(%d(p->sid)\
821 @ .%0*d(fossil_num_digits(p->nEdit))(p->rev))
822 if( fossil_strcmp(zPosterName, zEditorName)==0 ){
823 @ By %s(zPosterName) on %h(zDate) edited from \
 
 
824 @ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
825 @ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
826 }else{
827 @ Originally by %s(zPosterName) \
828 @ with edits by %s(zEditorName) on %h(zDate) from \
 
 
829 @ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
830 @ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
831 }
832 }else{
833 zPosterName = forum_post_display_name(p, pManifest);
834 @ <h3 class='forumPostHdr'>(%d(p->sid))
835 @ By %s(zPosterName) on \
836 style_copy_button(1, zDateTag, 0, 0, "%h", zDate);
837 cgi_printf(" ");
838 }
839 fossil_free(zDate);
840 fossil_free(zDateTag);
841
842
843 /* If debugging is enabled, link to the artifact page. */
844 if( g.perm.Debug ){
845 @ <span class="debug">\
846
--- src/forum.c
+++ src/forum.c
@@ -763,12 +763,13 @@
763 char *zQuery /* Common query string */
764 ){
765 char *zPosterName; /* Name of user who originally made this post */
766 char *zEditorName; /* Name of user who provided the current edit */
767 char *zDate; /* The time/date string */
768 char *zDateZulu; /* The date/time string in Zulul time */
769 char *zHist; /* History query string */
770 char *z;
771 Manifest *pManifest; /* Manifest comprising the current post */
772 int bPrivate; /* True for posts awaiting moderation */
773 int bSameUser; /* True if author is also the reader */
774 int iIndent; /* Indent level */
775 int iClosed; /* True if (sub)thread is closed */
@@ -802,44 +803,47 @@
803 ** varies depending on whether:
804 ** * The post is unedited
805 ** * The post was last edited by the original author
806 ** * The post was last edited by a different person
807 */
808 if( !p->pEditHead ){
 
 
 
809 zPosterName = forum_post_display_name(p, pManifest);
810 zEditorName = zPosterName;
811 }
812 zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", p->rDate);
813 zDateZulu = db_text(0,
814 "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ',%.17g)",
815 p->rDate);
816 if( p->pEditPrev ){
817 zPosterName = forum_post_display_name(p->pEditHead, 0);
818 zEditorName = forum_post_display_name(p, pManifest);
819 zHist = bHist ? "" : zQuery[0]==0 ? "?hist" : "&hist";
820 @ <h3 class='forumPostHdr'>(%d(p->sid)\
821 @ .%0*d(fossil_num_digits(p->nEdit))(p->rev))
822 if( fossil_strcmp(zPosterName, zEditorName)==0 ){
823 @ By %s(zPosterName) on \
824 style_copy_button(1, 0, 0, 0, zDateZulu, "%h", zDate);
825 @ &#32;edited from \
826 @ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
827 @ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
828 }else{
829 @ Originally by %s(zPosterName) \
830 @ with edits by %s(zEditorName) on \
831 style_copy_button(1, 0, 0, 0, zDateZulu, "%h", zDate);
832 @ &#32;from \
833 @ %z(href("%R/forumpost/%S%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
834 @ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
835 }
836 }else{
837 zPosterName = forum_post_display_name(p, pManifest);
838 @ <h3 class='forumPostHdr'>(%d(p->sid))
839 @ By %s(zPosterName) on \
840 style_copy_button(1, 0, 0, 0, zDateZulu, "%h", zDate);
841 cgi_append_content(" ", 1);
842 }
843 fossil_free(zDate);
844 fossil_free(zDateZulu);
845
846
847 /* If debugging is enabled, link to the artifact page. */
848 if( g.perm.Debug ){
849 @ <span class="debug">\
850
+15 -9
--- src/info.c
+++ src/info.c
@@ -945,12 +945,17 @@
945945
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
946946
rid
947947
);
948948
isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid);
949949
db_prepare(&q1,
950
- "SELECT uuid, datetime(mtime,toLocal(),'subsec'), user, comment,"
951
- " datetime(omtime,toLocal(),'subsec'), mtime"
950
+ "SELECT uuid," /* 0 */
951
+ " datetime(mtime,toLocal(),'subsec')," /* 1 */
952
+ " user," /* 2 */
953
+ " comment," /* 3 */
954
+ " datetime(omtime,toLocal(),'subsec')," /* 4 */
955
+ " mtime," /* 5 */
956
+ " strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',mtime)" /* 6 */
952957
" FROM blob, event"
953958
" WHERE blob.rid=%d"
954959
" AND event.objid=%d",
955960
rid, rid
956961
);
@@ -963,11 +968,11 @@
963968
int nUuid = db_column_bytes(&q1, 0);
964969
char *zEUser, *zEComment;
965970
const char *zUser;
966971
const char *zOrigUser;
967972
const char *zComment;
968
- const char *zDate;
973
+ const char *zDate, *zZulu;
969974
const char *zOrigDate;
970975
int okWiki = 0;
971976
Blob wiki_read_links = BLOB_INITIALIZER;
972977
Blob wiki_add_links = BLOB_INITIALIZER;
973978
@@ -985,10 +990,11 @@
985990
zUser = zEUser ? zEUser : zOrigUser;
986991
zComment = db_column_text(&q1, 3);
987992
zDate = db_column_text(&q1,1);
988993
zOrigDate = db_column_text(&q1, 4);
989994
if( zOrigDate==0 ) zOrigDate = zDate;
995
+ zZulu = db_column_text(&q1, 6);
990996
@ <div class="section accordion">Overview</div>
991997
@ <div class="accordion_panel">
992998
@ <table class="label-value">
993999
@ <tr><th>Comment:</th><td class="infoComment">\
9941000
@ %!W(zEComment?zEComment:zComment)</td></tr>
@@ -1027,11 +1033,11 @@
10271033
" AND +tag.tagname GLOB 'sym-*'", rid);
10281034
while( db_step(&q2)==SQLITE_ROW ){
10291035
const char *zTagName = db_column_text(&q2, 0);
10301036
if( fossil_strcmp(zTagName,zBrName)==0 ){
10311037
cgi_printf(" | ");
1032
- style_copy_button(1, "name-br", 0, 0, "%z%h</a>",
1038
+ style_copy_button(1, "name-br", 0, 0, 0, "%z%h</a>",
10331039
href("%R/timeline?r=%T&unhide",zTagName), zTagName);
10341040
cgi_printf("\n");
10351041
if( wiki_tagid2("branch",zTagName)!=0 ){
10361042
blob_appendf(&wiki_read_links, " | %z%h</a>",
10371043
href("%R/%s?name=branch/%h",
@@ -1063,18 +1069,18 @@
10631069
@ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
10641070
@ </td>
10651071
@ </tr>
10661072
10671073
@ <tr><th>%s(hname_alg(nUuid)):</th><td>
1068
- style_copy_button(1, "hash-ci", 0, 2, "%.32s<wbr>%s", zUuid, zUuid+32);
1074
+ style_copy_button(1, "hash-ci", 0, 2, 0, "%.32s<wbr>%s", zUuid, zUuid+32);
10691075
if( g.perm.Setup ){
10701076
@ (Record ID: %d(rid))
10711077
}
10721078
@ </td></tr>
10731079
@ <tr><th>User&nbsp;&amp;&nbsp;Date:</th><td>
10741080
hyperlink_to_user(zUser,zDate," on ");
1075
- style_copy_button(1, "date-ci", 0, 0,
1081
+ style_copy_button(1, 0, 0, 0, zZulu,
10761082
"%z%h</a>", href("%R/timeline?c=%T",zDate), zDate);
10771083
@ </td></tr>
10781084
// hyperlink_to_date(zDate, "</td></tr>");
10791085
if( zEComment ){
10801086
@ <tr><th>Original&nbsp;Comment:</th>
@@ -2429,11 +2435,11 @@
24292435
}
24302436
style_header("Hex Artifact Content");
24312437
zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
24322438
etag_check(ETAG_HASH, zUuid);
24332439
@ <h2>Artifact
2434
- style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2440
+ style_copy_button(1, "hash-ar", 0, 2, 0, "%s", zUuid);
24352441
if( g.perm.Setup ){
24362442
@ (%d(rid)):</h2>
24372443
}else{
24382444
@ :</h2>
24392445
}
@@ -2862,11 +2868,11 @@
28622868
Blob path;
28632869
blob_zero(&path);
28642870
hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
28652871
zPath = blob_str(&path);
28662872
@ <h2>File %s(zPath) artifact \
2867
- style_copy_button(1,"hash-fid",0,0,"%z%S</a> ",
2873
+ style_copy_button(1,"hash-fid",0,0,0,"%z%S</a> ",
28682874
href("%R/info/%s",zUuid),zUuid);
28692875
if( isBranchCI ){
28702876
@ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
28712877
}else if( isSymbolicCI ){
28722878
@ part of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
@@ -2886,11 +2892,11 @@
28862892
}
28872893
blob_init(&downloadName, zName, -1);
28882894
objType = OBJTYPE_CONTENT;
28892895
}else{
28902896
@ <h2>Artifact
2891
- style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2897
+ style_copy_button(1, "hash-ar", 0, 2, 0, "%s", zUuid);
28922898
if( g.perm.Setup ){
28932899
@ (%d(rid)):</h2>
28942900
}else{
28952901
@ :</h2>
28962902
}
28972903
--- src/info.c
+++ src/info.c
@@ -945,12 +945,17 @@
945 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
946 rid
947 );
948 isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid);
949 db_prepare(&q1,
950 "SELECT uuid, datetime(mtime,toLocal(),'subsec'), user, comment,"
951 " datetime(omtime,toLocal(),'subsec'), mtime"
 
 
 
 
 
952 " FROM blob, event"
953 " WHERE blob.rid=%d"
954 " AND event.objid=%d",
955 rid, rid
956 );
@@ -963,11 +968,11 @@
963 int nUuid = db_column_bytes(&q1, 0);
964 char *zEUser, *zEComment;
965 const char *zUser;
966 const char *zOrigUser;
967 const char *zComment;
968 const char *zDate;
969 const char *zOrigDate;
970 int okWiki = 0;
971 Blob wiki_read_links = BLOB_INITIALIZER;
972 Blob wiki_add_links = BLOB_INITIALIZER;
973
@@ -985,10 +990,11 @@
985 zUser = zEUser ? zEUser : zOrigUser;
986 zComment = db_column_text(&q1, 3);
987 zDate = db_column_text(&q1,1);
988 zOrigDate = db_column_text(&q1, 4);
989 if( zOrigDate==0 ) zOrigDate = zDate;
 
990 @ <div class="section accordion">Overview</div>
991 @ <div class="accordion_panel">
992 @ <table class="label-value">
993 @ <tr><th>Comment:</th><td class="infoComment">\
994 @ %!W(zEComment?zEComment:zComment)</td></tr>
@@ -1027,11 +1033,11 @@
1027 " AND +tag.tagname GLOB 'sym-*'", rid);
1028 while( db_step(&q2)==SQLITE_ROW ){
1029 const char *zTagName = db_column_text(&q2, 0);
1030 if( fossil_strcmp(zTagName,zBrName)==0 ){
1031 cgi_printf(" | ");
1032 style_copy_button(1, "name-br", 0, 0, "%z%h</a>",
1033 href("%R/timeline?r=%T&unhide",zTagName), zTagName);
1034 cgi_printf("\n");
1035 if( wiki_tagid2("branch",zTagName)!=0 ){
1036 blob_appendf(&wiki_read_links, " | %z%h</a>",
1037 href("%R/%s?name=branch/%h",
@@ -1063,18 +1069,18 @@
1063 @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
1064 @ </td>
1065 @ </tr>
1066
1067 @ <tr><th>%s(hname_alg(nUuid)):</th><td>
1068 style_copy_button(1, "hash-ci", 0, 2, "%.32s<wbr>%s", zUuid, zUuid+32);
1069 if( g.perm.Setup ){
1070 @ (Record ID: %d(rid))
1071 }
1072 @ </td></tr>
1073 @ <tr><th>User&nbsp;&amp;&nbsp;Date:</th><td>
1074 hyperlink_to_user(zUser,zDate," on ");
1075 style_copy_button(1, "date-ci", 0, 0,
1076 "%z%h</a>", href("%R/timeline?c=%T",zDate), zDate);
1077 @ </td></tr>
1078 // hyperlink_to_date(zDate, "</td></tr>");
1079 if( zEComment ){
1080 @ <tr><th>Original&nbsp;Comment:</th>
@@ -2429,11 +2435,11 @@
2429 }
2430 style_header("Hex Artifact Content");
2431 zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
2432 etag_check(ETAG_HASH, zUuid);
2433 @ <h2>Artifact
2434 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2435 if( g.perm.Setup ){
2436 @ (%d(rid)):</h2>
2437 }else{
2438 @ :</h2>
2439 }
@@ -2862,11 +2868,11 @@
2862 Blob path;
2863 blob_zero(&path);
2864 hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
2865 zPath = blob_str(&path);
2866 @ <h2>File %s(zPath) artifact \
2867 style_copy_button(1,"hash-fid",0,0,"%z%S</a> ",
2868 href("%R/info/%s",zUuid),zUuid);
2869 if( isBranchCI ){
2870 @ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
2871 }else if( isSymbolicCI ){
2872 @ part of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
@@ -2886,11 +2892,11 @@
2886 }
2887 blob_init(&downloadName, zName, -1);
2888 objType = OBJTYPE_CONTENT;
2889 }else{
2890 @ <h2>Artifact
2891 style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
2892 if( g.perm.Setup ){
2893 @ (%d(rid)):</h2>
2894 }else{
2895 @ :</h2>
2896 }
2897
--- src/info.c
+++ src/info.c
@@ -945,12 +945,17 @@
945 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
946 rid
947 );
948 isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid);
949 db_prepare(&q1,
950 "SELECT uuid," /* 0 */
951 " datetime(mtime,toLocal(),'subsec')," /* 1 */
952 " user," /* 2 */
953 " comment," /* 3 */
954 " datetime(omtime,toLocal(),'subsec')," /* 4 */
955 " mtime," /* 5 */
956 " strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',mtime)" /* 6 */
957 " FROM blob, event"
958 " WHERE blob.rid=%d"
959 " AND event.objid=%d",
960 rid, rid
961 );
@@ -963,11 +968,11 @@
968 int nUuid = db_column_bytes(&q1, 0);
969 char *zEUser, *zEComment;
970 const char *zUser;
971 const char *zOrigUser;
972 const char *zComment;
973 const char *zDate, *zZulu;
974 const char *zOrigDate;
975 int okWiki = 0;
976 Blob wiki_read_links = BLOB_INITIALIZER;
977 Blob wiki_add_links = BLOB_INITIALIZER;
978
@@ -985,10 +990,11 @@
990 zUser = zEUser ? zEUser : zOrigUser;
991 zComment = db_column_text(&q1, 3);
992 zDate = db_column_text(&q1,1);
993 zOrigDate = db_column_text(&q1, 4);
994 if( zOrigDate==0 ) zOrigDate = zDate;
995 zZulu = db_column_text(&q1, 6);
996 @ <div class="section accordion">Overview</div>
997 @ <div class="accordion_panel">
998 @ <table class="label-value">
999 @ <tr><th>Comment:</th><td class="infoComment">\
1000 @ %!W(zEComment?zEComment:zComment)</td></tr>
@@ -1027,11 +1033,11 @@
1033 " AND +tag.tagname GLOB 'sym-*'", rid);
1034 while( db_step(&q2)==SQLITE_ROW ){
1035 const char *zTagName = db_column_text(&q2, 0);
1036 if( fossil_strcmp(zTagName,zBrName)==0 ){
1037 cgi_printf(" | ");
1038 style_copy_button(1, "name-br", 0, 0, 0, "%z%h</a>",
1039 href("%R/timeline?r=%T&unhide",zTagName), zTagName);
1040 cgi_printf("\n");
1041 if( wiki_tagid2("branch",zTagName)!=0 ){
1042 blob_appendf(&wiki_read_links, " | %z%h</a>",
1043 href("%R/%s?name=branch/%h",
@@ -1063,18 +1069,18 @@
1069 @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
1070 @ </td>
1071 @ </tr>
1072
1073 @ <tr><th>%s(hname_alg(nUuid)):</th><td>
1074 style_copy_button(1, "hash-ci", 0, 2, 0, "%.32s<wbr>%s", zUuid, zUuid+32);
1075 if( g.perm.Setup ){
1076 @ (Record ID: %d(rid))
1077 }
1078 @ </td></tr>
1079 @ <tr><th>User&nbsp;&amp;&nbsp;Date:</th><td>
1080 hyperlink_to_user(zUser,zDate," on ");
1081 style_copy_button(1, 0, 0, 0, zZulu,
1082 "%z%h</a>", href("%R/timeline?c=%T",zDate), zDate);
1083 @ </td></tr>
1084 // hyperlink_to_date(zDate, "</td></tr>");
1085 if( zEComment ){
1086 @ <tr><th>Original&nbsp;Comment:</th>
@@ -2429,11 +2435,11 @@
2435 }
2436 style_header("Hex Artifact Content");
2437 zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
2438 etag_check(ETAG_HASH, zUuid);
2439 @ <h2>Artifact
2440 style_copy_button(1, "hash-ar", 0, 2, 0, "%s", zUuid);
2441 if( g.perm.Setup ){
2442 @ (%d(rid)):</h2>
2443 }else{
2444 @ :</h2>
2445 }
@@ -2862,11 +2868,11 @@
2868 Blob path;
2869 blob_zero(&path);
2870 hyperlinked_path(zName, &path, zCI, "dir", "", LINKPATH_FINFO);
2871 zPath = blob_str(&path);
2872 @ <h2>File %s(zPath) artifact \
2873 style_copy_button(1,"hash-fid",0,0,0,"%z%S</a> ",
2874 href("%R/info/%s",zUuid),zUuid);
2875 if( isBranchCI ){
2876 @ on branch %z(href("%R/timeline?r=%T",zCI))%h(zCI)</a></h2>
2877 }else if( isSymbolicCI ){
2878 @ part of check-in %z(href("%R/info/%!S",zCIUuid))%s(zCI)</a></h2>
@@ -2886,11 +2892,11 @@
2892 }
2893 blob_init(&downloadName, zName, -1);
2894 objType = OBJTYPE_CONTENT;
2895 }else{
2896 @ <h2>Artifact
2897 style_copy_button(1, "hash-ar", 0, 2, 0, "%s", zUuid);
2898 if( g.perm.Setup ){
2899 @ (%d(rid)):</h2>
2900 }else{
2901 @ :</h2>
2902 }
2903
+68 -63
--- src/style.c
+++ src/style.c
@@ -474,24 +474,34 @@
474474
free(zVarName);
475475
free(zUrl);
476476
}
477477
478478
/*
479
-** Output text generated from zTextFmt,... with a click-to-copy button
479
+** Output text generated from zTextFmt with a click-to-copy button
480480
** next to it. This routine assures that the copybtn.js Javascript module
481
-** is loaded. It generates HTML elements with the following IDs:
481
+** is loaded. It generates HTML elements that show the click-to-copy
482
+** button and text described by zTextFmt.
483
+**
484
+** The text generated by zTextFmt may contain HTML markup. That markup
485
+** is not captured by the copy when the button is pressed - only the
486
+** display text is copied. It is the caller's responsibility to ensure
487
+** that the text generated by zTextFmt does not contain XSS vulnerabilities
488
+** or other injections. Text that is under the control of users should
489
+** be inserted into the display text using %h or similar.
482490
**
483
-** zTargetId: The <span> wrapper around the generated text.
484
-** copy-zTargetId: The <button> for the copy button.
491
+** If zTargetId is provide (if zTargetId!=NULL) then zTargetId becomes
492
+** the ID of the <span> that surrounds the display text and the ID
493
+** of the <button> becomes "copy-%s" where %s is filled in by zTargetId.
494
+** If zTargetId is NULL (the usual case) then IDs are selected automatically.
485495
**
486496
** The bOutputCGI parameter is usually true, meaning that the output
487497
** is appended to the CGI result under construction. However, if
488498
** bOutputCGI is false, the generated HTML is written into memory
489499
** obtained from fossil_malloc() and returned.
490500
**
491
-** If the bFlipped argument is non-zero, the copy button is displayed
492
-** after the text. Normally the copy button comes before.
501
+** If the bAfter argument is non-zero, the copy button is displayed
502
+** after the text. Normally the copy button comes before the text.
493503
**
494504
** The mxLength argument defines the length of the substring of the
495505
** text to be copied to the clipboard:
496506
**
497507
** <= 0: Use all of the text
@@ -498,80 +508,75 @@
498508
** >= 3: Truncate the text after mxLength bytes.
499509
** 1: Use the "hash-digits" setting as the limit.
500510
** 2: Use the length appropriate for URLs as the limit (defined at
501511
** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16).
502512
**
503
-** Note: If the text to be copied is an ISO8601 date-time with a space
504
-** separator between the date and the time, that space is converted to "T"
505
-** for the copy.
513
+** If zToCopy is not NULL then it holds the text that is to be copied
514
+** when the button is pressed. If zToCopy is NULL, then zTextFmt is
515
+** copied, with length restrictions specified by mxLength. If zToCopy
516
+** is provided, mxLength is ignored.
506517
*/
507518
char *style_copy_button(
508519
int bOutputCGI, /* Don't return result, but send to cgi_printf(). */
509520
const char *zTargetId, /* HTML id of the text */
510
- int bFlipped, /* True to put copy button after text */
521
+ int bAfter, /* True to put copy button after text */
511522
int mxLength, /* Length of text to copy to clipboard */
512
- const char *zTextFmt, /* Formatting of the TEXT argument (htmlized). */
523
+ const char *zToCopy, /* Optional text to copy when button is pressed */
524
+ const char *zTextFmt, /* Formatting of the TEXT argument. */
513525
... /* Formatting parameters of the TEXT argument. */
514526
){
515527
va_list ap;
516528
char *zText;
517529
char *zResult = 0;
530
+ char *zId = 0;
531
+ Blob btn;
532
+
518533
va_start(ap,zTextFmt);
519534
zText = vmprintf(zTextFmt/*works-like:?*/,ap);
520535
va_end(ap);
521
- if( mxLength==1 ) mxLength = hash_digits(0);
522
- else if( mxLength==2 ) mxLength = hash_digits(1);
523
- if( !bFlipped ){
524
- const char *zBtnFmt =
525
- "<span class=\"nobr\">"
526
- "<button "
527
- "class=\"copy-button\" "
528
- "id=\"copy-%h\" "
529
- "data-copytarget=\"%h\" "
530
- "data-copylength=\"%d\">"
531
- "<span>"
532
- "</span>"
533
- "</button>"
534
- "<span id=\"%h\">"
535
- "%s"
536
- "</span>"
537
- "</span>";
538
- if( bOutputCGI ){
539
- cgi_printf(
540
- zBtnFmt/*works-like:"%h%h%d%h%s"*/,
541
- zTargetId,zTargetId,mxLength,zTargetId,zText);
542
- }else{
543
- zResult = mprintf(
544
- zBtnFmt/*works-like:"%h%h%d%h%s"*/,
545
- zTargetId,zTargetId,mxLength,zTargetId,zText);
546
- }
547
- }else{
548
- const char *zBtnFmt =
549
- "<span class=\"nobr\">"
550
- "<span id=\"%h\">"
551
- "%s"
552
- "</span>"
553
- "<button "
554
- "class=\"copy-button copy-button-flipped\" "
555
- "id=\"copy-%h\" "
556
- "data-copytarget=\"%h\" "
557
- "data-copylength=\"%d\">"
558
- "<span>"
559
- "</span>"
560
- "</button>"
561
- "</span>";
562
- if( bOutputCGI ){
563
- cgi_printf(
564
- zBtnFmt/*works-like:"%h%s%h%h%d"*/,
565
- zTargetId,zText,zTargetId,zTargetId,mxLength);
566
- }else{
567
- zResult = mprintf(
568
- zBtnFmt/*works-like:"%h%s%h%h%d"*/,
569
- zTargetId,zText,zTargetId,zTargetId,mxLength);
570
- }
571
- }
572
- free(zText);
536
+
537
+ if( mxLength==1 ){
538
+ mxLength = hash_digits(0);
539
+ }else if( mxLength==2 ){
540
+ mxLength = hash_digits(1);
541
+ }
542
+ blob_init(&btn, 0, 0);
543
+ blob_append_string(&btn, "<span class=\"nobr\">");
544
+ if( zTargetId==0 ){
545
+ static unsigned int cnt = 0;
546
+ zId = mprintf("copy-button-id-%u", ++cnt);
547
+ zTargetId = zId;
548
+ }
549
+ if( bAfter ){
550
+ blob_appendf(&btn, "<span id=\"%h\">%s</span>",
551
+ zTargetId, zText);
552
+ }
553
+ blob_appendf(&btn,
554
+ "<button "
555
+ "class=\"copy-button\" "
556
+ "id=\"copy-%h\" "
557
+ "data-copytarget=\"%h\" "
558
+ "data-copylength=\"%d\"",
559
+ zTargetId, zTargetId, mxLength);
560
+ if( zToCopy ){
561
+ blob_appendf(&btn," data-content=\"%h\"", zToCopy);
562
+ }
563
+ blob_append_string(&btn, "><span></span></button>");
564
+ if( !bAfter ){
565
+ blob_appendf(&btn, "<span id=\"%h\">%s</span>",
566
+ zTargetId, zText);
567
+ }
568
+ blob_appendf(&btn,"</span>");
569
+ if( bOutputCGI ){
570
+ cgi_append_content(blob_str(&btn), blob_strlen(&btn));
571
+ blob_reset(&btn);
572
+ zResult = 0;
573
+ }else{
574
+ zResult = blob_str(&btn);
575
+ }
576
+ fossil_free(zText);
577
+ fossil_free(zId);
573578
builtin_request_js("copybtn.js");
574579
return zResult;
575580
}
576581
577582
/*
578583
--- src/style.c
+++ src/style.c
@@ -474,24 +474,34 @@
474 free(zVarName);
475 free(zUrl);
476 }
477
478 /*
479 ** Output text generated from zTextFmt,... with a click-to-copy button
480 ** next to it. This routine assures that the copybtn.js Javascript module
481 ** is loaded. It generates HTML elements with the following IDs:
 
 
 
 
 
 
 
 
482 **
483 ** zTargetId: The <span> wrapper around the generated text.
484 ** copy-zTargetId: The <button> for the copy button.
 
 
485 **
486 ** The bOutputCGI parameter is usually true, meaning that the output
487 ** is appended to the CGI result under construction. However, if
488 ** bOutputCGI is false, the generated HTML is written into memory
489 ** obtained from fossil_malloc() and returned.
490 **
491 ** If the bFlipped argument is non-zero, the copy button is displayed
492 ** after the text. Normally the copy button comes before.
493 **
494 ** The mxLength argument defines the length of the substring of the
495 ** text to be copied to the clipboard:
496 **
497 ** <= 0: Use all of the text
@@ -498,80 +508,75 @@
498 ** >= 3: Truncate the text after mxLength bytes.
499 ** 1: Use the "hash-digits" setting as the limit.
500 ** 2: Use the length appropriate for URLs as the limit (defined at
501 ** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16).
502 **
503 ** Note: If the text to be copied is an ISO8601 date-time with a space
504 ** separator between the date and the time, that space is converted to "T"
505 ** for the copy.
 
506 */
507 char *style_copy_button(
508 int bOutputCGI, /* Don't return result, but send to cgi_printf(). */
509 const char *zTargetId, /* HTML id of the text */
510 int bFlipped, /* True to put copy button after text */
511 int mxLength, /* Length of text to copy to clipboard */
512 const char *zTextFmt, /* Formatting of the TEXT argument (htmlized). */
 
513 ... /* Formatting parameters of the TEXT argument. */
514 ){
515 va_list ap;
516 char *zText;
517 char *zResult = 0;
 
 
 
518 va_start(ap,zTextFmt);
519 zText = vmprintf(zTextFmt/*works-like:?*/,ap);
520 va_end(ap);
521 if( mxLength==1 ) mxLength = hash_digits(0);
522 else if( mxLength==2 ) mxLength = hash_digits(1);
523 if( !bFlipped ){
524 const char *zBtnFmt =
525 "<span class=\"nobr\">"
526 "<button "
527 "class=\"copy-button\" "
528 "id=\"copy-%h\" "
529 "data-copytarget=\"%h\" "
530 "data-copylength=\"%d\">"
531 "<span>"
532 "</span>"
533 "</button>"
534 "<span id=\"%h\">"
535 "%s"
536 "</span>"
537 "</span>";
538 if( bOutputCGI ){
539 cgi_printf(
540 zBtnFmt/*works-like:"%h%h%d%h%s"*/,
541 zTargetId,zTargetId,mxLength,zTargetId,zText);
542 }else{
543 zResult = mprintf(
544 zBtnFmt/*works-like:"%h%h%d%h%s"*/,
545 zTargetId,zTargetId,mxLength,zTargetId,zText);
546 }
547 }else{
548 const char *zBtnFmt =
549 "<span class=\"nobr\">"
550 "<span id=\"%h\">"
551 "%s"
552 "</span>"
553 "<button "
554 "class=\"copy-button copy-button-flipped\" "
555 "id=\"copy-%h\" "
556 "data-copytarget=\"%h\" "
557 "data-copylength=\"%d\">"
558 "<span>"
559 "</span>"
560 "</button>"
561 "</span>";
562 if( bOutputCGI ){
563 cgi_printf(
564 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
565 zTargetId,zText,zTargetId,zTargetId,mxLength);
566 }else{
567 zResult = mprintf(
568 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
569 zTargetId,zText,zTargetId,zTargetId,mxLength);
570 }
571 }
572 free(zText);
573 builtin_request_js("copybtn.js");
574 return zResult;
575 }
576
577 /*
578
--- src/style.c
+++ src/style.c
@@ -474,24 +474,34 @@
474 free(zVarName);
475 free(zUrl);
476 }
477
478 /*
479 ** Output text generated from zTextFmt with a click-to-copy button
480 ** next to it. This routine assures that the copybtn.js Javascript module
481 ** is loaded. It generates HTML elements that show the click-to-copy
482 ** button and text described by zTextFmt.
483 **
484 ** The text generated by zTextFmt may contain HTML markup. That markup
485 ** is not captured by the copy when the button is pressed - only the
486 ** display text is copied. It is the caller's responsibility to ensure
487 ** that the text generated by zTextFmt does not contain XSS vulnerabilities
488 ** or other injections. Text that is under the control of users should
489 ** be inserted into the display text using %h or similar.
490 **
491 ** If zTargetId is provide (if zTargetId!=NULL) then zTargetId becomes
492 ** the ID of the <span> that surrounds the display text and the ID
493 ** of the <button> becomes "copy-%s" where %s is filled in by zTargetId.
494 ** If zTargetId is NULL (the usual case) then IDs are selected automatically.
495 **
496 ** The bOutputCGI parameter is usually true, meaning that the output
497 ** is appended to the CGI result under construction. However, if
498 ** bOutputCGI is false, the generated HTML is written into memory
499 ** obtained from fossil_malloc() and returned.
500 **
501 ** If the bAfter argument is non-zero, the copy button is displayed
502 ** after the text. Normally the copy button comes before the text.
503 **
504 ** The mxLength argument defines the length of the substring of the
505 ** text to be copied to the clipboard:
506 **
507 ** <= 0: Use all of the text
@@ -498,80 +508,75 @@
508 ** >= 3: Truncate the text after mxLength bytes.
509 ** 1: Use the "hash-digits" setting as the limit.
510 ** 2: Use the length appropriate for URLs as the limit (defined at
511 ** compile-time by FOSSIL_HASH_DIGITS_URL, defaults to 16).
512 **
513 ** If zToCopy is not NULL then it holds the text that is to be copied
514 ** when the button is pressed. If zToCopy is NULL, then zTextFmt is
515 ** copied, with length restrictions specified by mxLength. If zToCopy
516 ** is provided, mxLength is ignored.
517 */
518 char *style_copy_button(
519 int bOutputCGI, /* Don't return result, but send to cgi_printf(). */
520 const char *zTargetId, /* HTML id of the text */
521 int bAfter, /* True to put copy button after text */
522 int mxLength, /* Length of text to copy to clipboard */
523 const char *zToCopy, /* Optional text to copy when button is pressed */
524 const char *zTextFmt, /* Formatting of the TEXT argument. */
525 ... /* Formatting parameters of the TEXT argument. */
526 ){
527 va_list ap;
528 char *zText;
529 char *zResult = 0;
530 char *zId = 0;
531 Blob btn;
532
533 va_start(ap,zTextFmt);
534 zText = vmprintf(zTextFmt/*works-like:?*/,ap);
535 va_end(ap);
536
537 if( mxLength==1 ){
538 mxLength = hash_digits(0);
539 }else if( mxLength==2 ){
540 mxLength = hash_digits(1);
541 }
542 blob_init(&btn, 0, 0);
543 blob_append_string(&btn, "<span class=\"nobr\">");
544 if( zTargetId==0 ){
545 static unsigned int cnt = 0;
546 zId = mprintf("copy-button-id-%u", ++cnt);
547 zTargetId = zId;
548 }
549 if( bAfter ){
550 blob_appendf(&btn, "<span id=\"%h\">%s</span>",
551 zTargetId, zText);
552 }
553 blob_appendf(&btn,
554 "<button "
555 "class=\"copy-button\" "
556 "id=\"copy-%h\" "
557 "data-copytarget=\"%h\" "
558 "data-copylength=\"%d\"",
559 zTargetId, zTargetId, mxLength);
560 if( zToCopy ){
561 blob_appendf(&btn," data-content=\"%h\"", zToCopy);
562 }
563 blob_append_string(&btn, "><span></span></button>");
564 if( !bAfter ){
565 blob_appendf(&btn, "<span id=\"%h\">%s</span>",
566 zTargetId, zText);
567 }
568 blob_appendf(&btn,"</span>");
569 if( bOutputCGI ){
570 cgi_append_content(blob_str(&btn), blob_strlen(&btn));
571 blob_reset(&btn);
572 zResult = 0;
573 }else{
574 zResult = blob_str(&btn);
575 }
576 fossil_free(zText);
577 fossil_free(zId);
 
 
 
 
 
 
 
 
 
 
578 builtin_request_js("copybtn.js");
579 return zResult;
580 }
581
582 /*
583
+1 -1
--- src/th_main.c
+++ src/th_main.c
@@ -1194,11 +1194,11 @@
11941194
if( argc==5 ){
11951195
if( Th_ToInt(interp, argv[4], argl[4], &copylength) ) return TH_ERROR;
11961196
}
11971197
zResult = style_copy_button(
11981198
/*bOutputCGI==*/0, /*TARGETID==*/(char*)argv[1],
1199
- flipped, copylength, "%h", /*TEXT==*/(char*)argv[3]);
1199
+ flipped, copylength, 0, "%h", /*TEXT==*/(char*)argv[3]);
12001200
sendText(0,zResult, -1, 0);
12011201
free(zResult);
12021202
}
12031203
return TH_OK;
12041204
}
12051205
--- src/th_main.c
+++ src/th_main.c
@@ -1194,11 +1194,11 @@
1194 if( argc==5 ){
1195 if( Th_ToInt(interp, argv[4], argl[4], &copylength) ) return TH_ERROR;
1196 }
1197 zResult = style_copy_button(
1198 /*bOutputCGI==*/0, /*TARGETID==*/(char*)argv[1],
1199 flipped, copylength, "%h", /*TEXT==*/(char*)argv[3]);
1200 sendText(0,zResult, -1, 0);
1201 free(zResult);
1202 }
1203 return TH_OK;
1204 }
1205
--- src/th_main.c
+++ src/th_main.c
@@ -1194,11 +1194,11 @@
1194 if( argc==5 ){
1195 if( Th_ToInt(interp, argv[4], argl[4], &copylength) ) return TH_ERROR;
1196 }
1197 zResult = style_copy_button(
1198 /*bOutputCGI==*/0, /*TARGETID==*/(char*)argv[1],
1199 flipped, copylength, 0, "%h", /*TEXT==*/(char*)argv[3]);
1200 sendText(0,zResult, -1, 0);
1201 free(zResult);
1202 }
1203 return TH_OK;
1204 }
1205
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -420,11 +420,11 @@
420420
{ "pop3_print", 2, FMT_SAFE },
421421
{ "smtp_send_line", 2, FMT_SAFE },
422422
{ "smtp_server_send", 2, FMT_SAFE },
423423
{ "socket_set_errmsg", 1, FMT_SAFE },
424424
{ "ssl_set_errmsg", 1, FMT_SAFE },
425
- { "style_copy_button", 5, FMT_SAFE },
425
+ { "style_copy_button", 6, FMT_SAFE },
426426
{ "style_header", 1, FMT_HTML },
427427
{ "style_set_current_page", 1, FMT_URL },
428428
{ "style_submenu_element", 2, FMT_URL },
429429
{ "style_submenu_sql", 3, FMT_SQL },
430430
{ "textarea_attribute", 5, FMT_LIT },
431431
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -420,11 +420,11 @@
420 { "pop3_print", 2, FMT_SAFE },
421 { "smtp_send_line", 2, FMT_SAFE },
422 { "smtp_server_send", 2, FMT_SAFE },
423 { "socket_set_errmsg", 1, FMT_SAFE },
424 { "ssl_set_errmsg", 1, FMT_SAFE },
425 { "style_copy_button", 5, FMT_SAFE },
426 { "style_header", 1, FMT_HTML },
427 { "style_set_current_page", 1, FMT_URL },
428 { "style_submenu_element", 2, FMT_URL },
429 { "style_submenu_sql", 3, FMT_SQL },
430 { "textarea_attribute", 5, FMT_LIT },
431
--- tools/codecheck1.c
+++ tools/codecheck1.c
@@ -420,11 +420,11 @@
420 { "pop3_print", 2, FMT_SAFE },
421 { "smtp_send_line", 2, FMT_SAFE },
422 { "smtp_server_send", 2, FMT_SAFE },
423 { "socket_set_errmsg", 1, FMT_SAFE },
424 { "ssl_set_errmsg", 1, FMT_SAFE },
425 { "style_copy_button", 6, FMT_SAFE },
426 { "style_header", 1, FMT_HTML },
427 { "style_set_current_page", 1, FMT_URL },
428 { "style_submenu_element", 2, FMT_URL },
429 { "style_submenu_sql", 3, FMT_SQL },
430 { "textarea_attribute", 5, FMT_LIT },
431

Keyboard Shortcuts

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