Fossil SCM
Add "Quit" and "Save As.." buttons to the "diff --tk" command.
Commit
29d80dd2f5d2c7afd33589481157b87740a80cc8
Parent
a526d71968062df…
1 file changed
+75
-43
+75
-43
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -598,12 +598,13 @@ | ||
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | /* A Tcl/Tk script used to render diff output. |
| 601 | 601 | */ |
| 602 | 602 | static const char zDiffScript[] = |
| 603 | +@ set prog { | |
| 603 | 604 | @ package require Tk |
| 604 | -@ | |
| 605 | +@ | |
| 605 | 606 | @ array set CFG { |
| 606 | 607 | @ TITLE {Fossil Diff} |
| 607 | 608 | @ LN_COL_BG #dddddd |
| 608 | 609 | @ LN_COL_FG #444444 |
| 609 | 610 | @ TXT_COL_BG #ffffff |
| @@ -622,69 +623,84 @@ | ||
| 622 | 623 | @ PADX 5 |
| 623 | 624 | @ WIDTH 80 |
| 624 | 625 | @ HEIGHT 45 |
| 625 | 626 | @ LB_HEIGHT 25 |
| 626 | 627 | @ } |
| 627 | -@ | |
| 628 | +@ | |
| 628 | 629 | @ if {![namespace exists ttk]} { |
| 629 | 630 | @ interp alias {} ::ttk::scrollbar {} ::scrollbar |
| 630 | 631 | @ interp alias {} ::ttk::menubutton {} ::menubutton |
| 631 | 632 | @ } |
| 632 | -@ | |
| 633 | +@ | |
| 633 | 634 | @ proc dehtml {x} { |
| 634 | 635 | @ set x [regsub -all {<[^>]*>} $x {}] |
| 635 | 636 | @ return [string map {& & < < > > ' ' " \"} $x] |
| 636 | 637 | @ } |
| 637 | -@ | |
| 638 | +@ | |
| 638 | 639 | @ proc cols {} { |
| 639 | 640 | @ return [list .lnA .txtA .mkr .lnB .txtB] |
| 640 | 641 | @ } |
| 641 | -@ | |
| 642 | +@ | |
| 642 | 643 | @ proc colType {c} { |
| 643 | 644 | @ regexp {[a-z]+} $c type |
| 644 | 645 | @ return $type |
| 645 | 646 | @ } |
| 646 | -@ | |
| 647 | +@ | |
| 648 | +@ proc getLine {difftxt N iivar} { | |
| 649 | +@ upvar $iivar ii | |
| 650 | +@ if {$ii>=$N} {return -1} | |
| 651 | +@ set x [lindex $difftxt $ii] | |
| 652 | +@ incr ii | |
| 653 | +@ return $x | |
| 654 | +@ } | |
| 655 | +@ | |
| 647 | 656 | @ proc readDiffs {fossilcmd} { |
| 648 | -@ set in [open $fossilcmd r] | |
| 649 | -@ fconfigure $in -encoding utf-8 | |
| 657 | +@ global difftxt | |
| 658 | +@ if {![info exists difftxt]} { | |
| 659 | +@ set in [open $fossilcmd r] | |
| 660 | +@ fconfigure $in -encoding utf-8 | |
| 661 | +@ set difftxt [split [read $in] \n] | |
| 662 | +@ close $in | |
| 663 | +@ } | |
| 664 | +@ set N [llength $difftxt] | |
| 665 | +@ set ii 0 | |
| 650 | 666 | @ set nDiffs 0 |
| 651 | 667 | @ array set widths {txt 0 ln 0 mkr 0} |
| 652 | -@ while {[gets $in line] != -1} { | |
| 668 | +@ while {[set line [getLine $difftxt $N ii]] != -1} { | |
| 653 | 669 | @ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} { |
| 654 | 670 | @ continue |
| 655 | 671 | @ } |
| 656 | -@ if {[string compare -length 6 [gets $in] "<table"]} { | |
| 672 | +@ if {[string compare -length 6 [getLine $difftxt $N ii] "<table"]} { | |
| 657 | 673 | @ continue |
| 658 | 674 | @ } |
| 659 | 675 | @ incr nDiffs |
| 660 | 676 | @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}] |
| 661 | 677 | @ .wfiles.lb insert end $fn |
| 662 | -@ | |
| 678 | +@ | |
| 663 | 679 | @ foreach c [cols] { |
| 664 | -@ while {[gets $in] ne "<pre>"} continue | |
| 665 | -@ | |
| 680 | +@ while {[getLine $difftxt $N ii] ne "<pre>"} continue | |
| 681 | +@ | |
| 666 | 682 | @ if {$nDiffs > 1} { |
| 667 | 683 | @ $c insert end \n - |
| 668 | 684 | @ } |
| 669 | 685 | @ if {[colType $c] eq "txt"} { |
| 670 | 686 | @ $c insert end $fn\n fn |
| 671 | 687 | @ } else { |
| 672 | 688 | @ $c insert end \n fn |
| 673 | 689 | @ } |
| 674 | 690 | @ $c insert end \n - |
| 675 | -@ | |
| 691 | +@ | |
| 676 | 692 | @ set type [colType $c] |
| 677 | 693 | @ set str {} |
| 678 | -@ while {[set line [gets $in]] ne "</pre>"} { | |
| 694 | +@ while {[set line [getLine $difftxt $N ii]] ne "</pre>"} { | |
| 679 | 695 | @ set len [string length [dehtml $line]] |
| 680 | 696 | @ if {$len > $widths($type)} { |
| 681 | 697 | @ set widths($type) $len |
| 682 | 698 | @ } |
| 683 | 699 | @ append str $line\n |
| 684 | 700 | @ } |
| 685 | -@ | |
| 701 | +@ | |
| 686 | 702 | @ set re {<span class="diff([a-z]+)">([^<]*)</span>} |
| 687 | 703 | @ # Use \r as separator since it can't appear in the diff output (it gets |
| 688 | 704 | @ # converted to a space). |
| 689 | 705 | @ set str [regsub -all $re $str "\r\\1\r\\2\r"] |
| 690 | 706 | @ foreach {pre class mid} [split $str \r] { |
| @@ -694,12 +710,11 @@ | ||
| 694 | 710 | @ $c insert end [dehtml $pre] - |
| 695 | 711 | @ } |
| 696 | 712 | @ } |
| 697 | 713 | @ } |
| 698 | 714 | @ } |
| 699 | -@ close $in | |
| 700 | -@ | |
| 715 | +@ | |
| 701 | 716 | @ foreach c [cols] { |
| 702 | 717 | @ set type [colType $c] |
| 703 | 718 | @ if {$type ne "txt"} { |
| 704 | 719 | @ $c config -width $widths($type) |
| 705 | 720 | @ } |
| @@ -707,19 +722,19 @@ | ||
| 707 | 722 | @ } |
| 708 | 723 | @ if {$nDiffs <= [.wfiles.lb cget -height]} { |
| 709 | 724 | @ .wfiles.lb config -height $nDiffs |
| 710 | 725 | @ grid remove .wfiles.sb |
| 711 | 726 | @ } |
| 712 | -@ | |
| 727 | +@ | |
| 713 | 728 | @ return $nDiffs |
| 714 | 729 | @ } |
| 715 | -@ | |
| 730 | +@ | |
| 716 | 731 | @ proc viewDiff {idx} { |
| 717 | 732 | @ .txtA yview $idx |
| 718 | 733 | @ .txtA xview moveto 0 |
| 719 | 734 | @ } |
| 720 | -@ | |
| 735 | +@ | |
| 721 | 736 | @ proc cycleDiffs {{reverse 0}} { |
| 722 | 737 | @ if {$reverse} { |
| 723 | 738 | @ set range [.txtA tag prevrange fn @0,0 1.0] |
| 724 | 739 | @ if {$range eq ""} { |
| 725 | 740 | @ viewDiff {fn.last -1c} |
| @@ -733,36 +748,36 @@ | ||
| 733 | 748 | @ } else { |
| 734 | 749 | @ viewDiff [lindex $range 0] |
| 735 | 750 | @ } |
| 736 | 751 | @ } |
| 737 | 752 | @ } |
| 738 | -@ | |
| 753 | +@ | |
| 739 | 754 | @ proc xvis {col} { |
| 740 | 755 | @ set view [$col xview] |
| 741 | 756 | @ return [expr {[lindex $view 1]-[lindex $view 0]}] |
| 742 | 757 | @ } |
| 743 | -@ | |
| 758 | +@ | |
| 744 | 759 | @ proc scroll-x {args} { |
| 745 | 760 | @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}] |
| 746 | 761 | @ eval $c xview $args |
| 747 | 762 | @ } |
| 748 | -@ | |
| 763 | +@ | |
| 749 | 764 | @ interp alias {} scroll-y {} .txtA yview |
| 750 | -@ | |
| 765 | +@ | |
| 751 | 766 | @ proc noop {args} {} |
| 752 | -@ | |
| 767 | +@ | |
| 753 | 768 | @ proc enableSync {axis} { |
| 754 | 769 | @ update idletasks |
| 755 | 770 | @ interp alias {} sync-$axis {} |
| 756 | 771 | @ rename _sync-$axis sync-$axis |
| 757 | 772 | @ } |
| 758 | -@ | |
| 773 | +@ | |
| 759 | 774 | @ proc disableSync {axis} { |
| 760 | 775 | @ rename sync-$axis _sync-$axis |
| 761 | 776 | @ interp alias {} sync-$axis {} noop |
| 762 | 777 | @ } |
| 763 | -@ | |
| 778 | +@ | |
| 764 | 779 | @ proc sync-x {col first last} { |
| 765 | 780 | @ disableSync x |
| 766 | 781 | @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}] |
| 767 | 782 | @ foreach side {A B} { |
| 768 | 783 | @ set sb .sbx$side |
| @@ -774,11 +789,11 @@ | ||
| 774 | 789 | @ grid remove $sb |
| 775 | 790 | @ } |
| 776 | 791 | @ } |
| 777 | 792 | @ enableSync x |
| 778 | 793 | @ } |
| 779 | -@ | |
| 794 | +@ | |
| 780 | 795 | @ proc sync-y {first last} { |
| 781 | 796 | @ disableSync y |
| 782 | 797 | @ foreach c [cols] { |
| 783 | 798 | @ $c yview moveto $first |
| 784 | 799 | @ } |
| @@ -788,21 +803,21 @@ | ||
| 788 | 803 | @ } else { |
| 789 | 804 | @ grid remove .sby |
| 790 | 805 | @ } |
| 791 | 806 | @ enableSync y |
| 792 | 807 | @ } |
| 793 | -@ | |
| 808 | +@ | |
| 794 | 809 | @ wm withdraw . |
| 795 | 810 | @ wm title . $CFG(TITLE) |
| 796 | 811 | @ wm iconname . $CFG(TITLE) |
| 797 | 812 | @ bind . <q> exit |
| 798 | 813 | @ bind . <Destroy> {after 0 exit} |
| 799 | 814 | @ bind . <Tab> {cycleDiffs; break} |
| 800 | 815 | @ bind . <<PrevWindow>> {cycleDiffs 1; break} |
| 801 | 816 | @ bind . <Return> { |
| 802 | -@ event generate .files <1> | |
| 803 | -@ event generate .files <ButtonRelease-1> | |
| 817 | +@ event generate .bb.files <1> | |
| 818 | +@ event generate .bb.files <ButtonRelease-1> | |
| 804 | 819 | @ break |
| 805 | 820 | @ } |
| 806 | 821 | @ foreach {key axis args} { |
| 807 | 822 | @ Up y {scroll -5 units} |
| 808 | 823 | @ Down y {scroll 5 units} |
| @@ -814,22 +829,23 @@ | ||
| 814 | 829 | @ End y {moveto 1} |
| 815 | 830 | @ } { |
| 816 | 831 | @ bind . <$key> "scroll-$axis $args; break" |
| 817 | 832 | @ bind . <Shift-$key> continue |
| 818 | 833 | @ } |
| 819 | -@ | |
| 820 | -@ ::ttk::menubutton .files -text "Files" | |
| 834 | +@ | |
| 835 | +@ frame .bb | |
| 836 | +@ ::ttk::menubutton .bb.files -text "Files" | |
| 821 | 837 | @ toplevel .wfiles |
| 822 | 838 | @ wm withdraw .wfiles |
| 823 | 839 | @ update idletasks |
| 824 | 840 | @ wm transient .wfiles . |
| 825 | 841 | @ wm overrideredirect .wfiles 1 |
| 826 | 842 | @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \ |
| 827 | 843 | @ -yscroll {.wfiles.sb set} |
| 828 | 844 | @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 829 | 845 | @ grid .wfiles.lb .wfiles.sb -sticky ns |
| 830 | -@ bind .files <1> { | |
| 846 | +@ bind .bb.files <1> { | |
| 831 | 847 | @ set x [winfo rootx %W] |
| 832 | 848 | @ set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| 833 | 849 | @ wm geometry .wfiles +$x+$y |
| 834 | 850 | @ wm deiconify .wfiles |
| 835 | 851 | @ focus .wfiles.lb |
| @@ -848,16 +864,16 @@ | ||
| 848 | 864 | @ } |
| 849 | 865 | @ bind .wfiles.lb <Motion> { |
| 850 | 866 | @ %W selection clear 0 end |
| 851 | 867 | @ %W selection set @%x,%y |
| 852 | 868 | @ } |
| 853 | -@ | |
| 869 | +@ | |
| 854 | 870 | @ foreach {side syncCol} {A .txtB B .txtA} { |
| 855 | 871 | @ set ln .ln$side |
| 856 | 872 | @ text $ln |
| 857 | 873 | @ $ln tag config - -justify right |
| 858 | -@ | |
| 874 | +@ | |
| 859 | 875 | @ set txt .txt$side |
| 860 | 876 | @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \ |
| 861 | 877 | @ -xscroll "sync-x $syncCol" |
| 862 | 878 | @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5 |
| 863 | 879 | @ foreach tag {add rm chng} { |
| @@ -866,11 +882,11 @@ | ||
| 866 | 882 | @ } |
| 867 | 883 | @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \ |
| 868 | 884 | @ -justify center |
| 869 | 885 | @ } |
| 870 | 886 | @ text .mkr |
| 871 | -@ | |
| 887 | +@ | |
| 872 | 888 | @ foreach c [cols] { |
| 873 | 889 | @ set keyPrefix [string toupper [colType $c]]_COL_ |
| 874 | 890 | @ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}} |
| 875 | 891 | @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \ |
| 876 | 892 | @ -padx $CFG(PADX) -yscroll sync-y |
| @@ -878,34 +894,50 @@ | ||
| 878 | 894 | @ -foreground $CFG(HR_FG) |
| 879 | 895 | @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD) |
| 880 | 896 | @ bindtags $c ". $c Text all" |
| 881 | 897 | @ bind $c <1> {focus %W} |
| 882 | 898 | @ } |
| 883 | -@ | |
| 899 | +@ | |
| 884 | 900 | @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical |
| 885 | 901 | @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal |
| 886 | 902 | @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal |
| 887 | 903 | @ frame .spacer |
| 888 | -@ | |
| 904 | +@ | |
| 889 | 905 | @ if {[readDiffs $fossilcmd] == 0} { |
| 890 | 906 | @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes" |
| 891 | 907 | @ exit |
| 892 | 908 | @ } |
| 893 | 909 | @ update idletasks |
| 894 | -@ | |
| 910 | +@ | |
| 911 | +@ proc saveDiff {} { | |
| 912 | +@ set fn [tk_getSaveFile] | |
| 913 | +@ set out [open $fn wb] | |
| 914 | +@ puts $out "set fossilcmd {}" | |
| 915 | +@ puts $out "set difftxt [list $::difftxt]" | |
| 916 | +@ puts $out "set prog [list $::prog]" | |
| 917 | +@ puts $out "eval \$prog" | |
| 918 | +@ close $out | |
| 919 | +@ } | |
| 920 | +@ ::ttk::button .bb.quit -text {Quit} -command exit | |
| 921 | +@ ::ttk::button .bb.save -text {Save As...} -command saveDiff | |
| 922 | +@ pack .bb.quit -side left | |
| 923 | +@ pack .bb.save -side left | |
| 924 | +@ pack .bb.files -side left | |
| 895 | 925 | @ grid rowconfigure . 1 -weight 1 |
| 896 | 926 | @ grid columnconfigure . 1 -weight 1 |
| 897 | 927 | @ grid columnconfigure . 4 -weight 1 |
| 898 | -@ grid .files -row 0 -columnspan 6 | |
| 928 | +@ grid .bb -row 0 -columnspan 6 | |
| 899 | 929 | @ eval grid [cols] -row 1 -sticky nsew |
| 900 | 930 | @ grid .sby -row 1 -column 5 -sticky ns |
| 901 | 931 | @ grid .sbxA -row 2 -columnspan 2 -sticky ew |
| 902 | 932 | @ grid .spacer -row 2 -column 2 |
| 903 | 933 | @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew |
| 904 | -@ | |
| 934 | +@ | |
| 905 | 935 | @ .spacer config -height [winfo height .sbxA] |
| 906 | 936 | @ wm deiconify . |
| 937 | +@ } | |
| 938 | +@ eval $prog | |
| 907 | 939 | ; |
| 908 | 940 | |
| 909 | 941 | /* |
| 910 | 942 | ** Show diff output in a Tcl/Tk window, in response to the --tk option |
| 911 | 943 | ** to the diff command. |
| 912 | 944 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -598,12 +598,13 @@ | |
| 598 | } |
| 599 | |
| 600 | /* A Tcl/Tk script used to render diff output. |
| 601 | */ |
| 602 | static const char zDiffScript[] = |
| 603 | @ package require Tk |
| 604 | @ |
| 605 | @ array set CFG { |
| 606 | @ TITLE {Fossil Diff} |
| 607 | @ LN_COL_BG #dddddd |
| 608 | @ LN_COL_FG #444444 |
| 609 | @ TXT_COL_BG #ffffff |
| @@ -622,69 +623,84 @@ | |
| 622 | @ PADX 5 |
| 623 | @ WIDTH 80 |
| 624 | @ HEIGHT 45 |
| 625 | @ LB_HEIGHT 25 |
| 626 | @ } |
| 627 | @ |
| 628 | @ if {![namespace exists ttk]} { |
| 629 | @ interp alias {} ::ttk::scrollbar {} ::scrollbar |
| 630 | @ interp alias {} ::ttk::menubutton {} ::menubutton |
| 631 | @ } |
| 632 | @ |
| 633 | @ proc dehtml {x} { |
| 634 | @ set x [regsub -all {<[^>]*>} $x {}] |
| 635 | @ return [string map {& & < < > > ' ' " \"} $x] |
| 636 | @ } |
| 637 | @ |
| 638 | @ proc cols {} { |
| 639 | @ return [list .lnA .txtA .mkr .lnB .txtB] |
| 640 | @ } |
| 641 | @ |
| 642 | @ proc colType {c} { |
| 643 | @ regexp {[a-z]+} $c type |
| 644 | @ return $type |
| 645 | @ } |
| 646 | @ |
| 647 | @ proc readDiffs {fossilcmd} { |
| 648 | @ set in [open $fossilcmd r] |
| 649 | @ fconfigure $in -encoding utf-8 |
| 650 | @ set nDiffs 0 |
| 651 | @ array set widths {txt 0 ln 0 mkr 0} |
| 652 | @ while {[gets $in line] != -1} { |
| 653 | @ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} { |
| 654 | @ continue |
| 655 | @ } |
| 656 | @ if {[string compare -length 6 [gets $in] "<table"]} { |
| 657 | @ continue |
| 658 | @ } |
| 659 | @ incr nDiffs |
| 660 | @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}] |
| 661 | @ .wfiles.lb insert end $fn |
| 662 | @ |
| 663 | @ foreach c [cols] { |
| 664 | @ while {[gets $in] ne "<pre>"} continue |
| 665 | @ |
| 666 | @ if {$nDiffs > 1} { |
| 667 | @ $c insert end \n - |
| 668 | @ } |
| 669 | @ if {[colType $c] eq "txt"} { |
| 670 | @ $c insert end $fn\n fn |
| 671 | @ } else { |
| 672 | @ $c insert end \n fn |
| 673 | @ } |
| 674 | @ $c insert end \n - |
| 675 | @ |
| 676 | @ set type [colType $c] |
| 677 | @ set str {} |
| 678 | @ while {[set line [gets $in]] ne "</pre>"} { |
| 679 | @ set len [string length [dehtml $line]] |
| 680 | @ if {$len > $widths($type)} { |
| 681 | @ set widths($type) $len |
| 682 | @ } |
| 683 | @ append str $line\n |
| 684 | @ } |
| 685 | @ |
| 686 | @ set re {<span class="diff([a-z]+)">([^<]*)</span>} |
| 687 | @ # Use \r as separator since it can't appear in the diff output (it gets |
| 688 | @ # converted to a space). |
| 689 | @ set str [regsub -all $re $str "\r\\1\r\\2\r"] |
| 690 | @ foreach {pre class mid} [split $str \r] { |
| @@ -694,12 +710,11 @@ | |
| 694 | @ $c insert end [dehtml $pre] - |
| 695 | @ } |
| 696 | @ } |
| 697 | @ } |
| 698 | @ } |
| 699 | @ close $in |
| 700 | @ |
| 701 | @ foreach c [cols] { |
| 702 | @ set type [colType $c] |
| 703 | @ if {$type ne "txt"} { |
| 704 | @ $c config -width $widths($type) |
| 705 | @ } |
| @@ -707,19 +722,19 @@ | |
| 707 | @ } |
| 708 | @ if {$nDiffs <= [.wfiles.lb cget -height]} { |
| 709 | @ .wfiles.lb config -height $nDiffs |
| 710 | @ grid remove .wfiles.sb |
| 711 | @ } |
| 712 | @ |
| 713 | @ return $nDiffs |
| 714 | @ } |
| 715 | @ |
| 716 | @ proc viewDiff {idx} { |
| 717 | @ .txtA yview $idx |
| 718 | @ .txtA xview moveto 0 |
| 719 | @ } |
| 720 | @ |
| 721 | @ proc cycleDiffs {{reverse 0}} { |
| 722 | @ if {$reverse} { |
| 723 | @ set range [.txtA tag prevrange fn @0,0 1.0] |
| 724 | @ if {$range eq ""} { |
| 725 | @ viewDiff {fn.last -1c} |
| @@ -733,36 +748,36 @@ | |
| 733 | @ } else { |
| 734 | @ viewDiff [lindex $range 0] |
| 735 | @ } |
| 736 | @ } |
| 737 | @ } |
| 738 | @ |
| 739 | @ proc xvis {col} { |
| 740 | @ set view [$col xview] |
| 741 | @ return [expr {[lindex $view 1]-[lindex $view 0]}] |
| 742 | @ } |
| 743 | @ |
| 744 | @ proc scroll-x {args} { |
| 745 | @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}] |
| 746 | @ eval $c xview $args |
| 747 | @ } |
| 748 | @ |
| 749 | @ interp alias {} scroll-y {} .txtA yview |
| 750 | @ |
| 751 | @ proc noop {args} {} |
| 752 | @ |
| 753 | @ proc enableSync {axis} { |
| 754 | @ update idletasks |
| 755 | @ interp alias {} sync-$axis {} |
| 756 | @ rename _sync-$axis sync-$axis |
| 757 | @ } |
| 758 | @ |
| 759 | @ proc disableSync {axis} { |
| 760 | @ rename sync-$axis _sync-$axis |
| 761 | @ interp alias {} sync-$axis {} noop |
| 762 | @ } |
| 763 | @ |
| 764 | @ proc sync-x {col first last} { |
| 765 | @ disableSync x |
| 766 | @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}] |
| 767 | @ foreach side {A B} { |
| 768 | @ set sb .sbx$side |
| @@ -774,11 +789,11 @@ | |
| 774 | @ grid remove $sb |
| 775 | @ } |
| 776 | @ } |
| 777 | @ enableSync x |
| 778 | @ } |
| 779 | @ |
| 780 | @ proc sync-y {first last} { |
| 781 | @ disableSync y |
| 782 | @ foreach c [cols] { |
| 783 | @ $c yview moveto $first |
| 784 | @ } |
| @@ -788,21 +803,21 @@ | |
| 788 | @ } else { |
| 789 | @ grid remove .sby |
| 790 | @ } |
| 791 | @ enableSync y |
| 792 | @ } |
| 793 | @ |
| 794 | @ wm withdraw . |
| 795 | @ wm title . $CFG(TITLE) |
| 796 | @ wm iconname . $CFG(TITLE) |
| 797 | @ bind . <q> exit |
| 798 | @ bind . <Destroy> {after 0 exit} |
| 799 | @ bind . <Tab> {cycleDiffs; break} |
| 800 | @ bind . <<PrevWindow>> {cycleDiffs 1; break} |
| 801 | @ bind . <Return> { |
| 802 | @ event generate .files <1> |
| 803 | @ event generate .files <ButtonRelease-1> |
| 804 | @ break |
| 805 | @ } |
| 806 | @ foreach {key axis args} { |
| 807 | @ Up y {scroll -5 units} |
| 808 | @ Down y {scroll 5 units} |
| @@ -814,22 +829,23 @@ | |
| 814 | @ End y {moveto 1} |
| 815 | @ } { |
| 816 | @ bind . <$key> "scroll-$axis $args; break" |
| 817 | @ bind . <Shift-$key> continue |
| 818 | @ } |
| 819 | @ |
| 820 | @ ::ttk::menubutton .files -text "Files" |
| 821 | @ toplevel .wfiles |
| 822 | @ wm withdraw .wfiles |
| 823 | @ update idletasks |
| 824 | @ wm transient .wfiles . |
| 825 | @ wm overrideredirect .wfiles 1 |
| 826 | @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \ |
| 827 | @ -yscroll {.wfiles.sb set} |
| 828 | @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 829 | @ grid .wfiles.lb .wfiles.sb -sticky ns |
| 830 | @ bind .files <1> { |
| 831 | @ set x [winfo rootx %W] |
| 832 | @ set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| 833 | @ wm geometry .wfiles +$x+$y |
| 834 | @ wm deiconify .wfiles |
| 835 | @ focus .wfiles.lb |
| @@ -848,16 +864,16 @@ | |
| 848 | @ } |
| 849 | @ bind .wfiles.lb <Motion> { |
| 850 | @ %W selection clear 0 end |
| 851 | @ %W selection set @%x,%y |
| 852 | @ } |
| 853 | @ |
| 854 | @ foreach {side syncCol} {A .txtB B .txtA} { |
| 855 | @ set ln .ln$side |
| 856 | @ text $ln |
| 857 | @ $ln tag config - -justify right |
| 858 | @ |
| 859 | @ set txt .txt$side |
| 860 | @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \ |
| 861 | @ -xscroll "sync-x $syncCol" |
| 862 | @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5 |
| 863 | @ foreach tag {add rm chng} { |
| @@ -866,11 +882,11 @@ | |
| 866 | @ } |
| 867 | @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \ |
| 868 | @ -justify center |
| 869 | @ } |
| 870 | @ text .mkr |
| 871 | @ |
| 872 | @ foreach c [cols] { |
| 873 | @ set keyPrefix [string toupper [colType $c]]_COL_ |
| 874 | @ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}} |
| 875 | @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \ |
| 876 | @ -padx $CFG(PADX) -yscroll sync-y |
| @@ -878,34 +894,50 @@ | |
| 878 | @ -foreground $CFG(HR_FG) |
| 879 | @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD) |
| 880 | @ bindtags $c ". $c Text all" |
| 881 | @ bind $c <1> {focus %W} |
| 882 | @ } |
| 883 | @ |
| 884 | @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical |
| 885 | @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal |
| 886 | @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal |
| 887 | @ frame .spacer |
| 888 | @ |
| 889 | @ if {[readDiffs $fossilcmd] == 0} { |
| 890 | @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes" |
| 891 | @ exit |
| 892 | @ } |
| 893 | @ update idletasks |
| 894 | @ |
| 895 | @ grid rowconfigure . 1 -weight 1 |
| 896 | @ grid columnconfigure . 1 -weight 1 |
| 897 | @ grid columnconfigure . 4 -weight 1 |
| 898 | @ grid .files -row 0 -columnspan 6 |
| 899 | @ eval grid [cols] -row 1 -sticky nsew |
| 900 | @ grid .sby -row 1 -column 5 -sticky ns |
| 901 | @ grid .sbxA -row 2 -columnspan 2 -sticky ew |
| 902 | @ grid .spacer -row 2 -column 2 |
| 903 | @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew |
| 904 | @ |
| 905 | @ .spacer config -height [winfo height .sbxA] |
| 906 | @ wm deiconify . |
| 907 | ; |
| 908 | |
| 909 | /* |
| 910 | ** Show diff output in a Tcl/Tk window, in response to the --tk option |
| 911 | ** to the diff command. |
| 912 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -598,12 +598,13 @@ | |
| 598 | } |
| 599 | |
| 600 | /* A Tcl/Tk script used to render diff output. |
| 601 | */ |
| 602 | static const char zDiffScript[] = |
| 603 | @ set prog { |
| 604 | @ package require Tk |
| 605 | @ |
| 606 | @ array set CFG { |
| 607 | @ TITLE {Fossil Diff} |
| 608 | @ LN_COL_BG #dddddd |
| 609 | @ LN_COL_FG #444444 |
| 610 | @ TXT_COL_BG #ffffff |
| @@ -622,69 +623,84 @@ | |
| 623 | @ PADX 5 |
| 624 | @ WIDTH 80 |
| 625 | @ HEIGHT 45 |
| 626 | @ LB_HEIGHT 25 |
| 627 | @ } |
| 628 | @ |
| 629 | @ if {![namespace exists ttk]} { |
| 630 | @ interp alias {} ::ttk::scrollbar {} ::scrollbar |
| 631 | @ interp alias {} ::ttk::menubutton {} ::menubutton |
| 632 | @ } |
| 633 | @ |
| 634 | @ proc dehtml {x} { |
| 635 | @ set x [regsub -all {<[^>]*>} $x {}] |
| 636 | @ return [string map {& & < < > > ' ' " \"} $x] |
| 637 | @ } |
| 638 | @ |
| 639 | @ proc cols {} { |
| 640 | @ return [list .lnA .txtA .mkr .lnB .txtB] |
| 641 | @ } |
| 642 | @ |
| 643 | @ proc colType {c} { |
| 644 | @ regexp {[a-z]+} $c type |
| 645 | @ return $type |
| 646 | @ } |
| 647 | @ |
| 648 | @ proc getLine {difftxt N iivar} { |
| 649 | @ upvar $iivar ii |
| 650 | @ if {$ii>=$N} {return -1} |
| 651 | @ set x [lindex $difftxt $ii] |
| 652 | @ incr ii |
| 653 | @ return $x |
| 654 | @ } |
| 655 | @ |
| 656 | @ proc readDiffs {fossilcmd} { |
| 657 | @ global difftxt |
| 658 | @ if {![info exists difftxt]} { |
| 659 | @ set in [open $fossilcmd r] |
| 660 | @ fconfigure $in -encoding utf-8 |
| 661 | @ set difftxt [split [read $in] \n] |
| 662 | @ close $in |
| 663 | @ } |
| 664 | @ set N [llength $difftxt] |
| 665 | @ set ii 0 |
| 666 | @ set nDiffs 0 |
| 667 | @ array set widths {txt 0 ln 0 mkr 0} |
| 668 | @ while {[set line [getLine $difftxt $N ii]] != -1} { |
| 669 | @ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} { |
| 670 | @ continue |
| 671 | @ } |
| 672 | @ if {[string compare -length 6 [getLine $difftxt $N ii] "<table"]} { |
| 673 | @ continue |
| 674 | @ } |
| 675 | @ incr nDiffs |
| 676 | @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}] |
| 677 | @ .wfiles.lb insert end $fn |
| 678 | @ |
| 679 | @ foreach c [cols] { |
| 680 | @ while {[getLine $difftxt $N ii] ne "<pre>"} continue |
| 681 | @ |
| 682 | @ if {$nDiffs > 1} { |
| 683 | @ $c insert end \n - |
| 684 | @ } |
| 685 | @ if {[colType $c] eq "txt"} { |
| 686 | @ $c insert end $fn\n fn |
| 687 | @ } else { |
| 688 | @ $c insert end \n fn |
| 689 | @ } |
| 690 | @ $c insert end \n - |
| 691 | @ |
| 692 | @ set type [colType $c] |
| 693 | @ set str {} |
| 694 | @ while {[set line [getLine $difftxt $N ii]] ne "</pre>"} { |
| 695 | @ set len [string length [dehtml $line]] |
| 696 | @ if {$len > $widths($type)} { |
| 697 | @ set widths($type) $len |
| 698 | @ } |
| 699 | @ append str $line\n |
| 700 | @ } |
| 701 | @ |
| 702 | @ set re {<span class="diff([a-z]+)">([^<]*)</span>} |
| 703 | @ # Use \r as separator since it can't appear in the diff output (it gets |
| 704 | @ # converted to a space). |
| 705 | @ set str [regsub -all $re $str "\r\\1\r\\2\r"] |
| 706 | @ foreach {pre class mid} [split $str \r] { |
| @@ -694,12 +710,11 @@ | |
| 710 | @ $c insert end [dehtml $pre] - |
| 711 | @ } |
| 712 | @ } |
| 713 | @ } |
| 714 | @ } |
| 715 | @ |
| 716 | @ foreach c [cols] { |
| 717 | @ set type [colType $c] |
| 718 | @ if {$type ne "txt"} { |
| 719 | @ $c config -width $widths($type) |
| 720 | @ } |
| @@ -707,19 +722,19 @@ | |
| 722 | @ } |
| 723 | @ if {$nDiffs <= [.wfiles.lb cget -height]} { |
| 724 | @ .wfiles.lb config -height $nDiffs |
| 725 | @ grid remove .wfiles.sb |
| 726 | @ } |
| 727 | @ |
| 728 | @ return $nDiffs |
| 729 | @ } |
| 730 | @ |
| 731 | @ proc viewDiff {idx} { |
| 732 | @ .txtA yview $idx |
| 733 | @ .txtA xview moveto 0 |
| 734 | @ } |
| 735 | @ |
| 736 | @ proc cycleDiffs {{reverse 0}} { |
| 737 | @ if {$reverse} { |
| 738 | @ set range [.txtA tag prevrange fn @0,0 1.0] |
| 739 | @ if {$range eq ""} { |
| 740 | @ viewDiff {fn.last -1c} |
| @@ -733,36 +748,36 @@ | |
| 748 | @ } else { |
| 749 | @ viewDiff [lindex $range 0] |
| 750 | @ } |
| 751 | @ } |
| 752 | @ } |
| 753 | @ |
| 754 | @ proc xvis {col} { |
| 755 | @ set view [$col xview] |
| 756 | @ return [expr {[lindex $view 1]-[lindex $view 0]}] |
| 757 | @ } |
| 758 | @ |
| 759 | @ proc scroll-x {args} { |
| 760 | @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}] |
| 761 | @ eval $c xview $args |
| 762 | @ } |
| 763 | @ |
| 764 | @ interp alias {} scroll-y {} .txtA yview |
| 765 | @ |
| 766 | @ proc noop {args} {} |
| 767 | @ |
| 768 | @ proc enableSync {axis} { |
| 769 | @ update idletasks |
| 770 | @ interp alias {} sync-$axis {} |
| 771 | @ rename _sync-$axis sync-$axis |
| 772 | @ } |
| 773 | @ |
| 774 | @ proc disableSync {axis} { |
| 775 | @ rename sync-$axis _sync-$axis |
| 776 | @ interp alias {} sync-$axis {} noop |
| 777 | @ } |
| 778 | @ |
| 779 | @ proc sync-x {col first last} { |
| 780 | @ disableSync x |
| 781 | @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}] |
| 782 | @ foreach side {A B} { |
| 783 | @ set sb .sbx$side |
| @@ -774,11 +789,11 @@ | |
| 789 | @ grid remove $sb |
| 790 | @ } |
| 791 | @ } |
| 792 | @ enableSync x |
| 793 | @ } |
| 794 | @ |
| 795 | @ proc sync-y {first last} { |
| 796 | @ disableSync y |
| 797 | @ foreach c [cols] { |
| 798 | @ $c yview moveto $first |
| 799 | @ } |
| @@ -788,21 +803,21 @@ | |
| 803 | @ } else { |
| 804 | @ grid remove .sby |
| 805 | @ } |
| 806 | @ enableSync y |
| 807 | @ } |
| 808 | @ |
| 809 | @ wm withdraw . |
| 810 | @ wm title . $CFG(TITLE) |
| 811 | @ wm iconname . $CFG(TITLE) |
| 812 | @ bind . <q> exit |
| 813 | @ bind . <Destroy> {after 0 exit} |
| 814 | @ bind . <Tab> {cycleDiffs; break} |
| 815 | @ bind . <<PrevWindow>> {cycleDiffs 1; break} |
| 816 | @ bind . <Return> { |
| 817 | @ event generate .bb.files <1> |
| 818 | @ event generate .bb.files <ButtonRelease-1> |
| 819 | @ break |
| 820 | @ } |
| 821 | @ foreach {key axis args} { |
| 822 | @ Up y {scroll -5 units} |
| 823 | @ Down y {scroll 5 units} |
| @@ -814,22 +829,23 @@ | |
| 829 | @ End y {moveto 1} |
| 830 | @ } { |
| 831 | @ bind . <$key> "scroll-$axis $args; break" |
| 832 | @ bind . <Shift-$key> continue |
| 833 | @ } |
| 834 | @ |
| 835 | @ frame .bb |
| 836 | @ ::ttk::menubutton .bb.files -text "Files" |
| 837 | @ toplevel .wfiles |
| 838 | @ wm withdraw .wfiles |
| 839 | @ update idletasks |
| 840 | @ wm transient .wfiles . |
| 841 | @ wm overrideredirect .wfiles 1 |
| 842 | @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \ |
| 843 | @ -yscroll {.wfiles.sb set} |
| 844 | @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 845 | @ grid .wfiles.lb .wfiles.sb -sticky ns |
| 846 | @ bind .bb.files <1> { |
| 847 | @ set x [winfo rootx %W] |
| 848 | @ set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| 849 | @ wm geometry .wfiles +$x+$y |
| 850 | @ wm deiconify .wfiles |
| 851 | @ focus .wfiles.lb |
| @@ -848,16 +864,16 @@ | |
| 864 | @ } |
| 865 | @ bind .wfiles.lb <Motion> { |
| 866 | @ %W selection clear 0 end |
| 867 | @ %W selection set @%x,%y |
| 868 | @ } |
| 869 | @ |
| 870 | @ foreach {side syncCol} {A .txtB B .txtA} { |
| 871 | @ set ln .ln$side |
| 872 | @ text $ln |
| 873 | @ $ln tag config - -justify right |
| 874 | @ |
| 875 | @ set txt .txt$side |
| 876 | @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \ |
| 877 | @ -xscroll "sync-x $syncCol" |
| 878 | @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5 |
| 879 | @ foreach tag {add rm chng} { |
| @@ -866,11 +882,11 @@ | |
| 882 | @ } |
| 883 | @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \ |
| 884 | @ -justify center |
| 885 | @ } |
| 886 | @ text .mkr |
| 887 | @ |
| 888 | @ foreach c [cols] { |
| 889 | @ set keyPrefix [string toupper [colType $c]]_COL_ |
| 890 | @ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}} |
| 891 | @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \ |
| 892 | @ -padx $CFG(PADX) -yscroll sync-y |
| @@ -878,34 +894,50 @@ | |
| 894 | @ -foreground $CFG(HR_FG) |
| 895 | @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD) |
| 896 | @ bindtags $c ". $c Text all" |
| 897 | @ bind $c <1> {focus %W} |
| 898 | @ } |
| 899 | @ |
| 900 | @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical |
| 901 | @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal |
| 902 | @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal |
| 903 | @ frame .spacer |
| 904 | @ |
| 905 | @ if {[readDiffs $fossilcmd] == 0} { |
| 906 | @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes" |
| 907 | @ exit |
| 908 | @ } |
| 909 | @ update idletasks |
| 910 | @ |
| 911 | @ proc saveDiff {} { |
| 912 | @ set fn [tk_getSaveFile] |
| 913 | @ set out [open $fn wb] |
| 914 | @ puts $out "set fossilcmd {}" |
| 915 | @ puts $out "set difftxt [list $::difftxt]" |
| 916 | @ puts $out "set prog [list $::prog]" |
| 917 | @ puts $out "eval \$prog" |
| 918 | @ close $out |
| 919 | @ } |
| 920 | @ ::ttk::button .bb.quit -text {Quit} -command exit |
| 921 | @ ::ttk::button .bb.save -text {Save As...} -command saveDiff |
| 922 | @ pack .bb.quit -side left |
| 923 | @ pack .bb.save -side left |
| 924 | @ pack .bb.files -side left |
| 925 | @ grid rowconfigure . 1 -weight 1 |
| 926 | @ grid columnconfigure . 1 -weight 1 |
| 927 | @ grid columnconfigure . 4 -weight 1 |
| 928 | @ grid .bb -row 0 -columnspan 6 |
| 929 | @ eval grid [cols] -row 1 -sticky nsew |
| 930 | @ grid .sby -row 1 -column 5 -sticky ns |
| 931 | @ grid .sbxA -row 2 -columnspan 2 -sticky ew |
| 932 | @ grid .spacer -row 2 -column 2 |
| 933 | @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew |
| 934 | @ |
| 935 | @ .spacer config -height [winfo height .sbxA] |
| 936 | @ wm deiconify . |
| 937 | @ } |
| 938 | @ eval $prog |
| 939 | ; |
| 940 | |
| 941 | /* |
| 942 | ** Show diff output in a Tcl/Tk window, in response to the --tk option |
| 943 | ** to the diff command. |
| 944 |