Fossil SCM

Split recognizable names of query parameters into three groups: 1) "...smplX" for the common use within user content 2) "...smplXa" that is provisioned to be used in aliases; 3) "...smplXs" that is provisioned to be used in custom skins. In all three groups X is a digit from {1,2,3,4,5}.

george 2021-05-25 16:14 rptview-submenu-paralink
Commit 588b37656058c6b5f26ae0f8cebdd25d59b192974fae7959282cb5e73d615c5f
2 files changed +9 -5 +53 -47
+9 -5
--- src/report.c
+++ src/report.c
@@ -971,15 +971,20 @@
971971
** WEBPAGE: rptview
972972
**
973973
** Generate a report. The "rn" query parameter is the report number
974974
** corresponding to REPORTFMT.RN. If the "tablist" query parameter exists,
975975
** then the output consists of lines of tab-separated fields instead of
976
-** an HTML table. If the "rvsmpl" query parameter is set then report's
977
-** submenu will contain an extra hyperlink that have a value-driven
978
-** label and target.
976
+** an HTML table.
977
+**
978
+** Submenu of the /rptview page can be extended with additional
979
+** hyperlinks by providing query parameter(s) of the form rvsmplXY=Z.
980
+** Optional ending XY consists of a digit X from the set {1,2,3,4,5}
981
+** and an optional letter Y that (if present) must be either 'a' or 's'.
982
+** Mandatory Z is a repo-local hyperlink's target (wihout leading '/').
979983
**
980
-** "rvsmpl" stands for Report View SubMenu's Parametric Link.
984
+** For details see function style_submenu_parametric() in src/style.c
985
+** on branch "rptview-submenu-paralink".
981986
*/
982987
void rptview_page(void){
983988
int count = 0;
984989
int rn, rc;
985990
char *zSql;
@@ -1045,11 +1050,10 @@
10451050
style_submenu_element("Reports","%R/reportlist?%s",zQS);
10461051
} else {
10471052
style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
10481053
style_submenu_element("Reports","%R/reportlist");
10491054
}
1050
- style_submenu_parametric("rptview_");
10511055
style_submenu_parametric("rv");
10521056
10531057
if( g.perm.Admin
10541058
|| (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
10551059
style_submenu_element("Edit", "rptedit?rn=%d", rn);
10561060
--- src/report.c
+++ src/report.c
@@ -971,15 +971,20 @@
971 ** WEBPAGE: rptview
972 **
973 ** Generate a report. The "rn" query parameter is the report number
974 ** corresponding to REPORTFMT.RN. If the "tablist" query parameter exists,
975 ** then the output consists of lines of tab-separated fields instead of
976 ** an HTML table. If the "rvsmpl" query parameter is set then report's
977 ** submenu will contain an extra hyperlink that have a value-driven
978 ** label and target.
 
 
 
 
979 **
980 ** "rvsmpl" stands for Report View SubMenu's Parametric Link.
 
981 */
982 void rptview_page(void){
983 int count = 0;
984 int rn, rc;
985 char *zSql;
@@ -1045,11 +1050,10 @@
1045 style_submenu_element("Reports","%R/reportlist?%s",zQS);
1046 } else {
1047 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1048 style_submenu_element("Reports","%R/reportlist");
1049 }
1050 style_submenu_parametric("rptview_");
1051 style_submenu_parametric("rv");
1052
1053 if( g.perm.Admin
1054 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1055 style_submenu_element("Edit", "rptedit?rn=%d", rn);
1056
--- src/report.c
+++ src/report.c
@@ -971,15 +971,20 @@
971 ** WEBPAGE: rptview
972 **
973 ** Generate a report. The "rn" query parameter is the report number
974 ** corresponding to REPORTFMT.RN. If the "tablist" query parameter exists,
975 ** then the output consists of lines of tab-separated fields instead of
976 ** an HTML table.
977 **
978 ** Submenu of the /rptview page can be extended with additional
979 ** hyperlinks by providing query parameter(s) of the form rvsmplXY=Z.
980 ** Optional ending XY consists of a digit X from the set {1,2,3,4,5}
981 ** and an optional letter Y that (if present) must be either 'a' or 's'.
982 ** Mandatory Z is a repo-local hyperlink's target (wihout leading '/').
983 **
984 ** For details see function style_submenu_parametric() in src/style.c
985 ** on branch "rptview-submenu-paralink".
986 */
987 void rptview_page(void){
988 int count = 0;
989 int rn, rc;
990 char *zSql;
@@ -1045,11 +1050,10 @@
1050 style_submenu_element("Reports","%R/reportlist?%s",zQS);
1051 } else {
1052 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1053 style_submenu_element("Reports","%R/reportlist");
1054 }
 
1055 style_submenu_parametric("rv");
1056
1057 if( g.perm.Admin
1058 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1059 style_submenu_element("Edit", "rptedit?rn=%d", rn);
1060
+53 -47
--- src/style.c
+++ src/style.c
@@ -333,13 +333,15 @@
333333
}
334334
335335
/* Add hyperlinks depending on the existence and values of special
336336
** parameters in the request's query string. The names of a query's
337337
** parameters that are investigated are obtainted by concatenation of
338
-** the caller-provided zPrefix with suffix "smplX", where X is either
339
-** nothing or a positive digit. zPrefix must start with a lowercase
340
-** letter, be short and have no strange characters. Parameter's value
338
+** the caller-provided zPrefix with suffix "smplXY", where optional
339
+** ending XY consists of a digit X from the set {1,2,3,4,5} and an
340
+** optional letter Y which (if present) must be either 'a' or 's'.
341
+** zPrefix must start with a lowercase letter,
342
+** be short and have no strange characters. Parameter's value
341343
** is well-formed if its first filepath segment (separated by '/')
342344
** has no strange characters. Malformed values are silently ignored.
343345
**
344346
** The text for the resulting submenu label equals to the value of the
345347
** parameter modulus some prettification for better UX:
@@ -360,65 +362,69 @@
360362
void style_submenu_parametric(
361363
const char *zPrefix /* common prefix of the query parameters names */
362364
){
363365
static const char *suffix = "smpl"; /* common suffix for param names */
364366
static const short sfxlen = 4; /* length of the above suffix */
367
+ static const char sfxext[3] = {'a','s',0}; /* extra suffix ending */
365368
const char *zQS; /* QUERY_STRING */
366369
char zN[32]; /* buffer for parameter names to probe */
367
- short i,l;
370
+ short i,j,l;
368371
369372
/* zPrefix must be tidy and short; also filter out ENV/CGI variables */
370373
assert( zPrefix != 0 && fossil_islower(zPrefix[0]) );
371374
l = strnlen( zPrefix, sizeof(zN) );
372
- assert( l+sfxlen+2 <= sizeof(zN) );
375
+ assert( l+sfxlen+3 <= sizeof(zN) );
373376
assert( fossil_no_strange_characters(zPrefix) );
374377
/* concatenate zPrefix and suffix */
375378
strcpy( zN, zPrefix );
376379
strcpy( zN + l, suffix );
377380
l += sfxlen;
378
- zN[l+1] = 0; /* nul-terminator after digit's placeholder (if any) */
379
- zQS = PD("QUERY_STRING","");
380
- for( i = 0; i <= 9; i++ ){
381
- const char *zV, *z;
382
- zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
383
- zV = PD(zN,"");
384
- if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
385
- continue;
386
- }
387
- /* require the first path segment to be unfancy ASCII string */
388
- for( z = zV; z[0] && z[0] != '/' ;){
389
- if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
390
- else break;
391
- }
392
- if( z[0] != 0 && z[0] != '/' )
393
- continue;
394
- assert( nSubmenu < count(aSubmenu) );
395
- if(fossil_islower(zV[0]) && z[0]=='/'){
396
- aSubmenu[nSubmenu].zLabel = mprintf( "%s",zV); /* memory leak? */
397
- }else{
398
- /* prepend a label with an unobtrusive symbol that "sorts-last";
399
- ** this clearly distincts it from the built-in elements */
400
- static const char *mark = "✧";
401
- char *z = mprintf("%s%s",mark,zV);
402
- aSubmenu[nSubmenu].zLabel = z;
403
- /* also prettify the first segment */
404
- z += strlen(mark);
405
- z[0] = fossil_toupper(z[0]);
406
- for(; z[0]!=0; z++ ){
407
- if( z[0]=='_' ) z[0] = ' ';
408
- else if( z[0] == '/' ){ /* show just the first segment */
409
- z[0] = 0;
410
- break;
411
- }
412
- }
413
- }
414
- if( zQS[0] ){
415
- aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
416
- }else{
417
- aSubmenu[nSubmenu].zLink = mprintf("%R/%s",zV);
418
- }
419
- nSubmenu++;
381
+ zN[l+2] = 0; /* nul-terminator after ...smplXY suffix */
382
+ zQS = PD("QUERY_STRING","");
383
+ for( i = 0; i <= 5; i++ ){
384
+ zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
385
+ for( j = (i ? 0 : sizeof(sfxext)-1); j < sizeof(sfxext); j++ ){
386
+ const char *zV, *z;
387
+ zN[l+1] = sfxext[j];
388
+ zV = PD(zN,"");
389
+ if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
390
+ continue;
391
+ }
392
+ /* require the first path segment to be unfancy ASCII string */
393
+ for( z = zV; z[0] && z[0] != '/' ;){
394
+ if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
395
+ else break;
396
+ }
397
+ if( z[0] != 0 && z[0] != '/' )
398
+ continue;
399
+ assert( nSubmenu < count(aSubmenu) );
400
+ if(fossil_islower(zV[0]) && z[0]=='/'){
401
+ aSubmenu[nSubmenu].zLabel = mprintf( "%s",zV); /* memory leak? */
402
+ }else{
403
+ /* prepend a label with an unobtrusive symbol that "sorts-last";
404
+ ** this clearly distincts it from the built-in elements */
405
+ static const char *mark = "✧";
406
+ char *z = mprintf("%s%s",mark,zV);
407
+ aSubmenu[nSubmenu].zLabel = z;
408
+ /* also prettify the first segment */
409
+ z += strlen(mark);
410
+ z[0] = fossil_toupper(z[0]);
411
+ for(; z[0]!=0; z++ ){
412
+ if( z[0]=='_' ) z[0] = ' ';
413
+ else if( z[0] == '/' ){ /* show just the first segment */
414
+ z[0] = 0;
415
+ break;
416
+ }
417
+ }
418
+ }
419
+ if( zQS[0] ){
420
+ aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
421
+ }else{
422
+ aSubmenu[nSubmenu].zLink = mprintf("%R/%s",zV);
423
+ }
424
+ nSubmenu++;
425
+ }
420426
}
421427
}
422428
423429
/*
424430
** Disable or enable the submenu
425431
--- src/style.c
+++ src/style.c
@@ -333,13 +333,15 @@
333 }
334
335 /* Add hyperlinks depending on the existence and values of special
336 ** parameters in the request's query string. The names of a query's
337 ** parameters that are investigated are obtainted by concatenation of
338 ** the caller-provided zPrefix with suffix "smplX", where X is either
339 ** nothing or a positive digit. zPrefix must start with a lowercase
340 ** letter, be short and have no strange characters. Parameter's value
 
 
341 ** is well-formed if its first filepath segment (separated by '/')
342 ** has no strange characters. Malformed values are silently ignored.
343 **
344 ** The text for the resulting submenu label equals to the value of the
345 ** parameter modulus some prettification for better UX:
@@ -360,65 +362,69 @@
360 void style_submenu_parametric(
361 const char *zPrefix /* common prefix of the query parameters names */
362 ){
363 static const char *suffix = "smpl"; /* common suffix for param names */
364 static const short sfxlen = 4; /* length of the above suffix */
 
365 const char *zQS; /* QUERY_STRING */
366 char zN[32]; /* buffer for parameter names to probe */
367 short i,l;
368
369 /* zPrefix must be tidy and short; also filter out ENV/CGI variables */
370 assert( zPrefix != 0 && fossil_islower(zPrefix[0]) );
371 l = strnlen( zPrefix, sizeof(zN) );
372 assert( l+sfxlen+2 <= sizeof(zN) );
373 assert( fossil_no_strange_characters(zPrefix) );
374 /* concatenate zPrefix and suffix */
375 strcpy( zN, zPrefix );
376 strcpy( zN + l, suffix );
377 l += sfxlen;
378 zN[l+1] = 0; /* nul-terminator after digit's placeholder (if any) */
379 zQS = PD("QUERY_STRING","");
380 for( i = 0; i <= 9; i++ ){
381 const char *zV, *z;
382 zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
383 zV = PD(zN,"");
384 if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
385 continue;
386 }
387 /* require the first path segment to be unfancy ASCII string */
388 for( z = zV; z[0] && z[0] != '/' ;){
389 if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
390 else break;
391 }
392 if( z[0] != 0 && z[0] != '/' )
393 continue;
394 assert( nSubmenu < count(aSubmenu) );
395 if(fossil_islower(zV[0]) && z[0]=='/'){
396 aSubmenu[nSubmenu].zLabel = mprintf( "%s",zV); /* memory leak? */
397 }else{
398 /* prepend a label with an unobtrusive symbol that "sorts-last";
399 ** this clearly distincts it from the built-in elements */
400 static const char *mark = "✧";
401 char *z = mprintf("%s%s",mark,zV);
402 aSubmenu[nSubmenu].zLabel = z;
403 /* also prettify the first segment */
404 z += strlen(mark);
405 z[0] = fossil_toupper(z[0]);
406 for(; z[0]!=0; z++ ){
407 if( z[0]=='_' ) z[0] = ' ';
408 else if( z[0] == '/' ){ /* show just the first segment */
409 z[0] = 0;
410 break;
411 }
412 }
413 }
414 if( zQS[0] ){
415 aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
416 }else{
417 aSubmenu[nSubmenu].zLink = mprintf("%R/%s",zV);
418 }
419 nSubmenu++;
 
 
 
420 }
421 }
422
423 /*
424 ** Disable or enable the submenu
425
--- src/style.c
+++ src/style.c
@@ -333,13 +333,15 @@
333 }
334
335 /* Add hyperlinks depending on the existence and values of special
336 ** parameters in the request's query string. The names of a query's
337 ** parameters that are investigated are obtainted by concatenation of
338 ** the caller-provided zPrefix with suffix "smplXY", where optional
339 ** ending XY consists of a digit X from the set {1,2,3,4,5} and an
340 ** optional letter Y which (if present) must be either 'a' or 's'.
341 ** zPrefix must start with a lowercase letter,
342 ** be short and have no strange characters. Parameter's value
343 ** is well-formed if its first filepath segment (separated by '/')
344 ** has no strange characters. Malformed values are silently ignored.
345 **
346 ** The text for the resulting submenu label equals to the value of the
347 ** parameter modulus some prettification for better UX:
@@ -360,65 +362,69 @@
362 void style_submenu_parametric(
363 const char *zPrefix /* common prefix of the query parameters names */
364 ){
365 static const char *suffix = "smpl"; /* common suffix for param names */
366 static const short sfxlen = 4; /* length of the above suffix */
367 static const char sfxext[3] = {'a','s',0}; /* extra suffix ending */
368 const char *zQS; /* QUERY_STRING */
369 char zN[32]; /* buffer for parameter names to probe */
370 short i,j,l;
371
372 /* zPrefix must be tidy and short; also filter out ENV/CGI variables */
373 assert( zPrefix != 0 && fossil_islower(zPrefix[0]) );
374 l = strnlen( zPrefix, sizeof(zN) );
375 assert( l+sfxlen+3 <= sizeof(zN) );
376 assert( fossil_no_strange_characters(zPrefix) );
377 /* concatenate zPrefix and suffix */
378 strcpy( zN, zPrefix );
379 strcpy( zN + l, suffix );
380 l += sfxlen;
381 zN[l+2] = 0; /* nul-terminator after ...smplXY suffix */
382 zQS = PD("QUERY_STRING","");
383 for( i = 0; i <= 5; i++ ){
384 zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
385 for( j = (i ? 0 : sizeof(sfxext)-1); j < sizeof(sfxext); j++ ){
386 const char *zV, *z;
387 zN[l+1] = sfxext[j];
388 zV = PD(zN,"");
389 if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
390 continue;
391 }
392 /* require the first path segment to be unfancy ASCII string */
393 for( z = zV; z[0] && z[0] != '/' ;){
394 if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
395 else break;
396 }
397 if( z[0] != 0 && z[0] != '/' )
398 continue;
399 assert( nSubmenu < count(aSubmenu) );
400 if(fossil_islower(zV[0]) && z[0]=='/'){
401 aSubmenu[nSubmenu].zLabel = mprintf( "%s",zV); /* memory leak? */
402 }else{
403 /* prepend a label with an unobtrusive symbol that "sorts-last";
404 ** this clearly distincts it from the built-in elements */
405 static const char *mark = "✧";
406 char *z = mprintf("%s%s",mark,zV);
407 aSubmenu[nSubmenu].zLabel = z;
408 /* also prettify the first segment */
409 z += strlen(mark);
410 z[0] = fossil_toupper(z[0]);
411 for(; z[0]!=0; z++ ){
412 if( z[0]=='_' ) z[0] = ' ';
413 else if( z[0] == '/' ){ /* show just the first segment */
414 z[0] = 0;
415 break;
416 }
417 }
418 }
419 if( zQS[0] ){
420 aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
421 }else{
422 aSubmenu[nSubmenu].zLink = mprintf("%R/%s",zV);
423 }
424 nSubmenu++;
425 }
426 }
427 }
428
429 /*
430 ** Disable or enable the submenu
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