Fossil

Check-in [33394207]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Alternative skins can be determined by the "skin" field of the display preferences cookie. The "skn_X" mechanism is removed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 3339420778776126eb80c9ef23d98e964dc5411d1d0ed920240d0bf418696eea
User & Date: drh 2021-03-02 13:55:26
Context
2021-03-02
15:01
When skin=X query parameter is processed, if a param named 'once' is also set then apply the skin change but do not save it to the cookie, as per /chat discussion. The intent is mainly to facilitate the development of docs using both light- and dark-mode skins at the same time, which is somewhat painful when the cookie constantly gets overwritten. ... (check-in: 7db18bfe user: stephan tags: trunk)
13:55
Alternative skins can be determined by the "skin" field of the display preferences cookie. The "skn_X" mechanism is removed. ... (check-in: 33394207 user: drh tags: trunk)
08:54
Updated changes.wiki to replace skn_X references with skin=X. ... (Closed-Leaf check-in: 7fed83c9 user: stephan tags: skin-preference-cookie)
2021-03-01
20:54
Change the algorithm for detecting when a user agent is a narrow-screen mobile device to the algorithm recommanded at https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_device_detection. ... (check-in: 4de677dc user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/branch.c.

681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }

  style_set_current_feature("branch");
  style_header("Branches");
  style_submenu_element("List", "brlist");
  login_anonymous_available();
  timeline_ss_submenu();
  cookie_render();
  @ <h2>The initial check-in for each branch:</h2>
  blob_append(&sql, timeline_query_for_www(), -1);
  blob_append_sql(&sql,
    "AND blob.rid IN (SELECT rid FROM tagxref"
    "                  WHERE tagtype>0 AND tagid=%d AND srcid!=0)", TAG_BRANCH);
  if( fNoHidden || fOnlyHidden ){
    const char* zUnaryOp = fNoHidden ? "NOT" : "";







<







681
682
683
684
685
686
687

688
689
690
691
692
693
694
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }

  style_set_current_feature("branch");
  style_header("Branches");
  style_submenu_element("List", "brlist");
  login_anonymous_available();
  timeline_ss_submenu();

  @ <h2>The initial check-in for each branch:</h2>
  blob_append(&sql, timeline_query_for_www(), -1);
  blob_append_sql(&sql,
    "AND blob.rid IN (SELECT rid FROM tagxref"
    "                  WHERE tagtype>0 AND tagid=%d AND srcid!=0)", TAG_BRANCH);
  if( fNoHidden || fOnlyHidden ){
    const char* zUnaryOp = fNoHidden ? "NOT" : "";

Changes to src/cgi.c.

1157
1158
1159
1160
1161
1162
1163




1164
1165
1166
1167
1168
1169








1170
1171
1172
1173
1174
1175
1176
           "Internal misconfiguration of g.json.isJsonMode");
  }
#endif
  z = (char*)P("HTTP_COOKIE");
  if( z ){
    z = fossil_strdup(z);
    add_param_list(z, ';');




  }

  z = (char*)P("QUERY_STRING");
  if( z ){
    z = fossil_strdup(z);
    add_param_list(z, '&');








  }

  z = (char*)P("REMOTE_ADDR");
  if( z ){
    g.zIpAddr = fossil_strdup(z);
  }








>
>
>
>






>
>
>
>
>
>
>
>







1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
           "Internal misconfiguration of g.json.isJsonMode");
  }
#endif
  z = (char*)P("HTTP_COOKIE");
  if( z ){
    z = fossil_strdup(z);
    add_param_list(z, ';');
    z = (char*)cookie_value("skin",0);
    if(z){
      skin_use_alternative(z, 2);
    }
  }

  z = (char*)P("QUERY_STRING");
  if( z ){
    z = fossil_strdup(z);
    add_param_list(z, '&');
    z = (char*)P("skin");
    if(z){
      char *zErr = skin_use_alternative(z, 2);
      if(!zErr){
        cookie_write_parameter("skin","skin",z);
      }
      fossil_free(zErr);
    }
  }

  z = (char*)P("REMOTE_ADDR");
  if( z ){
    g.zIpAddr = fossil_strdup(z);
  }

Changes to src/cookies.c.

171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
  const char *zQP,       /* The query parameter */
  const char *zPName,    /* The name of the cookie value */
  const char *zDflt      /* Default value for the parameter */
){
  cookie_readwrite(zQP, zPName, zDflt, COOKIE_READ|COOKIE_WRITE);
}

/* Update the user preferences cookie, if necessary, and shut down this
** module

*/
void cookie_render(void){
  if( cookies.bChanged && P("udc")!=0 ){
    Blob new;
    int i;
    blob_init(&new, 0, 0);
    for(i=0;i<cookies.nParam;i++){
      if( i>0 ) blob_append(&new, ",", 1);
      blob_appendf(&new, "%s=%T",
          cookies.aParam[i].zPName, cookies.aParam[i].zPValue);







|
|
>


|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  const char *zQP,       /* The query parameter */
  const char *zPName,    /* The name of the cookie value */
  const char *zDflt      /* Default value for the parameter */
){
  cookie_readwrite(zQP, zPName, zDflt, COOKIE_READ|COOKIE_WRITE);
}

/* Update the user preferences cookie, if necessary, and shut down
** this module. The cookie is only emitted if its value has actually
** changed since the request started.
*/
void cookie_render(void){
  if( cookies.bChanged ){
    Blob new;
    int i;
    blob_init(&new, 0, 0);
    for(i=0;i<cookies.nParam;i++){
      if( i>0 ) blob_append(&new, ",", 1);
      blob_appendf(&new, "%s=%T",
          cookies.aParam[i].zPName, cookies.aParam[i].zPValue);

Changes to src/descendants.c.

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
    style_submenu_element("Open", "%s", url_render(&url, 0, 0, 0, 0));
  }
  url_reset(&url);
  style_set_current_feature("leaves");
  style_header("Leaves");
  login_anonymous_available();
  timeline_ss_submenu();
  cookie_render();
#if 0
  style_sidebox_begin("Nomenclature:", "33%");
  @ <ol>
  @ <li> A <div class="sideboxDescribed">leaf</div>
  @ is a check-in with no descendants in the same branch.</li>
  @ <li> An <div class="sideboxDescribed">open leaf</div>
  @ is a leaf that does not have a "closed" tag







<







563
564
565
566
567
568
569

570
571
572
573
574
575
576
    style_submenu_element("Open", "%s", url_render(&url, 0, 0, 0, 0));
  }
  url_reset(&url);
  style_set_current_feature("leaves");
  style_header("Leaves");
  login_anonymous_available();
  timeline_ss_submenu();

#if 0
  style_sidebox_begin("Nomenclature:", "33%");
  @ <ol>
  @ <li> A <div class="sideboxDescribed">leaf</div>
  @ is a check-in with no descendants in the same branch.</li>
  @ <li> An <div class="sideboxDescribed">open leaf</div>
  @ is a leaf that does not have a "closed" tag

Changes to src/finfo.c.

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
    zStyle = "Modern";
  }
  url_initialize(&url, "finfo");
  if( brBg ) url_add_parameter(&url, "brbg", 0);
  if( uBg ) url_add_parameter(&url, "ubg", 0);
  ridFrom = name_to_rid_www("from");
  zPrevDate[0] = 0;
  cookie_render();
  if( fnid==0 ){
    @ No such file: %h(zFilename)
    style_finish_page();
    return;
  }
  if( g.perm.Admin ){
    style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename);







<







362
363
364
365
366
367
368

369
370
371
372
373
374
375
    zStyle = "Modern";
  }
  url_initialize(&url, "finfo");
  if( brBg ) url_add_parameter(&url, "brbg", 0);
  if( uBg ) url_add_parameter(&url, "ubg", 0);
  ridFrom = name_to_rid_www("from");
  zPrevDate[0] = 0;

  if( fnid==0 ){
    @ No such file: %h(zFilename)
    style_finish_page();
    return;
  }
  if( g.perm.Admin ){
    style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename);

Changes to src/info.c.

937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
    const char *zNew = db_column_text(&q3,3);
    const char *zOldName = db_column_text(&q3, 4);
    append_file_change_line(zUuid, zName, zOld, zNew, zOldName, 
                            diffFlags,pRe,mperm);
  }
  db_finalize(&q3);
  append_diff_javascript(diffType==2);
  cookie_render();
  style_finish_page();
}

/*
** WEBPAGE: winfo
** URL:  /winfo?name=HASH
**







<







937
938
939
940
941
942
943

944
945
946
947
948
949
950
    const char *zNew = db_column_text(&q3,3);
    const char *zOldName = db_column_text(&q3, 4);
    append_file_change_line(zUuid, zName, zOld, zNew, zOldName, 
                            diffFlags,pRe,mperm);
  }
  db_finalize(&q3);
  append_diff_javascript(diffType==2);

  style_finish_page();
}

/*
** WEBPAGE: winfo
** URL:  /winfo?name=HASH
**
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
  char *zMergeOrigin = 0;
  ReCompiled *pRe = 0;
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  login_anonymous_available();
  load_control();
  diffType = preferred_diff_type();
  cookie_render();
  zRe = P("regex");
  if( zRe ) re_compile(&pRe, zRe, 0);
  zBranch = P("branch");
  if( zBranch && zBranch[0]==0 ) zBranch = 0;
  if( zBranch ){
    zQuery = mprintf("branch=%T", zBranch);
    zMergeOrigin = mprintf("merge-in:%s", zBranch);







<







1182
1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
  char *zMergeOrigin = 0;
  ReCompiled *pRe = 0;
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  login_anonymous_available();
  load_control();
  diffType = preferred_diff_type();

  zRe = P("regex");
  if( zRe ) re_compile(&pRe, zRe, 0);
  zBranch = P("branch");
  if( zBranch && zBranch[0]==0 ) zBranch = 0;
  if( zBranch ){
    zQuery = mprintf("branch=%T", zBranch);
    zMergeOrigin = mprintf("merge-in:%s", zBranch);
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
  u64 diffFlags;
  u32 objdescFlags = 0;
  int verbose = PB("verbose");

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  diffType = preferred_diff_type();
  cookie_render();
  if( P("from") && P("to") ){
    v1 = artifact_from_ci_and_filename("from");
    v2 = artifact_from_ci_and_filename("to");
  }else{
    Stmt q;
    v1 = name_to_rid_www("v1");
    v2 = name_to_rid_www("v2");







<







1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
  u64 diffFlags;
  u32 objdescFlags = 0;
  int verbose = PB("verbose");

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  diffType = preferred_diff_type();

  if( P("from") && P("to") ){
    v1 = artifact_from_ci_and_filename("from");
    v2 = artifact_from_ci_and_filename("to");
  }else{
    Stmt q;
    v1 = name_to_rid_www("v1");
    v2 = name_to_rid_www("v2");

Changes to src/main.c.

1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
    if( g.zTop ) g.zTop = mprintf("%R/draft%d", iSkin);
    if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
    zPathInfo += 7;
    g.nExtraURL += 7;
    cgi_replace_parameter("PATH_INFO", zPathInfo);
    cgi_replace_parameter("SCRIPT_NAME", zNewScript);
    etag_cancel();
  }else if( zPathInfo && strncmp(zPathInfo, "/skn_", 5)==0 ){
    int i;
    char *zAlt;
    char *zErr;
    char *z;
    while( (z = strstr(zPathInfo+1,"/skn_"))!=0 ) zPathInfo = z;
    for(i=5; zPathInfo[i] && zPathInfo[i]!='/'; i++){}
    zAlt = mprintf("%.*s", i-5, zPathInfo+5);
    zErr = skin_use_alternative(zAlt);
    if( zErr ){
      fossil_free(zErr);
    }else{
      char *zNewScript;
      zNewScript = mprintf("%T/skn_%s", P("SCRIPT_NAME"), zAlt);
      if( g.zTop ) g.zTop = mprintf("%R/skn_%s", zAlt);
      if( g.zBaseURL ) g.zBaseURL = mprintf("%s/skn_%s", g.zBaseURL, zAlt);
      zPathInfo += i;
      g.nExtraURL += i;
      cgi_replace_parameter("PATH_INFO", zPathInfo);
      cgi_replace_parameter("SCRIPT_NAME", zNewScript);
    }
    fossil_free(zAlt);
  }  

  /* If the content type is application/x-fossil or 
  ** application/x-fossil-debug, then a sync/push/pull/clone is
  ** desired, so default the PATH_INFO to /xfer
  */
  if( g.zContentType &&
      strncmp(g.zContentType, "application/x-fossil", 20)==0 ){







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<







1836
1837
1838
1839
1840
1841
1842




















1843


1844
1845
1846
1847
1848
1849
1850
    if( g.zTop ) g.zTop = mprintf("%R/draft%d", iSkin);
    if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
    zPathInfo += 7;
    g.nExtraURL += 7;
    cgi_replace_parameter("PATH_INFO", zPathInfo);
    cgi_replace_parameter("SCRIPT_NAME", zNewScript);
    etag_cancel();




















  }



  /* If the content type is application/x-fossil or 
  ** application/x-fossil-debug, then a sync/push/pull/clone is
  ** desired, so default the PATH_INFO to /xfer
  */
  if( g.zContentType &&
      strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
      /* skin: LABEL
      **
      ** Use one of the built-in skins defined by LABEL.  LABEL is the
      ** name of the subdirectory under the skins/ directory that holds
      ** the elements of the built-in skin.  If LABEL does not match,
      ** this directive is a silent no-op.
      */
      skin_use_alternative(blob_str(&value));
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
      /* jsmode: MODE
      **
      ** Change how JavaScript resources are delivered with each HTML







|







2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
      /* skin: LABEL
      **
      ** Use one of the built-in skins defined by LABEL.  LABEL is the
      ** name of the subdirectory under the skins/ directory that holds
      ** the elements of the built-in skin.  If LABEL does not match,
      ** this directive is a silent no-op.
      */
      fossil_free(skin_use_alternative(blob_str(&value), 1));
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
      /* jsmode: MODE
      **
      ** Change how JavaScript resources are delivered with each HTML

Changes to src/skins.c.

102
103
104
105
106
107
108

































109
110

111
112

113
114
115
116
117
118
119





120
121
122
123
124
125
126
** for the returned string comes from fossil_malloc() and should be freed
** by the caller.
**
** If the alternative skin name contains one or more '/' characters, then
** it is assumed to be a directory on disk that holds override css.txt,
** footer.txt, and header.txt.  This mode can be used for interactive
** development of new skins.

































*/
char *skin_use_alternative(const char *zName){

  int i;
  Blob err = BLOB_INITIALIZER;

  if( strchr(zName, '/')!=0 ){
    zAltSkinDir = fossil_strdup(zName);
    return 0;
  }
  if( sqlite3_strglob("draft[1-9]", zName)==0 ){
    skin_use_draft(zName[5] - '0');
    return 0;





  }
  for(i=0; i<count(aBuiltinSkin); i++){
    if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
      pAltSkin = &aBuiltinSkin[i];
      return 0;
    }
  }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>


>
|






>
>
>
>
>







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
** for the returned string comes from fossil_malloc() and should be freed
** by the caller.
**
** If the alternative skin name contains one or more '/' characters, then
** it is assumed to be a directory on disk that holds override css.txt,
** footer.txt, and header.txt.  This mode can be used for interactive
** development of new skins.
**
** The 2nd parameter is a ranking of how important this alternative
** skin declaration is, and lower values trump higher ones. If a call
** to this function passes a higher-valued rank than a previous call,
** the subsequent call becomes a no-op. Only calls with the same or
** lower rank (i.e. higher priority) will overwrite a previous
** setting. This approach is used because the CGI/server-time
** initialization happens in an order which is incompatible with our
** preferred ranking, making it otherwise more invasive to tell the
** internals "the --skin flag ranks higher than a URL parameter" (the
** former gets initialized before both URL parameters and the /draft
** path determination).
**
** The rankings were initially defined in
** https://fossil-scm.org/forum/forumpost/caf8c9a8bb
** and are:
**
** 0) A skin name matching the glob draft[1-9] trumps everything else.
**
** 1) The --skin flag or skin: CGI config setting.
**
** 2) The "skin" display setting cookie or URL argument, in that
** order. If the "skin" URL argument is provided and refers to a legal
** skin then that will update the display cookie. If the skin name is
** illegal it is silently ignored.
**
** 3) Skin properties from the CONFIG db table
**
** 4) Default skin.
**
** As a special case, the name "_repo" resets zAltSkinDir and
** pAltSkin to 0 to indicate that the current config-side skin should
** be used (rank 3, above), then returns 0.
*/
char *skin_use_alternative(const char *zName, int rank){
  static int currentRank = 5;
  int i;
  Blob err = BLOB_INITIALIZER;
  if(rank > currentRank) return 0;
  if( 1==rank && strchr(zName, '/')!=0 ){
    zAltSkinDir = fossil_strdup(zName);
    return 0;
  }
  if( sqlite3_strglob("draft[1-9]", zName)==0 ){
    skin_use_draft(zName[5] - '0');
    return 0;
  }
  if(zName && 0==strcmp("_repo",zName)){
    pAltSkin = 0;
    zAltSkinDir = 0;
    return 0;
  }
  for(i=0; i<count(aBuiltinSkin); i++){
    if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
      pAltSkin = &aBuiltinSkin[i];
      return 0;
    }
  }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
** Look for the --skin command-line option and process it.  Or
** call fossil_fatal() if an unknown skin is specified.
*/
void skin_override(void){
  const char *zSkin = find_option("skin",0,1);
  if( zSkin ){
    char *zErr = skin_use_alternative(zSkin);
    if( zErr ) fossil_fatal("%s", zErr);
  }
}

/*
** Use one of the draft skins.
*/







|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
** Look for the --skin command-line option and process it.  Or
** call fossil_fatal() if an unknown skin is specified.
*/
void skin_override(void){
  const char *zSkin = find_option("skin",0,1);
  if( zSkin ){
    char *zErr = skin_use_alternative(zSkin, 1);
    if( zErr ) fossil_fatal("%s", zErr);
  }
}

/*
** Use one of the draft skins.
*/
1152
1153
1154
1155
1156
1157
1158








1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
      nBase -= strlen(zPattern)-1;
      zBase[nBase] = 0;
    }
    fossil_free(zPattern);
  } 
  login_check_credentials();
  style_header("Skins");








  @ <p>The following skins are available for this repository:</p>
  @ <ul>
  if( pAltSkin==0 && zAltSkinDir==0 && iDraftSkin==0 ){
    @ <li> Standard skin for this repository &larr; <i>Currently in use</i>
  }else{
    @ <li> %z(href("%s/skins",zBase))Standard skin for this repository</a>
  }
  for(i=0; i<count(aBuiltinSkin); i++){
    if( pAltSkin==&aBuiltinSkin[i] ){
      @ <li> %h(aBuiltinSkin[i].zDesc) &larr; <i>Currently in use</i>
    }else{
      char *zUrl = href("%s/skn_%s/skins", zBase, aBuiltinSkin[i].zLabel);
      @ <li> %z(zUrl)%h(aBuiltinSkin[i].zDesc)</a>
    }
  }
  @ </ul>
  style_finish_page();
  fossil_free(zBase);
}







>
>
>
>
>
>
>
>





|





|







1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
      nBase -= strlen(zPattern)-1;
      zBase[nBase] = 0;
    }
    fossil_free(zPattern);
  } 
  login_check_credentials();
  style_header("Skins");
  if(zAltSkinDir && zAltSkinDir[0]){
    @ <p class="warning">Warning: this fossil instance was started with
    @ a hard-coded skin value which trumps any option selected below.
    @ A skins selected below will be recorded in your prefere cookie
    @ but will not be used until/unless the site administrator
    @ configures the site to run without a forced hard-coded skin.
    @ </p>
  }
  @ <p>The following skins are available for this repository:</p>
  @ <ul>
  if( pAltSkin==0 && zAltSkinDir==0 && iDraftSkin==0 ){
    @ <li> Standard skin for this repository &larr; <i>Currently in use</i>
  }else{
    @ <li> %z(href("%R/skins?skin=_repo"))Standard skin for this repository</a>
  }
  for(i=0; i<count(aBuiltinSkin); i++){
    if( pAltSkin==&aBuiltinSkin[i] ){
      @ <li> %h(aBuiltinSkin[i].zDesc) &larr; <i>Currently in use</i>
    }else{
      char *zUrl = href("%R/skins?skin=%T", aBuiltinSkin[i].zLabel);
      @ <li> %z(zUrl)%h(aBuiltinSkin[i].zDesc)</a>
    }
  }
  @ </ul>
  style_finish_page();
  fossil_free(zBase);
}

Changes to src/style.c.

1009
1010
1011
1012
1013
1014
1015




1016
1017
1018
1019
1020
1021
1022

  /* Add document end mark if it was not in the footer */
  if( sqlite3_strlike("%</body>%", zFooter, 0)!=0 ){
    style_load_all_js_files();
    @ </body>
    @ </html>
  }




}

/*
** Begin a side-box on the right-hand side of a page.  The title and
** the width of the box are given as arguments.  The width is usually
** a percentage of total screen width.
*/







>
>
>
>







1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026

  /* Add document end mark if it was not in the footer */
  if( sqlite3_strlike("%</body>%", zFooter, 0)!=0 ){
    style_load_all_js_files();
    @ </body>
    @ </html>
  }
  /* Update the user display prefs cookie if it was modified during
  ** this request.
  */
  cookie_render();
}

/*
** Begin a side-box on the right-hand side of a page.  The title and
** the width of the box are given as arguments.  The width is usually
** a percentage of total screen width.
*/

Changes to src/tag.c.

753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }

  style_header("Tagged Check-ins");
  style_submenu_element("List", "taglist");
  login_anonymous_available();
  timeline_ss_submenu();
  cookie_render();
  @ <h2>Check-ins with non-propagating tags:</h2>
  blob_append(&sql, timeline_query_for_www(), -1);
  blob_append_sql(&sql,
    "AND blob.rid IN (SELECT rid FROM tagxref"
    "                  WHERE tagtype=1 AND srcid>0"
    "                    AND tagid IN (SELECT tagid FROM tag "
    "                                   WHERE tagname GLOB 'sym-*'))");







<







753
754
755
756
757
758
759

760
761
762
763
764
765
766
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }

  style_header("Tagged Check-ins");
  style_submenu_element("List", "taglist");
  login_anonymous_available();
  timeline_ss_submenu();

  @ <h2>Check-ins with non-propagating tags:</h2>
  blob_append(&sql, timeline_query_for_www(), -1);
  blob_append_sql(&sql,
    "AND blob.rid IN (SELECT rid FROM tagxref"
    "                  WHERE tagtype=1 AND srcid>0"
    "                    AND tagid IN (SELECT tagid FROM tag "
    "                                   WHERE tagname GLOB 'sym-*'))");

Changes to src/timeline.c.

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
  if( zType==0 ){
    zType = g.perm.Read ? "ci" : "all";
    cgi_set_parameter("y", zType);
  }
  if( zType[0]=='a' || zType[0]=='c' ){
    cookie_write_parameter("y","y",zType);
  }
  cookie_render();

  /* Convert the cf=FILEHASH query parameter into a c=CHECKINHASH value */
  if( P("cf")!=0 ){
    zCirca = db_text(0,
      "SELECT (SELECT uuid FROM blob WHERE rid=mlink.mid)"
      "  FROM mlink, event"
      " WHERE mlink.fid=(SELECT rid FROM blob WHERE uuid LIKE '%q%%')"







<







1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
  if( zType==0 ){
    zType = g.perm.Read ? "ci" : "all";
    cgi_set_parameter("y", zType);
  }
  if( zType[0]=='a' || zType[0]=='c' ){
    cookie_write_parameter("y","y",zType);
  }


  /* Convert the cf=FILEHASH query parameter into a c=CHECKINHASH value */
  if( P("cf")!=0 ){
    zCirca = db_text(0,
      "SELECT (SELECT uuid FROM blob WHERE rid=mlink.mid)"
      "  FROM mlink, event"
      " WHERE mlink.fid=(SELECT rid FROM blob WHERE uuid LIKE '%q%%')"

Changes to www/changes.wiki.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
     "[/help?cmd=/doc|/doc/ckout/...]", to facilitate testing of
     [./embeddeddoc.wiki|embedded documentation] changes prior to
     check-in.
  *  The "pikchr-background" settings is now available in 
     "detail.txt" skin files, for better control of Pikchr
     colors in inverted color schemes.
  *  The hamburger menu is now available on the built-in
     "[/skn_ardoise/doc/trunk/www/changes.wiki#v2_15|ardoise]" and
     "[/skn_plain_gray/doc/trunk/www/changes.wiki#v2_15|plain_gray]"
     skins.
  *  Add the --list option to the 
     [/help?cmd=tarball|tarball],
     [/help?cmd=zip|zip], and [/help?cmd=sqlar|sqlar]
     commands.
  *  The javascript used to implement the hamburger menu on the
     default built-in skin has been made generic so that it is usable
     by a variety of skins, and promoted to an ordinary built-in
     javascript file.
  *  Any built-in skin named "X" can be used instead of the standard
     repository skin by including the term "skn_X" at the beginning

     of the URL path.
  *  New TH1 commands:  "builtin_request_js", "capexpr",
     "foreach", "string match"

<a name='v2_14'></a>
<h2>Changes for Version 2.14 (2021-01-20)</h2>

  *  <b>Schema Update Notice #1:</b>







|
|

|








|
>
|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
     "[/help?cmd=/doc|/doc/ckout/...]", to facilitate testing of
     [./embeddeddoc.wiki|embedded documentation] changes prior to
     check-in.
  *  The "pikchr-background" settings is now available in 
     "detail.txt" skin files, for better control of Pikchr
     colors in inverted color schemes.
  *  The hamburger menu is now available on the built-in
     "[/doc/trunk/www/changes.wiki?skin=ardoise#v2_15|ardoise]" and
     "[/doc/trunk/www/changes.wiki?skin=plain_gray#v2_15|plain_gray]"
     skins.
  *  Add the <tt>--list</tt> option to the 
     [/help?cmd=tarball|tarball],
     [/help?cmd=zip|zip], and [/help?cmd=sqlar|sqlar]
     commands.
  *  The javascript used to implement the hamburger menu on the
     default built-in skin has been made generic so that it is usable
     by a variety of skins, and promoted to an ordinary built-in
     javascript file.
  *  Any built-in skin named "X" can be used instead of the standard
     repository skin by adding the URL parameter <tt>skin=X</tt> to the
     request, and that selection is persistent using a cookie. The
     [/skins] page may be used to select a skin.
  *  New TH1 commands:  "builtin_request_js", "capexpr",
     "foreach", "string match"

<a name='v2_14'></a>
<h2>Changes for Version 2.14 (2021-01-20)</h2>

  *  <b>Schema Update Notice #1:</b>