| | @@ -23,21 +23,40 @@ |
| 23 | 23 | #include "style.h" |
| 24 | 24 | |
| 25 | 25 | |
| 26 | 26 | /* |
| 27 | 27 | ** Elements of the submenu are collected into the following |
| 28 | | -** structure and displayed below the main menu by style_header(). |
| 28 | +** structure and displayed below the main menu. |
| 29 | +** |
| 30 | +** Populate these structure with calls to |
| 31 | +** |
| 32 | +** style_submenu_element() |
| 33 | +** style_submenu_entry() |
| 34 | +** style_submenu_checkbox() |
| 35 | +** style_submenu_multichoice() |
| 29 | 36 | ** |
| 30 | | -** Populate this structure with calls to style_submenu_element() |
| 31 | | -** prior to calling style_header(). |
| 37 | +** prior to calling style_footer(). The style_footer() routine |
| 38 | +** will generate the appropriate HTML text just below the main |
| 39 | +** menu. |
| 32 | 40 | */ |
| 33 | 41 | static struct Submenu { |
| 34 | | - const char *zLabel; |
| 42 | + const char *zLabel; /* Button label */ |
| 35 | 43 | const char *zTitle; |
| 36 | | - const char *zLink; |
| 44 | + const char *zLink; /* Jump to this link when button is pressed */ |
| 37 | 45 | } aSubmenu[30]; |
| 38 | | -static int nSubmenu = 0; |
| 46 | +static int nSubmenu = 0; /* Number of buttons */ |
| 47 | +static struct SubmenuCtrl { |
| 48 | + const char *zName; /* Form query parameter */ |
| 49 | + const char *zLabel; /* Label. Might be NULL for FF_MULTI */ |
| 50 | + int eType; /* FF_ENTRY, FF_CKBOX, FF_MULTI */ |
| 51 | + int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */ |
| 52 | + const char **azChoice; /* value/display pairs for FF_MULTI */ |
| 53 | +} aSubmenuCtrl[20]; |
| 54 | +static int nSubmenuCtrl = 0; |
| 55 | +#define FF_ENTRY 1 |
| 56 | +#define FF_CKBOX 2 |
| 57 | +#define FF_MULTI 3 |
| 39 | 58 | |
| 40 | 59 | /* |
| 41 | 60 | ** Remember that the header has been generated. The footer is omitted |
| 42 | 61 | ** if an error occurs before the header. |
| 43 | 62 | */ |
| | @@ -216,16 +235,51 @@ |
| 216 | 235 | ... |
| 217 | 236 | ){ |
| 218 | 237 | va_list ap; |
| 219 | 238 | assert( nSubmenu < sizeof(aSubmenu)/sizeof(aSubmenu[0]) ); |
| 220 | 239 | aSubmenu[nSubmenu].zLabel = zLabel; |
| 221 | | - aSubmenu[nSubmenu].zTitle = zTitle; |
| 240 | + aSubmenu[nSubmenu].zTitle = zTitle ? zTitle : zLabel; |
| 222 | 241 | va_start(ap, zLink); |
| 223 | 242 | aSubmenu[nSubmenu].zLink = vmprintf(zLink, ap); |
| 224 | 243 | va_end(ap); |
| 225 | 244 | nSubmenu++; |
| 226 | 245 | } |
| 246 | +void style_submenu_entry( |
| 247 | + const char *zName, /* Query parameter name */ |
| 248 | + const char *zLabel, /* Label before the entry box */ |
| 249 | + int iSize /* Size of the entry box */ |
| 250 | +){ |
| 251 | + assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); |
| 252 | + aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 253 | + aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 254 | + aSubmenuCtrl[nSubmenuCtrl].iSize = iSize; |
| 255 | + aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY; |
| 256 | + nSubmenuCtrl++; |
| 257 | +} |
| 258 | +void style_submenu_checkbox( |
| 259 | + const char *zName, /* Query parameter name */ |
| 260 | + const char *zLabel /* Label before the checkbox */ |
| 261 | +){ |
| 262 | + assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); |
| 263 | + aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 264 | + aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel; |
| 265 | + aSubmenuCtrl[nSubmenuCtrl].eType = FF_CKBOX; |
| 266 | + nSubmenuCtrl++; |
| 267 | +} |
| 268 | +void style_submenu_multichoice( |
| 269 | + const char *zName, /* Query parameter name */ |
| 270 | + int nChoice, /* Number of options */ |
| 271 | + const char **azChoice /* value/display pairs. 2*nChoice entries */ |
| 272 | +){ |
| 273 | + assert( nSubmenuCtrl < ArraySize(aSubmenuCtrl) ); |
| 274 | + aSubmenuCtrl[nSubmenuCtrl].zName = zName; |
| 275 | + aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice; |
| 276 | + aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice; |
| 277 | + aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; |
| 278 | + nSubmenuCtrl++; |
| 279 | +} |
| 280 | + |
| 227 | 281 | |
| 228 | 282 | /* |
| 229 | 283 | ** Compare two submenu items for sorting purposes |
| 230 | 284 | */ |
| 231 | 285 | static int submenuCompare(const void *a, const void *b){ |
| | @@ -411,23 +465,84 @@ |
| 411 | 465 | /* Go back and put the submenu at the top of the page. We delay the |
| 412 | 466 | ** creation of the submenu until the end so that we can add elements |
| 413 | 467 | ** to the submenu while generating page text. |
| 414 | 468 | */ |
| 415 | 469 | cgi_destination(CGI_HEADER); |
| 416 | | - if( nSubmenu>0 ){ |
| 470 | + if( nSubmenu+nSubmenuCtrl>0 ){ |
| 417 | 471 | int i; |
| 472 | + if( nSubmenuCtrl ){ |
| 473 | + cgi_printf("<form id='f01' method='GET' action='%R/%s'>", g.zPath); |
| 474 | + } |
| 418 | 475 | @ <div class="submenu"> |
| 419 | | - qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare); |
| 420 | | - for(i=0; i<nSubmenu; i++){ |
| 421 | | - struct Submenu *p = &aSubmenu[i]; |
| 422 | | - if( p->zLink==0 ){ |
| 423 | | - @ <span class="label">%h(p->zLabel)</span> |
| 424 | | - }else{ |
| 425 | | - @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 476 | + if( nSubmenu>0 ){ |
| 477 | + qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare); |
| 478 | + for(i=0; i<nSubmenu; i++){ |
| 479 | + struct Submenu *p = &aSubmenu[i]; |
| 480 | + if( p->zLink==0 ){ |
| 481 | + @ <span class="label">%h(p->zLabel)</span> |
| 482 | + }else{ |
| 483 | + @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> |
| 484 | + } |
| 485 | + } |
| 486 | + } |
| 487 | + if( nSubmenuCtrl>0 ){ |
| 488 | + for(i=0; i<nSubmenuCtrl; i++){ |
| 489 | + const char *zQPN = aSubmenuCtrl[i].zName; |
| 490 | + cgi_tag_query_parameter(zQPN); |
| 491 | + switch( aSubmenuCtrl[i].eType ){ |
| 492 | + case FF_ENTRY: { |
| 493 | + cgi_printf( |
| 494 | + "<span class='submenuctrl'>" |
| 495 | + "%h: <input type='text' name='%s' size='%d' " |
| 496 | + "value='%h'></span>\n", |
| 497 | + aSubmenuCtrl[i].zLabel, |
| 498 | + zQPN, |
| 499 | + aSubmenuCtrl[i].iSize, |
| 500 | + PD(zQPN,"") |
| 501 | + ); |
| 502 | + break; |
| 503 | + } |
| 504 | + case FF_CKBOX: { |
| 505 | + cgi_printf( |
| 506 | + "<span class='submenuctrl'>" |
| 507 | + "%h: <input type='checkbox' name='%s'%s " |
| 508 | + "onchange='gebi(\"f01\").submit();'></span>\n", |
| 509 | + aSubmenuCtrl[i].zLabel, |
| 510 | + zQPN, |
| 511 | + PB(zQPN) ? " checked":"" |
| 512 | + ); |
| 513 | + break; |
| 514 | + } |
| 515 | + case FF_MULTI: { |
| 516 | + int j; |
| 517 | + const char *zVal = P(zQPN); |
| 518 | + cgi_printf( |
| 519 | + "<select class='submenuctrl' size='1' name='%s' " |
| 520 | + "onchange='gebi(\"f01\").submit();'>\n", |
| 521 | + zQPN |
| 522 | + ); |
| 523 | + for(j=0; j<aSubmenuCtrl[i].iSize*2; j+=2){ |
| 524 | + const char *zQPV = aSubmenuCtrl[i].azChoice[j]; |
| 525 | + cgi_printf( |
| 526 | + "<option value='%h'%s>%h</option>\n", |
| 527 | + zQPV, |
| 528 | + fossil_strcmp(zVal,zQPV)==0 ? " selected" : "", |
| 529 | + aSubmenuCtrl[i].azChoice[j+1] |
| 530 | + ); |
| 531 | + } |
| 532 | + @ </select> |
| 533 | + break; |
| 534 | + } |
| 535 | + } |
| 426 | 536 | } |
| 427 | 537 | } |
| 428 | 538 | @ </div> |
| 539 | + if( nSubmenuCtrl ){ |
| 540 | + cgi_query_parameters_to_hidden(); |
| 541 | + cgi_tag_query_parameter(0); |
| 542 | + @ </form> |
| 543 | + } |
| 429 | 544 | } |
| 430 | 545 | |
| 431 | 546 | zAd = style_adunit_text(&mAdFlags); |
| 432 | 547 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| 433 | 548 | @ <div class="content adunit_right_container"> |
| | @@ -1246,22 +1361,21 @@ |
| 1246 | 1361 | } |
| 1247 | 1362 | for(i=0; i<count(azCgiVars); i++) (void)P(azCgiVars[i]); |
| 1248 | 1363 | style_header("Environment Test"); |
| 1249 | 1364 | showAll = atoi(PD("showall","0")); |
| 1250 | 1365 | if( !showAll ){ |
| 1251 | | - style_submenu_element("Show Cookies", "Show Cookies", |
| 1252 | | - "%s/test_env?showall=1", g.zTop); |
| 1366 | + style_submenu_element("Show Cookies", 0, "%R/test_env?showall=1"); |
| 1253 | 1367 | }else{ |
| 1254 | | - style_submenu_element("Hide Cookies", "Hide Cookies", |
| 1255 | | - "%s/test_env", g.zTop); |
| 1368 | + style_submenu_element("Hide Cookies", 0, "%R/test_env"); |
| 1256 | 1369 | } |
| 1257 | 1370 | #if !defined(_WIN32) |
| 1258 | 1371 | @ uid=%d(getuid()), gid=%d(getgid())<br /> |
| 1259 | 1372 | #endif |
| 1260 | 1373 | @ g.zBaseURL = %h(g.zBaseURL)<br /> |
| 1261 | 1374 | @ g.zHttpsURL = %h(g.zHttpsURL)<br /> |
| 1262 | 1375 | @ g.zTop = %h(g.zTop)<br /> |
| 1376 | + @ g.zPath = %h(g.zPath)<br /> |
| 1263 | 1377 | for(i=0, c='a'; c<='z'; c++){ |
| 1264 | 1378 | if( login_has_capability(&c, 1) ) zCap[i++] = c; |
| 1265 | 1379 | } |
| 1266 | 1380 | zCap[i] = 0; |
| 1267 | 1381 | @ g.userUid = %d(g.userUid)<br /> |
| 1268 | 1382 | |