Fossil SCM

Merge trunk

jan.nijtmans 2014-01-06 10:36 UTC sqlite-min-to-3.7.17 merge
Commit 99af4d2a1264cd99cb5f90d3b78e2dc002162a71
+36 -39
--- src/browse.c
+++ src/browse.c
@@ -386,24 +386,10 @@
386386
pNew->isLast = 1;
387387
while( zPath[i]=='/' ){ i++; }
388388
pParent = pNew;
389389
}
390390
}
391
-
392
-/*
393
-** Render parent lines for pNode
394
-*/
395
-static void tree_indentation(FileTreeNode *p){
396
- if( p==0 ) return;
397
- tree_indentation(p->pParent);
398
- if( p->isLast ){
399
- cgi_append_content(" ", 4);
400
- }else{
401
- cgi_append_content("│ ", 11);
402
- }
403
-}
404
-
405391
406392
/*
407393
** WEBPAGE: tree
408394
**
409395
** Query parameters:
@@ -422,16 +408,16 @@
422408
Manifest *pM = 0;
423409
int nFile = 0; /* Number of files */
424410
int linkTrunk = 1; /* include link to "trunk" */
425411
int linkTip = 1; /* include link to "tip" */
426412
const char *zRE; /* the value for the re=REGEXP query parameter */
427
- char *zPrefix; /* Prefix on all filenames */
428413
char *zREx = ""; /* Extra parameters for path hyperlinks */
429414
ReCompiled *pRE = 0; /* Compiled regular expression */
430415
FileTreeNode *p; /* One line of the tree */
431416
FileTree sTree; /* The complete tree of files */
432417
HQuery sURI; /* Hyperlink */
418
+ char *zProjectName = db_get("project-name", 0);
433419
434420
if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; }
435421
memset(&sTree, 0, sizeof(sTree));
436422
login_check_credentials();
437423
if( !g.perm.Read ){ login_needed(); return; }
@@ -474,18 +460,16 @@
474460
if( zD ){
475461
url_add_parameter(&sURI, "name", zD);
476462
blob_append(&dirname, "within directory ", -1);
477463
hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
478464
if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
479
- zPrefix = mprintf("%T/", zD);
480465
style_submenu_element("Top-Level", "Top-Level", "%s",
481466
url_render(&sURI, "name", 0, 0, 0));
482467
}else{
483468
if( zRE ){
484469
blob_appendf(&dirname, "matching \"%s\"", zRE);
485470
}
486
- zPrefix = "";
487471
}
488472
if( zCI ){
489473
style_submenu_element("All", "All", "%s",
490474
url_render(&sURI, "ci", 0, 0, 0));
491475
}
@@ -519,11 +503,11 @@
519503
|| pFile->zName[nD-1]!='/')
520504
){
521505
continue;
522506
}
523507
if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
524
- db_bind_text(&ins, ":f", &pFile->zName[nD]);
508
+ db_bind_text(&ins, ":f", pFile->zName);
525509
db_bind_text(&ins, ":u", pFile->zUuid);
526510
db_step(&ins);
527511
db_reset(&ins);
528512
}
529513
db_finalize(&ins);
@@ -540,11 +524,11 @@
540524
const char *z = db_column_text(&q, 0);
541525
if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
542526
continue;
543527
}
544528
if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
545
- tree_add_node(&sTree, z+nD, 0);
529
+ tree_add_node(&sTree, z, 0);
546530
nFile++;
547531
}
548532
db_finalize(&q);
549533
}
550534
@@ -560,39 +544,52 @@
560544
561545
562546
/* Generate a multi-column table listing the contents of zD[]
563547
** directory.
564548
*/
565
- @ <pre>
549
+ @ <div class="filetree"><ul>
566550
if( nD ){
567
- cgi_printf("%.*h\n", nD, zD);
568
- }else{
569
- @ .
570
- }
571
- for(p=sTree.pFirst; p; p=p->pNext){
572
- tree_indentation(p->pParent);
573
- if( p->isLast ){
574
- cgi_append_content("&#x2514;&#x2500;&#x2500; ", 25);
575
- }else{
576
- cgi_append_content("&#x251c;&#x2500;&#x2500; ", 25);
577
- }
551
+ char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0));
552
+ @ <li class="dir">
553
+ @ %z(zLink)%h(zProjectName)</a>
554
+ }else{
555
+ @ <li class="dir subdir">
556
+ @ <a>%h(zProjectName)</a>
557
+ }
558
+ @ <ul>
559
+ for(p=sTree.pFirst; p; p=p->pNext){
578560
if( p->isDir ){
579
- char *zName = mprintf("%s%T", zPrefix, p->zFullName);
580
- char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0));
581
- fossil_free(zName);
582
- @ %z(zLink)%h(p->zName)</a>
561
+ if( nD && strlen(p->zFullName)==nD-1 ){
562
+ @ <li class="dir subdir">
563
+ }else{
564
+ @ <li class="dir">
565
+ }
566
+ if( fossil_strcmp(p->zFullName, zD)==0 ){
567
+ @ <a>%h(p->zName)</a>
568
+ }else{
569
+ char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0));
570
+ @ %z(zLink)%h(p->zName)</a>
571
+ }
572
+ @ <ul>
583573
}else{
584574
char *zLink;
585575
if( zCI ){
586576
zLink = href("%R/artifact/%s",p->zUuid);
587577
}else{
588
- zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName);
578
+ zLink = href("%R/finfo?name=%T",p->zFullName);
589579
}
590
- @ %z(zLink)%h(p->zName)</a>
580
+ @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a>
581
+ }
582
+ if( p->isLast ){
583
+ int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
584
+ while( nClose-- > 0 ){
585
+ @ </ul>
586
+ }
591587
}
592588
}
593
- @ </pre>
589
+ @ </ul>
590
+ @ </ul></div>
594591
style_footer();
595592
596593
/* We could free memory used by sTree here if we needed to. But
597594
** the process is about to exit, so doing so would not really accomplish
598595
** anything useful. */
@@ -607,11 +604,11 @@
607604
const char *zExt = strrchr(zFilename, '.');
608605
int isExt = zExt && zExt!=zFilename && zExt[1];
609606
int i;
610607
for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
611608
if( isExt ){
612
- zClass = mprintf("file-%s", zExt+1);
609
+ zClass = mprintf("file file-%s", zExt+1);
613610
for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
614611
}else{
615612
zClass = mprintf("file");
616613
}
617614
return zClass;
618615
--- src/browse.c
+++ src/browse.c
@@ -386,24 +386,10 @@
386 pNew->isLast = 1;
387 while( zPath[i]=='/' ){ i++; }
388 pParent = pNew;
389 }
390 }
391
392 /*
393 ** Render parent lines for pNode
394 */
395 static void tree_indentation(FileTreeNode *p){
396 if( p==0 ) return;
397 tree_indentation(p->pParent);
398 if( p->isLast ){
399 cgi_append_content(" ", 4);
400 }else{
401 cgi_append_content("&#x2502; ", 11);
402 }
403 }
404
405
406 /*
407 ** WEBPAGE: tree
408 **
409 ** Query parameters:
@@ -422,16 +408,16 @@
422 Manifest *pM = 0;
423 int nFile = 0; /* Number of files */
424 int linkTrunk = 1; /* include link to "trunk" */
425 int linkTip = 1; /* include link to "tip" */
426 const char *zRE; /* the value for the re=REGEXP query parameter */
427 char *zPrefix; /* Prefix on all filenames */
428 char *zREx = ""; /* Extra parameters for path hyperlinks */
429 ReCompiled *pRE = 0; /* Compiled regular expression */
430 FileTreeNode *p; /* One line of the tree */
431 FileTree sTree; /* The complete tree of files */
432 HQuery sURI; /* Hyperlink */
 
433
434 if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; }
435 memset(&sTree, 0, sizeof(sTree));
436 login_check_credentials();
437 if( !g.perm.Read ){ login_needed(); return; }
@@ -474,18 +460,16 @@
474 if( zD ){
475 url_add_parameter(&sURI, "name", zD);
476 blob_append(&dirname, "within directory ", -1);
477 hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
478 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
479 zPrefix = mprintf("%T/", zD);
480 style_submenu_element("Top-Level", "Top-Level", "%s",
481 url_render(&sURI, "name", 0, 0, 0));
482 }else{
483 if( zRE ){
484 blob_appendf(&dirname, "matching \"%s\"", zRE);
485 }
486 zPrefix = "";
487 }
488 if( zCI ){
489 style_submenu_element("All", "All", "%s",
490 url_render(&sURI, "ci", 0, 0, 0));
491 }
@@ -519,11 +503,11 @@
519 || pFile->zName[nD-1]!='/')
520 ){
521 continue;
522 }
523 if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
524 db_bind_text(&ins, ":f", &pFile->zName[nD]);
525 db_bind_text(&ins, ":u", pFile->zUuid);
526 db_step(&ins);
527 db_reset(&ins);
528 }
529 db_finalize(&ins);
@@ -540,11 +524,11 @@
540 const char *z = db_column_text(&q, 0);
541 if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
542 continue;
543 }
544 if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
545 tree_add_node(&sTree, z+nD, 0);
546 nFile++;
547 }
548 db_finalize(&q);
549 }
550
@@ -560,39 +544,52 @@
560
561
562 /* Generate a multi-column table listing the contents of zD[]
563 ** directory.
564 */
565 @ <pre>
566 if( nD ){
567 cgi_printf("%.*h\n", nD, zD);
568 }else{
569 @ .
570 }
571 for(p=sTree.pFirst; p; p=p->pNext){
572 tree_indentation(p->pParent);
573 if( p->isLast ){
574 cgi_append_content("&#x2514;&#x2500;&#x2500; ", 25);
575 }else{
576 cgi_append_content("&#x251c;&#x2500;&#x2500; ", 25);
577 }
578 if( p->isDir ){
579 char *zName = mprintf("%s%T", zPrefix, p->zFullName);
580 char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0));
581 fossil_free(zName);
582 @ %z(zLink)%h(p->zName)</a>
 
 
 
 
 
 
 
 
583 }else{
584 char *zLink;
585 if( zCI ){
586 zLink = href("%R/artifact/%s",p->zUuid);
587 }else{
588 zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName);
589 }
590 @ %z(zLink)%h(p->zName)</a>
 
 
 
 
 
 
591 }
592 }
593 @ </pre>
 
594 style_footer();
595
596 /* We could free memory used by sTree here if we needed to. But
597 ** the process is about to exit, so doing so would not really accomplish
598 ** anything useful. */
@@ -607,11 +604,11 @@
607 const char *zExt = strrchr(zFilename, '.');
608 int isExt = zExt && zExt!=zFilename && zExt[1];
609 int i;
610 for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
611 if( isExt ){
612 zClass = mprintf("file-%s", zExt+1);
613 for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
614 }else{
615 zClass = mprintf("file");
616 }
617 return zClass;
618
--- src/browse.c
+++ src/browse.c
@@ -386,24 +386,10 @@
386 pNew->isLast = 1;
387 while( zPath[i]=='/' ){ i++; }
388 pParent = pNew;
389 }
390 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
392 /*
393 ** WEBPAGE: tree
394 **
395 ** Query parameters:
@@ -422,16 +408,16 @@
408 Manifest *pM = 0;
409 int nFile = 0; /* Number of files */
410 int linkTrunk = 1; /* include link to "trunk" */
411 int linkTip = 1; /* include link to "tip" */
412 const char *zRE; /* the value for the re=REGEXP query parameter */
 
413 char *zREx = ""; /* Extra parameters for path hyperlinks */
414 ReCompiled *pRE = 0; /* Compiled regular expression */
415 FileTreeNode *p; /* One line of the tree */
416 FileTree sTree; /* The complete tree of files */
417 HQuery sURI; /* Hyperlink */
418 char *zProjectName = db_get("project-name", 0);
419
420 if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; }
421 memset(&sTree, 0, sizeof(sTree));
422 login_check_credentials();
423 if( !g.perm.Read ){ login_needed(); return; }
@@ -474,18 +460,16 @@
460 if( zD ){
461 url_add_parameter(&sURI, "name", zD);
462 blob_append(&dirname, "within directory ", -1);
463 hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
464 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
 
465 style_submenu_element("Top-Level", "Top-Level", "%s",
466 url_render(&sURI, "name", 0, 0, 0));
467 }else{
468 if( zRE ){
469 blob_appendf(&dirname, "matching \"%s\"", zRE);
470 }
 
471 }
472 if( zCI ){
473 style_submenu_element("All", "All", "%s",
474 url_render(&sURI, "ci", 0, 0, 0));
475 }
@@ -519,11 +503,11 @@
503 || pFile->zName[nD-1]!='/')
504 ){
505 continue;
506 }
507 if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
508 db_bind_text(&ins, ":f", pFile->zName);
509 db_bind_text(&ins, ":u", pFile->zUuid);
510 db_step(&ins);
511 db_reset(&ins);
512 }
513 db_finalize(&ins);
@@ -540,11 +524,11 @@
524 const char *z = db_column_text(&q, 0);
525 if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
526 continue;
527 }
528 if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
529 tree_add_node(&sTree, z, 0);
530 nFile++;
531 }
532 db_finalize(&q);
533 }
534
@@ -560,39 +544,52 @@
544
545
546 /* Generate a multi-column table listing the contents of zD[]
547 ** directory.
548 */
549 @ <div class="filetree"><ul>
550 if( nD ){
551 char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0));
552 @ <li class="dir">
553 @ %z(zLink)%h(zProjectName)</a>
554 }else{
555 @ <li class="dir subdir">
556 @ <a>%h(zProjectName)</a>
557 }
558 @ <ul>
559 for(p=sTree.pFirst; p; p=p->pNext){
 
 
560 if( p->isDir ){
561 if( nD && strlen(p->zFullName)==nD-1 ){
562 @ <li class="dir subdir">
563 }else{
564 @ <li class="dir">
565 }
566 if( fossil_strcmp(p->zFullName, zD)==0 ){
567 @ <a>%h(p->zName)</a>
568 }else{
569 char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0));
570 @ %z(zLink)%h(p->zName)</a>
571 }
572 @ <ul>
573 }else{
574 char *zLink;
575 if( zCI ){
576 zLink = href("%R/artifact/%s",p->zUuid);
577 }else{
578 zLink = href("%R/finfo?name=%T",p->zFullName);
579 }
580 @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a>
581 }
582 if( p->isLast ){
583 int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
584 while( nClose-- > 0 ){
585 @ </ul>
586 }
587 }
588 }
589 @ </ul>
590 @ </ul></div>
591 style_footer();
592
593 /* We could free memory used by sTree here if we needed to. But
594 ** the process is about to exit, so doing so would not really accomplish
595 ** anything useful. */
@@ -607,11 +604,11 @@
604 const char *zExt = strrchr(zFilename, '.');
605 int isExt = zExt && zExt!=zFilename && zExt[1];
606 int i;
607 for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
608 if( isExt ){
609 zClass = mprintf("file file-%s", zExt+1);
610 for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
611 }else{
612 zClass = mprintf("file");
613 }
614 return zClass;
615
+36 -39
--- src/browse.c
+++ src/browse.c
@@ -386,24 +386,10 @@
386386
pNew->isLast = 1;
387387
while( zPath[i]=='/' ){ i++; }
388388
pParent = pNew;
389389
}
390390
}
391
-
392
-/*
393
-** Render parent lines for pNode
394
-*/
395
-static void tree_indentation(FileTreeNode *p){
396
- if( p==0 ) return;
397
- tree_indentation(p->pParent);
398
- if( p->isLast ){
399
- cgi_append_content(" ", 4);
400
- }else{
401
- cgi_append_content("&#x2502; ", 11);
402
- }
403
-}
404
-
405391
406392
/*
407393
** WEBPAGE: tree
408394
**
409395
** Query parameters:
@@ -422,16 +408,16 @@
422408
Manifest *pM = 0;
423409
int nFile = 0; /* Number of files */
424410
int linkTrunk = 1; /* include link to "trunk" */
425411
int linkTip = 1; /* include link to "tip" */
426412
const char *zRE; /* the value for the re=REGEXP query parameter */
427
- char *zPrefix; /* Prefix on all filenames */
428413
char *zREx = ""; /* Extra parameters for path hyperlinks */
429414
ReCompiled *pRE = 0; /* Compiled regular expression */
430415
FileTreeNode *p; /* One line of the tree */
431416
FileTree sTree; /* The complete tree of files */
432417
HQuery sURI; /* Hyperlink */
418
+ char *zProjectName = db_get("project-name", 0);
433419
434420
if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; }
435421
memset(&sTree, 0, sizeof(sTree));
436422
login_check_credentials();
437423
if( !g.perm.Read ){ login_needed(); return; }
@@ -474,18 +460,16 @@
474460
if( zD ){
475461
url_add_parameter(&sURI, "name", zD);
476462
blob_append(&dirname, "within directory ", -1);
477463
hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
478464
if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
479
- zPrefix = mprintf("%T/", zD);
480465
style_submenu_element("Top-Level", "Top-Level", "%s",
481466
url_render(&sURI, "name", 0, 0, 0));
482467
}else{
483468
if( zRE ){
484469
blob_appendf(&dirname, "matching \"%s\"", zRE);
485470
}
486
- zPrefix = "";
487471
}
488472
if( zCI ){
489473
style_submenu_element("All", "All", "%s",
490474
url_render(&sURI, "ci", 0, 0, 0));
491475
}
@@ -519,11 +503,11 @@
519503
|| pFile->zName[nD-1]!='/')
520504
){
521505
continue;
522506
}
523507
if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
524
- db_bind_text(&ins, ":f", &pFile->zName[nD]);
508
+ db_bind_text(&ins, ":f", pFile->zName);
525509
db_bind_text(&ins, ":u", pFile->zUuid);
526510
db_step(&ins);
527511
db_reset(&ins);
528512
}
529513
db_finalize(&ins);
@@ -540,11 +524,11 @@
540524
const char *z = db_column_text(&q, 0);
541525
if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
542526
continue;
543527
}
544528
if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
545
- tree_add_node(&sTree, z+nD, 0);
529
+ tree_add_node(&sTree, z, 0);
546530
nFile++;
547531
}
548532
db_finalize(&q);
549533
}
550534
@@ -560,39 +544,52 @@
560544
561545
562546
/* Generate a multi-column table listing the contents of zD[]
563547
** directory.
564548
*/
565
- @ <pre>
549
+ @ <div class="filetree"><ul>
566550
if( nD ){
567
- cgi_printf("%.*h\n", nD, zD);
568
- }else{
569
- @ .
570
- }
571
- for(p=sTree.pFirst; p; p=p->pNext){
572
- tree_indentation(p->pParent);
573
- if( p->isLast ){
574
- cgi_append_content("&#x2514;&#x2500;&#x2500; ", 25);
575
- }else{
576
- cgi_append_content("&#x251c;&#x2500;&#x2500; ", 25);
577
- }
551
+ char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0));
552
+ @ <li class="dir">
553
+ @ %z(zLink)%h(zProjectName)</a>
554
+ }else{
555
+ @ <li class="dir subdir">
556
+ @ <a>%h(zProjectName)</a>
557
+ }
558
+ @ <ul>
559
+ for(p=sTree.pFirst; p; p=p->pNext){
578560
if( p->isDir ){
579
- char *zName = mprintf("%s%T", zPrefix, p->zFullName);
580
- char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0));
581
- fossil_free(zName);
582
- @ %z(zLink)%h(p->zName)</a>
561
+ if( nD && strlen(p->zFullName)==nD-1 ){
562
+ @ <li class="dir subdir">
563
+ }else{
564
+ @ <li class="dir">
565
+ }
566
+ if( fossil_strcmp(p->zFullName, zD)==0 ){
567
+ @ <a>%h(p->zName)</a>
568
+ }else{
569
+ char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0));
570
+ @ %z(zLink)%h(p->zName)</a>
571
+ }
572
+ @ <ul>
583573
}else{
584574
char *zLink;
585575
if( zCI ){
586576
zLink = href("%R/artifact/%s",p->zUuid);
587577
}else{
588
- zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName);
578
+ zLink = href("%R/finfo?name=%T",p->zFullName);
589579
}
590
- @ %z(zLink)%h(p->zName)</a>
580
+ @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a>
581
+ }
582
+ if( p->isLast ){
583
+ int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
584
+ while( nClose-- > 0 ){
585
+ @ </ul>
586
+ }
591587
}
592588
}
593
- @ </pre>
589
+ @ </ul>
590
+ @ </ul></div>
594591
style_footer();
595592
596593
/* We could free memory used by sTree here if we needed to. But
597594
** the process is about to exit, so doing so would not really accomplish
598595
** anything useful. */
@@ -607,11 +604,11 @@
607604
const char *zExt = strrchr(zFilename, '.');
608605
int isExt = zExt && zExt!=zFilename && zExt[1];
609606
int i;
610607
for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
611608
if( isExt ){
612
- zClass = mprintf("file-%s", zExt+1);
609
+ zClass = mprintf("file file-%s", zExt+1);
613610
for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
614611
}else{
615612
zClass = mprintf("file");
616613
}
617614
return zClass;
618615
--- src/browse.c
+++ src/browse.c
@@ -386,24 +386,10 @@
386 pNew->isLast = 1;
387 while( zPath[i]=='/' ){ i++; }
388 pParent = pNew;
389 }
390 }
391
392 /*
393 ** Render parent lines for pNode
394 */
395 static void tree_indentation(FileTreeNode *p){
396 if( p==0 ) return;
397 tree_indentation(p->pParent);
398 if( p->isLast ){
399 cgi_append_content(" ", 4);
400 }else{
401 cgi_append_content("&#x2502; ", 11);
402 }
403 }
404
405
406 /*
407 ** WEBPAGE: tree
408 **
409 ** Query parameters:
@@ -422,16 +408,16 @@
422 Manifest *pM = 0;
423 int nFile = 0; /* Number of files */
424 int linkTrunk = 1; /* include link to "trunk" */
425 int linkTip = 1; /* include link to "tip" */
426 const char *zRE; /* the value for the re=REGEXP query parameter */
427 char *zPrefix; /* Prefix on all filenames */
428 char *zREx = ""; /* Extra parameters for path hyperlinks */
429 ReCompiled *pRE = 0; /* Compiled regular expression */
430 FileTreeNode *p; /* One line of the tree */
431 FileTree sTree; /* The complete tree of files */
432 HQuery sURI; /* Hyperlink */
 
433
434 if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; }
435 memset(&sTree, 0, sizeof(sTree));
436 login_check_credentials();
437 if( !g.perm.Read ){ login_needed(); return; }
@@ -474,18 +460,16 @@
474 if( zD ){
475 url_add_parameter(&sURI, "name", zD);
476 blob_append(&dirname, "within directory ", -1);
477 hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
478 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
479 zPrefix = mprintf("%T/", zD);
480 style_submenu_element("Top-Level", "Top-Level", "%s",
481 url_render(&sURI, "name", 0, 0, 0));
482 }else{
483 if( zRE ){
484 blob_appendf(&dirname, "matching \"%s\"", zRE);
485 }
486 zPrefix = "";
487 }
488 if( zCI ){
489 style_submenu_element("All", "All", "%s",
490 url_render(&sURI, "ci", 0, 0, 0));
491 }
@@ -519,11 +503,11 @@
519 || pFile->zName[nD-1]!='/')
520 ){
521 continue;
522 }
523 if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
524 db_bind_text(&ins, ":f", &pFile->zName[nD]);
525 db_bind_text(&ins, ":u", pFile->zUuid);
526 db_step(&ins);
527 db_reset(&ins);
528 }
529 db_finalize(&ins);
@@ -540,11 +524,11 @@
540 const char *z = db_column_text(&q, 0);
541 if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
542 continue;
543 }
544 if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
545 tree_add_node(&sTree, z+nD, 0);
546 nFile++;
547 }
548 db_finalize(&q);
549 }
550
@@ -560,39 +544,52 @@
560
561
562 /* Generate a multi-column table listing the contents of zD[]
563 ** directory.
564 */
565 @ <pre>
566 if( nD ){
567 cgi_printf("%.*h\n", nD, zD);
568 }else{
569 @ .
570 }
571 for(p=sTree.pFirst; p; p=p->pNext){
572 tree_indentation(p->pParent);
573 if( p->isLast ){
574 cgi_append_content("&#x2514;&#x2500;&#x2500; ", 25);
575 }else{
576 cgi_append_content("&#x251c;&#x2500;&#x2500; ", 25);
577 }
578 if( p->isDir ){
579 char *zName = mprintf("%s%T", zPrefix, p->zFullName);
580 char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0));
581 fossil_free(zName);
582 @ %z(zLink)%h(p->zName)</a>
 
 
 
 
 
 
 
 
583 }else{
584 char *zLink;
585 if( zCI ){
586 zLink = href("%R/artifact/%s",p->zUuid);
587 }else{
588 zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName);
589 }
590 @ %z(zLink)%h(p->zName)</a>
 
 
 
 
 
 
591 }
592 }
593 @ </pre>
 
594 style_footer();
595
596 /* We could free memory used by sTree here if we needed to. But
597 ** the process is about to exit, so doing so would not really accomplish
598 ** anything useful. */
@@ -607,11 +604,11 @@
607 const char *zExt = strrchr(zFilename, '.');
608 int isExt = zExt && zExt!=zFilename && zExt[1];
609 int i;
610 for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
611 if( isExt ){
612 zClass = mprintf("file-%s", zExt+1);
613 for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
614 }else{
615 zClass = mprintf("file");
616 }
617 return zClass;
618
--- src/browse.c
+++ src/browse.c
@@ -386,24 +386,10 @@
386 pNew->isLast = 1;
387 while( zPath[i]=='/' ){ i++; }
388 pParent = pNew;
389 }
390 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
392 /*
393 ** WEBPAGE: tree
394 **
395 ** Query parameters:
@@ -422,16 +408,16 @@
408 Manifest *pM = 0;
409 int nFile = 0; /* Number of files */
410 int linkTrunk = 1; /* include link to "trunk" */
411 int linkTip = 1; /* include link to "tip" */
412 const char *zRE; /* the value for the re=REGEXP query parameter */
 
413 char *zREx = ""; /* Extra parameters for path hyperlinks */
414 ReCompiled *pRE = 0; /* Compiled regular expression */
415 FileTreeNode *p; /* One line of the tree */
416 FileTree sTree; /* The complete tree of files */
417 HQuery sURI; /* Hyperlink */
418 char *zProjectName = db_get("project-name", 0);
419
420 if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; }
421 memset(&sTree, 0, sizeof(sTree));
422 login_check_credentials();
423 if( !g.perm.Read ){ login_needed(); return; }
@@ -474,18 +460,16 @@
460 if( zD ){
461 url_add_parameter(&sURI, "name", zD);
462 blob_append(&dirname, "within directory ", -1);
463 hyperlinked_path(zD, &dirname, zCI, "tree", zREx);
464 if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE);
 
465 style_submenu_element("Top-Level", "Top-Level", "%s",
466 url_render(&sURI, "name", 0, 0, 0));
467 }else{
468 if( zRE ){
469 blob_appendf(&dirname, "matching \"%s\"", zRE);
470 }
 
471 }
472 if( zCI ){
473 style_submenu_element("All", "All", "%s",
474 url_render(&sURI, "ci", 0, 0, 0));
475 }
@@ -519,11 +503,11 @@
503 || pFile->zName[nD-1]!='/')
504 ){
505 continue;
506 }
507 if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue;
508 db_bind_text(&ins, ":f", pFile->zName);
509 db_bind_text(&ins, ":u", pFile->zUuid);
510 db_step(&ins);
511 db_reset(&ins);
512 }
513 db_finalize(&ins);
@@ -540,11 +524,11 @@
524 const char *z = db_column_text(&q, 0);
525 if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){
526 continue;
527 }
528 if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue;
529 tree_add_node(&sTree, z, 0);
530 nFile++;
531 }
532 db_finalize(&q);
533 }
534
@@ -560,39 +544,52 @@
544
545
546 /* Generate a multi-column table listing the contents of zD[]
547 ** directory.
548 */
549 @ <div class="filetree"><ul>
550 if( nD ){
551 char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0));
552 @ <li class="dir">
553 @ %z(zLink)%h(zProjectName)</a>
554 }else{
555 @ <li class="dir subdir">
556 @ <a>%h(zProjectName)</a>
557 }
558 @ <ul>
559 for(p=sTree.pFirst; p; p=p->pNext){
 
 
560 if( p->isDir ){
561 if( nD && strlen(p->zFullName)==nD-1 ){
562 @ <li class="dir subdir">
563 }else{
564 @ <li class="dir">
565 }
566 if( fossil_strcmp(p->zFullName, zD)==0 ){
567 @ <a>%h(p->zName)</a>
568 }else{
569 char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0));
570 @ %z(zLink)%h(p->zName)</a>
571 }
572 @ <ul>
573 }else{
574 char *zLink;
575 if( zCI ){
576 zLink = href("%R/artifact/%s",p->zUuid);
577 }else{
578 zLink = href("%R/finfo?name=%T",p->zFullName);
579 }
580 @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a>
581 }
582 if( p->isLast ){
583 int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
584 while( nClose-- > 0 ){
585 @ </ul>
586 }
587 }
588 }
589 @ </ul>
590 @ </ul></div>
591 style_footer();
592
593 /* We could free memory used by sTree here if we needed to. But
594 ** the process is about to exit, so doing so would not really accomplish
595 ** anything useful. */
@@ -607,11 +604,11 @@
604 const char *zExt = strrchr(zFilename, '.');
605 int isExt = zExt && zExt!=zFilename && zExt[1];
606 int i;
607 for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]);
608 if( isExt ){
609 zClass = mprintf("file file-%s", zExt+1);
610 for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]);
611 }else{
612 zClass = mprintf("file");
613 }
614 return zClass;
615
+46
--- src/db.c
+++ src/db.c
@@ -852,10 +852,32 @@
852852
g.zConfigDbType = "configdb";
853853
}
854854
g.zConfigDbName = zDbName;
855855
}
856856
857
+
858
+/*
859
+** Returns TRUE if zTable exists in the local database but lacks column
860
+** zColumn
861
+*/
862
+static int db_local_table_exists_but_lacks_column(
863
+ const char *zTable,
864
+ const char *zColumn
865
+){
866
+ char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
867
+ " WHERE name=='%s' /*scan*/",
868
+ db_name("localdb"), zTable);
869
+ int rc = 0;
870
+ if( zDef ){
871
+ char *zPattern = mprintf("* %s *", zColumn);
872
+ rc = strglob(zPattern, zDef)==0;
873
+ fossil_free(zPattern);
874
+ fossil_free(zDef);
875
+ }
876
+ return rc;
877
+}
878
+
857879
/*
858880
** If zDbName is a valid local database file, open it and return
859881
** true. If it is not a valid local database file, return 0.
860882
*/
861883
static int isValidLocalDb(const char *zDbName){
@@ -868,10 +890,34 @@
868890
db_open_or_attach(zDbName, "localdb", 0);
869891
zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
870892
" WHERE name=='vfile'", db_name("localdb"));
871893
if( zVFileDef==0 ) return 0;
872894
895
+ /* If the "isexe" column is missing from the vfile table, then
896
+ ** add it now. This code added on 2010-03-06. After all users have
897
+ ** upgraded, this code can be safely deleted.
898
+ */
899
+ if( !strglob("* isexe *", zVFileDef) ){
900
+ db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
901
+ }
902
+
903
+ /* If "islink"/"isLink" columns are missing from tables, then
904
+ ** add them now. This code added on 2011-01-17 and 2011-08-27.
905
+ ** After all users have upgraded, this code can be safely deleted.
906
+ */
907
+ if( !strglob("* islink *", zVFileDef) ){
908
+ db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
909
+ if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
910
+ db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
911
+ }
912
+ if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
913
+ db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
914
+ }
915
+ if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
916
+ db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
917
+ }
918
+ }
873919
return 1;
874920
}
875921
876922
/*
877923
** Locate the root directory of the local repository tree. The root
878924
--- src/db.c
+++ src/db.c
@@ -852,10 +852,32 @@
852 g.zConfigDbType = "configdb";
853 }
854 g.zConfigDbName = zDbName;
855 }
856
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
857 /*
858 ** If zDbName is a valid local database file, open it and return
859 ** true. If it is not a valid local database file, return 0.
860 */
861 static int isValidLocalDb(const char *zDbName){
@@ -868,10 +890,34 @@
868 db_open_or_attach(zDbName, "localdb", 0);
869 zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
870 " WHERE name=='vfile'", db_name("localdb"));
871 if( zVFileDef==0 ) return 0;
872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
873 return 1;
874 }
875
876 /*
877 ** Locate the root directory of the local repository tree. The root
878
--- src/db.c
+++ src/db.c
@@ -852,10 +852,32 @@
852 g.zConfigDbType = "configdb";
853 }
854 g.zConfigDbName = zDbName;
855 }
856
857
858 /*
859 ** Returns TRUE if zTable exists in the local database but lacks column
860 ** zColumn
861 */
862 static int db_local_table_exists_but_lacks_column(
863 const char *zTable,
864 const char *zColumn
865 ){
866 char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
867 " WHERE name=='%s' /*scan*/",
868 db_name("localdb"), zTable);
869 int rc = 0;
870 if( zDef ){
871 char *zPattern = mprintf("* %s *", zColumn);
872 rc = strglob(zPattern, zDef)==0;
873 fossil_free(zPattern);
874 fossil_free(zDef);
875 }
876 return rc;
877 }
878
879 /*
880 ** If zDbName is a valid local database file, open it and return
881 ** true. If it is not a valid local database file, return 0.
882 */
883 static int isValidLocalDb(const char *zDbName){
@@ -868,10 +890,34 @@
890 db_open_or_attach(zDbName, "localdb", 0);
891 zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master"
892 " WHERE name=='vfile'", db_name("localdb"));
893 if( zVFileDef==0 ) return 0;
894
895 /* If the "isexe" column is missing from the vfile table, then
896 ** add it now. This code added on 2010-03-06. After all users have
897 ** upgraded, this code can be safely deleted.
898 */
899 if( !strglob("* isexe *", zVFileDef) ){
900 db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0");
901 }
902
903 /* If "islink"/"isLink" columns are missing from tables, then
904 ** add them now. This code added on 2011-01-17 and 2011-08-27.
905 ** After all users have upgraded, this code can be safely deleted.
906 */
907 if( !strglob("* islink *", zVFileDef) ){
908 db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0");
909 if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){
910 db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0");
911 }
912 if( db_local_table_exists_but_lacks_column("undo", "isLink") ){
913 db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
914 }
915 if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
916 db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
917 }
918 }
919 return 1;
920 }
921
922 /*
923 ** Locate the root directory of the local repository tree. The root
924
+69
--- src/style.c
+++ src/style.c
@@ -771,10 +771,79 @@
771771
"format for the list in the file browser",
772772
@ margin-left: 0.5em;
773773
@ padding-left: 0.5em;
774774
@ white-space: nowrap;
775775
},
776
+ { ".filetree",
777
+ "tree-view file browser",
778
+ @ margin: 1em 0;
779
+ @ line-height: 1.5;
780
+ },
781
+ { ".filetree ul",
782
+ "tree-view lists",
783
+ @ display: inline;
784
+ @ margin: 0;
785
+ @ padding: 0;
786
+ },
787
+ { ".filetree li",
788
+ "tree-view list items",
789
+ @ display: inline;
790
+ },
791
+ { ".filetree .subdir ul",
792
+ "tree-view lists below subdir",
793
+ @ position: relative;
794
+ @ display: block;
795
+ @ margin: 0 0 0 21px;
796
+ @ padding: 0;
797
+ },
798
+ { ".filetree .subdir li",
799
+ "tree-view lists items below subdir",
800
+ @ position: relative;
801
+ @ display: block;
802
+ @ margin: 0;
803
+ @ padding: 0;
804
+ },
805
+ { ".filetree .subdir li:before",
806
+ "tree-view node lines",
807
+ @ content: '';
808
+ @ position: absolute;
809
+ @ top: -.8em;
810
+ @ left: -14px;
811
+ @ width: 14px;
812
+ @ height: 1.5em;
813
+ @ border-left: 2px solid #aaa;
814
+ @ border-bottom: 2px solid #aaa;
815
+ },
816
+ { ".filetree .subdir > ul ul:before",
817
+ "tree-view directory lines",
818
+ @ content: '';
819
+ @ position: absolute;
820
+ @ top: -1.5em;
821
+ @ bottom: 0;
822
+ @ left: -35px;
823
+ @ border-left: 2px solid #aaa;
824
+ },
825
+ { ".filetree .subdir li:last-child > ul:before",
826
+ "hide lines for last-child directories",
827
+ @ display: none;
828
+ },
829
+ { ".filetree a",
830
+ "tree-view links",
831
+ @ position: relative;
832
+ @ z-index: 1;
833
+ @ display: inline-block;
834
+ @ min-height: 16px;
835
+ @ margin-right: .5em;
836
+ @ padding-left: 21px;
837
+ @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
838
+ @ background-position: center left;
839
+ @ background-repeat: no-repeat;
840
+ },
841
+ { ".filetree .dir > a",
842
+ "tree-view directory links",
843
+ @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
844
+ },
776845
{ "table.login_out",
777846
"table format for login/out label/input table",
778847
@ text-align: left;
779848
@ margin-right: 10px;
780849
@ margin-left: 10px;
781850
--- src/style.c
+++ src/style.c
@@ -771,10 +771,79 @@
771 "format for the list in the file browser",
772 @ margin-left: 0.5em;
773 @ padding-left: 0.5em;
774 @ white-space: nowrap;
775 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776 { "table.login_out",
777 "table format for login/out label/input table",
778 @ text-align: left;
779 @ margin-right: 10px;
780 @ margin-left: 10px;
781
--- src/style.c
+++ src/style.c
@@ -771,10 +771,79 @@
771 "format for the list in the file browser",
772 @ margin-left: 0.5em;
773 @ padding-left: 0.5em;
774 @ white-space: nowrap;
775 },
776 { ".filetree",
777 "tree-view file browser",
778 @ margin: 1em 0;
779 @ line-height: 1.5;
780 },
781 { ".filetree ul",
782 "tree-view lists",
783 @ display: inline;
784 @ margin: 0;
785 @ padding: 0;
786 },
787 { ".filetree li",
788 "tree-view list items",
789 @ display: inline;
790 },
791 { ".filetree .subdir ul",
792 "tree-view lists below subdir",
793 @ position: relative;
794 @ display: block;
795 @ margin: 0 0 0 21px;
796 @ padding: 0;
797 },
798 { ".filetree .subdir li",
799 "tree-view lists items below subdir",
800 @ position: relative;
801 @ display: block;
802 @ margin: 0;
803 @ padding: 0;
804 },
805 { ".filetree .subdir li:before",
806 "tree-view node lines",
807 @ content: '';
808 @ position: absolute;
809 @ top: -.8em;
810 @ left: -14px;
811 @ width: 14px;
812 @ height: 1.5em;
813 @ border-left: 2px solid #aaa;
814 @ border-bottom: 2px solid #aaa;
815 },
816 { ".filetree .subdir > ul ul:before",
817 "tree-view directory lines",
818 @ content: '';
819 @ position: absolute;
820 @ top: -1.5em;
821 @ bottom: 0;
822 @ left: -35px;
823 @ border-left: 2px solid #aaa;
824 },
825 { ".filetree .subdir li:last-child > ul:before",
826 "hide lines for last-child directories",
827 @ display: none;
828 },
829 { ".filetree a",
830 "tree-view links",
831 @ position: relative;
832 @ z-index: 1;
833 @ display: inline-block;
834 @ min-height: 16px;
835 @ margin-right: .5em;
836 @ padding-left: 21px;
837 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
838 @ background-position: center left;
839 @ background-repeat: no-repeat;
840 },
841 { ".filetree .dir > a",
842 "tree-view directory links",
843 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
844 },
845 { "table.login_out",
846 "table format for login/out label/input table",
847 @ text-align: left;
848 @ margin-right: 10px;
849 @ margin-left: 10px;
850
+69
--- src/style.c
+++ src/style.c
@@ -771,10 +771,79 @@
771771
"format for the list in the file browser",
772772
@ margin-left: 0.5em;
773773
@ padding-left: 0.5em;
774774
@ white-space: nowrap;
775775
},
776
+ { ".filetree",
777
+ "tree-view file browser",
778
+ @ margin: 1em 0;
779
+ @ line-height: 1.5;
780
+ },
781
+ { ".filetree ul",
782
+ "tree-view lists",
783
+ @ display: inline;
784
+ @ margin: 0;
785
+ @ padding: 0;
786
+ },
787
+ { ".filetree li",
788
+ "tree-view list items",
789
+ @ display: inline;
790
+ },
791
+ { ".filetree .subdir ul",
792
+ "tree-view lists below subdir",
793
+ @ position: relative;
794
+ @ display: block;
795
+ @ margin: 0 0 0 21px;
796
+ @ padding: 0;
797
+ },
798
+ { ".filetree .subdir li",
799
+ "tree-view lists items below subdir",
800
+ @ position: relative;
801
+ @ display: block;
802
+ @ margin: 0;
803
+ @ padding: 0;
804
+ },
805
+ { ".filetree .subdir li:before",
806
+ "tree-view node lines",
807
+ @ content: '';
808
+ @ position: absolute;
809
+ @ top: -.8em;
810
+ @ left: -14px;
811
+ @ width: 14px;
812
+ @ height: 1.5em;
813
+ @ border-left: 2px solid #aaa;
814
+ @ border-bottom: 2px solid #aaa;
815
+ },
816
+ { ".filetree .subdir > ul ul:before",
817
+ "tree-view directory lines",
818
+ @ content: '';
819
+ @ position: absolute;
820
+ @ top: -1.5em;
821
+ @ bottom: 0;
822
+ @ left: -35px;
823
+ @ border-left: 2px solid #aaa;
824
+ },
825
+ { ".filetree .subdir li:last-child > ul:before",
826
+ "hide lines for last-child directories",
827
+ @ display: none;
828
+ },
829
+ { ".filetree a",
830
+ "tree-view links",
831
+ @ position: relative;
832
+ @ z-index: 1;
833
+ @ display: inline-block;
834
+ @ min-height: 16px;
835
+ @ margin-right: .5em;
836
+ @ padding-left: 21px;
837
+ @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
838
+ @ background-position: center left;
839
+ @ background-repeat: no-repeat;
840
+ },
841
+ { ".filetree .dir > a",
842
+ "tree-view directory links",
843
+ @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
844
+ },
776845
{ "table.login_out",
777846
"table format for login/out label/input table",
778847
@ text-align: left;
779848
@ margin-right: 10px;
780849
@ margin-left: 10px;
781850
--- src/style.c
+++ src/style.c
@@ -771,10 +771,79 @@
771 "format for the list in the file browser",
772 @ margin-left: 0.5em;
773 @ padding-left: 0.5em;
774 @ white-space: nowrap;
775 },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776 { "table.login_out",
777 "table format for login/out label/input table",
778 @ text-align: left;
779 @ margin-right: 10px;
780 @ margin-left: 10px;
781
--- src/style.c
+++ src/style.c
@@ -771,10 +771,79 @@
771 "format for the list in the file browser",
772 @ margin-left: 0.5em;
773 @ padding-left: 0.5em;
774 @ white-space: nowrap;
775 },
776 { ".filetree",
777 "tree-view file browser",
778 @ margin: 1em 0;
779 @ line-height: 1.5;
780 },
781 { ".filetree ul",
782 "tree-view lists",
783 @ display: inline;
784 @ margin: 0;
785 @ padding: 0;
786 },
787 { ".filetree li",
788 "tree-view list items",
789 @ display: inline;
790 },
791 { ".filetree .subdir ul",
792 "tree-view lists below subdir",
793 @ position: relative;
794 @ display: block;
795 @ margin: 0 0 0 21px;
796 @ padding: 0;
797 },
798 { ".filetree .subdir li",
799 "tree-view lists items below subdir",
800 @ position: relative;
801 @ display: block;
802 @ margin: 0;
803 @ padding: 0;
804 },
805 { ".filetree .subdir li:before",
806 "tree-view node lines",
807 @ content: '';
808 @ position: absolute;
809 @ top: -.8em;
810 @ left: -14px;
811 @ width: 14px;
812 @ height: 1.5em;
813 @ border-left: 2px solid #aaa;
814 @ border-bottom: 2px solid #aaa;
815 },
816 { ".filetree .subdir > ul ul:before",
817 "tree-view directory lines",
818 @ content: '';
819 @ position: absolute;
820 @ top: -1.5em;
821 @ bottom: 0;
822 @ left: -35px;
823 @ border-left: 2px solid #aaa;
824 },
825 { ".filetree .subdir li:last-child > ul:before",
826 "hide lines for last-child directories",
827 @ display: none;
828 },
829 { ".filetree a",
830 "tree-view links",
831 @ position: relative;
832 @ z-index: 1;
833 @ display: inline-block;
834 @ min-height: 16px;
835 @ margin-right: .5em;
836 @ padding-left: 21px;
837 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==);
838 @ background-position: center left;
839 @ background-repeat: no-repeat;
840 },
841 { ".filetree .dir > a",
842 "tree-view directory links",
843 @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=);
844 },
845 { "table.login_out",
846 "table format for login/out label/input table",
847 @ text-align: left;
848 @ margin-right: 10px;
849 @ margin-left: 10px;
850
+3 -2
--- src/th.c
+++ src/th.c
@@ -1154,11 +1154,12 @@
11541154
11551155
/*
11561156
** Return true if variable (zVar, nVar) exists.
11571157
*/
11581158
int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){
1159
- return thFindValue(interp, zVar, nVar, 0, 0)!=0;
1159
+ Th_Variable *pValue = thFindValue(interp, zVar, nVar, 0, 0);
1160
+ return pValue && pValue->zData;
11601161
}
11611162
11621163
/*
11631164
** String (zVar, nVar) must contain the name of a scalar variable or
11641165
** array member. If the variable does not exist it is created. The
@@ -1240,11 +1241,11 @@
12401241
** in the interpreter result and TH_ERROR is returned.
12411242
*/
12421243
int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){
12431244
Th_Variable *pValue;
12441245
1245
- pValue = thFindValue(interp, zVar, nVar, 1, 1);
1246
+ pValue = thFindValue(interp, zVar, nVar, 0, 1);
12461247
if( !pValue ){
12471248
return TH_ERROR;
12481249
}
12491250
12501251
Th_Free(interp, pValue->zData);
12511252
--- src/th.c
+++ src/th.c
@@ -1154,11 +1154,12 @@
1154
1155 /*
1156 ** Return true if variable (zVar, nVar) exists.
1157 */
1158 int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){
1159 return thFindValue(interp, zVar, nVar, 0, 0)!=0;
 
1160 }
1161
1162 /*
1163 ** String (zVar, nVar) must contain the name of a scalar variable or
1164 ** array member. If the variable does not exist it is created. The
@@ -1240,11 +1241,11 @@
1240 ** in the interpreter result and TH_ERROR is returned.
1241 */
1242 int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){
1243 Th_Variable *pValue;
1244
1245 pValue = thFindValue(interp, zVar, nVar, 1, 1);
1246 if( !pValue ){
1247 return TH_ERROR;
1248 }
1249
1250 Th_Free(interp, pValue->zData);
1251
--- src/th.c
+++ src/th.c
@@ -1154,11 +1154,12 @@
1154
1155 /*
1156 ** Return true if variable (zVar, nVar) exists.
1157 */
1158 int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){
1159 Th_Variable *pValue = thFindValue(interp, zVar, nVar, 0, 0);
1160 return pValue && pValue->zData;
1161 }
1162
1163 /*
1164 ** String (zVar, nVar) must contain the name of a scalar variable or
1165 ** array member. If the variable does not exist it is created. The
@@ -1240,11 +1241,11 @@
1241 ** in the interpreter result and TH_ERROR is returned.
1242 */
1243 int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){
1244 Th_Variable *pValue;
1245
1246 pValue = thFindValue(interp, zVar, nVar, 0, 1);
1247 if( !pValue ){
1248 return TH_ERROR;
1249 }
1250
1251 Th_Free(interp, pValue->zData);
1252
--- test/th1.test
+++ test/th1.test
@@ -107,5 +107,40 @@
107107
###############################################################################
108108
109109
fossil test-th-eval "expr 42.0%0.0"
110110
test th1-modulus-by-zero-4 {$RESULT eq \
111111
{TH_ERROR: expected integer, got: "42.0"}}
112
+
113
+###############################################################################
114
+
115
+fossil test-th-eval "set var 1; info exists var"
116
+test th1-info-exists-1 {$RESULT eq {1}}
117
+
118
+###############################################################################
119
+
120
+fossil test-th-eval "set var 1; unset var; info exists var"
121
+test th1-info-exists-2 {$RESULT eq {0}}
122
+
123
+###############################################################################
124
+
125
+fossil test-th-eval "set var 1; unset var; set var 2; info exists var"
126
+test th1-info-exists-3 {$RESULT eq {1}}
127
+
128
+###############################################################################
129
+
130
+fossil test-th-eval "set var 1; expr {\$var+0}"
131
+test th1-info-exists-4 {$RESULT eq {1}}
132
+
133
+###############################################################################
134
+
135
+fossil test-th-eval "set var 1; unset var; expr {\$var+0}"
136
+test th1-info-exists-5 {$RESULT eq {TH_ERROR: no such variable: var}}
137
+
138
+###############################################################################
139
+
140
+fossil test-th-eval "set var 1; unset var"
141
+test th1-unset-1 {$RESULT eq {var}}
142
+
143
+###############################################################################
144
+
145
+fossil test-th-eval "unset var"
146
+test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}}
112147
--- test/th1.test
+++ test/th1.test
@@ -107,5 +107,40 @@
107 ###############################################################################
108
109 fossil test-th-eval "expr 42.0%0.0"
110 test th1-modulus-by-zero-4 {$RESULT eq \
111 {TH_ERROR: expected integer, got: "42.0"}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
--- test/th1.test
+++ test/th1.test
@@ -107,5 +107,40 @@
107 ###############################################################################
108
109 fossil test-th-eval "expr 42.0%0.0"
110 test th1-modulus-by-zero-4 {$RESULT eq \
111 {TH_ERROR: expected integer, got: "42.0"}}
112
113 ###############################################################################
114
115 fossil test-th-eval "set var 1; info exists var"
116 test th1-info-exists-1 {$RESULT eq {1}}
117
118 ###############################################################################
119
120 fossil test-th-eval "set var 1; unset var; info exists var"
121 test th1-info-exists-2 {$RESULT eq {0}}
122
123 ###############################################################################
124
125 fossil test-th-eval "set var 1; unset var; set var 2; info exists var"
126 test th1-info-exists-3 {$RESULT eq {1}}
127
128 ###############################################################################
129
130 fossil test-th-eval "set var 1; expr {\$var+0}"
131 test th1-info-exists-4 {$RESULT eq {1}}
132
133 ###############################################################################
134
135 fossil test-th-eval "set var 1; unset var; expr {\$var+0}"
136 test th1-info-exists-5 {$RESULT eq {TH_ERROR: no such variable: var}}
137
138 ###############################################################################
139
140 fossil test-th-eval "set var 1; unset var"
141 test th1-unset-1 {$RESULT eq {var}}
142
143 ###############################################################################
144
145 fossil test-th-eval "unset var"
146 test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}}
147

Keyboard Shortcuts

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