Code

Merge git://repo.or.cz/git-gui
authorJunio C Hamano <gitster@pobox.com>
Thu, 24 Jan 2008 05:37:12 +0000 (21:37 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 24 Jan 2008 05:37:12 +0000 (21:37 -0800)
* git://repo.or.cz/git-gui:
  git-gui: Correctly cleanup msgfmt '1 message untranslated' output
  git-gui: Make the statistics of po2msg match those of msgfmt
  git-gui: Fallback to Tcl based po2msg.sh if msgfmt isn't available
  git-gui: Work around random missing scrollbar in revision list

1  2 
git-gui/Makefile
git-gui/lib/choose_rev.tcl
git-gui/po/po2msg.sh

index 1baf4b086131a10ab7e33529274ebd15100f375e,0000000000000000000000000000000000000000..34438cdf5cc219ac71cbc90a23c23550276f5af2
mode 100644,000000..100644
--- /dev/null
@@@ -1,308 -1,0 +1,311 @@@
-       QUIET_MSGFMT1  = 2>&1` && echo "$$v" | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages//g'
 +all::
 +
 +# Define V=1 to have a more verbose compile.
 +#
 +# Define NO_MSGFMT if you do not have msgfmt from the GNU gettext
 +# package and want to use our rough pure Tcl po->msg translator.
 +# TCL_PATH must be vaild for this to work.
 +#
 +
 +GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 +      @$(SHELL_PATH) ./GIT-VERSION-GEN
 +-include GIT-VERSION-FILE
 +
 +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
 +uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
 +
 +SCRIPT_SH = git-gui.sh
 +GITGUI_MAIN := git-gui
 +GITGUI_BUILT_INS = git-citool
 +ALL_LIBFILES = $(wildcard lib/*.tcl)
 +PRELOAD_FILES = lib/class.tcl
 +NONTCL_LIBFILES = \
 +      lib/git-gui.ico \
 +      $(wildcard lib/win32_*.js) \
 +#end NONTCL_LIBFILES
 +
 +ifndef SHELL_PATH
 +      SHELL_PATH = /bin/sh
 +endif
 +
 +ifndef gitexecdir
 +      gitexecdir := $(shell git --exec-path)
 +endif
 +
 +ifndef sharedir
 +      sharedir := $(dir $(gitexecdir))share
 +endif
 +
 +ifndef INSTALL
 +      INSTALL = install
 +endif
 +
 +RM_RF     ?= rm -rf
 +RMDIR     ?= rmdir
 +
 +INSTALL_D0 = $(INSTALL) -d -m 755 # space is required here
 +INSTALL_D1 =
 +INSTALL_R0 = $(INSTALL) -m 644 # space is required here
 +INSTALL_R1 =
 +INSTALL_X0 = $(INSTALL) -m 755 # space is required here
 +INSTALL_X1 =
 +INSTALL_A0 = find # space is required here
 +INSTALL_A1 = | cpio -pud
 +INSTALL_L0 = rm -f # space is required here
 +INSTALL_L1 = && ln # space is required here
 +INSTALL_L2 =
 +INSTALL_L3 =
 +
 +REMOVE_D0  = $(RMDIR) # space is required here
 +REMOVE_D1  = || true
 +REMOVE_F0  = $(RM_RF) # space is required here
 +REMOVE_F1  =
 +CLEAN_DST  = true
 +
 +ifndef V
 +      QUIET          = @
 +      QUIET_GEN      = $(QUIET)echo '   ' GEN '$@' &&
 +      QUIET_INDEX    = $(QUIET)echo '   ' INDEX $(dir $@) &&
 +      QUIET_MSGFMT0  = $(QUIET)printf '    MSGFMT %12s ' $@ && v=`
++      QUIET_MSGFMT1  = 2>&1` && echo "$$v" | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages*//g'
 +      QUIET_2DEVNULL = 2>/dev/null
 +
 +      INSTALL_D0 = dir=
 +      INSTALL_D1 = && echo ' ' DEST $$dir && $(INSTALL) -d -m 755 "$$dir"
 +      INSTALL_R0 = src=
 +      INSTALL_R1 = && echo '   ' INSTALL 644 `basename $$src` && $(INSTALL) -m 644 $$src
 +      INSTALL_X0 = src=
 +      INSTALL_X1 = && echo '   ' INSTALL 755 `basename $$src` && $(INSTALL) -m 755 $$src
 +      INSTALL_A0 = src=
 +      INSTALL_A1 = && echo '   ' INSTALL '   ' `basename "$$src"` && find "$$src" | cpio -pud
 +
 +      INSTALL_L0 = dst=
 +      INSTALL_L1 = && src=
 +      INSTALL_L2 = && dst=
 +      INSTALL_L3 = && echo '   ' 'LINK       ' `basename "$$dst"` '->' `basename "$$src"` && rm -f "$$dst" && ln "$$src" "$$dst"
 +
 +      CLEAN_DST = echo ' ' UNINSTALL
 +      REMOVE_D0 = dir=
 +      REMOVE_D1 = && echo ' ' REMOVE $$dir && test -d "$$dir" && $(RMDIR) "$$dir" || true
 +      REMOVE_F0 = dst=
 +      REMOVE_F1 = && echo '   ' REMOVE `basename "$$dst"` && $(RM_RF) "$$dst"
 +endif
 +
 +TCL_PATH   ?= tclsh
 +TCLTK_PATH ?= wish
 +TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app
 +
 +ifeq ($(findstring $(MAKEFLAGS),s),s)
 +QUIET_GEN =
 +endif
 +
 +-include config.mak
 +
 +DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
 +gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
 +SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 +TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH))
 +TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 +TCLTK_PATH_SED = $(subst ','\'',$(subst \,\\,$(TCLTK_PATH)))
 +
 +gg_libdir ?= $(sharedir)/git-gui/lib
 +libdir_SQ  = $(subst ','\'',$(gg_libdir))
 +libdir_SED = $(subst ','\'',$(subst \,\\,$(gg_libdir_sed_in)))
 +exedir     = $(dir $(gitexecdir))share/git-gui/lib
 +
 +GITGUI_SCRIPT   := $$0
 +GITGUI_RELATIVE :=
 +GITGUI_MACOSXAPP :=
 +
 +ifeq ($(uname_O),Cygwin)
 +      GITGUI_SCRIPT := `cygpath --windows --absolute "$(GITGUI_SCRIPT)"`
 +      gg_libdir_sed_in := $(shell cygpath --windows --absolute "$(gg_libdir)")
 +else
 +      ifeq ($(exedir),$(gg_libdir))
 +              GITGUI_RELATIVE := 1
 +      endif
 +      gg_libdir_sed_in := $(gg_libdir)
 +endif
 +ifeq ($(uname_S),Darwin)
 +      ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y)
 +              GITGUI_MACOSXAPP := YesPlease
 +      endif
 +endif
 +ifneq (,$(findstring MINGW,$(uname_S)))
 +      NO_MSGFMT=1
 +      GITGUI_WINDOWS_WRAPPER := YesPlease
 +endif
 +
 +ifdef GITGUI_MACOSXAPP
 +GITGUI_MAIN := git-gui.tcl
 +
 +git-gui: GIT-VERSION-FILE GIT-GUI-VARS
 +      $(QUIET_GEN)rm -f $@ $@+ && \
 +      echo '#!$(SHELL_PATH_SQ)' >$@+ && \
 +      echo 'if test "z$$*" = zversion ||' >>$@+ && \
 +      echo '   test "z$$*" = z--version' >>$@+ && \
 +      echo then >>$@+ && \
 +      echo '  'echo \'git-gui version '$(GITGUI_VERSION)'\' >>$@+ && \
 +      echo else >>$@+ && \
 +      echo '  'exec \''$(libdir_SQ)/Git Gui.app/Contents/MacOS/Wish'\' \
 +              '"$$0" "$$@"' >>$@+ && \
 +      echo fi >>$@+ && \
 +      chmod +x $@+ && \
 +      mv $@+ $@
 +
 +Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-VARS \
 +              macosx/Info.plist \
 +              macosx/git-gui.icns \
 +              macosx/AppMain.tcl \
 +              $(TKFRAMEWORK)/Contents/MacOS/Wish
 +      $(QUIET_GEN)rm -rf '$@' '$@'+ && \
 +      mkdir -p '$@'+/Contents/MacOS && \
 +      mkdir -p '$@'+/Contents/Resources/Scripts && \
 +      cp '$(subst ','\'',$(TKFRAMEWORK))/Contents/MacOS/Wish' \
 +              '$@'+/Contents/MacOS && \
 +      cp macosx/git-gui.icns '$@'+/Contents/Resources && \
 +      sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
 +              macosx/Info.plist \
 +              >'$@'+/Contents/Info.plist && \
 +      sed -e 's|@@gitexecdir@@|$(gitexecdir_SQ)|' \
 +              -e 's|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \
 +              macosx/AppMain.tcl \
 +              >'$@'+/Contents/Resources/Scripts/AppMain.tcl && \
 +      mv '$@'+ '$@'
 +endif
 +
 +ifdef GITGUI_WINDOWS_WRAPPER
 +GITGUI_MAIN := git-gui.tcl
 +
 +git-gui: windows/git-gui.sh
 +      cp $< $@
 +endif
 +
 +$(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS
 +      $(QUIET_GEN)rm -f $@ $@+ && \
 +      sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
 +              -e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \
 +              -e '1,30s|^ exec wish | exec '\''$(TCLTK_PATH_SED)'\'' |' \
 +              -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
 +              -e 's|@@GITGUI_RELATIVE@@|$(GITGUI_RELATIVE)|' \
 +              -e '$(GITGUI_RELATIVE)s|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \
 +              git-gui.sh >$@+ && \
 +      chmod +x $@+ && \
 +      mv $@+ $@
 +
 +XGETTEXT   ?= xgettext
 +ifdef NO_MSGFMT
 +      MSGFMT ?= $(TCL_PATH) po/po2msg.sh
 +else
 +      MSGFMT ?= msgfmt
++      ifeq ($(shell $(MSGFMT) >/dev/null 2>&1 || echo $$?),127)
++              MSGFMT := $(TCL_PATH) po/po2msg.sh
++      endif
 +endif
 +
 +msgsdir     = $(gg_libdir)/msgs
 +msgsdir_SQ  = $(subst ','\'',$(msgsdir))
 +PO_TEMPLATE = po/git-gui.pot
 +ALL_POFILES = $(wildcard po/*.po)
 +ALL_MSGFILES = $(subst .po,.msg,$(ALL_POFILES))
 +
 +$(PO_TEMPLATE): $(SCRIPT_SH) $(ALL_LIBFILES)
 +      $(XGETTEXT) -kmc -LTcl -o $@ $(SCRIPT_SH) $(ALL_LIBFILES)
 +update-po:: $(PO_TEMPLATE)
 +      $(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; )
 +$(ALL_MSGFILES): %.msg : %.po
 +      $(QUIET_MSGFMT0)$(MSGFMT) --statistics --tcl -l $(basename $(notdir $<)) -d $(dir $@) $< $(QUIET_MSGFMT1)
 +
 +lib/tclIndex: $(ALL_LIBFILES) GIT-GUI-VARS
 +      $(QUIET_INDEX)if echo \
 +        $(foreach p,$(PRELOAD_FILES),source $p\;) \
 +        auto_mkindex lib '*.tcl' \
 +      | $(TCL_PATH) $(QUIET_2DEVNULL); then : ok; \
 +      else \
 +       echo 1>&2 "    * $(TCL_PATH) failed; using unoptimized loading"; \
 +       rm -f $@ ; \
 +       echo '# Autogenerated by git-gui Makefile' >$@ && \
 +       echo >>$@ && \
 +       $(foreach p,$(PRELOAD_FILES) $(ALL_LIBFILES),echo '$(subst lib/,,$p)' >>$@ &&) \
 +       echo >>$@ ; \
 +      fi
 +
 +TRACK_VARS = \
 +      $(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \
 +      $(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \
 +      $(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \
 +      $(subst ','\'',gitexecdir='$(gitexecdir_SQ)') \
 +      $(subst ','\'',gg_libdir='$(libdir_SQ)') \
 +      GITGUI_MACOSXAPP=$(GITGUI_MACOSXAPP) \
 +#end TRACK_VARS
 +
 +GIT-GUI-VARS: .FORCE-GIT-GUI-VARS
 +      @VARS='$(TRACK_VARS)'; \
 +      if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
 +              echo 1>&2 "    * new locations or Tcl/Tk interpreter"; \
 +              echo 1>$@ "$$VARS"; \
 +      fi
 +
 +ifdef GITGUI_MACOSXAPP
 +all:: git-gui Git\ Gui.app
 +endif
 +ifdef GITGUI_WINDOWS_WRAPPER
 +all:: git-gui
 +endif
 +all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES)
 +
 +install: all
 +      $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
 +      $(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 +      $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true
 +ifdef GITGUI_WINDOWS_WRAPPER
 +      $(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 +endif
 +      $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1)
 +      $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)'
 +ifdef GITGUI_MACOSXAPP
 +      $(QUIET)$(INSTALL_A0)'Git Gui.app' $(INSTALL_A1) '$(DESTDIR_SQ)$(libdir_SQ)'
 +      $(QUIET)$(INSTALL_X0)git-gui.tcl $(INSTALL_X1) '$(DESTDIR_SQ)$(libdir_SQ)'
 +endif
 +      $(QUIET)$(foreach p,$(ALL_LIBFILES) $(NONTCL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true
 +      $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(INSTALL_D1)
 +      $(QUIET)$(foreach p,$(ALL_MSGFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true
 +
 +uninstall:
 +      $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
 +      $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)
 +      $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true
 +ifdef GITGUI_WINDOWS_WRAPPER
 +      $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1)
 +endif
 +      $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)'
 +      $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1)
 +ifdef GITGUI_MACOSXAPP
 +      $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)/Git Gui.app' $(REMOVE_F1)
 +      $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.tcl $(REMOVE_F1)
 +endif
 +      $(QUIET)$(foreach p,$(ALL_LIBFILES) $(NONTCL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true
 +      $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(msgsdir_SQ)'
 +      $(QUIET)$(foreach p,$(ALL_MSGFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(msgsdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true
 +      $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(REMOVE_D1)
 +      $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(REMOVE_D1)
 +      $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(REMOVE_D1)
 +      $(QUIET)$(REMOVE_D0)`dirname '$(DESTDIR_SQ)$(libdir_SQ)'` $(REMOVE_D1)
 +
 +dist-version:
 +      @mkdir -p $(TARDIR)
 +      @echo $(GITGUI_VERSION) > $(TARDIR)/version
 +
 +clean::
 +      $(RM_RF) $(GITGUI_MAIN) lib/tclIndex po/*.msg
 +      $(RM_RF) GIT-VERSION-FILE GIT-GUI-VARS
 +ifdef GITGUI_MACOSXAPP
 +      $(RM_RF) 'Git Gui.app'* git-gui
 +endif
 +ifdef GITGUI_WINDOWS_WRAPPER
 +      $(RM_RF) git-gui
 +endif
 +
 +.PHONY: all install uninstall dist-version clean
 +.PHONY: .FORCE-GIT-VERSION-FILE
 +.PHONY: .FORCE-GIT-GUI-VARS
index a063c5bc49fc9bad58f7fd78e7446a097ce86b88,0000000000000000000000000000000000000000..c8821c146386f850c0794df70f605cd9f18dcff3
mode 100644,000000..100644
--- /dev/null
@@@ -1,627 -1,0 +1,628 @@@
-       $sb set $first $last
 +# git-gui revision chooser
 +# Copyright (C) 2006, 2007 Shawn Pearce
 +
 +class choose_rev {
 +
 +image create photo ::choose_rev::img_find -data {R0lGODlhEAAQAIYAAPwCBCQmJDw+PBQSFAQCBMza3NTm5MTW1HyChOT29Ozq7MTq7Kze5Kzm7Oz6/NTy9Iza5GzGzKzS1Nzy9Nz29Kzq9HTGzHTK1Lza3AwKDLzu9JTi7HTW5GTCzITO1Mzq7Hza5FTK1ESyvHzKzKzW3DQyNDyqtDw6PIzW5HzGzAT+/Dw+RKyurNTOzMTGxMS+tJSGdATCxHRydLSqpLymnLSijBweHERCRNze3Pz69PTy9Oze1OTSxOTGrMSqlLy+vPTu5OzSvMymjNTGvNS+tMy2pMyunMSefAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAe4gACCAAECA4OIiAIEBQYHBAKJgwIICQoLDA0IkZIECQ4PCxARCwSSAxITFA8VEBYXGBmJAQYLGhUbHB0eH7KIGRIMEBAgISIjJKaIJQQLFxERIialkieUGigpKRoIBCqJKyyLBwvJAioEyoICLS4v6QQwMQQyLuqLli8zNDU2BCf1lN3AkUPHDh49fAQAAEnGD1MCCALZEaSHkIUMBQS8wWMIkSJGhBzBmFEGgRsBUqpMiSgdAD+BAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIuNQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7}
 +
 +field w               ; # our megawidget path
 +field w_list          ; # list of currently filtered specs
 +field w_filter        ; # filter entry for $w_list
 +
 +field c_expr        {}; # current revision expression
 +field filter          ; # current filter string
 +field revtype     head; # type of revision chosen
 +field cur_specs [list]; # list of specs for $revtype
 +field spec_head       ; # list of all head specs
 +field spec_trck       ; # list of all tracking branch specs
 +field spec_tag        ; # list of all tag specs
 +field tip_data        ; # array of tip commit info by refname
 +field log_last        ; # array of reflog date by refname
 +
 +field tooltip_wm        {} ; # Current tooltip toplevel, if open
 +field tooltip_t         {} ; # Text widget in $tooltip_wm
 +field tooltip_timer     {} ; # Current timer event for our tooltip
 +
 +proc new {path {title {}}} {
 +      return [_new $path 0 $title]
 +}
 +
 +proc new_unmerged {path {title {}}} {
 +      return [_new $path 1 $title]
 +}
 +
 +constructor _new {path unmerged_only title} {
 +      global current_branch is_detached
 +
 +      if {![info exists ::all_remotes]} {
 +              load_all_remotes
 +      }
 +
 +      set w $path
 +
 +      if {$title ne {}} {
 +              labelframe $w -text $title
 +      } else {
 +              frame $w
 +      }
 +      bind $w <Destroy> [cb _delete %W]
 +
 +      if {$is_detached} {
 +              radiobutton $w.detachedhead_r \
 +                      -anchor w \
 +                      -text [mc "This Detached Checkout"] \
 +                      -value HEAD \
 +                      -variable @revtype
 +              grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2
 +      }
 +
 +      radiobutton $w.expr_r \
 +              -text [mc "Revision Expression:"] \
 +              -value expr \
 +              -variable @revtype
 +      entry $w.expr_t \
 +              -borderwidth 1 \
 +              -relief sunken \
 +              -width 50 \
 +              -textvariable @c_expr \
 +              -validate key \
 +              -validatecommand [cb _validate %d %S]
 +      grid $w.expr_r $w.expr_t -sticky we -padx {0 5}
 +
 +      frame $w.types
 +      radiobutton $w.types.head_r \
 +              -text [mc "Local Branch"] \
 +              -value head \
 +              -variable @revtype
 +      pack $w.types.head_r -side left
 +      radiobutton $w.types.trck_r \
 +              -text [mc "Tracking Branch"] \
 +              -value trck \
 +              -variable @revtype
 +      pack $w.types.trck_r -side left
 +      radiobutton $w.types.tag_r \
 +              -text [mc "Tag"] \
 +              -value tag \
 +              -variable @revtype
 +      pack $w.types.tag_r -side left
 +      set w_filter $w.types.filter
 +      entry $w_filter \
 +              -borderwidth 1 \
 +              -relief sunken \
 +              -width 12 \
 +              -textvariable @filter \
 +              -validate key \
 +              -validatecommand [cb _filter %P]
 +      pack $w_filter -side right
 +      pack [label $w.types.filter_icon \
 +              -image ::choose_rev::img_find \
 +              ] -side right
 +      grid $w.types -sticky we -padx {0 5} -columnspan 2
 +
 +      frame $w.list
 +      set w_list $w.list.l
 +      listbox $w_list \
 +              -font font_diff \
 +              -width 50 \
 +              -height 10 \
 +              -selectmode browse \
 +              -exportselection false \
 +              -xscrollcommand [cb _sb_set $w.list.sbx h] \
 +              -yscrollcommand [cb _sb_set $w.list.sby v]
 +      pack $w_list -fill both -expand 1
 +      grid $w.list -sticky nswe -padx {20 5} -columnspan 2
 +      bind $w_list <Any-Motion>  [cb _show_tooltip @%x,%y]
 +      bind $w_list <Any-Enter>   [cb _hide_tooltip]
 +      bind $w_list <Any-Leave>   [cb _hide_tooltip]
 +      bind $w_list <Destroy>     [cb _hide_tooltip]
 +
 +      grid columnconfigure $w 1 -weight 1
 +      if {$is_detached} {
 +              grid rowconfigure $w 3 -weight 1
 +      } else {
 +              grid rowconfigure $w 2 -weight 1
 +      }
 +
 +      trace add variable @revtype write [cb _select]
 +      bind $w_filter <Key-Return> [list focus $w_list]\;break
 +      bind $w_filter <Key-Down>   [list focus $w_list]
 +
 +      set fmt list
 +      append fmt { %(refname)}
 +      append fmt { [list}
 +      append fmt { %(objecttype)}
 +      append fmt { %(objectname)}
 +      append fmt { [concat %(taggername) %(authorname)]}
 +      append fmt { [reformat_date [concat %(taggerdate) %(authordate)]]}
 +      append fmt { %(subject)}
 +      append fmt {] [list}
 +      append fmt { %(*objecttype)}
 +      append fmt { %(*objectname)}
 +      append fmt { %(*authorname)}
 +      append fmt { [reformat_date %(*authordate)]}
 +      append fmt { %(*subject)}
 +      append fmt {]}
 +      set all_refn [list]
 +      set fr_fd [git_read for-each-ref \
 +              --tcl \
 +              --sort=-taggerdate \
 +              --format=$fmt \
 +              refs/heads \
 +              refs/remotes \
 +              refs/tags \
 +              ]
 +      fconfigure $fr_fd -translation lf -encoding utf-8
 +      while {[gets $fr_fd line] > 0} {
 +              set line [eval $line]
 +              if {[lindex $line 1 0] eq {tag}} {
 +                      if {[lindex $line 2 0] eq {commit}} {
 +                              set sha1 [lindex $line 2 1]
 +                      } else {
 +                              continue
 +                      }
 +              } elseif {[lindex $line 1 0] eq {commit}} {
 +                      set sha1 [lindex $line 1 1]
 +              } else {
 +                      continue
 +              }
 +              set refn [lindex $line 0]
 +              set tip_data($refn) [lrange $line 1 end]
 +              lappend cmt_refn($sha1) $refn
 +              lappend all_refn $refn
 +      }
 +      close $fr_fd
 +
 +      if {$unmerged_only} {
 +              set fr_fd [git_read rev-list --all ^$::HEAD]
 +              while {[gets $fr_fd sha1] > 0} {
 +                      if {[catch {set rlst $cmt_refn($sha1)}]} continue
 +                      foreach refn $rlst {
 +                              set inc($refn) 1
 +                      }
 +              }
 +              close $fr_fd
 +      } else {
 +              foreach refn $all_refn {
 +                      set inc($refn) 1
 +              }
 +      }
 +
 +      set spec_head [list]
 +      foreach name [load_all_heads] {
 +              set refn refs/heads/$name
 +              if {[info exists inc($refn)]} {
 +                      lappend spec_head [list $name $refn]
 +              }
 +      }
 +
 +      set spec_trck [list]
 +      foreach spec [all_tracking_branches] {
 +              set refn [lindex $spec 0]
 +              if {[info exists inc($refn)]} {
 +                      regsub ^refs/(heads|remotes)/ $refn {} name
 +                      lappend spec_trck [concat $name $spec]
 +              }
 +      }
 +
 +      set spec_tag [list]
 +      foreach name [load_all_tags] {
 +              set refn refs/tags/$name
 +              if {[info exists inc($refn)]} {
 +                      lappend spec_tag [list $name $refn]
 +              }
 +      }
 +
 +                if {$is_detached}             { set revtype HEAD
 +      } elseif {[llength $spec_head] > 0} { set revtype head
 +      } elseif {[llength $spec_trck] > 0} { set revtype trck
 +      } elseif {[llength $spec_tag ] > 0} { set revtype tag
 +      } else {                              set revtype expr
 +      }
 +
 +      if {$revtype eq {head} && $current_branch ne {}} {
 +              set i 0
 +              foreach spec $spec_head {
 +                      if {[lindex $spec 0] eq $current_branch} {
 +                              $w_list selection clear 0 end
 +                              $w_list selection set $i
 +                              break
 +                      }
 +                      incr i
 +              }
 +      }
 +
 +      return $this
 +}
 +
 +method none {text} {
 +      if {![winfo exists $w.none_r]} {
 +              radiobutton $w.none_r \
 +                      -anchor w \
 +                      -value none \
 +                      -variable @revtype
 +              grid $w.none_r -sticky we -padx {0 5} -columnspan 2
 +      }
 +      $w.none_r configure -text $text
 +}
 +
 +method get {} {
 +      switch -- $revtype {
 +      head -
 +      trck -
 +      tag  {
 +              set i [$w_list curselection]
 +              if {$i ne {}} {
 +                      return [lindex $cur_specs $i 0]
 +              } else {
 +                      return {}
 +              }
 +      }
 +
 +      HEAD { return HEAD                     }
 +      expr { return $c_expr                  }
 +      none { return {}                       }
 +      default { error "unknown type of revision" }
 +      }
 +}
 +
 +method pick_tracking_branch {} {
 +      set revtype trck
 +}
 +
 +method focus_filter {} {
 +      if {[$w_filter cget -state] eq {normal}} {
 +              focus $w_filter
 +      }
 +}
 +
 +method bind_listbox {event script}  {
 +      bind $w_list $event $script
 +}
 +
 +method get_local_branch {} {
 +      if {$revtype eq {head}} {
 +              return [_expr $this]
 +      } else {
 +              return {}
 +      }
 +}
 +
 +method get_tracking_branch {} {
 +      set i [$w_list curselection]
 +      if {$i eq {} || $revtype ne {trck}} {
 +              return {}
 +      }
 +      return [lrange [lindex $cur_specs $i] 1 end]
 +}
 +
 +method get_commit {} {
 +      set e [_expr $this]
 +      if {$e eq {}} {
 +              return {}
 +      }
 +      return [git rev-parse --verify "$e^0"]
 +}
 +
 +method commit_or_die {} {
 +      if {[catch {set new [get_commit $this]} err]} {
 +
 +              # Cleanup the not-so-friendly error from rev-parse.
 +              #
 +              regsub {^fatal:\s*} $err {} err
 +              if {$err eq {Needed a single revision}} {
 +                      set err {}
 +              }
 +
 +              set top [winfo toplevel $w]
 +              set msg [strcat [mc "Invalid revision: %s" [get $this]] "\n\n$err"]
 +              tk_messageBox \
 +                      -icon error \
 +                      -type ok \
 +                      -title [wm title $top] \
 +                      -parent $top \
 +                      -message $msg
 +              error $msg
 +      }
 +      return $new
 +}
 +
 +method _expr {} {
 +      switch -- $revtype {
 +      head -
 +      trck -
 +      tag  {
 +              set i [$w_list curselection]
 +              if {$i ne {}} {
 +                      return [lindex $cur_specs $i 1]
 +              } else {
 +                      error [mc "No revision selected."]
 +              }
 +      }
 +
 +      expr {
 +              if {$c_expr ne {}} {
 +                      return $c_expr
 +              } else {
 +                      error [mc "Revision expression is empty."]
 +              }
 +      }
 +      HEAD { return HEAD                     }
 +      none { return {}                       }
 +      default { error "unknown type of revision"      }
 +      }
 +}
 +
 +method _validate {d S} {
 +      if {$d == 1} {
 +              if {[regexp {\s} $S]} {
 +                      return 0
 +              }
 +              if {[string length $S] > 0} {
 +                      set revtype expr
 +              }
 +      }
 +      return 1
 +}
 +
 +method _filter {P} {
 +      if {[regexp {\s} $P]} {
 +              return 0
 +      }
 +      _rebuild $this $P
 +      return 1
 +}
 +
 +method _select {args} {
 +      _rebuild $this $filter
 +      focus_filter $this
 +}
 +
 +method _rebuild {pat} {
 +      set ste normal
 +      switch -- $revtype {
 +      head { set new $spec_head }
 +      trck { set new $spec_trck }
 +      tag  { set new $spec_tag  }
 +      expr -
 +      HEAD -
 +      none {
 +              set new [list]
 +              set ste disabled
 +      }
 +      }
 +
 +      if {[$w_list cget -state] eq {disabled}} {
 +              $w_list configure -state normal
 +      }
 +      $w_list delete 0 end
 +
 +      if {$pat ne {}} {
 +              set pat *${pat}*
 +      }
 +      set cur_specs [list]
 +      foreach spec $new {
 +              set txt [lindex $spec 0]
 +              if {$pat eq {} || [string match $pat $txt]} {
 +                      lappend cur_specs $spec
 +                      $w_list insert end $txt
 +              }
 +      }
 +      if {$cur_specs ne {}} {
 +              $w_list selection clear 0 end
 +              $w_list selection set 0
 +      }
 +
 +      if {[$w_filter cget -state] ne $ste} {
 +              $w_list   configure -state $ste
 +              $w_filter configure -state $ste
 +      }
 +}
 +
 +method _delete {current} {
 +      if {$current eq $w} {
 +              delete_this
 +      }
 +}
 +
 +method _sb_set {sb orient first last} {
 +      set old_focus [focus -lastfor $w]
 +
 +      if {$first == 0 && $last == 1} {
 +              if {[winfo exists $sb]} {
 +                      destroy $sb
 +                      if {$old_focus ne {}} {
 +                              update
 +                              focus $old_focus
 +                      }
 +              }
 +              return
 +      }
 +
 +      if {![winfo exists $sb]} {
 +              if {$orient eq {h}} {
 +                      scrollbar $sb -orient h -command [list $w_list xview]
 +                      pack $sb -fill x -side bottom -before $w_list
 +              } else {
 +                      scrollbar $sb -orient v -command [list $w_list yview]
 +                      pack $sb -fill y -side right -before $w_list
 +              }
 +              if {$old_focus ne {}} {
 +                      update
 +                      focus $old_focus
 +              }
 +      }
++
++      catch {$sb set $first $last}
 +}
 +
 +method _show_tooltip {pos} {
 +      if {$tooltip_wm ne {}} {
 +              _open_tooltip $this
 +      } elseif {$tooltip_timer eq {}} {
 +              set tooltip_timer [after 1000 [cb _open_tooltip]]
 +      }
 +}
 +
 +method _open_tooltip {} {
 +      global remote_url
 +
 +      set tooltip_timer {}
 +      set pos_x [winfo pointerx $w_list]
 +      set pos_y [winfo pointery $w_list]
 +      if {[winfo containing $pos_x $pos_y] ne $w_list} {
 +              _hide_tooltip $this
 +              return
 +      }
 +
 +      set pos @[join [list \
 +              [expr {$pos_x - [winfo rootx $w_list]}] \
 +              [expr {$pos_y - [winfo rooty $w_list]}]] ,]
 +      set lno [$w_list index $pos]
 +      if {$lno eq {}} {
 +              _hide_tooltip $this
 +              return
 +      }
 +
 +      set spec [lindex $cur_specs $lno]
 +      set refn [lindex $spec 1]
 +      if {$refn eq {}} {
 +              _hide_tooltip $this
 +              return
 +      }
 +
 +      if {$tooltip_wm eq {}} {
 +              set tooltip_wm [toplevel $w_list.tooltip -borderwidth 1]
 +              wm overrideredirect $tooltip_wm 1
 +              wm transient $tooltip_wm [winfo toplevel $w_list]
 +              set tooltip_t $tooltip_wm.label
 +              text $tooltip_t \
 +                      -takefocus 0 \
 +                      -highlightthickness 0 \
 +                      -relief flat \
 +                      -borderwidth 0 \
 +                      -wrap none \
 +                      -background lightyellow \
 +                      -foreground black
 +              $tooltip_t tag conf section_header -font font_uibold
 +              bind $tooltip_wm <Escape> [cb _hide_tooltip]
 +              pack $tooltip_t
 +      } else {
 +              $tooltip_t conf -state normal
 +              $tooltip_t delete 0.0 end
 +      }
 +
 +      set data $tip_data($refn)
 +      if {[lindex $data 0 0] eq {tag}} {
 +              set tag  [lindex $data 0]
 +              if {[lindex $data 1 0] eq {commit}} {
 +                      set cmit [lindex $data 1]
 +              } else {
 +                      set cmit {}
 +              }
 +      } elseif {[lindex $data 0 0] eq {commit}} {
 +              set tag  {}
 +              set cmit [lindex $data 0]
 +      }
 +
 +      $tooltip_t insert end [lindex $spec 0]
 +      set last [_reflog_last $this [lindex $spec 1]]
 +      if {$last ne {}} {
 +              $tooltip_t insert end "\n"
 +              $tooltip_t insert end [mc "Updated"]
 +              $tooltip_t insert end " $last"
 +      }
 +      $tooltip_t insert end "\n"
 +
 +      if {$tag ne {}} {
 +              $tooltip_t insert end "\n"
 +              $tooltip_t insert end [mc "Tag"] section_header
 +              $tooltip_t insert end "  [lindex $tag 1]\n"
 +              $tooltip_t insert end [lindex $tag 2]
 +              $tooltip_t insert end " ([lindex $tag 3])\n"
 +              $tooltip_t insert end [lindex $tag 4]
 +              $tooltip_t insert end "\n"
 +      }
 +
 +      if {$cmit ne {}} {
 +              $tooltip_t insert end "\n"
 +              $tooltip_t insert end [mc "Commit@@noun"] section_header
 +              $tooltip_t insert end "  [lindex $cmit 1]\n"
 +              $tooltip_t insert end [lindex $cmit 2]
 +              $tooltip_t insert end " ([lindex $cmit 3])\n"
 +              $tooltip_t insert end [lindex $cmit 4]
 +      }
 +
 +      if {[llength $spec] > 2} {
 +              $tooltip_t insert end "\n"
 +              $tooltip_t insert end [mc "Remote"] section_header
 +              $tooltip_t insert end "  [lindex $spec 2]\n"
 +              $tooltip_t insert end [mc "URL"]
 +              $tooltip_t insert end " $remote_url([lindex $spec 2])\n"
 +              $tooltip_t insert end [mc "Branch"]
 +              $tooltip_t insert end " [lindex $spec 3]"
 +      }
 +
 +      $tooltip_t conf -state disabled
 +      _position_tooltip $this
 +}
 +
 +method _reflog_last {name} {
 +      if {[info exists reflog_last($name)]} {
 +              return reflog_last($name)
 +      }
 +
 +      set last {}
 +      if {[catch {set last [file mtime [gitdir $name]]}]
 +      && ![catch {set g [open [gitdir logs $name] r]}]} {
 +              fconfigure $g -translation binary
 +              while {[gets $g line] >= 0} {
 +                      if {[regexp {> ([1-9][0-9]*) } $line line when]} {
 +                              set last $when
 +                      }
 +              }
 +              close $g
 +      }
 +
 +      if {$last ne {}} {
 +              set last [format_date $last]
 +      }
 +      set reflog_last($name) $last
 +      return $last
 +}
 +
 +method _position_tooltip {} {
 +      set max_h [lindex [split [$tooltip_t index end] .] 0]
 +      set max_w 0
 +      for {set i 1} {$i <= $max_h} {incr i} {
 +              set c [lindex [split [$tooltip_t index "$i.0 lineend"] .] 1]
 +              if {$c > $max_w} {set max_w $c}
 +      }
 +      $tooltip_t conf -width $max_w -height $max_h
 +
 +      set req_w [winfo reqwidth  $tooltip_t]
 +      set req_h [winfo reqheight $tooltip_t]
 +      set pos_x [expr {[winfo pointerx .] +  5}]
 +      set pos_y [expr {[winfo pointery .] + 10}]
 +
 +      set g "${req_w}x${req_h}"
 +      if {$pos_x >= 0} {append g +}
 +      append g $pos_x
 +      if {$pos_y >= 0} {append g +}
 +      append g $pos_y
 +
 +      wm geometry $tooltip_wm $g
 +      raise $tooltip_wm
 +}
 +
 +method _hide_tooltip {} {
 +      if {$tooltip_wm ne {}} {
 +              destroy $tooltip_wm
 +              set tooltip_wm {}
 +      }
 +      if {$tooltip_timer ne {}} {
 +              after cancel $tooltip_timer
 +              set tooltip_timer {}
 +      }
 +}
 +
 +}
index c63248e3752b8b479f75ad2fe772dd40f684be54,0000000000000000000000000000000000000000..b7c4bf3fdffb3d04b8c01b25e99a706e499de0d1
mode 100644,000000..100644
--- /dev/null
@@@ -1,133 -1,0 +1,152 @@@
-       puts [concat "$translated_count translated messages, " \
-               "$fuzzy_count fuzzy ones, " \
-               "$not_translated_count untranslated ones."]
 +#!/bin/sh
 +# Tcl ignores the next line -*- tcl -*- \
 +exec tclsh "$0" -- "$@"
 +
 +# This is a really stupid program, which serves as an alternative to
 +# msgfmt.  It _only_ translates to Tcl mode, does _not_ validate the
 +# input, and does _not_ output any statistics.
 +
 +proc u2a {s} {
 +      set res ""
 +      foreach i [split $s ""] {
 +              scan $i %c c
 +              if {$c<128} {
 +                      # escape '[', '\' and ']'
 +                      if {$c == 0x5b || $c == 0x5d} {
 +                              append res "\\"
 +                      }
 +                      append res $i
 +              } else {
 +                      append res \\u[format %04.4x $c]
 +              }
 +      }
 +      return $res
 +}
 +
 +set output_directory "."
 +set lang "dummy"
 +set files [list]
 +set show_statistics 0
 +
 +# parse options
 +for {set i 0} {$i < $argc} {incr i} {
 +      set arg [lindex $argv $i]
 +      if {$arg == "--statistics"} {
 +              incr show_statistics
 +              continue
 +      }
 +      if {$arg == "--tcl"} {
 +              # we know
 +              continue
 +      }
 +      if {$arg == "-l"} {
 +              incr i
 +              set lang [lindex $argv $i]
 +              continue
 +      }
 +      if {$arg == "-d"} {
 +              incr i
 +              set tmp [lindex $argv $i]
 +              regsub "\[^/\]$" $tmp "&/" output_directory
 +              continue
 +      }
 +      lappend files $arg
 +}
 +
 +proc flush_msg {} {
 +      global msgid msgstr mode lang out fuzzy
 +      global translated_count fuzzy_count not_translated_count
 +
 +      if {![info exists msgid] || $mode == ""} {
 +              return
 +      }
 +      set mode ""
 +      if {$fuzzy == 1} {
 +              incr fuzzy_count
 +              set fuzzy 0
 +              return
 +      }
 +
 +      if {$msgid == ""} {
 +              set prefix "set ::msgcat::header"
 +      } else {
 +              if {$msgstr == ""} {
 +                      incr not_translated_count
 +                      return
 +              }
 +              set prefix "::msgcat::mcset $lang \"[u2a $msgid]\""
 +              incr translated_count
 +      }
 +
 +      puts $out "$prefix \"[u2a $msgstr]\""
 +}
 +
 +set fuzzy 0
 +set translated_count 0
 +set fuzzy_count 0
 +set not_translated_count 0
 +foreach file $files {
 +      regsub "^.*/\(\[^/\]*\)\.po$" $file "$output_directory\\1.msg" outfile
 +      set in [open $file "r"]
 +      fconfigure $in -encoding utf-8
 +      set out [open $outfile "w"]
 +
 +      set mode ""
 +      while {[gets $in line] >= 0} {
 +              if {[regexp "^#" $line]} {
 +                      if {[regexp ", fuzzy" $line]} {
 +                              set fuzzy 1
 +                      } else {
 +                              flush_msg
 +                      }
 +                      continue
 +              } elseif {[regexp "^msgid \"(.*)\"$" $line dummy match]} {
 +                      flush_msg
 +                      set msgid $match
 +                      set mode "msgid"
 +              } elseif {[regexp "^msgstr \"(.*)\"$" $line dummy match]} {
 +                      set msgstr $match
 +                      set mode "msgstr"
 +              } elseif {$line == ""} {
 +                      flush_msg
 +              } elseif {[regexp "^\"(.*)\"$" $line dummy match]} {
 +                      if {$mode == "msgid"} {
 +                              append msgid $match
 +                      } elseif {$mode == "msgstr"} {
 +                              append msgstr $match
 +                      } else {
 +                              puts stderr "I do not know what to do: $match"
 +                      }
 +              } else {
 +                      puts stderr "Cannot handle $line"
 +              }
 +      }
 +      flush_msg
 +      close $in
 +      close $out
 +}
 +
 +if {$show_statistics} {
++      set str ""
++
++      append str  "$translated_count translated message"
++      if {$translated_count != 1} {
++              append str s
++      }
++
++      if {$fuzzy_count > 1} {
++              append str  ", $fuzzy_count fuzzy translation"
++              if {$fuzzy_count != 1} {
++                      append str s
++              }
++      }
++      if {$not_translated_count > 0} {
++              append str  ", $not_translated_count untranslated message"
++              if {$not_translated_count != 1} {
++                      append str s
++              }
++      }
++
++      append str  .
++      puts $str
 +}