Full Code of jonas/tig for AI

master e77e4f6ade58 cached
308 files
3.8 MB
998.9k tokens
1526 symbols
1 requests
Download .txt
Showing preview only (3,990K chars total). Download the full file or copy to clipboard to get everything.
Repository: jonas/tig
Branch: master
Commit: e77e4f6ade58
Files: 308
Total size: 3.8 MB

Directory structure:
gitextract_jul00w11/

├── .bookignore
├── .github/
│   └── workflows/
│       ├── linux.yml
│       └── macos.yml
├── .gitignore
├── .mailmap
├── COPYING
├── INSTALL.adoc
├── Makefile
├── NEWS.adoc
├── README.adoc
├── appveyor.yml
├── autogen.sh
├── book.json
├── book.md
├── compat/
│   ├── ansidecl.h
│   ├── compat.h
│   ├── hashtab.c
│   ├── hashtab.h
│   ├── mkstemps.c
│   ├── setenv.c
│   ├── strndup.c
│   ├── utf8proc.c
│   ├── utf8proc.h
│   ├── utf8proc.license.md
│   ├── utf8proc_data.c
│   └── wordexp.c
├── config.make.in
├── configure.ac
├── contrib/
│   ├── bindings-v1.x.tigrc
│   ├── chocolate.theme.tigrc
│   ├── config.make
│   ├── config.make-CYGWIN_NT-6.1
│   ├── config.make-Darwin
│   ├── config.make-Linux
│   ├── git-flow.tigrc
│   ├── large-repo.tigrc
│   ├── tig-completion.bash
│   ├── tig-completion.zsh
│   ├── tig-pick
│   ├── tig.spec.in
│   └── vim.tigrc
├── doc/
│   ├── asciidoc.conf
│   ├── manual.adoc
│   ├── tig.1.adoc
│   ├── tigmanual.7.adoc
│   └── tigrc.5.adoc
├── include/
│   └── tig/
│       ├── apps.h
│       ├── argv.h
│       ├── blame.h
│       ├── blob.h
│       ├── diff.h
│       ├── display.h
│       ├── draw.h
│       ├── git.h
│       ├── graph.h
│       ├── grep.h
│       ├── help.h
│       ├── io.h
│       ├── keys.h
│       ├── line.h
│       ├── log.h
│       ├── main.h
│       ├── map.h
│       ├── options.h
│       ├── pager.h
│       ├── parse.h
│       ├── prompt.h
│       ├── refdb.h
│       ├── reflog.h
│       ├── refs.h
│       ├── repo.h
│       ├── request.h
│       ├── search.h
│       ├── stage.h
│       ├── stash.h
│       ├── status.h
│       ├── string.h
│       ├── tig.h
│       ├── tree.h
│       ├── types.h
│       ├── ui.h
│       ├── util.h
│       ├── view.h
│       └── watch.h
├── snap/
│   └── snapcraft.yaml
├── src/
│   ├── apps.c
│   ├── argv.c
│   ├── blame.c
│   ├── blob.c
│   ├── diff.c
│   ├── display.c
│   ├── draw.c
│   ├── graph-v1.c
│   ├── graph-v2.c
│   ├── graph.c
│   ├── grep.c
│   ├── help.c
│   ├── io.c
│   ├── keys.c
│   ├── line.c
│   ├── log.c
│   ├── main.c
│   ├── map.c
│   ├── options.c
│   ├── pager.c
│   ├── parse.c
│   ├── prompt.c
│   ├── refdb.c
│   ├── reflog.c
│   ├── refs.c
│   ├── repo.c
│   ├── request.c
│   ├── search.c
│   ├── stage.c
│   ├── stash.c
│   ├── status.c
│   ├── string.c
│   ├── tig.c
│   ├── tree.c
│   ├── types.c
│   ├── ui.c
│   ├── util.c
│   ├── view.c
│   └── watch.c
├── test/
│   ├── API.adoc
│   ├── README.adoc
│   ├── blame/
│   │   ├── blob-blame-test
│   │   ├── default-test
│   │   ├── initial-diff-test
│   │   ├── navigation-parent-test
│   │   ├── revargs-test
│   │   ├── start-on-line-test
│   │   └── stash-test
│   ├── blob/
│   │   └── wrap-lines-test
│   ├── diff/
│   │   ├── diff-context-test
│   │   ├── diff-highlight-color-test
│   │   ├── diff-highlight-test
│   │   ├── diff-stat-split-test
│   │   ├── diff-stat-test
│   │   ├── diff-stdin-test
│   │   ├── diff-wdiff-context-test
│   │   ├── editor-test
│   │   ├── line-number-test
│   │   ├── maximized-navigation-test
│   │   ├── open-after-split-test
│   │   ├── start-on-line-test
│   │   ├── submodule-editor-diffstat-test
│   │   ├── submodule-editor-test
│   │   ├── worktree-editor-test
│   │   └── wrap-lines-test
│   ├── files/
│   │   ├── refs-repo.tgz
│   │   ├── repo-authornamechange.tgz
│   │   ├── repo-one.tgz
│   │   ├── repo-two.tgz
│   │   └── scala-js-benchmarks.tgz
│   ├── graph/
│   │   ├── 00-simple-test
│   │   ├── 01-merge-from-left-test
│   │   ├── 02-duplicate-parent-test
│   │   ├── 03-octo-merge-test
│   │   ├── 04-missing-bar-test
│   │   ├── 05-extra-pipe-test
│   │   ├── 06-extra-bars-test
│   │   ├── 07-multi-collapse-test
│   │   ├── 08-multi-collapse-2-test
│   │   ├── 09-parallel-siblings-test
│   │   ├── 10-shorter-merge-than-branch-test
│   │   ├── 11-new-branch-in-middle-test
│   │   ├── 12-cross-over-collapse-test
│   │   ├── 13-collapse-parallel-branches-with-different-middle-branch-test
│   │   ├── 14-long-collapse-line-test
│   │   ├── 15-many-merges-test
│   │   ├── 16-changes-test
│   │   ├── 17-more-merges-test
│   │   ├── 18-tig-test
│   │   ├── 19-tig-all-test
│   │   ├── 20-tig-all-long-test
│   │   ├── 20-tig-all-long-test.in
│   │   ├── gh-490-heap-buffer-overflow-test
│   │   └── regression/
│   │       ├── horizontal-artifact-test
│   │       └── horizontal-bar-wrong-2-test
│   ├── grep/
│   │   ├── default-test
│   │   ├── editor-test
│   │   ├── refspec-test
│   │   └── start-on-line-test
│   ├── help/
│   │   ├── all-keybindings-test
│   │   ├── all-keybindings-test.expected
│   │   ├── default-test
│   │   └── user-command-test
│   ├── log/
│   │   ├── diff-stat-test
│   │   ├── log-graph-test
│   │   ├── pretty-format-test
│   │   ├── start-on-line-test
│   │   └── submodule-test
│   ├── main/
│   │   ├── all-arg-test
│   │   ├── author-name-change-test
│   │   ├── boundary-test
│   │   ├── branch-var-test
│   │   ├── commit-order-edge-case-test
│   │   ├── commit-order-edge-case-test.tgz
│   │   ├── commit-title-overflow-test
│   │   ├── date-test
│   │   ├── date-test.in
│   │   ├── default-test
│   │   ├── emoji-test
│   │   ├── escape-control-characters-test
│   │   ├── escape-control-characters-test.in
│   │   ├── filter-args-test
│   │   ├── git-alias-test
│   │   ├── goto-test
│   │   ├── graph-argument-test
│   │   ├── jump-ends-test
│   │   ├── mailmap-test
│   │   ├── main-options-test
│   │   ├── merge-test
│   │   ├── no-matching-commmits-test
│   │   ├── no-merges-test
│   │   ├── pretty-raw-test
│   │   ├── refresh-periodic-test
│   │   ├── refresh-test
│   │   ├── search-preload-test
│   │   ├── search-test
│   │   ├── show-changes-after-rename-test
│   │   ├── show-changes-test
│   │   ├── start-on-line-test
│   │   ├── stdin-test
│   │   ├── submodule-test
│   │   ├── unbind-default-quit-key-test
│   │   ├── untracked-test
│   │   ├── update-unstaged-changes-test
│   │   ├── util.sh
│   │   ├── vertical-lines-test
│   │   └── view-split-test
│   ├── prompt/
│   │   └── exec-test
│   ├── reflog/
│   │   └── default-test
│   ├── refs/
│   │   ├── branch-checkout-test
│   │   ├── branch-tag-test
│   │   ├── branch-var-test
│   │   ├── default-test
│   │   ├── filter-test
│   │   ├── refresh-test
│   │   ├── replace-test
│   │   ├── start-on-line-test
│   │   └── worktree-test
│   ├── regressions/
│   │   ├── github-1136-test
│   │   ├── github-370-test
│   │   ├── github-390-test
│   │   └── github-434-test
│   ├── script/
│   │   ├── comment-test
│   │   └── default-test
│   ├── stage/
│   │   ├── default-test
│   │   ├── gh-410-test
│   │   ├── maximized-unstaged-changes-test
│   │   ├── split-chunk-test
│   │   └── update-part-test
│   ├── stash/
│   │   └── start-on-line-test
│   ├── status/
│   │   ├── file-name-test
│   │   ├── file-var-test
│   │   ├── on-branch-test
│   │   ├── on-branch-tracking-info-test
│   │   ├── refresh-test
│   │   ├── repo-var-test
│   │   ├── start-on-line-test
│   │   ├── submodule-editor-test
│   │   ├── untracked-files-test
│   │   ├── worktree-editor-test
│   │   └── worktree-test
│   ├── tigrc/
│   │   ├── builtin-error-test
│   │   ├── builtin-save-test
│   │   ├── command-value-long-test
│   │   ├── compat-error-test
│   │   ├── contrib-tigrc-test
│   │   ├── env-vars-test
│   │   ├── escape-var-test
│   │   ├── parse-test
│   │   ├── quote-test
│   │   ├── save-option-test
│   │   ├── source-test
│   │   ├── tigrc-manpage-examples-test
│   │   ├── truncation-test
│   │   ├── view-column-test
│   │   ├── width-test
│   │   └── xdg-config-home-test
│   ├── tools/
│   │   ├── libgit.sh
│   │   ├── libtest.sh
│   │   ├── setup-conflict.sh
│   │   ├── show-results.sh
│   │   ├── test-graph.c
│   │   └── valgrind-Darwin.supp
│   └── tree/
│       ├── chdir-test
│       ├── default-test
│       ├── file-name-test
│       ├── submodule-editor-test
│       └── worktree-editor-test
├── tigrc
└── tools/
    ├── announcement.sh
    ├── aspell.dict
    ├── ax_lib_readline.m4
    ├── ax_require_defined.m4
    ├── ax_with_curses.m4
    ├── doc-gen.c
    ├── gcov.m4
    ├── header.h
    ├── iconv.m4
    ├── install.sh
    ├── make-builtin-config.sh
    ├── release.sh
    ├── travis.sh
    └── uninstall.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .bookignore
================================================
# Blacklist most files since documentation is co-located with the rest
# of the source to avoid that GitBook copies them to the output
# directory.
*.*
*-*
COPYING
Makefile
tigrc

## Whitelist AsciiDoc and GitBook files
!*.adoc
!*.md
!*.json

# ... except the manual man-page
doc/tigmanual.7.adoc


================================================
FILE: .github/workflows/linux.yml
================================================
name: Linux

on: [push, pull_request]

jobs:
  ci:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        compiler: [clang, gcc]
        tig_build: [autoconf, "config.make"]
        include:
          - name: Address Sanitizer
            compiler: clang
            tig_build: "address-sanitizer"

          - name: Valgrind
            compiler: gcc
            tig_build: valgrind

    steps:
      - uses: actions/checkout@v4
      - name: Test Tig
        shell: 'script -q -e -c "sh {0}"' # Workaround to get a TTY, see https://github.com/gfx/example-github-actions-with-tty
        run: |
          set -ex
          export LANG=en_US.utf8
          sudo apt update
          sudo DEBIAN_FRONTEND=noninteractive apt -yq install --no-install-recommends \
            asciidoc valgrind xmlto
          CC=${{ matrix.compiler }} TIG_BUILD=${{ matrix.tig_build }} tools/travis.sh


================================================
FILE: .github/workflows/macos.yml
================================================
name: macOS

on: [push, pull_request]

jobs:
  install:
    runs-on: macos-latest
    if: github.ref == 'refs/heads/master'

    strategy:
      matrix:
        compiler: [clang, gcc]

    steps:
      - name: Patch
        run: |
          brew tap homebrew/core
          cd "$(brew --repo homebrew/core)" && patch -p1 <<\EOF
          diff --git a/Formula/t/tig.rb b/Formula/t/tig.rb
          index c726e53c519..920b0fbc1c2 100644
          --- a/Formula/t/tig.rb
          +++ b/Formula/t/tig.rb
          @@ -31,9 +31,11 @@ class Tig < Formula
             depends_on "readline"
           
             def install
          +    ENV.deparallelize
               system "./autogen.sh" if build.head?
               system "./configure", "--prefix=#{prefix}", "--sysconfdir=#{etc}"
               system "make"
          +    system "make", "test"
               # Ensure the configured `sysconfdir` is used during runtime by
               # installing in a separate step.
               system "make", "install", "sysconfdir=#{pkgshare}/examples"
          EOF
      - name: Install latest Tig
        shell: 'script -q typescript sh {0}' # Workaround to get a TTY, see https://github.com/gfx/example-github-actions-with-tty
        run: HOMEBREW_NO_INSTALL_FROM_API=1 HOMEBREW_CC=${{ matrix.compiler }} HOMEBREW_NO_AUTO_UPDATE=1 brew install --HEAD tig

  ci:
    runs-on: macos-latest
    if: github.ref != 'refs/heads/master'

    steps:
      - uses: actions/checkout@v4
      - name: Test Tig
        shell: 'script -q typescript sh {0}' # Workaround to get a TTY, see https://github.com/gfx/example-github-actions-with-tty
        run: |
          brew install asciidoc autoconf automake coreutils gnu-sed ncurses xmlto
          TIG_BUILD=autoconf tools/travis.sh


================================================
FILE: .gitignore
================================================
*.gcno
*.gcda
*.html
*.o
*.swp
*~
.deps
/_book
/config.make
/node_modules/
aclocal.m4
autom4te.cache
/compile_commands/
/compile_commands.json
config.h
config.h.in
config.log
config.status
configure
cscope.out
ctags
doc/*.[157]
doc/*.xml
doc/manual.html-chunked
doc/manual.pdf
doc/manual.toc
doc/release-docs/
src/builtin-config.c
src/tig
tags
test/coverage
test/tools/test-graph
test/tmp
tig-*.tar.gz
tig-*.tar.gz.sha256
tig.spec
tools/doc-gen
tig.dSYM


================================================
FILE: .mailmap
================================================
Jonas Fonseca <jonas.fonseca@gmail.com> <fonseca@diku.dk>
Jonas Fonseca <jonas.fonseca@gmail.com> <jonas.fonseca@savoirfairelinux.com>
Jonas Fonseca <jonas.fonseca@gmail.com> <fonseca@antimatter.localdomain>


================================================
FILE: COPYING
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.


================================================
FILE: INSTALL.adoc
================================================
Installation instructions
=========================
:docext: adoc

Download a tarball from https://github.com/jonas/tig/releases[] or clone the Tig
repository https://github.com/jonas/tig[https://github.com/jonas/tig.git].

The latest version is:
https://github.com/jonas/tig/releases/download/tig-2.6.0/tig-2.6.0.tar.gz[tig-2.6.0]
https://github.com/jonas/tig/releases/download/tig-2.6.0/tig-2.6.0.tar.gz.sha256[(sha256)]

*Note:* Do not use the tar.gz file for version 2.0 because it will fail
to compile due to issue https://github.com/jonas/tig/pull/283[#283] and
https://github.com/jonas/tig/issues/337[#337]

The quick and simple way to install Tig is:

	$ make
	$ make install

By default, `tig` is installed in `$HOME/bin`. To install `tig` elsewhere set
`prefix` to the desired path:

	$ make prefix=/usr/local
	$ sudo make install prefix=/usr/local

Additional build options can be defined in the `config.make` file, which is
loaded automatically when running `make` if it exists. By default,
`contrib/config.make-$kernel_name` is loaded if it exists (currently
available for Linux, macOS [`Darwin`] and Cygwin but Linux users should
prefer the `configure` script). See `contrib/config.make` for example build
options.

Documentation files, such as manpages, are distributed in the release tarballs,
and can be installed using:

	$ make install-doc

When installing directly from the Tig repository, `make install-doc` will assume
that the documentation tool chain is available and build the documentation
locally. In case you do not wish to install the required tools, documentation
can be installed from the 'release' branch using:

	$ make install-release-doc

Before upgrading, you are advised to read link:NEWS.{docext}[the release notes].

Installation using `configure`
------------------------------

If you prefer an autotools-based installation process, you can use the
`configure` script to detect dependencies and enable features. If you downloaded
the Tig sources from https://github.com/jonas/tig/releases/[a release tarball]
there's already a `configure` script. However, if you are building from the Tig
repository, you need to ensure that `autoconf` is installed on your system and
generate the `configure` script yourself.

To install using `configure`, run the following commands:

	$ make configure # Only run if you are building from the Git repository
	$ ./configure
	$ make
	$ make install

If your `iconv` library is not in the default library and include path, you need
to pass the `--with-libiconv` option to `configure` to tell it where to look.

If you have installed ncurses with brew, run configure with the following
flags to have it properly detected (note this done out of the box if you
build without `configure`):

        $ ./configure LDFLAGS=-L/usr/local/opt/ncurses/lib CPPFLAGS=-I/usr/local/opt/ncurses/include

Installation using Homebrew
---------------------------

You can use link:https://brew.sh[Homebrew] to install Tig on macOS and Linux:

        $ brew install tig

Note, for older installations of Tig, Homebrew does not automatically
update the system-wide `tigrc` file when upgrading Tig and the
link:https://github.com/Homebrew/homebrew-core/commit/5600463d68620d68c9745acc490af7f8a16a75cb[behavior]
was changed in 2015 to install the system-wide `tigrc` in the
`/usr/local/share/tig/examples` directory so Tig always uses the
defaults compiled into the binary.

If you see warnings when starting Tig after upgrading, e.g.:

	tig warning: Errors while loading /usr/local/etc/tigrc

It means you either need to manually update `/usr/local/etc/tigrc` with
changes from `/usr/local/share/tig/examples` rename the file if you
never made any changes to it.

	$ mv /usr/local/etc/tigrc{,.old}


Installation using Nix
----------------------

You can use link:https://nixos.org/nix/[Nix] to install Tig on NixOS, or any Linux/macOS distribution with Nix installed:

        $ nix-env -i tig
	
Installation on Linux
---------------------

Depending on your distribution, you may be able to use one of the following commands to install Tig on Linux:

        $ apt-get install tig (Debian, Ubuntu)
        $ dnf install tig (Fedora)
        $ pacman -S tig (Arch Linux)
        $ apk add tig (Alpine)

Installation on FreeBSD
-----------------------

You can use link:https://man.freebsd.org/pkg/8[pkg] to install Tig on FreeBSD:

        $ pkg install tig

Installation on Windows
-----------------------

Easiest way is to install link:https://gitforwindows.org/[Git-for-Windows]. As 
of version `2.14.2`, it comes bundled with `tig`.

Alternatively, you can also use it by installing link:https://www.cygwin.com/[cygwin].
You must then install the packages `git`, `gcc-core`, `make`, `libiconv-devel`
and `libncurses-devel`. Extract the tarball and install by using `configure`
as explained above.

If you want to install from the sources, then you will also need the `automake`
package (which will also install `autoconf`). Then run `make configure` and install
by using `configure` as explained above.

Build configuration
-------------------

Build settings are read from the file `config.make` and for certain systems also
from `contrib/config.make-$kernel`. An example of the latter is macOS, where
`contrib/config.make-Darwin` provides out-of-the-box configuration for using the
system ncurses library and linking with the iconv library. This makes it easy to
configure the build without having to use the `configure` script. As a side
note, `configure` itself generates a `config.make` file.

Apart from the different standard `make` build variables (`CC`, `CFLAGS`, etc.)
and standard `configure` variables (`prefix`, `bindir`, etc.), build settings
can be one of the following flags:

 - `NO_SETENV`: Define this variable to enable work-around for missing
   `setenv()`.
 - `NO_MKSTEMPS`: Define this variable to enable work-around for missing
   `mkstemps()`.
 - `NO_WORDEXP`: Define this variable to enable work-around for missing
   `wordexp()`.
 - `NO_BUILTIN_TIGRC`: Reduce the size of the binary by not including a
   built-in tigrc. The built-in tigrc is used as a fallback when no
   `tigrc` is found in the system configuration directory (e.g. `/etc`).
 - `TIG_USER_CONFIG`: Allow to customize the `tigrc` path (default `~/.tigrc`).

The following example `config.make` manually configures Tig to use the ncurses
library with wide character support and include the proper ncurses header file
(see tig.h for more information):

	LDLIBS = -lncursesw
	CPPFLAGS = -DHAVE_NCURSESW_CURSES_H

For more examples of build settings, see `contrib/config.make` and
`config.make.in`.

Tools and packages
------------------

The following tools and packages are needed:

[cols="2<,8<",options="header"]
|=============================================================================
|Tool				|Description
|git-core			|Tig is just a frontend for Git.
|ncurses or ncursesw		|Be sure to have the development files
				 installed. Usually they are available in a
				 separate package ending with `-dev`.

				 Ncurses with wide character support (ncursesw)
				 is required to properly handle UTF-8 encoded
				 strings.

				 Note for packagers: For Tig's `configure`
				 script to work as expected you should avoid
				 configuring and building ncurses using
				 `--with-shared`.
|iconv				|If iconv is not provided by the c library
				 you need to change the Makefile to link it
				 into the binary.
|=============================================================================

The following tools and packages are optional and mainly needed for creating the
configure script and building documentation:

[cols="2<,8<",options="header"]
|=============================================================================
|Tool				|Description
|readline			|Adds support for completion and history in
				 search and command prompts.
|PCRE				|Adds support for Perl Compatible Regular
				 Expressions in searches.
|autoconf			|Contains autoreconf for generating configure
				 from configure.ac.
|asciidoc (>= 8.4)		|Generates HTML and (DocBook) XML from text.
|xmlto				|Generates manpages and chunked HTML from XML.
|DocBook XSL (>= 1.72.0)	|Used by xmlto for building manpages.
|DocBook (DSSL/Jade) tools	|Generates PDF from XML.
				 Also known as docbook-utils.
|=============================================================================


================================================
FILE: Makefile
================================================
## Makefile for tig

# The last tagged version. Can be overridden either by the version from
# git or from the value of the DIST_VERSION environment variable.
VERSION	= 2.6.0

all:

# Include kernel specific configuration
kernel_name := $(shell sh -c 'uname -s 2>/dev/null || echo unknown')
-include contrib/config.make-$(kernel_name)

# Include setting from the configure script
-include config.make

# Optional defaults.
# TIG_ variables are set by contrib/config.make-$(kernel_name).
TIG_NCURSES ?= -lcurses
LDFLAGS ?= $(TIG_LDFLAGS)
CPPFLAGS ?= $(TIG_CPPFLAGS)
LDLIBS ?= $(TIG_NCURSES) $(TIG_LDLIBS)
CFLAGS ?= -Wall -O2 $(TIG_CFLAGS)

prefix ?= $(HOME)
bindir ?= $(prefix)/bin
datarootdir ?= $(prefix)/share
sysconfdir ?= $(prefix)/etc
docdir ?= $(datarootdir)/doc
mandir ?= $(datarootdir)/man
# DESTDIR=

ifneq (,$(wildcard .git))
GITDESC	= $(subst tig-,,$(shell git describe 2>/dev/null))
COMMIT := $(if $(GITDESC),$(GITDESC),$(VERSION)-g$(shell git describe --always))
WTDIRTY	= $(if $(shell git diff-index HEAD 2>/dev/null),-dirty)
VERSION	= $(COMMIT)$(WTDIRTY)
endif
ifdef DIST_VERSION
VERSION = $(DIST_VERSION)
endif

# Split the version "TAG-OFFSET-gSHA1-DIRTY" into "TAG OFFSET"
# and append 0 as a fallback offset for "exact" tagged versions.
RPM_VERLIST = $(filter-out g% dirty,$(subst -, ,$(VERSION))) 0
RPM_VERSION = $(word 1,$(RPM_VERLIST))
RPM_RELEASE = $(word 2,$(RPM_VERLIST))$(if $(WTDIRTY),.dirty)

DFLAGS	= -g -DDEBUG -Werror -O0
EXE	= src/tig
TOOLS	= test/tools/test-graph tools/doc-gen
TXTDOC	= doc/tig.1.adoc doc/tigrc.5.adoc doc/manual.adoc NEWS.adoc README.adoc INSTALL.adoc test/API.adoc
MANDOC	= doc/tig.1 doc/tigrc.5 doc/tigmanual.7
HTMLDOC = doc/tig.1.html doc/tigrc.5.html doc/manual.html README.html INSTALL.html NEWS.html
ALLDOC	= $(MANDOC) $(HTMLDOC) doc/manual.html-chunked doc/manual.pdf

# Never include the release number in the tarname for tagged
# versions.
ifneq ($(if $(DIST_VERSION),$(words $(RPM_VERLIST))),2)
TARNAME	= tig-$(RPM_VERSION)-$(RPM_RELEASE)
else
TARNAME	= tig-$(RPM_VERSION)
endif

override CPPFLAGS += '-DTIG_VERSION="$(VERSION)"'
override CPPFLAGS += '-DSYSCONFDIR="$(sysconfdir)"'
ifdef TIG_USER_CONFIG
override CPPFLAGS += '-DTIG_USER_CONFIG="$(TIG_USER_CONFIG)"'
endif

ASCIIDOC ?= asciidoc
ASCIIDOC_FLAGS = -aversion=$(VERSION) -asysconfdir=$(sysconfdir) \
		-arevdate=$(shell git show -s --format=%cs) -f doc/asciidoc.conf
XMLTO ?= xmlto
DOCBOOK2PDF ?= docbook2pdf

LCOV ?= lcov
GENHTML ?= genhtml
ifneq (,$(shell which gsed 2>/dev/null))
SED ?= gsed
else
SED ?= sed
endif
ifneq (,$(shell which gtar 2>/dev/null))
TAR ?= gtar
else
TAR ?= tar
endif

GENERATE_COMPILATION_DATABASE ?= no
ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
compdb_check = $(shell $(CC) $(ALL_CFLAGS) \
	-c -MJ /dev/null \
	-x c /dev/null -o /dev/null 2>&1; \
	echo $$?)
ifneq ($(compdb_check),0)
override GENERATE_COMPILATION_DATABASE = no
$(warning GENERATE_COMPILATION_DATABASE is set to "yes", but your compiler does not \
support generating compilation database entries)
endif
else
ifneq ($(GENERATE_COMPILATION_DATABASE),no)
$(error please set GENERATE_COMPILATION_DATABASE to "yes" or "no" \
(not "$(GENERATE_COMPILATION_DATABASE)"))
endif
endif

compdb_dir = compile_commands
ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
missing_compdb_dir = $(compdb_dir)
$(missing_compdb_dir):
	@mkdir -p $@

compdb_file = $(compdb_dir)/$(subst /,-,$@.json)
compdb_args = -MJ $(compdb_file)
else
missing_compdb_dir = 
compdb_args =
endif

all: $(EXE) $(TOOLS)
all-debug: all
all-debug: CFLAGS += $(DFLAGS)
doc: $(ALLDOC)
doc-man: $(MANDOC)
doc-html: $(HTMLDOC)

ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
all: compile_commands.json
compile_commands.json:
	$(QUIET_GEN)sed -e '1s/^/[/' -e '$$s/,$$/]/' $(compdb_dir)/*.o.json > $@+
	@if test -s $@+; then mv $@+ $@; else $(RM) $@+; fi
endif

export sysconfdir

install: all
	$(QUIET_INSTALL)tools/install.sh bin $(EXE) "$(DESTDIR)$(bindir)"
	$(QUIET_INSTALL)tools/install.sh data tigrc "$(DESTDIR)$(sysconfdir)"

install-doc-man: doc-man
	$(Q)$(foreach doc, $(filter %.1, $(MANDOC)), \
		$(QUIET_INSTALL_EACH)tools/install.sh data $(doc) "$(DESTDIR)$(mandir)/man1";)
	$(Q)$(foreach doc, $(filter %.5, $(MANDOC)), \
		$(QUIET_INSTALL_EACH)tools/install.sh data $(doc) "$(DESTDIR)$(mandir)/man5";)
	$(Q)$(foreach doc, $(filter %.7, $(MANDOC)), \
		$(QUIET_INSTALL_EACH)tools/install.sh data $(doc) "$(DESTDIR)$(mandir)/man7";)

install-release-doc-man:
	GIT_INDEX_FILE=.tmp-doc-index git read-tree origin/release
	GIT_INDEX_FILE=.tmp-doc-index git checkout-index -f --prefix=./ $(MANDOC)
	rm -f .tmp-doc-index
	$(MAKE) install-doc-man

install-doc-html: doc-html
	$(Q)$(foreach doc, $(HTMLDOC), \
		$(QUIET_INSTALL_EACH)tools/install.sh data $(doc) "$(DESTDIR)$(docdir)/tig";)

install-release-doc-html:
	GIT_INDEX_FILE=.tmp-doc-index git read-tree origin/release
	GIT_INDEX_FILE=.tmp-doc-index git checkout-index -f --prefix=./ $(HTMLDOC)
	rm -f .tmp-doc-index
	$(MAKE) install-doc-html

install-doc: install-doc-man install-doc-html
install-release-doc: install-release-doc-man install-release-doc-html

uninstall:
	$(QUIET_UNINSTALL)tools/uninstall.sh "$(DESTDIR)$(bindir)/$(EXE:src/%=%)"
	$(QUIET_UNINSTALL)tools/uninstall.sh "$(DESTDIR)$(sysconfdir)/tigrc"
	$(Q)$(foreach doc, $(filter %.1, $(MANDOC:doc/%=%)), \
		$(QUIET_UNINSTALL_EACH)tools/uninstall.sh "$(DESTDIR)$(mandir)/man1/$(doc)";)
	$(Q)$(foreach doc, $(filter %.5, $(MANDOC:doc/%=%)), \
		$(QUIET_UNINSTALL_EACH)tools/uninstall.sh "$(DESTDIR)$(mandir)/man5/$(doc)";)
	$(Q)$(foreach doc, $(filter %.7, $(MANDOC:doc/%=%)), \
		$(QUIET_UNINSTALL_EACH)tools/uninstall.sh "$(DESTDIR)$(mandir)/man7/$(doc)";)
	$(Q)$(foreach doc, $(HTMLDOC:doc/%=%), \
		$(QUIET_UNINSTALL_EACH)tools/uninstall.sh "$(DESTDIR)$(docdir)/tig/$(doc)";)

clean: clean-test clean-coverage
	$(Q)$(RM) -r $(TARNAME) tig-*.tar.gz tig-*.tar.gz.sha256 .deps _book node_modules
	$(Q)$(RM) -r $(compdb_dir) compile_commands.json
	$(Q)$(RM) $(EXE) $(TOOLS) $(OBJS) core doc/*.xml src/builtin-config.c
	$(Q)$(RM) $(OBJS:%.o=%.gcda) $(OBJS:%.o=%.gcno)

distclean: clean
	$(RM) -r doc/manual.html-chunked autom4te.cache
	$(RM) doc/*.toc configure~
	$(RM) config.h config.log config.make config.status config.h.in~

veryclean: distclean
	$(RM) tig.spec $(ALLDOC) aclocal.m4 configure config.h.in

spell-check:
	for file in $(TXTDOC) src/tig.c; do \
		aspell --lang=en --dont-backup \
		       --personal=./tools/aspell.dict check $$file; \
	done

strip: $(EXE)
	strip $(EXE)

update-headers:
	@for file in include/tig/*.h src/*.c tools/*.c test/tools/*.c; do \
		grep -q '/* Copyright' "$$file" && \
			$(SED) '0,/.*\*\//d' < "$$file" | \
			grep -v '/* vim: set' > "$$file.tmp"; \
		{ cat tools/header.h "$$file.tmp"; \
		  echo "/* vim: set ts=8 sw=8 noexpandtab: */"; } > "$$file"; \
		rm "$$file.tmp"; \
		echo "Updated $$file"; \
	done

update-docs: tools/doc-gen
	doc="doc/tigrc.5.adoc"; \
	$(SED) -n '0,/ifndef::DOC_GEN_ACTIONS/p' < "$$doc" > "$$doc.gen"; \
	./tools/doc-gen actions >> "$$doc.gen"; \
	$(SED) -n '/endif::DOC_GEN_ACTIONS/,$$p' < "$$doc" >> "$$doc.gen" ; \
	mv "$$doc.gen" "$$doc"

dist: configure config.h.in aclocal.m4 tig.spec
	$(Q)mkdir -p $(TARNAME) && \
	cp Makefile tig.spec configure config.h.in aclocal.m4 $(TARNAME) && \
	$(SED) -i "s/VERSION\s\+=\s\+[0-9]\+\([.][0-9]\+\)\+/VERSION	= $(VERSION)/" $(TARNAME)/Makefile
	git archive --format=tar --prefix=$(TARNAME)/ HEAD | \
	$(TAR) --delete $(TARNAME)/Makefile > $(TARNAME).tar && \
	find $(TARNAME) -type f -print0 | LC_ALL=C sort -z | $(TAR) --mtime=$(shell git show -s --format=@%ct) --mode=o=rX,ug+rw,a-s --owner=root --group=root --null -T - -rf $(TARNAME).tar && \
	gzip -f -n -9 $(TARNAME).tar && \
	sha256sum $(TARNAME).tar.gz > $(TARNAME).tar.gz.sha256
	$(Q)$(RM) -r $(TARNAME)

rpm: dist
	rpmbuild -ta $(TARNAME).tar.gz

COVERAGE_CFLAGS ?= -fprofile-arcs -ftest-coverage
all-coverage: all
all-coverage: CFLAGS += $(COVERAGE_CFLAGS)

COVERAGE_DIR 	?= test/coverage

clean-coverage:
	@$(RM) -rf $(COVERAGE_DIR)

reset-coverage: clean-coverage
	$(LCOV) --reset-counters

test-coverage: clean-coverage all-coverage test $(COVERAGE_DIR)/index.html

$(COVERAGE_DIR)/trace:
	@mkdir -p $(COVERAGE_DIR)
	$(QUIET_LCOV)$(LCOV) $(Q:@=--quiet) --capture --no-external --directory . --output-file $@

$(COVERAGE_DIR)/index.html: $(COVERAGE_DIR)/trace
	$(QUIET_GENHTML)$(GENHTML) $(Q:@=--quiet) --output-directory $(COVERAGE_DIR) $<

ADDRESS_SANITIZER_CFLAGS ?= -fsanitize=address -fno-omit-frame-pointer
all-address-sanitizer: all
all-address-sanitizer: CFLAGS += $(ADDRESS_SANITIZER_CFLAGS)

test-address-sanitizer: clean all-address-sanitizer test
test-address-sanitizer: export TIG_ADDRESS_SANITIZER_ENABLED=yes

TESTS  = $(sort $(shell find test -type f -name '*-test'))
TESTS_TODO = $(sort $(shell find test -type f -name '*-test' -exec grep -l '\(test_todo\|-todo=\)' {} \+))

clean-test:
	$(Q)$(RM) -r test/tmp

test: clean-test $(TESTS)
	$(QUIET_SUMMARY)test/tools/show-results.sh

ifneq (,$(strip $(V:@=)))
export MAKE_TEST_OPTS = no-indent
else
export MAKE_TEST_OPTS =
endif

$(TESTS): PATH := $(CURDIR)/test/tools:$(CURDIR)/src:$(PATH)
$(TESTS): $(EXE) test/tools/test-graph
	$(QUIET_TEST)$(TEST_SHELL) $@

test-todo: MAKE_TEST_OPTS += todo
test-todo: $(TESTS_TODO)

# Other autoconf-related rules are hidden in config.make.in so that
# they don't confuse Make when we aren't actually using ./configure
configure config.h.in aclocal.m4: configure.ac tools/*.m4
	$(QUIET_GEN)./autogen.sh

site:
	gitbook install
	gitbook build
	find _book -type f | grep -E -v '(gitbook|json|html)' | xargs rm

.PHONY: all all-coverage all-debug clean clean-coverage clean-test doc \
	doc-man doc-html dist distclean install install-doc \
	install-doc-man install-doc-html install-release-doc-html \
	install-release-doc-man rpm spell-check strip test \
	test-coverage update-docs update-headers veryclean $(TESTS)

ifdef NO_MKSTEMPS
COMPAT_CPPFLAGS += -DNO_MKSTEMPS
COMPAT_OBJS += compat/mkstemps.o
endif

ifdef NO_SETENV
COMPAT_CPPFLAGS += -DNO_SETENV
COMPAT_OBJS += compat/setenv.o
endif

ifdef NO_STRNDUP
COMPAT_CPPFLAGS += -DNO_STRNDUP
COMPAT_OBJS += compat/strndup.o
endif

ifdef NO_WORDEXP
COMPAT_CPPFLAGS += -DNO_WORDEXP
COMPAT_OBJS += compat/wordexp.o
endif

COMPAT_OBJS += compat/hashtab.o compat/utf8proc.o

override CPPFLAGS += $(COMPAT_CPPFLAGS)

GRAPH_OBJS = src/graph.o src/graph-v1.o src/graph-v2.o

TIG_OBJS = \
	src/tig.o \
	src/types.o \
	src/string.o \
	src/util.o \
	src/map.o \
	src/argv.o \
	src/io.o \
	src/refdb.o \
	src/builtin-config.o \
	src/request.o \
	src/line.o \
	src/keys.o \
	src/repo.o \
	src/options.o \
	src/draw.o \
	src/prompt.o \
	src/display.o \
	src/view.o \
	src/search.o \
	src/parse.o \
	src/watch.o \
	src/pager.o \
	src/log.o \
	src/reflog.o \
	src/diff.o \
	src/help.o \
	src/tree.o \
	src/blob.o \
	src/blame.o \
	src/refs.o \
	src/status.o \
	src/stage.o \
	src/main.o \
	src/stash.o \
	src/grep.o \
	src/ui.o \
	src/apps.o \
	$(GRAPH_OBJS) \
	$(COMPAT_OBJS)

src/tig: $(TIG_OBJS)

TEST_GRAPH_OBJS = test/tools/test-graph.o src/string.o src/util.o src/io.o $(GRAPH_OBJS) $(COMPAT_OBJS)
test/tools/test-graph: $(TEST_GRAPH_OBJS)

DOC_GEN_OBJS = tools/doc-gen.o src/string.o src/types.o src/util.o src/request.o $(COMPAT_OBJS)
tools/doc-gen: $(DOC_GEN_OBJS)

OBJS = $(sort $(TIG_OBJS) $(TEST_GRAPH_OBJS) $(DOC_GEN_OBJS))

DEPS_CFLAGS ?= -MMD -MP -MF .deps/$*.d

%: %.o
	$(QUIET_LINK)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@

%.o: %.c $(CONFIG_H) $(missing_compdb_dir)
	@mkdir -p .deps/$(*D)
	$(QUIET_CC)$(CC) -I. -Iinclude $(compdb_args) $(CFLAGS) $(DEPS_CFLAGS) $(CPPFLAGS) -c -o $@ $<

-include $(OBJS:%.o=.deps/%.d)

src/builtin-config.c: tigrc tools/make-builtin-config.sh
	$(QUIET_GEN)tools/make-builtin-config.sh $< > $@

tig.spec: contrib/tig.spec.in
	$(QUIET_GEN)$(SED) -e 's/@@VERSION@@/$(RPM_VERSION)/g' \
	    -e 's/@@RELEASE@@/$(RPM_RELEASE)/g' < $< > $@

doc/manual.html: doc/manual.toc
doc/manual.html: ASCIIDOC_FLAGS += -ainclude-manual-toc
%.toc: %.adoc
	$(QUIET_GEN)$(SED) -n '/^\[\[/,/\(---\|~~~\)/p' < $< | while read line; do \
		case "$$line" in \
		"----"*)  echo ". <<$$ref>>"; ref= ;; \
		"~~~~"*)  echo "- <<$$ref>>"; ref= ;; \
		"[["*"]]") ref="$$line" ;; \
		*)	   ref="$$ref, $$line" ;; \
		esac; done | $(SED) 's/\[\[\(.*\)\]\]/\1/' > $@

README.html: README.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d article -a readme $<

INSTALL.html: INSTALL.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d article $<

NEWS.html: NEWS.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d article $<

doc/tigmanual.7: doc/manual.adoc

test/API.adoc: test/tools/libtest.sh
	@printf '%s\n%s\n' 'Testing API' '-----------' > $@
	$(QUIET_ASCIIDOC)egrep '^#\|' test/tools/libtest.sh | $(SED) 's/^#| \{0,1\}//' | cat -s >> $@

%.1.html : %.1.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d manpage $<

%.1.xml : %.1.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b docbook -d manpage $<

%.5.html : %.5.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d manpage $<

%.5.xml : %.5.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b docbook -d manpage $<

%.7.xml : %.7.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b docbook -d manpage $<

%.html: ASCIIDOC_FLAGS += -adocext=html -afooter-style=revdate
%.html : %.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b xhtml11 -d article -n $<

%.xml : %.adoc doc/asciidoc.conf
	$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_FLAGS) -b docbook -d article $<

% : %.xml
	$(QUIET_XMLTO)$(XMLTO) man -o doc $<

%.html-chunked : %.xml
	$(QUIET_XMLTO)$(XMLTO) html -o $@ $<

%.pdf : %.xml
	$(QUIET_DB2PDF)$(DOCBOOK2PDF) -o doc $<

#############################################################################
# Quiet make
#############################################################################

ifneq ($(findstring $(MAKEFLAGS),s),s)
V			= @
Q			= $(V:1=)
QUIET_CC		= $(Q:@=@echo    '        CC  '$@;)
QUIET_LINK		= $(Q:@=@echo    '      LINK  '$@;)
QUIET_GEN		= $(Q:@=@echo    '       GEN  '$@;)
QUIET_ASCIIDOC		= $(Q:@=@echo    '  ASCIIDOC  '$@;)
QUIET_XMLTO		= $(Q:@=@echo    '     XMLTO  '$@;)
QUIET_DB2PDF		= $(Q:@=@echo    '    DB2PDF  '$@;)
# tools/install.sh will print 'file -> $install_dir/file'
QUIET_INSTALL		= $(Q:@=@printf  '   INSTALL  ';)
QUIET_INSTALL_EACH	= $(Q:@=printf   '   INSTALL  ';)
QUIET_UNINSTALL		= $(Q:@=@printf  ' UNINSTALL  ';)
QUIET_UNINSTALL_EACH	= $(Q:@=printf   ' UNINSTALL  ';)
QUIET_TEST		= $(Q:@=@echo    '      TEST  '$@;)
QUIET_SUMMARY		= $(Q:@=@printf  '   SUMMARY  ';)
QUIET_LCOV		= $(Q:@=@echo    '      LCOV  '$@;)
QUIET_GENHTML		= $(Q:@=@echo    '   GENHTML  '$@;)

export V
endif


================================================
FILE: NEWS.adoc
================================================
Release notes
=============

tig-2.6.0
---------

Bug fixes:

 - Initialise %(head) from command line arguments. (#1366)
 - Make `$GIT_EDITOR` value interpreted by the shell. (#1367)
 - Use correct line from recursively blamed commit. (#1369, #1370)
 - Use correct line when using `:parent` in blame view. (#1372)
 - Fix the incorrect line shift after stage file. (#1371)
 - Update display after setting column option. (#1384)
 - Fix file mode diff header handling.
 - Fix crash caused by too many diff cells. (#1389)
 - Fix issue with blame when using absolute file paths. (#1391)

Improvements:

 - Add color for cursor in backgrounded view. (#1374)
 - Blame view now works without a working tree.
 - Open diff view from blame at the correct line. (#1375)
 - Document how to get a `<` within TIG_SCRIPT. (#1357)
 - Allow to hide +/- signs in the diff view. (#855, #901)
 - Add toggle options to help. (#1381)
 - Add expand/collapse all options to help. (#1382)
 - Expand relevant sections only when opening the help view. (#782, #886)
 - Introduce committer column.
 - Open the blame and blob views from diffstat.
 - Update utf8proc to v2.11.0, supporting Unicode 17.

Note: Users should update the settings for the blame, main, reflog, and
refs views in their ~/.tigrc file to include the committer column.

tig-2.5.12
----------

Bug fixes:

 - Fix empty blame view when opened from the diff view on i586. (#1362)

tig-2.5.11
----------

Incompatibilities:

 - Update remote repo variables. (#1358)

Bug fixes:

 - Fix various issues with `diff.noprefix` and `--no-prefix`.
 - Fix `Ctrl-C` behavior within the Readline prompt. (#1342)
 - Fix message upon edit from diffstat without patch.
 - Fix missing dates in the refs view.
 - Don't report an error when diff-highlight is killed intentionally.
 - Fix parsing of reflog designator in timestamp format.

Improvements:

 - Open the blob corresponding to the diff line. (#1334)
 - Keep cursor position in the main view when toggling
   file-filter and rev-filter.
 - Make errors visible in views showing Git output. (#1346)
 - Allow different colors for all references types.
 - Enable search in sections titles. (#1043)
 - Show committer date by default in the date column. (#294)
 - Update utf8proc to v2.10.0, supporting Unicode 16.
 - Only show stash, notes and prefetch in the refs view when
   invoked with `tig refs --all`. (#1359)

tig-2.5.10
----------

Bug fixes:

 - Fix `stat-*` coloring file names in `tig status` instead of just
   markers (regression in 2.5.9). (#1326)
 - Fix keybinding with +[cmd] not triggering view refreshing. (#1324)
 - Fix reopening the blame view from the main view.
 - Fix editing when stdin is redirected. (#1330)
 - Fix compilation warnings with ncurses 6.5.
 - Make `Ctrl-C` to kill only the command running in the foreground. (#1331)

tig-2.5.9
---------

Improvements:

 - Update utf8proc to v2.9.0, supporting Unicode 15.1.
 - Also use lightweight tags in the Refs line of the diff view. (#1235)
 - Support %(text) in all views with a text column. (#1275)
 - Use HTTPS for GitHub clone URLs. (#1310)
 - Move default log view options to tigrc.
 - Allow to go to stage view without Enter. (#1284)
 - Add new "prefetch" reference type for refs created by `git maintenance`
   (hidden in default config). (#1318)
 - Show the selected commit in the blame view title window.
 - Improve the blob view experience.
 - Clear keybinding from all keymaps (unbind) with `bind generic <key> none`.

Bug fixes:

 - Fix "dangling pointer" warning. (#1268)
 - Don't use array size in function arguments. (#1269)
 - Fix rpmbuild -ta. (#1276)
 - Initialise struct timezone. (#1291)
 - Fix NULL dereference at startup. (#1293)
 - Enforce a blank before view scroll percentage.
 - Fix refresh-mode periodic not updating branch labels. (#1270)
 - Fix display non-ascii character. (#1299)
 - Fix readline echo when stdin is redirected. (#1229)
 - Fix tig blame --reverse. (#1300)
 - Fix status view lockup.
 - Fix untracked changes and chunk staging behaviour in plain stage view.
 - Reset state variables when selecting a commit with no reference.
 - Fix parsing of `git ls-tree` for submodules. (#1282)

tig-2.5.8
---------

Improvements:

 - Update utf8proc to v2.8.0, supporting Unicode 15.
 - Support editing from the pager and the log (-p) views. (#1243)
 - Adjust build for native Apple Silicon.
 - Autoscroll the pager view while loading. (#1223)
 - Automatically show next diff in the status view. (#413, #469)
 - Replace `Unknown` author with `Not Committed Yet`.
 - Allow use of regular expressions for coloring. (#1249)
 - Add support for option word-diff-regex. (#1252)
 - Include original blob name in temporary filename. (#1254)

Bug fixes:

 - Use %(file_old) for old filename in the blame view. (#1226)
 - Correctly report which version of libncurses was linked. (#1240, #1241)
 - Fix stage view closing when holding the ] key. (#1245)
 - Make tests work from a path with symlinks.
 - Fix encoding of very long lines. (#1227)
 - Fix diffstat color for tig log -p.
 - Clean IO before closing a view or quitting.

tig-2.5.7
---------

Bug fixes:

 - Fix running tests as root. (#1224)
 - Fix parsing of status.showUntrackedFiles. (#1219)
 - Avoid incorrect history path when $XDG_DATA_HOME is valid. (#1215, #1217)

tig-2.5.6
---------

Bug fixes:

 - Fix `:goto <tag>`. (#1178)
 - Fix typo in ui.c.
 - Revert terminal hacks and workarounds. (#748, #943, #1180, #1182)
 - Fix opening of an ambiguous ref in refs view.
 - Fix search when view is loading.
 - Use the full width for diffstat in the stage view.
 - Improve escaping of variables in external commands.
 - Fix cursor behaviour during staging. (#842, #1028)
 - Fix navigation in split tree view.
 - Enable textconv in the stage view.
 - Enable textconv in the blame view and fix blame -L. (#978, #1189)
 - Update lineno for untracked files. (#1192)
 - Fix alignment of transliterated text. (#1195)
 - Fix word diff in the stage, stash and blame views. (#1207)
 - Fix reading the value of status.showUntrackedFiles. (#1211)
 - Honor commit_title:no in view settings.
 - Fix segfault with PCRE.

tig-2.5.5
---------

Improvements:

 - Make word-diff a toggleable option. (#1119, #1125)
 - Add Linux installation instructions. (#1121, #1126)
 - Allow :back to work across separate blame views. (#1123, #1127)
 - Add auto-refresh to log view. (#1128)
 - Expose `%(file_old)`, useful for deleted and renamed files. (#1132)
 - Enable jumping back in main view. (#628, #1138)
 - Add PCRE (Perl Compatible Regular Expressions) support. (#1137, #1143)
 - Pass command line args through to diff-files in status view. (#1152, #1155)
 - Remove quotes from TIG_LS_REMOTE to allow inline shell commands. (#1160, #1161)
 - Avoid pushing identical history state in main view.
 - Replace useless strncpy to avoid compilation warning with GCC 8.
 - Update utf8proc to v2.7.0.
 - Update distclean rule to preserve tarball contents. (#1167, #1169)
 - Add reference types stash and other. (#1160, #1172)
 - Auto refresh view upon option change.
 - Allow to toggle revision filtering. (#1173)

Bug fixes:

 - Fix null dereferences on unset format strings. (#1136, #1159)
 - Fix invalid read in log_read. (#1128)
 - Restore support for tig log --graph. (#1128)
 - Further fix to fullscreen navigation.
 - Fix blame when opened from an initial diff view. (#1135)
 - Fix stash view when using tig --all or tig revs. (#1146, #1147)
 - Avoiding null pointer dereference. (#1096)
 - Fix navigation between chunks after splitting chunk. (#1101, #1162)
 - Fix status line when toggling general options. (#1163, #1164)
 - Honor reference-format = hide:tag in diff view. (#1168, #1170)
 - Fix crash on :toggle file-args.

tig-2.5.4
---------

Improvements:

 - Add FreeBSD installation instructions. (#1093)
 - Add TIG_EDITOR environment variable to configure editor. (#889, #1098)
 - Enable mailmap by default to match git log's behaviour. (#1104, #1105)
 - Enable tilde expansion for diff-highlight. (#1107)

Bug fixes:

 - Escape variables with %% in external commands. (#1091, #1095)
 - Fix parsing of -L argument. (#1100)
 - Bugfix: smart-case does not work when search term contains a space. (#1108)
 - Use ncursesw by default on Linux. (#920)
 - Replace obsolete macro `AC_CONFIG_HEADER' in configure.ac.

tig-2.5.3
---------

Bug fixes:

 - Fix autoconf checking for readline. (#1072)
 - Fix segfault when saving a view with no column.
 - Reset view->parent when main view is promoted.
 - Fix segfault when pressing Enter in a child main view.
 - Restore lazy navigation.
 - Format time_t values portably and fix other values too. (#1084, #1085)
 - Fix loop when wrapping line with ISO-8859-1 character. (#1087, #1088)

tig-2.5.2
---------

Incompatibilities:

 - Change directory from the next argument, from now use `tig -C /path/to/repo`. (#1079)

Improvements:

 - Jump from blame to commit. (#355)
 - Start blame of an uncommitted deleted line from HEAD so the line's origin can be traced. (#1008, #1009)
 - Add line-graphics = auto. (#834, #1019)
 - Allow maxwidth to be expressed in % of the view width. (#1021)
 - Pass stash args through. (#1022, #1030)
 - Make build work on IBM i. (#1051, #1052)
 - Restore fullscreen navigation. (#1053)
 - Update utf8proc to v2.6.1.
 - Add some range so control chars ^^ and ^_ are also supported. (#1041, #1058)
 - Disable ncurses extended key values so that esc-codes can be used. (#1046, #1049)
 - Use id column for commit id only. (#1025, #1056)
 - Some minor updates for scrolling and for a double-click in diff. (#1060)
 - Add scroll-half-page-up and scroll-half-page-down actions. (#531, #1075)
 - Allow to generate a compilation database. (#1064)
 - New command stage-update-part.
 - The line number before a diff was applied is exposed as `%(lineno_old)`. (#1081)

Bug fixes:

 - Fix wrapping of lines with multibyte characters. (#988)
 - Improve highlighting of search with $ regex. (#1000)
 - Update tracking branch when refreshing status view. (#1015)
 - Fix vertical lines in Putty with UTF-8 graphics. (#981, #983)
 - Fix parsing of three-way chunk headers with extra dashes.
 - Update tracking branch when refreshing status view. (#1015, #1020)
 - Handle filename with space in diff view. (#1035)
 - The stash view requires a working tree.
 - Replace useless strncpy to avoid compilation warning. (#1036)
 - Zsh completion fixes. (#940, #1047)
 - Handle undefined __git_complete. (#1011, #1055)
 - Fix help messages for half-page and page up. (#1054)
 - Let `-S`, `-G` and `--grep=` pattern override readline history.
 - Fix bash completion issue with worktrees (#1018).
 - Fix parsing of commit line from `git log --left-right` output in pager view.
 - Fix %(lineno) computation for hunk postimages that span only one line. (#1062)
 - Align relative-compact dates to the right. (#1067)
 - Fix empty split diff view when navigating quickly in the stash view.
 - Avoid depending on wcwidth in test by removing Variation Selector. (#1065)
 - Open the blob view with the cursor correctly positioned.
 - Update %(text) when navigating diff contents. (#1082)

tig-2.5.1
---------

Improvements:

 - bash/zsh completion: reimplement and decrease runtime by factor 1863. (#795)
 - Add binding to reflog view to toggle reference display.
 - Fail if tig is given an invalid or ambiguous ref. (#980)
 - Make tig process-group leader an option. (#986, #951)
 - Handle GIT_WORK_TREE environment variable.
 - The blame view requires a working tree.
 - Fix use of deprecated vwprintw() function.
 - Update utf8proc to v2.5.0.
 - Add --word-diff=plain colorizing support. (#221)

Bug fixes:

 - Fix segmentation fault. (#971)
 - Fix cursor position after "Move to parent" in blame view. (#973)
 - Fix crash on adding a line to a view. (#523)
 - Fix memory leak in diff unit.
 - Fix loop after refresh or change in refs/main split view. (#991)
 - Fix occasional crash on custom key bindings. (#1001)

tig-2.5.0
---------

Improvements:

 - Single file view enters blame mode on "b". (#804)
 - Show untracked files in the default view. (#762)
 - Disable graph if log.follow is enabled and there is only one pathspec. (#881)
 - Disable graph for author searches.
 - git_colors: interpret 'ul' as 'underline'.
 - Add refname variable. (#900)
 - Add -C option to specify the working directory. (#570)
 - Improve behaviour of auto and periodic refresh modes. (#389, #441, #482, #794, #888, #932)
 - Add support for repos created with git --work-tree. (#872)
 - Add diff-highlight to pager mode.
 - Show annotated commits in main view. (#819)
 - Introduce reflog view. (#538)
 - Add option to start with cursor on HEAD commit. (#755)
 - Support combined diffs with more than 2 parents.
 - Improve how a toggle option value is shown on the status line. (#879)
 - Add options to filter refs output. (#694)
 - Update utf8proc to v2.4.0. (#961)

Bug fixes:

 - Fix garbled cursor line with older ncurses versions.
 - Fix diff highlighting of removed lines starting with -- and added lines
   starting with ++. (#871, #875)
 - Fix loop when displaying search result if regex matches an empty string. (#866)
 - Add synchronous command description in tigrc.
 - Fix parsing of git rev-parse output. (#884)
 - Propagate --first-parent to diff arguments. (#861)
 - Use proper type for hash table size. (#858)
 - Fix incorrect cppcheck warning about realloc() use.
 - Don't shift signed int by 31 bits.
 - Fix Vim going background after running Tig outside of a git repository. (#906)
 - make-builtin-config: use "read -r". (#912)
 - Fix segfaults with readline 8.0. (#893)
 - Reset state before closing stage view automatically.
 - Don't use a child view as previous view.
 - Force reload of VIEW_FLEX_WIDTH views only when needed.
 - Combined diff uses @@@ as hunk marker.
 - Fix memory leak induced by 'tig grep'.
 - Fix memory leak in main view.
 - Exit gracefully if refs view was defined without ref column. (#897)
 - Fix pager view not moving up when child view is open.
 - make-builtin-config: Fix unportable sed usage in read_tigrc().
 - Properly detect combined diffs. (#942)

tig-2.4.1
---------

Bug fixes:

 - Add `CURSES_CFLAGS` to `CPPFLAGS`. (#856, Linuxbrew/homebrew-core#8440)

tig-2.4.0
---------

Improvements:

 - Add 'send-child-enter' option to control interaction with child views. (#791)
 - Update make config defaults for Cygwin to ncurses6. (#792)
 - Build against netbsd-curses. (#789)
 - Change the blame view to render more like `git blame`. (#812)
 - Improve worktree and submodule support. (#459, #781, #783)
 - Support running Tig via a Git alias. (#763)
 - Use ISO-8601 letters for short relative dates. (#759, #760)
 - Change date formatting to show time zones by default. (#428, #811)
 - Use utf8proc to handle Unicode characters. (#827)

Bug fixes:

 - Fix `file(1)` argument on Linux used for resolving encodings. (#788)
 - Fix underflow in the file search. (#800, #801)
 - Fix line numbers in grep view when scrolled. (#813)
 - Pass command line args through to the stage view. (#569, #823)
 - Fix resource leak. (#780)
 - Fix various compiler warnings and pointer arithmetic. (#799, #803)
 - Workaround potential null pointer dereferences. (#824)
 - Bind to single and double quotes by using the *<SingleQuote>* and
   *<DoubleQuote>* key mappings. (#821)
 - Make Tig the process-group leader and clean child processes. (#828, #837)
 - Fix sh compatibility in `contrib/tig-pick`. (#832)
 - Fix incorrect behaviour of up and down keys in diff view when opened from
   diff preview. (#802, #835)
 - Open the stage view when maximizing a split diff view of (un)staged changes.
   (#836)
 - Use fully qualified reference name for tags when conflicting with branch
   name. (#746, #787, #849)
 - Fix resize not working after entering command. (#845) (#846)
 - Use stack allocated memory to handle `TIG_LS_REMOTE`. (#839)
 - Fix deleted file mode line remains highlighted after hovering in diff or stage view. (#851)
 - Fix `TIG_LS_REMOTE` not working with git-ls-remote(1). (#853, #854)

tig-2.3.3
---------

Bug fixes:

 - Revert "Handle \n like \r (#758)". (GH #769)
 - Fix GH #164 by catching SIGHUP.
 - Change `refs_tags` type to `size_t`.

tig-2.3.2
---------

Bug fixes:

 - Fix busy loop detection to handle large repos. (GH #164)

tig-2.3.1
---------

Improvements:

 - Restore TTY attributes. (GH #725)
 - Handle `\n` like `\r`. (GH #758)

Bug fixes:

 - Add workaround that detects busy loops when Tig loses the TTY. This may
   happen if Tig does not receive the HUP signal (e.g. when started with
   `nohup`). (GH #164)
 - Fix compatibility with ncurses-5.4 which caused copy-pasting to not work
   in the prompt. (GH #767)
 - tig(1): document correct environment variable. (GH #752)

tig-2.3.0
---------

Incompatibilities:

 - The `width` setting on the `status`, `text` and `commit-title` columns was
   never applied and has been removed. (GH #617)

Improvements:

 - Improve load performance by throttling screen updates. (GH #622, #629)
 - Speed up graph rendering. (GH #638)
 - Enable scroll optimizations for Terminal.app and iTerm2. (GH #637)
 - Improve the test suite portability to not depend on GNU sed. (GH #609, #614)
 - Make build reproducible. (https://reproducible-builds.org/) (GH #613)
 - Enable binding to more symbolic keys and keys with control modifier:
   `F13`-`F19`, `ShiftLeft`, `ShiftRight`, `ShiftDel`, `ShiftHome`, `ShiftEnd`,
   `ShiftTab`, `Ctrl-C`, `Ctrl-V`, `Ctrl-S`, and `Ctrl-@`. (GH #314, #619, #642)
 - Persist readline history to `~/.tig_history` or `$XDG_DATA_HOME/tig/history`.
   Use `history-size` to control the number of entries to save. (GH #620, #713,
   #714, #718)
 - Preload last search from persistent history. (GH #630)
 - Add `view-close-no-quit` action, unbound by default. (GH #607)
 - Add `mouse-wheel-cursor` option (off by default) when set to true causes
   wheel actions to prefer moving the cursor instead of scrolling. (GH #608)
 - Add `truncation-delimiter` option, set to `~` by default. (GH #646)
 - Add `-q` parameter to `source` for "source-if-present". (GH #612)
 - Add `:echo` prompt command to display text in the status bar. (GH #626, #636)
 - Make `diff-highlight` colors configurable. (GH #625, #633)
 - Let Ctrl-C exit Y/N dialog, menu prompts and the file finder. (GH #632, #648)
 - Hide cursor unless at textual prompt. (GH #643)
 - Expand tilde ('~') in `:script` paths. (GH #674)
 - Show single-line output of external command in status bar. (GH #200, #557,
   #678)
 - Disable the graph when `--no-merges` is passed. (GH #687) 
 - Print backtraces on segfault in debug mode.
 - Ignore script lines starting with `#` (comment). (GH #705)
 - Complete `repo:*` variables when readline is enabled. (GH #702)
 - Incorporate XTerm's `wcwidth.c` to find Unicode widths. (GH #691)

Bug fixes:

 - Fix graph display issues. (GH #419, #638)
 - Fix and improve rendering of Unicode characters. (GH #330, #621, #644, #682)
 - Handle hyphenated directory names when listing content. (GH #602)
 - Do not jump to next match when cancelling the search prompt. (GH #627)
 - Fix clearing of the status line after `Ctrl-C`. (GH #623, #649)
 - Fix handling of width on line-number and trimmed width of 1. (GH #617)
 - Set cursor position when not updating prompt contents. (GH #647)
 - Erase status line at exit time for users without altscreen-capable terminals.
   (GH #589)
 - Fix unexpected keys when restoring from suspend (`Ctrl-Z`). (GH #232)
 - contrib/vim.tigrc: Also bind G in the main as a workaround for limitations of
   the `none` action. (GH #594, #599)
 - Only override `blame-options` when commands are given and fix parsing of
   `-C`. (GH #597)
 - Fix diff name discovery to better handle prefixes.
 - Interpret button5 as wheel-down. (GH #321, #606)
 - Fix `back` / `parent` in tree view. (GH #641)
 - Fix memory corruption in `concat_argv` and file finder. (GH #634, #655)
 - Fix reading from stdin for `tig show`.
 - Document problem of outdated system-wide `tigrc` files in Homebrew. (GH #598)
 - Repaint the display when toggling `line-graphics`. (GH #527)
 - Fix custom date formatting support longer strings. (GH #522)
 - Don't segfault on ":exec" irregular args. (GH #686)
 - Fix segfault when calling htab_empty. (GH #663, #745)

tig-2.2.2
---------

Upgrade instructions:

 - The `status-untracked-dirs` option was renamed to
   `status-show-untracked-dirs` to match the new `status-show-untracked-files`
   option.

Improvements:

 - Use `diff-options` when preparing the diff in the stage view to make the diff
   state configurable. (GH #545)
 - Add 'status-show-untracked-files' option mirroring Git's
   'status.showUntrackedFiles' to toggle display of untracked files.  in the
   status view. On by default. (GH #562)
 - Update `ax_with_curses.m4` and use `pkg-config` to detect. (GH #546)
 - Add `tig-pick` script for using Tig as a commit picker. (GH #575, #580)
 - Add "smart case" option ('set ignore-case = smart-case') to ignore case when
   the search string is lower-case only. (GH #320, #579)

Bug fixes:

 - Fix author ident cache being keyed by email only. (GH #424, #526, #547)
 - Fix periodic refresh mode to properly detect ref changes. (GH #430, #591)
 - Add workaround for detecting failure to start the diff-highlight process.
 - Show diffs in the stash view when `set mailmap = true`. (GH #556)
 - Fix parsing of git-log revision arguments, such as `--exclude=...` in
   conjunction with `--all`. (GH #555)
 - Fix diff stat parsing for binary copies.
 - Fix crash when resizing terminal while search is in progress. (GH #515, #550)
 - Fix argument filtering to pass more arguments through to Git.
 - Check for termcap support in split tinfo libs. (GH #568, #585)

tig-2.2.1
---------

Tarballs should now be downloaded from GitHub. Either go to
https://github.com/jonas/tig/releases or use the following pattern:

    https://github.com/jonas/tig/releases/download/tig-VERSION/tig-VERSION.tar.gz

MD5 checksums can be found at:

    https://github.com/jonas/tig/releases/download/tig-VERSION/tig-VERSION.tar.gz.md5

Similarly, the home page is now also on GitHub at https://jonas.github.io/tig/.
A big thanks to Simon L. B. Nielsen for generously hosting Tig on nitro.dk!

Improvements:

 - Support Git's 'diff-highlight' program when `diff-highlight` is set to either
   true or the path of the script to use for post-processing.
 - Add navigation between merge commits. (GH #525)
 - Add 'A' as a binding to apply a stash without dropping it.
 - Bind 'Ctrl-D' and 'Ctrl-U' to half-page movements by default.
 - manual: Mention how to change default Up/Down behavior in diff view.

Bug fixes:

 - Reorganize checking of libraries for termcap functions.
 - Fix `:goto <id>` error message.

tig-2.2
-------

Incompatibilities:

 - Note that all user-defined commands are now executed at the repository root
   instead of whatever subdirectory Tig was started in. (GH #412)
 - Remove `cmdline-args` option to avoid problems where setting it in `~/.tigrc`
   potentially breaks other views due to its "context-sensitive" nature, where
   a `git-log` option maybe cause `git-grep` to fail. (GH #431)

Improvements:

 - Use .mailmap to show canonical name and email addresses, off by default.
   Add `set mailmap = yes` to `~/.tigrc` to enable. (GH #411)
 - Highlight search results, configurable via `search-result` color. (GH #493)
 - Wrap around when searching, configurable via `wrap-search` setting.
 - Populate `%(file)` with file names from diff stat. (GH #404)
 - `tig --merge` implies `--boundary` similar to gitk.
 - Expose repository variables to external commands, e.g. `%(repo:head)` gives the
   branch name of the current HEAD and `%(repo:cdup)` for the repo root path.
 - Add `make uninstall`. (GH #417)
 - Add ZSH completion file (based on Bash completion) (GH #433)
 - Expose the text of the currently selected line as the %(text) (GH #457)
 - Allow users to specify rev arguments to blame (GH #439)
 - Update OSX make config to find brew installed ncurses
 - Add sample git-flow keybinding (GH #421)
 - Add chocolate theme (GH #432)
 - Show stash diffs. (GH #328)
 - Make user tigrc location configurable. (GH #479)
 - Compact relative date display mode. (GH #331)
 - Add date column option controlling whether to show local date.
 - Move to parent commit in the main view. (GH #388)
 - Add `:goto <rev>` prompt command to go to a `git-rev-parse`d revision, e.g.
   `:goto some/branch` or `:goto %(commit)^2`.
 - Respect the XDG standard for configuration files. (GH #513)
 - Show tracking information in `tig status` (GH #504)
 - Resolve diff paths when `diff.noprefix` is true. (GH #487, #488)
 - Support for custom `strftime(3)` date formats, e.g.:

	set main-view-date = custom
	set main-view-date-format = "%Y-%m-%d"

Bug fixes:

 - Prevent staged rename from displaying unstaged changes (GH #472, #491)
 - Fix corrupt chunk header during staging of single lines. (GH #410)
 - Fix out of bounds read in graph-v2 module. (GH #402)
 - Add currently checked out branch to `%(branch)`. (GH #416)
 - Size diff stats correctly for split views.
 - Fix `git-worktree` support by using `git-show-ref`. (GH #437)
 - Add currently checked out branch to `%(branch)` (GH #416)
 - Fix segfault when hitting return in empty file search (GH #464)
 - Remove separator on horizontal split when switching from vertical split
 - Do not expand `--all` when parsing `%(revargs)` (GH #442, #462)
 - Fix exit when the main view is reloaded due to option toggling. (GH #470)
 - Expand all whitespace and control characters to spaces. (GH #485)
 - Restore ability to unbind a default keybinding with `none`. (GH #483)
 - Fix blob view to honor the `wrap-lines` setting.

tig-2.1.1
---------

Improvements:

 - Add support for key combos. (GH #67)
 - See `contrib/vim.tigrc` for Vim-like keybindings. (GH #273, #351)
 - Add GitHub inspired file finder to search for and open any file. (GH #342)
 - Add `search` keymap for navigating file finder search results.

Bug fixes:

 - Fix display of multiple references per commit. (GH #390, #391)
 - Sync the prompt's cursor position with readline's internal position. (GH #396)
 - Keep unstaged changes view open after an staging command. (GH #399)

tig-2.1
-------

Improvements:

 - Improve C99 compliance so Tig compiles with the native compilers on
   Solaris (SunStudio cc) and AIX (xlc). (GH #380)
 - Add move-half-page-up and move-half-page-down actions. (GH #323)
 - Preserve the cursor position when changing the diff context.
 - Show 'Unstaged changes' above 'Staged changes' in the main view. (GH #383)
 - Add `:exec <flags><args...>` prompt command to execute commands.
 - Add shorthand for changing the view settings of a single column,
   eg. `set main-view-author = short`. (GH #318)
 - Show better diff context info in the stage view.
 - Add `%(lineno)` state variable. (GH #304)
 - Use hash table to speed up refs lookup. (GH #350)
 - Show the file path in the blob view when available.
 - Use `set commit-order = default` to use Git's default commit order, even when
   the commit graph is enabled. The option will turn off automatic enabling of
   `--topo-order` when the graph is shown in the main view. (GH #310, #324)
 - Speed up the diff view in large repos by loading git-describe info after the
   diff content has been read. (GH #324)
 - Add the old graph rendering as an option. (GH #310, #324)
 - Add `main-options` setting for specifying default main view options.
   Example: `set main-options = --max-count=1000`. (GH #368)
 - See `contrib/large-repo.tigrc` for settings that will help to speed up Tig in
   large repos. (GH #368)
 - Add `:save-options <file>` prompt command to save config to file. (GH #315)

Bug fixes:

 - Update manual to reflect default keybinding changes. (GH #325)
 - Fix graph support for `--first-parent`. (GH #326)
 - Fix off-by-one error when opening editor from the grep view.
 - Fix status on-branch information.
 - Fix main view to handle the case when git-log doesn't find any commits.
 - Fix corner case when parsing diff chunk when lines information is missing.
 - Ensure main view changes commits are shown right before the current HEAD.
 - Fix rendering of boundary commits.
 - Fix compilation with GNU Make 3.80 by removing `$(abspath)`. (GH #362)
 - Fix config parsing to support shell-like quoting in user-defined command,
   e.g. `bind generic <Ctrl-f> :!git log -G"%(prompt Prompt: )"` (GH #371)
 - Make diff meta information colors more consistent with Git. (GH #375)
 - Fix segfault when updating changes in a maximized stage view opened via the
   main view. (GH #376)
 - Handle line number configs where the interval is not specified. (GH #378)
 - Fix display of error messages during startup. (GH #385)
 - Show untracked files outside the current directory like git-status. (GH #230)

tig-2.0.3
---------

Improvements:

 - Add `:save-display <file>` prompt command to save the current display.
 - Add `:script <file>` prompt command for scripting the Tig UI.
 - Add test framework and convert existing tests to use it.
 - Add command-line option for starting in refs view: `tig refs`. (GH #309)
 - Make blame commit ID colors stable across reloads. (GH #303)
 - Increase blame ID and graph rendering color palette to 14 colors.
 - New setting 'split-view-width' controls the width for vertical splits. It
   takes the width of the right-most view either as a number or a percentage.
 - Expose settings holding command line argument lists: `file-args`, `rev-args`,
   and `cmdline-args`. They are mainly intended for testing purposes but also
   allows to change the filtering arguments dynamically. (GH #306)
 - Add `log-options` setting for specifying default log view options.
   Example: `set log-options = --pretty=fuller`.
 - Use option specific view flags to reload view after `:set` commands.

Bug fixes:

 - Refresh the current view when returning from an external command and
   `refresh-mode=after-command`. (GH #289)
 - Fix readline completion.
 - Fix '/' to `find-next` when readline support is enabled. (GH #302)
 - Fix readline prompt to correctly handle UTF-8 characters.
 - Add warnings for more obsolete actions and colors.
 - Fix passing of commit IDS via stdin to the main view.
 - Fix commit title overflow drawing for multibyte text. (GH #307)
 - Fix installation directory permissions.
 - Handle binary files matches reported by git-grep.
 - Toggling of "args"-typed options without any arguments will clear the current
   arguments. Example: `:toggle blame-options`.
 - Detect custom `pretty.format` settings that break the log view and fallback
   to use the `medium` format. (GH #225)
 - Fix invocation of git-diff for the blame view's line tracking. (GH #316)
 - Fix blame completion of directory names. (GH #317)
 - Fix display of conflicts in the main view when 'show-changes' is enabled.
 - Fix off-by-one error when displaying line numbers in the grep view.
 - When showing the commit graph ensure that either topo, date or author-date
   commit order is used. (Debian #757692) (GH #238)

tig-2.0.2
---------

Improvements:

 - Use git-status for diffing the index.
 - Group toggle options together in the help view.

Bug fixes:

 - Fix refs, main and grep loading when 'gui.encoding' is set. (GH #287)
 - Ignore 'gui.encoding' and 'i18n.commitencoding' when set to 'UTF-8'.
 - Add work-around for missing strndup() on Mac OS X v10.6. (GH #286)
 - Fix spurious abbreviation of author names. (GH #288)
 - Don't show empty action groups in the help view.

tig-2.0.1
---------

Bug fixes:

 - Fix compilation in watch.c.
 - Fix parsing of key bindings mapped to '^' and '<'. (GH #280, #282)

tig-2.0
-------

Note to packagers:

 - Add `.adoc` extension to AsciiDoc files so they show correctly on GitHub.
   This includes `README`, `INSTALL`, and `NEWS` and files in `doc/` directory.
 - `BUGS` file has been merged into `README.adoc`.
 - Default keybindings have been moved to a system-level `tigrc` file, which is
   installed to ${sysconfdir} by default. The content of the `tigrc` file is
   included inside the binary as a fall-back. Pass `NO_BUILTIN_TIGRC=y` to not
   include the system `tigrc` content and reduce the size of the binary.
 - The example `contrib/tigrc` file (made obsolete by `tigrc`) has been removed.
 - Source files have been moved to `src` and `include` and `tig.c` was split up.
 - Build output is less verbose by default; use `make V=1` for old output.

Incompatibilities:

 - In preparation for key combo support, key mappings for symbolic keys (e.g.
   `Up` and `Down`) must now start with `<` and end with `>`, e.g. `<Up>` and
   `<Down>`. Furthermore, escape key combos must now use `<Esc>key` instead of
   `^[key`, and control key mappings must now use `<Ctrl-key>` instead of
   `^key`.
 - Only use 'diff-options' for the diff view and introduce '%(cmdlineargs)' to
   hold non-file and non-revision flags passed on the command line. Affects all
   user-defined commands that expect '%(diffargs)' to hold both 'diff-options'
   arguments and those passed on the command line. (GH #228)
 - Remove built-in keybinding for `git gc`. Add the following line to `~/.tigrc`
   to restore it: `bind generic G ?git gc`.
 - To support view specific colors, '.' can no longer be used interchangeably
   with '-' and '_' in settings names and in particular color names.
 - Replace 'stage-next' action with prompt command using a predefined search
   (see below) and add binding (`@` by default) to also work in the diff view.
 - Most view display options must now be set via the new `*-view` options in
   tigrc. Existing options are no longer recognized, but a warning is shown.
 - Remap default bindings to have more consistent convention: use lower-case
   keys primarily for view switching and non-destructive actions, use upper-case
   keys for view-specific actions including user-defined commands. To preserve
   old default key bindings see `contrib/bindings-v1.x.tigrc`. (GH #257)

Improvements:

 - Add mouse support: scroll view, click line to move cursor, double click line
   (or click again) to "Enter" cursor line, e.g. open commit diff. Disabled by
   default, since it makes text selection less intuitive. If you enable this
   remember to hold down Shift (or Option on Mac) when selecting text.
 - Rewrite and improve the rendering of the commit graph. (GH #144, #46)
 - Add completion and history support to the prompt via readline. (GH #185)
 - Options can be configured and toggled individually for each view. Use the new
   view settings to configure the order and display options for each view
   columns. See system tigrc and tigrc(5) for examples. (GH #89, #222)
 - Add grep view as a front-end to git-grep(1): `tig grep -p strchr`. From
   within Tig, the key for switching or grepping is bound to 'g' by default.
 - Rename 'branch' view to 'refs' view and show tags. (GH #134)
 - Add main view pager mode that reads git-log's '--pretty=raw' data
   from stdin, e.g. `git reflog --pretty=raw | tig --pretty=raw`.
 - Add support for `--graph` and highlight diff stats in the log view.
 - Add default command bindings: `!` to delete branch, `!` to drop stash.
 - Add 'stage-split-chunk' action for splitting chunks in the stage view.
   Bound to '\' by default. (GH #107)
 - Add 'back' action bound to '<' by default, which will return the blame view
   to the previous revision and line after moving e.g. to the parent. (GH #124)
 - Auto-refresh views based on watched repository changes. Configure by setting
   `refresh-mode` to 'manual', 'auto', 'after-command', or 'periodic'. (GH #190)
 - All default settings are in well-documented system `tigrc`.
 - Add `:toggle` prompt command to manipulate options using keybindings. For
   example: `bind diff D :toggle diff-options --patience --notes`. (GH #69)
 - Add a new "auto" value for the 'vertical-split' option to let Tig choose the
   split orientation (this is the new default behavior). Can be toggled.
 - Make it possible to toggle the display of files in untracked directories.
 - Allow Tig to be started with no default configuration by specifying an
   alternative system `tigrc` file, e.g.: `TIGRC_SYSTEM=~/.tigrc.safe tig`. Set
   `TIGRC_SYSTEM` to the empty string to use built-in configuration instead of
 - Key mappings can contain UTF-8 multibyte unicode keys.
 - Warn about conflicting keybindings using Ctrl, e.g. `<Ctrl-f>` and
   `<Ctrl-F>`. (GH #218)
 - Extend key bindings for prompt commands (ie. `bind <keymap> <key> :<prompt>`)
   to support predefined searches, eg.: `bind stage 2 :?^@@`.
 - Git color mappings can be configured in tigrc.
 - More informative configuration error messages.
 - Make reference label formatting configurable, for example:
   `set reference-format = (branch) <tags> remote`. (GH #201)
 - Adjust author width and other view columns automatically. (GH #49)
 - Support view specific colors: `color stage.diff-add yellow default`.
 - Copy `-S`, `-G` and `--grep=` pattern to search buffer so 'find-next' and
   'find-prev' work as expected.
 - Optionally specify custom prompt for `%(prompt)` in shell commands, e.g.
   `bind main B ?git checkout -b "%(prompt Enter new branch name: )"`.
 - Add `%(remote)` and `%(tag)` symbols to complement `%(branch)`.
 - User-defined commands can now be prefixed with any of the supported flags,
   e.g. `?git checkout -b %(branch)`.
 - Open editor at line number for combined diffs e.g. diffs of unmerged files.
 - Add build configuration for Cygwin (OS name: CYGWIN_NT-6.1). (GH #92)
 - Document the Git commands supported by the pager mode.  (GH #1)
   system `tigrc` configuration. (GH #235)

Bug fixes:

 - Fix stash diff display when reloading the stash view after a deleting.
 - Set the commit reference when opening the blame view from the blob view.
 - Correctly identify and highlight the remote branch tracked by HEAD.
 - Pass --no-color after user defined arguments to ensure that colors do not
   break the output parsing. (GH #191)
 - Close stdin when pager mode is not supported.
 - Show newly created branches in the main view. (GH #196)
 - File with 0 changes breaks diffstat highlighting (GH #215)
 - Update %(branch) variable in the main view. (GH #223)
 - Disable graph rendering when either of `--reverse`, `-S`, `-G`, and `--grep`
   are passed to the main view. (GH #127)
 - Only refresh views that support it.
 - Fix author and date annotation of renamed entries in the tree view.
 - Fix use of unsafe methods in the signal handler. (GH #245)
 - Fix rendering in non-UTF8 terminals.
 - Fix stage-update-line by rewriting the diff chunk containing the line instead
   of using `--unidiff-zero` and a diff context of zero. (GH #130)
 - Fix status-update to work for untracked directories. (GH #236)
 - Don't pass log parameters given on the command line to the diff view.

tig-1.2.1
---------

Incompatibilities:

 - Move manual and man pages to doc/ directory and rename AsciiDoc files
   to have .asciidoc as the extension to make them render on GitHub.

Improvements:

 - Show blob sizes in the tree view either as bytes or using binary unit
   prefixes. Example: `set show-file-size = units`. (GH #163)
 - Reduce main view memory usage and startup time, especially when revision
   graph rendering is disabled. (GH #160)

Bug fixes:

 - Fix submodule-related setup to check for non-zero return value from
   setenv(). (GH #188)

tig-1.2
-------

 - Tig now has its own tag on Stack Overflow, where users are invited to
   ask questions: https://stackoverflow.com/questions/tagged/tig

Improvements:

 - Prompt commands can be bound to keys. For example:
   `bind diff F :set diff-options = --full-diff`. (GH #69, #116)
 - Add a diff-options setting for specifying default diff options.
   Example: `set diff-options = --patience`. (GH #116)
 - Options in diff-options and blame-options matching Tig browsing state
   variables are replaced.
 - Show diff stats as wide as the terminal. (GH #109)
 - Show line numbers in the branch view. (GH #135)
 - Add toggles for showing author email or email user names. (GH #115)
 - Open editor at the selected line by prefixing the file argument with
   `+<lineno>`. Tested in vi, Vim, Emacs, Nano, Gedit, Geany. Disable
   by adding `set editor-line-number = no` to ~/.tigrc. (GH #118, #119)
 - Add toggle-files to control whether to show full commit diff or only
   the diff concerning the currently selected file, e.g. for blame.
 - Optionally highlight exceeding characters in long commit titles.
   The default title max width is 50 characters. Customize using:
   `set title-overflow = 50` (GH #125)
 - Add +ESC key bindings. Example: `bind generic ^[v move-page-up` (GH #120)
 - Create temporary files in TMPDIR, TEMP, or TMP before defaulting to /tmp.
 - Reenable `tig log` as a subcommand. (GH #146)
 - Enable tilde expansion in ~/.tigrc "source" commands. (GH #168)
 - Introduce the stash view, bound to the 'y' keybinding. (GH #169, #174)

Bug fixes:

 - Fix blame and status to work in directories starting with a dot. (GH #172)
 - Reload current branch name when reloading the status view. (GH #93)
 - Fix compile errors on old Solaris. (GH #97)
 - Reload HEAD info when reloading the stage view. (GH #104, #93)
 - Fix disappearing branch labels after external commands. (GH #148)
 - Fix diff view display for staged/unstaged changes when using 'd'.
 - Fix display of status messages when toggling view options. (GH #111)
 - Fix illegal memory access. (GH #98)
 - Fix display of all branches label in repos with short branch names.
 - Fix rendering glitch for branch names.
 - Do not apply diff styling to untracked files in the stage view. (GH #153)
 - Fix tree indentation for entries containing combining characters. (GH #170)
 - Ignore unrepresentable characters when transliterating text for rendering.
 - Transliterate text to output encoding before trimming it to avoid
   misalignment. (GH #86)
 - Introduce a more natural context-sensitive log display. (GH #155)

tig-1.1
-------

Incompatibilities:

 - Disable diff move/copy detection by default, boosting diff
   performance on larger projects. Use git config 'diff.renames' option
   (Git-wide) to set your preferred behavior. Environment variable
   TIG_DIFF_OPTS can be used to restore the old behavior.
 - Fix manual keybinding for stage-single-line. (GH #108)
 - Values set for author-width and filename-width will result in widths
   one character bigger than previously.

Improvements:

 - Typing a text in the prompt will be interpreted as a Tig command.
   Prefixing the command with a '!' will execute this system command in
   an external pager. Entering a single key will execute the
   corresponding key binding.
 - Basic support for wrapping long line in pager, diff, and stage views.
   Enable using: `set wrap-lines = yes`. (GH #2)
 - User-defined commands prefixed with a '?' means prompt before
   execution. Example: `bind main B !?git rebase -i %(commit)`.
 - User-defined commands prefixed with a '<' means exit after execution.
   Example: `bind main C !<git commit`. (GH #66)
 - User-defined commands are executed unquoted to support shell commands.
   Example: `bind generic I !@sh -c "echo -n %(commit) | xclip -selection c"`.
   (GH #65)
 - Configure case-insensitive searches using: `set ignore-case = yes`.
 - Add "deleted mode" line type for better diff coloring.
 - Open editor when requesting edit action from within a file diff.
 - Update AX_WITH_CURSES to build under Cygwin.
 - Improve tigrc(5) documentation. (Debian #682766)
 - Allow to build on Mac OS 10.7 without the configure script. (GH #25)
 - Add option to split the view vertically instead of horizontally.
   Example: `set vertical-split = yes'. (GH #76)
 - Add 'show-id' and 'id-width' options to configure the display of
   commit IDs in the main view and ID width in the blame view. (GH #77)
 - Allow to override Git based encoding to UTF-8 by setting
   'i18n.commitencoding' or 'gui.encoding'.
 - Improve autobuild support to track generated files and work with
   autoreconf 2.61.
 - Commit IDs are read from stdin when --stdin is given; works for main
   and diff view, e.g. `tig --no-walk --stdin < cherry-picks.txt`.
 - Add option to disable focusing of the child view when it's opened.
   Disable using: `set focus-child = no`. (GH #83)
 - Allow to open blob related with added content in a diff. (GH #91)

Bug fixes:

 - Fix commit graph regression when a path spec is specified. (GH #53)
 - Main view: only show staged/unstaged changes for the current branch.
 - Support submodules created with current version of git. (GH #54)
 - Fix diff status message for file diffs with no content changes.
 - Fix parent blaming when Tig is launched in subdirectory. (GH #70)
 - Do not show deleted branch when reloading the branch view.

tig-1.0
-------

The master repository is git://github.com/jonas/tig.git, and the old
master repository (http://jonas.nitro.dk/tig/tig.git) will be retired.

Improvements:

 - Use git-log(1)s default commit ordering. The old behavior can be
   restored by adding `set commit-order = topo` to ~/.tigrc.
 - Support staging of single lines. Bound to '1' default. (GH #21)
 - Use +<lineno> to open the initial view at an arbitrary line. (GH #20)
 - Add show-notes ~/.tigrc option. Notes are displayed by default.
 - Support jumping to specific SHAs in the main view.
 - Decorate replaced commits.
 - Display line numbers in main view.
 - Colorize binary diff stats. (GH #17)
 - Custom colorization of lines matching a string prefix (GH #16).
   Example configuration: color "Reported-by:" green default
 - Use Git's color settings for the main, status and diff views.
   Put `set read-git-colors = no` in ~/.tigrc to disable.
 - Handle editor options with multiple arguments. (GH #12)
 - Show filename when running tig blame with copy detection. (GH #19)
 - Use 'source <path>' command to load additional files from ~/.tigrc
 - User-defined commands prefixed with '@' are run with no console
   output, e.g.

   	bind generic 3 !@rm sys$command

 - Make display of space changes togglable in the diff and stage view.
   Bound to 'W' by default.
 - Use per-file encoding specified in gitattributes(5) for blobs and
   unstaged files.
 - Obsolete commit-encoding option and pass --encoding=UTF-8 to revision
   commands.
 - Main view: show uncommitted changes as staged/unstaged commits.
   Can be disabled by putting `set show-changes = no` in ~/.tigrc.
 - Add %(prompt) external command variable, which will prompt for the
   argument value.
 - Log information about Git commands when the TIG_TRACE environment
   variable is set. Example: `TIG_TRACE=/tmp/tig.log tig`
 - Branch view: Show the title of the last commit.
 - Increase the author auto-abbreviation threshold to 10. (GH #49)
 - For old commits show number of years in relative dates. (GH #50)

Bug fixes:

 - Fix navigation behavior when going from branch to main view. (GH #38)
 - Fix segfault when sorting the tree view by author name.
 - Fix diff stat navigation for unmodified files with stat changes.
 - Show branches/refs which names are a substring of the current branch.
 - Stage view: fix off-by-one error when jumping to a file in a diff
   with only one file.
 - Fix diff-header colorization. (GH #15)

tig-0.18
--------

Incompatibilities:

 - Remove support for the deprecated TIG_{MAIN,DIFF,LOG,TREE,BLOB}_CMD
   environment variables.

Improvements:

 - Pressing enter on diff stat file lines will jump to file's diff.
 - Naïvely color blame IDs to distinguish lines.
 - Document palette color options used for revision graph and blame IDs.
 - Add support for blaming diff lines.
 - Add diff-context option and bindings to increase the diff context in
   the diff and stage view.
 - (GH-6) Make blame configurable via extra options passed from the command
   line and blame-options setting from ~/.tigrc. For example:

   	set blame-options = -C -C -C

Bug fixes:

 - Expand browsing state variables for prompt. (LP #694780, Debian #635546)
 - Fix segfault when sorting the branch view by author.
 - Expand %(directory) to . for the root directory. (GH-3)
 - Accept 'utf-8' for the line-graphics option as indicated in the docs.
 - Use erasechar() to check for the correct backspace character.

tig-0.17
--------

Improvements:

 - Start rewrite of the revision graph renderer. Three modes are
   supported UTF-8, ncurses line graphics, and ASCII. Also, enable
   revision graph rendering by default.

Bug fixes:

 - Fix ncurses 5.8 issue by passing non-zero column size to newwin().
 - Fix opening of diffs when browsing branches.

tig-0.16.2
----------

Bug fixes:

 - Fix regression causing empty tree view.
 - Fix set_tabsize() compile error for older versions of ncurses.

tig-0.16.1
----------

Improvements:

 - Add scroll-first-col action to jump to the first column. Bound to '|'
   by default.
 - Add 'status-untracked-dirs' option to ignore unknown directories
   contents in the status view. On by default.

Bug fixes:

 - Fix 'tig show <commit>' to show the provided commit.
 - Fix problem with empty diff views when file specs were passed on the
   command line.
 - Fix segfault when starting Tig in pager mode.

tig-0.16
--------

Incompatibilities:

 - Encode everything internally as UTF-8. This can affect performance,
   but should in general improve handling of character lengths etc.
   Also, to properly handle UTF-8 environments use ncurses with wide
   character support.
 - The use of TIG_{MAIN,DIFF,LOG,TREE,BLOB}_CMD environment variables
   has been deprecated. To allow configuration of the diff view,
   TIG_DIFF_OPTS can be used.

Improvements:

 - Plug several memory leaks.
 - Command line arguments are split into diff, revision, and file
   arguments and made available as %(diffargs), %(revargs), and
   %(fileargs). Diff view will limit diffs using %(fileargs).
 - Status view: update the file variable when a line is selected so
   %(file) works as expected.
 - Branch view: add %(branch) symbol providing access to the selected
   branch.
 - Branch view: add entry to browse all branches (uses git-log's --all
   flag).
 - Abbreviation of author names can now be configured and toggled.
 - Mark detached heads with [HEAD].
 - Add support for displaying dates in local time.

Bug fixes:

 - Status view: fix usage from sub directories, which was broken by the
   changes made to support blame view from sub directories.
 - Fix text expansion to not truncate long lines
 - Fix parsing of boolean show-date values.
 - Fix relative date.
 - Fix unbind to behave as if the keybinding was never defined.
 - Fix unbind to also cover built-in run requests.
 - Fix parsing of unknown keymap names.
 - Blame view: fix parent blame to detect renames. It uses "previous"
   line info from the blame porcelain output added in Git version 1.6.3.

tig-0.15
--------

Incompatibilities:

 - Setting the cursor color no longer automatically sets the text to
   bold. The old 'lazy' behavior was a bug.
 - Remove check for git-repo-config, which was officially deprecated in
   Git version 1.5.4. The configure script no longer depends on Git
   being installed.

Improvements:

 - Provide the manual as a man page named tigmanual(7).
 - Add ability to toggle between showing shorter dates (without time
   info) and relative dates. Use 'D' to toggle between date formats.
 - Show the active (instead of the default) keybindings in the help
   view. Furthermore, honor the keymap when suggesting actions in the
   help messages.
 - Add branch view for choosing which branch to display in the main
   view. Bound to 'H' by default.
 - Tree view: show entry to parent directory ('..') when running from
   subdirectory.
 - Tree view: sort entries by name, date or author. Toggling is bound to
   'i' by default, with 'I' controlling whether or not to sort in
   ascending order.
 - Make height of the lower view in a split view configurable by setting
   the 'split-view-height' variable to a number or a percentage.
   Defaults to 2/3 of the total view height.
 - Allow multiple text attributes for color commands:

	color cursor white blue underline bold

Bug fixes:

 - Blame view: fix loading of blame data when opened from the tree view
   and CWD is not the repo root. (Debian bug 540766)
 - Tree view: fix searching.

tig-0.14.1
----------

Improvements:

 - Status view: improve "on branch" information inspired by the prompt
   code in Git's bash completion script.
 - Colors for 256-capable terminals can be specified as colorN.
 - Entering a number in the prompt will jump to that line number.
 - Handle core.worktree by setting GIT_DIR and GIT_WORK_TREE.
 - Make behavior of horizontal scrolling configurable by setting the
   'horizontal-scroll' variable to a number or a percentage. Defaults to
   scrolling 50% of the view width.

Bug fixes:

 - Status view: show error when failing to open a file.
 - Status view: report failures to update a file.
 - Blame view: fix problem with uninitialized variable.
 - Blame view: use line number information when loading blame for
   specific commit.
 - Fix handling of quoted strings in the config file.
 - Fix horizontal scrolling glitches.

tig-0.14
--------

Incompatibilities:

 - The screen-resize action has been deprecated. It had no real use for
   users and was never meant to be exposed.
 - The "tree-parent" action was renamed to "parent". Warnings will be
   emitted for transition.
 - Remove parsing of deprecated option -S and subcommands log and diff.
 - The "author" color replaces "main-author". Setting the latter will
   now set the "author" color.

Improvements:

 - Horizontal scrolling. Bound to Left/Right by default.
 - Read tigrc(5) options from Git configuration files using the syntax:

	[tig] show-rev-graph = true
	[tig "color"] cursor = yellow red bold
	[tig "bind"] generic = P parent

 - Tree view: avoid flickering when updating.
 - Tree view: annotate entries with commit information.
 - Tree & blob view: open any blob in an editor.
 - Stage & main view: restore view position when reloading.
 - Blame view: load blame for parent commit. For merge commits the parent
   is queried. Bound to ',' by default via the existing "parent" action.
 - Abbreviate author names to initials when the width of the author column
   is below 6 characters.

Bug fixes:

 - Tree view: fix memory corruption bug when updating.
 - Tree view: improve handling of empty trees.
 - Status view: fix reverting of unmerged files.
 - Fix regression for non-UTF-8 locales corrupting the view data.
 - Fix regression parsing multiple spaces in ~/.tigrc.

tig-0.13
--------

Incompatibilities:

 - Commands from the environment (e.g. TIG_MAIN_CMD) will no longer have
   access to shell features, such as subshells and variable expansion.
   The easiest way to upgrade your configuration is to put such commands
   in a script file or as a Git alias.

Improvements:

 - Display repository references in the sorted order: tags, heads,
   tracked remotes, remotes.
 - Add bash completion for blame.
 - Tree view: edit files of the current branch.
 - Run requests: new identifiers %(directory), %(file), and %(ref)
 - Improve responsiveness and view loading speed by using select(2).

Bug fixes:

 - Separate blame revision and file argument by "--" to avoid problems.
 - Main view: fix redrawing of the last commit wrt. the revision graph.
 - Fix waiting for input after executing a run request in pager mode.
 - Status & stage view: refuse to open directories and deleted files.
 - Tree view: show error when requesting blame for all non-file entries.
 - Do not draw loading views, which are not displayed.
 - Fix launching of mergetool from a subdirectory.

tig-0.12.1
----------

Improvements:

 - Status view: revert uncommitted diff chunks and unstaged files with
   changes. Bound to '!' by default.
 - Main view: use --topo-order also when rev-list arguments are given on
   the command line.
 - Log view: support for refreshing.

Bug fixes:

 - Status view: use ls-files' --exclude-standard so user specific ignore
   rules are effective. The option was added in Git version 1.5.4.
 - Stage view: fix assertion failure triggered when updating while
   status view is not displayed.
 - Help view: avoid confusion by showing "(no key)" instead of "'?'" for
   unbound requests.
 - Reload repository references when refreshing the main (and log) view.
 - Do not maximize views when refreshing.

tig-0.12
--------

Improvements:

 - F5 also refreshes the current view.
 - Allow line graphics to be disabled with new line-graphics option.
 - Main view: also include the reference names when searching.
 - Main view: support for refreshing.
 - Main view: disable boundary commits by default. Use --boundary when
   they should be shown. (Debian bug 498628)
 - Stage view: add stage-next action to jump to next diff chunk that can
   be staged. By default bound to '@'.
 - Configure: check for the ncurses header files.
 - Add author-width option to customize the width of the author column.
   For example, put the following in ~/.tigrc: set author-width = 10

Bug fixes:

 - Fix regression when staging all diff chunks in a section.
 - Bind the maximize view action to 'O'; it conflicted with the
   keybinding to launch the merge tool in the status view.
 - Fix problem with $(cmd) usage in shell code. Some shells (jsh)
   installed as /bin/sh does not support it.
 - Do not show incomplete boundary commits when --no-walk is used.
 - Documentation: Rename gitlink macro to support AsciiDoc 8.2.3.
 - Ignore pipe reads with errno "Success" reported after a signals,
   for example when refreshing doing background loading.

tig-0.11
--------

Incompatibilities:

 - Remove parsing of deprecated options: -g, -l, -d.
 - The first seen '--' will stop option parsing and is passed to Git
   instead of breaking out of Tig's option parsing.

New features:

 - Blame view; bound to 'B' by default, reachable from the command line
   and the tree, status, and stage views.
 - Blame/main view: allow display of date, author, and references to be
   toggled on/off. Bound to 'D', 'A', and 'F' respectively.
 - Add action to maximize the current view.

Improvements:

 - Show the current branch in the status view.
 - Show local/light-weight tags.

Bug fixes:

 - Fix regressions for the pager mode.
 - Fix refreshing of the index with working directory info.

tig-0.10.1
----------

Improvements:

 - Status view: detect renamed files and show them with 'R'.
 - Status view: refresh the index to avoid "empty diffs".
 - Diff view: make diff headers more verbose to include e.g. committer.
 - Configure: check for the ncursesw library.

Bug fixes:

 - Fix UTF-8 handling for tag names and commit messages.
 - Fix the check for git-config(1) in configure to handle the case when
   Git has been installed using a libexecdir which is not in the path.
 - Fix replacing of SYSCONFDIR when installing from released tarballs.

tig-0.10
---------

Incompatibilities:

 - Deprecate most Tig specific command line options to make Tig more
   compatible with gitk. The deprecated options are: -g, -l, -d, and -S.
   Use of any of them will result in a warning being printed to stderr.
   Instead of '-S', use the new 'status' subcommand.
 - Make man page building depend on DocBook XSL version >= 1.72.0.
 - Install man pages in $(prefix)/share/man.
 - Implement the cherry pick action (bound to 'C') using new support for
   running external commands. This obsoletes the TIG_CHEERY_PICK
   environment variable

New features:

 - Add support for binding keys to external commands. To bind '.' to
   running git-commit(1), add the line: "bind generic . !git commit" to
   your ~/.tigrc. Each command can have replacement string such as
   %(commit), %(head), and %(blob), which are substituted before the
   command is run.
 - Add system-wide configuration file defaulting to $(prefix)/etc/tigrc.
 - Add the environment variables TIGRC_USER and TIGRC_SYSTEM to change
   user and system-wide configuration files, respectively.

Improvements:

 - Main view: color the revision graph.
 - Main view: show boundary commits; they are marked with '^' in the
   revision graph.
 - Tree view: add tree-parent action to jump to view of the parent tree.
   Bound to ',' by default.
 - Allow the default terminal colors to be overwritten. To use black
   text on white, add the line "color default white black" to your
   ~/.tigrc.
 - Misc. documentation improvements.

Bug fixes:

 - Use git-diff-index(1) and git-diff-files(1) instead of git-diff(1) to
   avoid running external diff drivers.
 - Use --no-color when calling git-log(1).
 - Fix crash when opening mergetool for lines that are not unmerged.

tig-0.9.1
---------

Incompatibilities:

 - Make the clean rule to never remove generated documentation files.
   Use the distclean rule for accomplishing this.

New features:

 - Add support for cherry-picking commits in the main view to the
   current branch. Bound to 'C' by default.

Improvements:

 - Add support for launching git-mergetool(1) from the status view.
   Bound to 'M' by default.
 - Add support for refreshing/reloading the status view
 - Detect working trees and disable the status view when it is missing.

Bug fixes:

 - Fix iconv() checking in configure.
 - Fix editor invocation to make paths relative to the project root.
 - Fix out-of-range current line when reloading the status view.
 - Include autoconf files in the tarball generated by `make dist`.

tig-0.9
-------

New features:

 - Add bash completion script for Tig (contrib/tig-completion.bash).
 - Add optional autoconf-based build infrastructure.
 - Add stage view for showing changes in the working tree and add
   support for staging individual diff chunks for commit.

Improvements:

 - Status view: allow all files in a section to be staged for commit.
 - Status view: Add support for opening files in an editor. Bound to 'e'
   by default.
 - Tree view: use a stack for remembering the lines for parent tree.

/* vim: set tw=80: */


================================================
FILE: README.adoc
================================================
Tig: text-mode interface for Git
================================
:docext: adoc

image:https://github.com/jonas/tig/workflows/Linux/badge.svg[Linux CI,link=https://github.com/jonas/tig/actions?query=workflow%3ALinux]
image:https://github.com/jonas/tig/workflows/macOS/badge.svg[macOS CI,link=https://github.com/jonas/tig/actions?query=workflow%3AmacOS]
image:https://ci.appveyor.com/api/projects/status/jxt1uf52o7r0a8r7/branch/master?svg=true[AppVeyor Build,link=https://ci.appveyor.com/project/fonseca/tig]

What is Tig?
------------
Tig is an ncurses-based text-mode interface for git. It functions mainly
as a Git repository browser, but can also assist in staging changes for
commit at chunk level and act as a pager for output from various Git
commands.

Resources
---------

 - Homepage:	https://github.com/jonas/tig[]
 - Manual:	https://www.mankier.com/7/tigmanual[]
 - Tarballs:	https://github.com/jonas/tig/releases[]
 - Q&A:		https://stackoverflow.com/questions/tagged/tig[]

Bugs and Feature Requests
-------------------------
Bugs and feature requests can be reported using the
https://github.com/jonas/tig/issues[issue tracker] or by mail to the
https://lore.kernel.org/git/[Git mailing list]. Ensure that the word
"tig" is in the subject. For other Tig related questions please use
Stack Overflow: https://stackoverflow.com/questions/tagged/tig[].

If you are sending a bug report, please include the following information:

- What Tig and ncurses versions are you using?
  (`tig -v`)
- What system do you have?
  (`uname -a`, `lsb_release -a`)
- What Git version are you using?
  (`git -v`)

Installation and News
---------------------

Information on how to build and install Tig are found in
link:INSTALL.{docext}[the installation instructions].

News about releases and latest features and bug fixes are found in
link:NEWS.{docext}[the release notes].


================================================
FILE: appveyor.yml
================================================
environment:
  matrix:
  - TARGET: cygwin64
    ARCH: x86_64

install:
 - appveyor DownloadFile https://cygwin.com/setup-%ARCH%.exe -FileName C:\%TARGET%\setup-%ARCH%.exe
 - cmd: C:\%TARGET%\setup-%ARCH%.exe -qgnNdO -l C:\%TARGET%\var\cache\setup -R C:\%TARGET% -s https://cygwin.mirror.constant.com -P git -P gcc-code -P make -P automake -P libiconv-devel -P libncurses-devel
 - cmd: SET PATH=C:\%TARGET%\bin;%PATH%
 - git config --global --add safe.directory /cygdrive/c/projects/tig

build_script:
 - make configure
 - sh configure
 - make

test_script:
 - make test


================================================
FILE: autogen.sh
================================================
#!/bin/sh

export WARNINGS="all"
set -e

# Ideally, we could just do this:
#
#${AUTORECONF:-autoreconf} -v -I tools
#
# Unfortunately, Autoconf 2.61's autoreconf(1) (found in Mac OS X 10.5
# Leopard) neglects to pass the -I on to aclocal(1), which is
# precisely where we need it!  So we do basically what it would have
# done.

run () {
    test "${V}" = 1 && echo $0: running: "$@"
    "$@"
}

run ${ACLOCAL:-aclocal} -I tools
run ${AUTOCONF:-autoconf} --include=tools
run ${AUTOHEADER:-autoheader} --include=tools


================================================
FILE: book.json
================================================
{
  "gitbook": "3.2.x",
  "title": "Tig - Text-mode interface for Git",
  "structure": {
     "readme": "README.adoc",
     "summary": "book.md"
  },
  "links": {
    "sharing": {
      "twitter": false,
      "facebook": false,
      "google": false,
      "all": false
    }
  }
}


================================================
FILE: book.md
================================================
# Summary

 - [Installation](INSTALL.adoc)
 - [Release notes](NEWS.adoc)
 - [tig(1)](doc/tig.1.adoc)
 - [tigrc(5)](doc/tigrc.5.adoc)
 - [Manual](doc/manual.adoc)
 - [Screenshots](https://www.flickr.com/photos/jonasfonseca/albums/72157614470764617)
 - Developer Documentation 
   - [Testing](test/README.adoc)


================================================
FILE: compat/ansidecl.h
================================================
/* Compiler compatibility macros
   Copyright (C) 1991-2025 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */

/* For ease of writing code which uses GCC extensions but needs to be
   portable to other compilers, we provide the GCC_VERSION macro that
   simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
   wrappers around __attribute__.  Also, __extension__ will be #defined
   to nothing if it doesn't work.  See below.  */

#ifndef	_ANSIDECL_H
#define _ANSIDECL_H	1

#ifdef __cplusplus
extern "C" {
#endif

/* Every source file includes this file,
   so they will all get the switch for lint.  */
/* LINTLIBRARY */

/* Using MACRO(x,y) in cpp #if conditionals does not work with some
   older preprocessors.  Thus we can't define something like this:

#define HAVE_GCC_VERSION(MAJOR, MINOR) \
  (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))

and then test "#if HAVE_GCC_VERSION(2,7)".

So instead we use the macro below and test it against specific values.  */

/* This macro simplifies testing whether we are using gcc, and if it
   is of a particular minimum version. (Both major & minor numbers are
   significant.)  This macro will evaluate to 0 if we are not using
   gcc at all.  */
#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif /* GCC_VERSION */

/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
   it too, but it's not in C89.  */
#undef inline
#if (!defined(__cplusplus) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__))
/* it's a keyword */
#else
# if GCC_VERSION >= 2007
#  define inline __inline__   /* __inline__ prevents -pedantic warnings */
# else
#  define inline  /* nothing */
# endif
#endif

/* Define macros for some gcc attributes.  This permits us to use the
   macros freely, and know that they will come into play for the
   version of gcc in which they are supported.  */

#if (GCC_VERSION < 2007)
# define __attribute__(x)
#endif

/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
#ifndef ATTRIBUTE_MALLOC
# if (GCC_VERSION >= 2096)
#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# else
#  define ATTRIBUTE_MALLOC
# endif /* GNUC >= 2.96 */
#endif /* ATTRIBUTE_MALLOC */

/* Attributes on labels were valid as of gcc 2.93 and g++ 4.5.  For
   g++ an attribute on a label must be followed by a semicolon.  */
#ifndef ATTRIBUTE_UNUSED_LABEL
# ifndef __cplusplus
#  if GCC_VERSION >= 2093
#   define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
#  else
#   define ATTRIBUTE_UNUSED_LABEL
#  endif
# else
#  if GCC_VERSION >= 4005
#   define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED ;
#  else
#   define ATTRIBUTE_UNUSED_LABEL
#  endif
# endif
#endif

/* Similarly to ARG_UNUSED below.  Prior to GCC 3.4, the C++ frontend
   couldn't parse attributes placed after the identifier name, and now
   the entire compiler is built with C++.  */
#ifndef ATTRIBUTE_UNUSED
#if GCC_VERSION >= 3004
#  define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif
#endif /* ATTRIBUTE_UNUSED */

/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
   identifier name.  */
#if ! defined(__cplusplus) || (GCC_VERSION >= 3004)
# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED
#else /* !__cplusplus || GNUC >= 3.4 */
# define ARG_UNUSED(NAME) NAME
#endif /* !__cplusplus || GNUC >= 3.4 */

#ifndef ATTRIBUTE_NORETURN
#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
#endif /* ATTRIBUTE_NORETURN */

/* Attribute `nonnull' was valid as of gcc 3.3.  */
#ifndef ATTRIBUTE_NONNULL
# if (GCC_VERSION >= 3003)
#  define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
# else
#  define ATTRIBUTE_NONNULL(m)
# endif /* GNUC >= 3.3 */
#endif /* ATTRIBUTE_NONNULL */

/* Attribute `returns_nonnull' was valid as of gcc 4.9.  */
#ifndef ATTRIBUTE_RETURNS_NONNULL
# if (GCC_VERSION >= 4009)
#  define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
# else
#  define ATTRIBUTE_RETURNS_NONNULL
# endif /* GNUC >= 4.9 */
#endif /* ATTRIBUTE_RETURNS_NONNULL */

/* Attribute `pure' was valid as of gcc 3.0.  */
#ifndef ATTRIBUTE_PURE
# if (GCC_VERSION >= 3000)
#  define ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
#  define ATTRIBUTE_PURE
# endif /* GNUC >= 3.0 */
#endif /* ATTRIBUTE_PURE */

/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
   This was the case for the `printf' format attribute by itself
   before GCC 3.3, but as of 3.3 we need to add the `nonnull'
   attribute to retain this behavior.  */
#ifndef ATTRIBUTE_PRINTF
#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
#endif /* ATTRIBUTE_PRINTF */

/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on
   a function pointer.  Format attributes were allowed on function
   pointers as of gcc 3.1.  */
#ifndef ATTRIBUTE_FPTR_PRINTF
# if (GCC_VERSION >= 3001)
#  define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n)
# else
#  define ATTRIBUTE_FPTR_PRINTF(m, n)
# endif /* GNUC >= 3.1 */
# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2)
# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3)
# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4)
# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5)
# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6)
#endif /* ATTRIBUTE_FPTR_PRINTF */

/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL.  A
   NULL format specifier was allowed as of gcc 3.3.  */
#ifndef ATTRIBUTE_NULL_PRINTF
# if (GCC_VERSION >= 3003)
#  define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
# else
#  define ATTRIBUTE_NULL_PRINTF(m, n)
# endif /* GNUC >= 3.3 */
# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
#endif /* ATTRIBUTE_NULL_PRINTF */

/* Attribute `sentinel' was valid as of gcc 3.5.  */
#ifndef ATTRIBUTE_SENTINEL
# if (GCC_VERSION >= 3005)
#  define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
# else
#  define ATTRIBUTE_SENTINEL
# endif /* GNUC >= 3.5 */
#endif /* ATTRIBUTE_SENTINEL */


#ifndef ATTRIBUTE_ALIGNED_ALIGNOF
# if (GCC_VERSION >= 3000)
#  define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m))))
# else
#  define ATTRIBUTE_ALIGNED_ALIGNOF(m)
# endif /* GNUC >= 3.0 */
#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */

/* Useful for structures whose layout must match some binary specification
   regardless of the alignment and padding qualities of the compiler.  */
#ifndef ATTRIBUTE_PACKED
# define ATTRIBUTE_PACKED __attribute__ ((packed))
#endif

/* Attribute `hot' and `cold' was valid as of gcc 4.3.  */
#ifndef ATTRIBUTE_COLD
# if (GCC_VERSION >= 4003)
#  define ATTRIBUTE_COLD __attribute__ ((__cold__))
# else
#  define ATTRIBUTE_COLD
# endif /* GNUC >= 4.3 */
#endif /* ATTRIBUTE_COLD */
#ifndef ATTRIBUTE_HOT
# if (GCC_VERSION >= 4003)
#  define ATTRIBUTE_HOT __attribute__ ((__hot__))
# else
#  define ATTRIBUTE_HOT
# endif /* GNUC >= 4.3 */
#endif /* ATTRIBUTE_HOT */

/* Attribute 'no_sanitize_undefined' was valid as of gcc 4.9.  */
#ifndef ATTRIBUTE_NO_SANITIZE_UNDEFINED
# if (GCC_VERSION >= 4009)
#  define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined))
# else
#  define ATTRIBUTE_NO_SANITIZE_UNDEFINED
# endif /* GNUC >= 4.9 */
#endif /* ATTRIBUTE_NO_SANITIZE_UNDEFINED */

/* Attribute 'nonstring' was valid as of gcc 8.  */
#ifndef ATTRIBUTE_NONSTRING
# if GCC_VERSION >= 8000
#  define ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__))
# else
#  define ATTRIBUTE_NONSTRING
# endif
#endif

/* Attribute `alloc_size' was valid as of gcc 4.3.  */
#ifndef ATTRIBUTE_RESULT_SIZE_1
# if (GCC_VERSION >= 4003)
#  define ATTRIBUTE_RESULT_SIZE_1 __attribute__ ((alloc_size (1)))
# else
#  define ATTRIBUTE_RESULT_SIZE_1
#endif
#endif

#ifndef ATTRIBUTE_RESULT_SIZE_2
# if (GCC_VERSION >= 4003)
#  define ATTRIBUTE_RESULT_SIZE_2 __attribute__ ((alloc_size (2)))
# else
#  define ATTRIBUTE_RESULT_SIZE_2
#endif
#endif

#ifndef ATTRIBUTE_RESULT_SIZE_1_2
# if (GCC_VERSION >= 4003)
#  define ATTRIBUTE_RESULT_SIZE_1_2 __attribute__ ((alloc_size (1, 2)))
# else
#  define ATTRIBUTE_RESULT_SIZE_1_2
#endif
#endif

/* Attribute `warn_unused_result' was valid as of gcc 3.3.  */
#ifndef ATTRIBUTE_WARN_UNUSED_RESULT
# if GCC_VERSION >= 3003
#  define ATTRIBUTE_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
#  define ATTRIBUTE_WARN_UNUSED_RESULT
# endif
#endif

/* We use __extension__ in some places to suppress -pedantic warnings
   about GCC extensions.  This feature didn't work properly before
   gcc 2.8.  */
#if GCC_VERSION < 2008
#define __extension__
#endif

/* This is used to declare a const variable which should be visible
   outside of the current compilation unit.  Use it as
     EXPORTED_CONST int i = 1;
   This is because the semantics of const are different in C and C++.
   "extern const" is permitted in C but it looks strange, and gcc
   warns about it when -Wc++-compat is not used.  */
#ifdef __cplusplus
#define EXPORTED_CONST extern const
#else
#define EXPORTED_CONST const
#endif

/* Be conservative and only use enum bitfields with C++ or GCC.
   FIXME: provide a complete autoconf test for buggy enum bitfields.  */

#ifdef __cplusplus
#define ENUM_BITFIELD(TYPE) enum TYPE
#elif (GCC_VERSION > 2000)
#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
#else
#define ENUM_BITFIELD(TYPE) unsigned int
#endif

#if defined(__cplusplus) && __cpp_constexpr >= 200704
#define CONSTEXPR constexpr
#else
#define CONSTEXPR
#endif

/* A macro to disable the copy constructor and assignment operator.
   When building with C++11 and above, the methods are explicitly
   deleted, causing a compile-time error if something tries to copy.
   For C++03, this just declares the methods, causing a link-time
   error if the methods end up called (assuming you don't
   define them).  For C++03, for best results, place the macro
   under the private: access specifier, like this,

   class name_lookup
   {
     private:
       DISABLE_COPY_AND_ASSIGN (name_lookup);
   };

   so that most attempts at copy are caught at compile-time.  */

#if defined(__cplusplus) && __cplusplus >= 201103
#define DISABLE_COPY_AND_ASSIGN(TYPE)		\
  TYPE (const TYPE&) = delete;			\
  void operator= (const TYPE &) = delete
  #else
#define DISABLE_COPY_AND_ASSIGN(TYPE)		\
  TYPE (const TYPE&);				\
  void operator= (const TYPE &)
#endif /* __cplusplus >= 201103 */

#ifdef __cplusplus
}
#endif

#endif	/* ansidecl.h	*/


================================================
FILE: compat/compat.h
================================================
/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>
 * Copyright (c) 2013 Drew Northup <n1xim.email@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef TIG_COMPAT_H
#define TIG_COMPAT_H

#ifndef HAVE_CONFIG_H
/*
 * Enable inclusion of header files checked by configure.
 */
#define HAVE_STDINT_H
#define HAVE_STDLIB_H
#define HAVE_STRING_H
#define HAVE_SYS_TIME_H
#define HAVE_UNISTD_H
#define HAVE_WORDEXP_H
#endif

/*
 * XXX: Compatibility code must never be enabled by default.
 */

#ifdef NO_MKSTEMPS
#define mkstemps compat_mkstemps
int compat_mkstemps(char *pattern, int suffix_len);
#endif

#ifdef NO_SETENV
#define setenv compat_setenv
int compat_setenv(const char *name, const char *value, int replace);
#endif

#ifdef NO_STRNDUP
#include <stddef.h>
#define strndup compat_strndup
char *compat_strndup(const char *s, size_t n);
#endif

#ifdef NO_WORDEXP
#define wordexp compat_wordexp
#define wordfree compat_wordfree
#define WRDE_NOCMD 4
typedef struct
{
	char **we_wordv;
} wordexp_t;
int compat_wordexp (const char *words, wordexp_t *pwordexp, int flags);
void compat_wordfree (wordexp_t *pwordexp);
#else
#include <wordexp.h>
#endif

#endif

/* vim: set ts=8 sw=8 noexpandtab: */


================================================
FILE: compat/hashtab.c
================================================
/* An expandable hash tables datatype.
   Copyright (C) 1999-2025 Free Software Foundation, Inc.
   Contributed by Vladimir Makarov (vmakarov@cygnus.com).

This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */

/* This package implements basic hash table functionality.  It is possible
   to search for an entry, create an entry and destroy an entry.

   Elements in the table are generic pointers.

   The size of the table is not fixed; if the occupancy of the table
   grows too high the hash table will be expanded.

   The abstract data implementation is based on generalized Algorithm D
   from Knuth's book "The art of computer programming".  Hash table is
   expanded by creation of new hash table and transferring elements from
   the old table to the new table. */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "compat.h"

#include <sys/types.h>

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif

#include <stdio.h>

#if 0
#include "libiberty.h"
#endif
#include "ansidecl.h"
#include "hashtab.h"

#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif

static unsigned int higher_prime_index (unsigned long);
static hashval_t htab_mod_1 (hashval_t, hashval_t, hashval_t, int);
static hashval_t htab_mod (hashval_t, htab_t);
static hashval_t htab_mod_m2 (hashval_t, htab_t);
static hashval_t hash_pointer (const void *);
static int eq_pointer (const void *, const void *);
static int htab_expand (htab_t);
static void **find_empty_slot_for_expand (htab_t, hashval_t);

/* At some point, we could make these be NULL, and modify the
   hash-table routines to handle NULL specially; that would avoid
   function-call overhead for the common case of hashing pointers.  */
htab_hash htab_hash_pointer = hash_pointer;
htab_eq htab_eq_pointer = eq_pointer;

/* Table of primes and multiplicative inverses.

   Note that these are not minimally reduced inverses.  Unlike when generating
   code to divide by a constant, we want to be able to use the same algorithm
   all the time.  All of these inverses (are implied to) have bit 32 set.

   For the record, here's the function that computed the table; it's a
   vastly simplified version of the function of the same name from gcc.  */

#if 0
unsigned int
ceil_log2 (unsigned int x)
{
  int i;
  for (i = 31; i >= 0 ; --i)
    if (x > (1u << i))
      return i+1;
  abort ();
}

unsigned int
choose_multiplier (unsigned int d, unsigned int *mlp, unsigned char *shiftp)
{
  unsigned long long mhigh;
  double nx;
  int lgup, post_shift;
  int pow, pow2;
  int n = 32, precision = 32;

  lgup = ceil_log2 (d);
  pow = n + lgup;
  pow2 = n + lgup - precision;

  nx = ldexp (1.0, pow) + ldexp (1.0, pow2);
  mhigh = nx / d;

  *shiftp = lgup - 1;
  *mlp = mhigh;
  return mhigh >> 32;
}
#endif

struct prime_ent
{
  hashval_t prime;
  hashval_t inv;
  hashval_t inv_m2;	/* inverse of prime-2 */
  hashval_t shift;
};

static struct prime_ent const prime_tab[] = {
  {          7, 0x24924925, 0x9999999b, 2 },
  {         13, 0x3b13b13c, 0x745d1747, 3 },
  {         31, 0x08421085, 0x1a7b9612, 4 },
  {         61, 0x0c9714fc, 0x15b1e5f8, 5 },
  {        127, 0x02040811, 0x0624dd30, 6 },
  {        251, 0x05197f7e, 0x073260a5, 7 },
  {        509, 0x01824366, 0x02864fc8, 8 },
  {       1021, 0x00c0906d, 0x014191f7, 9 },
  {       2039, 0x0121456f, 0x0161e69e, 10 },
  {       4093, 0x00300902, 0x00501908, 11 },
  {       8191, 0x00080041, 0x00180241, 12 },
  {      16381, 0x000c0091, 0x00140191, 13 },
  {      32749, 0x002605a5, 0x002a06e6, 14 },
  {      65521, 0x000f00e2, 0x00110122, 15 },
  {     131071, 0x00008001, 0x00018003, 16 },
  {     262139, 0x00014002, 0x0001c004, 17 },
  {     524287, 0x00002001, 0x00006001, 18 },
  {    1048573, 0x00003001, 0x00005001, 19 },
  {    2097143, 0x00004801, 0x00005801, 20 },
  {    4194301, 0x00000c01, 0x00001401, 21 },
  {    8388593, 0x00001e01, 0x00002201, 22 },
  {   16777213, 0x00000301, 0x00000501, 23 },
  {   33554393, 0x00001381, 0x00001481, 24 },
  {   67108859, 0x00000141, 0x000001c1, 25 },
  {  134217689, 0x000004e1, 0x00000521, 26 },
  {  268435399, 0x00000391, 0x000003b1, 27 },
  {  536870909, 0x00000019, 0x00000029, 28 },
  { 1073741789, 0x0000008d, 0x00000095, 29 },
  { 2147483647, 0x00000003, 0x00000007, 30 },
  /* Avoid "decimal constant so large it is unsigned" for 4294967291.  */
  { 0xfffffffb, 0x00000006, 0x00000008, 31 }
};

/* The following function returns an index into the above table of the
   nearest prime number which is greater than N, and near a power of two. */

static unsigned int
higher_prime_index (unsigned long n)
{
  unsigned int low = 0;
  unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);

  while (low != high)
    {
      unsigned int mid = low + (high - low) / 2;
      if (n > prime_tab[mid].prime)
	low = mid + 1;
      else
	high = mid;
    }

  /* If we've run out of primes, abort.  */
  if (n > prime_tab[low].prime)
    {
      fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
      abort ();
    }

  return low;
}

/* Returns non-zero if P1 and P2 are equal.  */

static int
eq_pointer (const void *p1, const void *p2)
{
  return p1 == p2;
}


/* The parens around the function names in the next two definitions
   are essential in order to prevent macro expansions of the name.
   The bodies, however, are expanded as expected, so they are not
   recursive definitions.  */

/* Return the current size of given hash table.  */

#define htab_size(htab)  ((htab)->size)

size_t
(htab_size) (htab_t htab)
{
  return htab_size (htab);
}

/* Return the current number of elements in given hash table. */

#define htab_elements(htab)  ((htab)->n_elements - (htab)->n_deleted)

size_t
(htab_elements) (htab_t htab)
{
  return htab_elements (htab);
}

/* Return X % Y.  */

static inline hashval_t
htab_mod_1 (hashval_t x, hashval_t y, hashval_t inv, int shift)
{
  /* The multiplicative inverses computed above are for 32-bit types, and
     requires that we be able to compute a highpart multiply.  */
#ifdef UNSIGNED_64BIT_TYPE
  __extension__ typedef UNSIGNED_64BIT_TYPE ull;
  if (sizeof (hashval_t) * CHAR_BIT <= 32)
    {
      hashval_t t1, t2, t3, t4, q, r;

      t1 = ((ull)x * inv) >> 32;
      t2 = x - t1;
      t3 = t2 >> 1;
      t4 = t1 + t3;
      q  = t4 >> shift;
      r  = x - (q * y);

      return r;
    }
#endif

  /* Otherwise just use the native division routines.  */
  return x % y;
}

/* Compute the primary hash for HASH given HTAB's current size.  */

static inline hashval_t
htab_mod (hashval_t hash, htab_t htab)
{
  const struct prime_ent *p = &prime_tab[htab->size_prime_index];
  return htab_mod_1 (hash, p->prime, p->inv, p->shift);
}

/* Compute the secondary hash for HASH given HTAB's current size.  */

static inline hashval_t
htab_mod_m2 (hashval_t hash, htab_t htab)
{
  const struct prime_ent *p = &prime_tab[htab->size_prime_index];
  return 1 + htab_mod_1 (hash, p->prime - 2, p->inv_m2, p->shift);
}

/* This function creates table with length slightly longer than given
   source length.  Created hash table is initiated as empty (all the
   hash table entries are HTAB_EMPTY_ENTRY).  The function returns the
   created hash table, or NULL if memory allocation fails.  */

htab_t
htab_create_alloc (size_t size, htab_hash hash_f, htab_eq eq_f,
                   htab_del del_f, htab_alloc alloc_f, htab_free free_f)
{
  return htab_create_typed_alloc (size, hash_f, eq_f, del_f, alloc_f, alloc_f,
				  free_f);
}

/* As above, but uses the variants of ALLOC_F and FREE_F which accept
   an extra argument.  */

htab_t
htab_create_alloc_ex (size_t size, htab_hash hash_f, htab_eq eq_f,
		      htab_del del_f, void *alloc_arg,
		      htab_alloc_with_arg alloc_f,
		      htab_free_with_arg free_f)
{
  htab_t result;
  unsigned int size_prime_index;

  size_prime_index = higher_prime_index (size);
  size = prime_tab[size_prime_index].prime;

  result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
  if (result == NULL)
    return NULL;
  result->entries = (void **) (*alloc_f) (alloc_arg, size, sizeof (void *));
  if (result->entries == NULL)
    {
      if (free_f != NULL)
	(*free_f) (alloc_arg, result);
      return NULL;
    }
  result->size = size;
  result->size_prime_index = size_prime_index;
  result->hash_f = hash_f;
  result->eq_f = eq_f;
  result->del_f = del_f;
  result->alloc_arg = alloc_arg;
  result->alloc_with_arg_f = alloc_f;
  result->free_with_arg_f = free_f;
  return result;
}

/*

@deftypefn Supplemental htab_t htab_create_typed_alloc (size_t @var{size}, @
htab_hash @var{hash_f}, htab_eq @var{eq_f}, htab_del @var{del_f}, @
htab_alloc @var{alloc_tab_f}, htab_alloc @var{alloc_f}, @
htab_free @var{free_f})

This function creates a hash table that uses two different allocators
@var{alloc_tab_f} and @var{alloc_f} to use for allocating the table itself
and its entries respectively.  This is useful when variables of different
types need to be allocated with different allocators.

The created hash table is slightly larger than @var{size} and it is
initially empty (all the hash table entries are @code{HTAB_EMPTY_ENTRY}).
The function returns the created hash table, or @code{NULL} if memory
allocation fails.

@end deftypefn

*/

htab_t
htab_create_typed_alloc (size_t size, htab_hash hash_f, htab_eq eq_f,
			 htab_del del_f, htab_alloc alloc_tab_f,
			 htab_alloc alloc_f, htab_free free_f)
{
  htab_t result;
  unsigned int size_prime_index;

  size_prime_index = higher_prime_index (size);
  size = prime_tab[size_prime_index].prime;

  result = (htab_t) (*alloc_tab_f) (1, sizeof (struct htab));
  if (result == NULL)
    return NULL;
  result->entries = (void **) (*alloc_f) (size, sizeof (void *));
  if (result->entries == NULL)
    {
      if (free_f != NULL)
	(*free_f) (result);
      return NULL;
    }
  result->size = size;
  result->size_prime_index = size_prime_index;
  result->hash_f = hash_f;
  result->eq_f = eq_f;
  result->del_f = del_f;
  result->alloc_f = alloc_f;
  result->free_f = free_f;
  return result;
}


/* Update the function pointers and allocation parameter in the htab_t.  */

void
htab_set_functions_ex (htab_t htab, htab_hash hash_f, htab_eq eq_f,
                       htab_del del_f, void *alloc_arg,
                       htab_alloc_with_arg alloc_f, htab_free_with_arg free_f)
{
  htab->hash_f = hash_f;
  htab->eq_f = eq_f;
  htab->del_f = del_f;
  htab->alloc_arg = alloc_arg;
  htab->alloc_with_arg_f = alloc_f;
  htab->free_with_arg_f = free_f;
}

/* These functions exist solely for backward compatibility.  */

#undef htab_create
#if 0
htab_t
htab_create (size_t size, htab_hash hash_f, htab_eq eq_f, htab_del del_f)
{
  return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
}

htab_t
htab_try_create (size_t size, htab_hash hash_f, htab_eq eq_f, htab_del del_f)
{
  return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
}
#endif

/* This function frees all memory allocated for given hash table.
   Naturally the hash table must already exist. */

void
htab_delete (htab_t htab)
{
  size_t size = htab_size (htab);
  void **entries = htab->entries;
  int i;

  if (htab->del_f)
    for (i = size - 1; i >= 0; i--)
      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
	(*htab->del_f) (entries[i]);

  if (htab->free_f != NULL)
    {
      (*htab->free_f) (entries);
      (*htab->free_f) (htab);
    }
  else if (htab->free_with_arg_f != NULL)
    {
      (*htab->free_with_arg_f) (htab->alloc_arg, entries);
      (*htab->free_with_arg_f) (htab->alloc_arg, htab);
    }
}

/* This function clears all entries in the given hash table.  */

void
htab_empty (htab_t htab)
{
  size_t size = htab_size (htab);
  void **entries = htab->entries;
  int i;

  if (htab->del_f)
    for (i = size - 1; i >= 0; i--)
      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
	(*htab->del_f) (entries[i]);

  /* Instead of clearing megabyte, downsize the table.  */
  if (size > 1024*1024 / sizeof (void *))
    {
      int nindex = higher_prime_index (1024 / sizeof (void *));
      int nsize = prime_tab[nindex].prime;

      if (htab->free_f != NULL)
	(*htab->free_f) (htab->entries);
      else if (htab->free_with_arg_f != NULL)
	(*htab->free_with_arg_f) (htab->alloc_arg, htab->entries);
      if (htab->alloc_with_arg_f != NULL)
	htab->entries = (void **) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
							     sizeof (void *));
      else
	htab->entries = (void **) (*htab->alloc_f) (nsize, sizeof (void *));
     htab->size = nsize;
     htab->size_prime_index = nindex;
    }
  else
    memset (entries, 0, size * sizeof (void *));
  htab->n_deleted = 0;
  htab->n_elements = 0;
}

/* Similar to htab_find_slot, but without several unwanted side effects:
    - Does not call htab->eq_f when it finds an existing entry.
    - Does not change the count of elements/searches/collisions in the
      hash table.
   This function also assumes there are no deleted entries in the table.
   HASH is the hash value for the element to be inserted.  */

static void **
find_empty_slot_for_expand (htab_t htab, hashval_t hash)
{
  hashval_t index = htab_mod (hash, htab);
  size_t size = htab_size (htab);
  void **slot = htab->entries + index;
  hashval_t hash2;

  if (*slot == HTAB_EMPTY_ENTRY)
    return slot;
  else if (*slot == HTAB_DELETED_ENTRY)
    abort ();

  hash2 = htab_mod_m2 (hash, htab);
  for (;;)
    {
      index += hash2;
      if (index >= size)
	index -= size;

      slot = htab->entries + index;
      if (*slot == HTAB_EMPTY_ENTRY)
	return slot;
      else if (*slot == HTAB_DELETED_ENTRY)
	abort ();
    }
}

/* The following function changes size of memory allocated for the
   entries and repeatedly inserts the table elements.  The occupancy
   of the table after the call will be about 50%.  Naturally the hash
   table must already exist.  Remember also that the place of the
   table entries is changed.  If memory allocation failures are allowed,
   this function will return zero, indicating that the table could not be
   expanded.  If all goes well, it will return a non-zero value.  */

static int
htab_expand (htab_t htab)
{
  void **oentries;
  void **olimit;
  void **p;
  void **nentries;
  size_t nsize, osize, elts;
  unsigned int oindex, nindex;

  oentries = htab->entries;
  oindex = htab->size_prime_index;
  osize = htab->size;
  olimit = oentries + osize;
  elts = htab_elements (htab);

  /* Resize only when table after removal of unused elements is either
     too full or too empty.  */
  if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
    {
      nindex = higher_prime_index (elts * 2);
      nsize = prime_tab[nindex].prime;
    }
  else
    {
      nindex = oindex;
      nsize = osize;
    }

  if (htab->alloc_with_arg_f != NULL)
    nentries = (void **) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
						    sizeof (void *));
  else
    nentries = (void **) (*htab->alloc_f) (nsize, sizeof (void *));
  if (nentries == NULL)
    return 0;
  htab->entries = nentries;
  htab->size = nsize;
  htab->size_prime_index = nindex;
  htab->n_elements -= htab->n_deleted;
  htab->n_deleted = 0;

  p = oentries;
  do
    {
      void *x = *p;

      if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
	{
	  void **q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));

	  *q = x;
	}

      p++;
    }
  while (p < olimit);

  if (htab->free_f != NULL)
    (*htab->free_f) (oentries);
  else if (htab->free_with_arg_f != NULL)
    (*htab->free_with_arg_f) (htab->alloc_arg, oentries);
  return 1;
}

/* This function searches for a hash table entry equal to the given
   element.  It cannot be used to insert or delete an element.  */

void *
htab_find_with_hash (htab_t htab, const void *element, hashval_t hash)
{
  hashval_t index, hash2;
  size_t size;
  void *entry;

  htab->searches++;
  size = htab_size (htab);
  index = htab_mod (hash, htab);

  entry = htab->entries[index];
  if (entry == HTAB_EMPTY_ENTRY
      || (entry != HTAB_DELETED_ENTRY && (*htab->eq_f) (entry, element)))
    return entry;

  hash2 = htab_mod_m2 (hash, htab);
  for (;;)
    {
      htab->collisions++;
      index += hash2;
      if (index >= size)
	index -= size;

      entry = htab->entries[index];
      if (entry == HTAB_EMPTY_ENTRY
	  || (entry != HTAB_DELETED_ENTRY && (*htab->eq_f) (entry, element)))
	return entry;
    }
}

/* Like htab_find_slot_with_hash, but compute the hash value from the
   element.  */

void *
htab_find (htab_t htab, const void *element)
{
  return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
}

/* This function searches for a hash table slot containing an entry
   equal to the given element.  To delete an entry, call this with
   insert=NO_INSERT, then call htab_clear_slot on the slot returned
   (possibly after doing some checks).  To insert an entry, call this
   with insert=INSERT, then write the value you want into the returned
   slot.  When inserting an entry, NULL may be returned if memory
   allocation fails.  */

void **
htab_find_slot_with_hash (htab_t htab, const void *element,
                          hashval_t hash, enum insert_option insert)
{
  void **first_deleted_slot;
  hashval_t index, hash2;
  size_t size;
  void *entry;

  size = htab_size (htab);
  if (insert == INSERT && size * 3 <= htab->n_elements * 4)
    {
      if (htab_expand (htab) == 0)
	return NULL;
      size = htab_size (htab);
    }

  index = htab_mod (hash, htab);

  htab->searches++;
  first_deleted_slot = NULL;

  entry = htab->entries[index];
  if (entry == HTAB_EMPTY_ENTRY)
    goto empty_entry;
  else if (entry == HTAB_DELETED_ENTRY)
    first_deleted_slot = &htab->entries[index];
  else if ((*htab->eq_f) (entry, element))
    return &htab->entries[index];

  hash2 = htab_mod_m2 (hash, htab);
  for (;;)
    {
      htab->collisions++;
      index += hash2;
      if (index >= size)
	index -= size;

      entry = htab->entries[index];
      if (entry == HTAB_EMPTY_ENTRY)
	goto empty_entry;
      else if (entry == HTAB_DELETED_ENTRY)
	{
	  if (!first_deleted_slot)
	    first_deleted_slot = &htab->entries[index];
	}
      else if ((*htab->eq_f) (entry, element))
	return &htab->entries[index];
    }

 empty_entry:
  if (insert == NO_INSERT)
    return NULL;

  if (first_deleted_slot)
    {
      htab->n_deleted--;
      *first_deleted_slot = HTAB_EMPTY_ENTRY;
      return first_deleted_slot;
    }

  htab->n_elements++;
  return &htab->entries[index];
}

/* Like htab_find_slot_with_hash, but compute the hash value from the
   element.  */

void **
htab_find_slot (htab_t htab, const void *element, enum insert_option insert)
{
  return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
				   insert);
}

/* This function deletes an element with the given value from hash
   table (the hash is computed from the element).  If there is no matching
   element in the hash table, this function does nothing.  */

void
htab_remove_elt (htab_t htab, const void *element)
{
  htab_remove_elt_with_hash (htab, element, (*htab->hash_f) (element));
}


/* This function deletes an element with the given value from hash
   table.  If there is no matching element in the hash table, this
   function does nothing.  */

void
htab_remove_elt_with_hash (htab_t htab, const void *element, hashval_t hash)
{
  void **slot;

  slot = htab_find_slot_with_hash (htab, element, hash, NO_INSERT);
  if (slot == NULL)
    return;

  if (htab->del_f)
    (*htab->del_f) (*slot);

  *slot = HTAB_DELETED_ENTRY;
  htab->n_deleted++;
}

/* This function clears a specified slot in a hash table.  It is
   useful when you've already done the lookup and don't want to do it
   again.  */

void
htab_clear_slot (htab_t htab, void **slot)
{
  if (slot < htab->entries || slot >= htab->entries + htab_size (htab)
      || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
    abort ();

  if (htab->del_f)
    (*htab->del_f) (*slot);

  *slot = HTAB_DELETED_ENTRY;
  htab->n_deleted++;
}

/* This function scans over the entire hash table calling
   CALLBACK for each live entry.  If CALLBACK returns false,
   the iteration stops.  INFO is passed as CALLBACK's second
   argument.  */

void
htab_traverse_noresize (htab_t htab, htab_trav callback, void *info)
{
  void **slot;
  void **limit;

  slot = htab->entries;
  limit = slot + htab_size (htab);

  do
    {
      void *x = *slot;

      if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
	if (!(*callback) (slot, info))
	  break;
    }
  while (++slot < limit);
}

/* Like htab_traverse_noresize, but does resize the table when it is
   too empty to improve effectivity of subsequent calls.  */

void
htab_traverse (htab_t htab, htab_trav callback, void *info)
{
  size_t size = htab_size (htab);
  if (htab_elements (htab) * 8 < size && size > 32)
    htab_expand (htab);

  htab_traverse_noresize (htab, callback, info);
}

/* Return the fraction of fixed collisions during all work with given
   hash table. */

double
htab_collisions (htab_t htab)
{
  if (htab->searches == 0)
    return 0.0;

  return (double) htab->collisions / (double) htab->searches;
}

/* Hash P as a null-terminated string.

   Copied from gcc/hashtable.c.  Zack had the following to say with respect
   to applicability, though note that unlike hashtable.c, this hash table
   implementation re-hashes rather than chain buckets.

   http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01021.html
   From: Zack Weinberg <zackw@panix.com>
   Date: Fri, 17 Aug 2001 02:15:56 -0400

   I got it by extracting all the identifiers from all the source code
   I had lying around in mid-1999, and testing many recurrences of
   the form "H_n = H_{n-1} * K + c_n * L + M" where K, L, M were either
   prime numbers or the appropriate identity.  This was the best one.
   I don't remember exactly what constituted "best", except I was
   looking at bucket-length distributions mostly.

   So it should be very good at hashing identifiers, but might not be
   as good at arbitrary strings.

   I'll add that it thoroughly trounces the hash functions recommended
   for this use at http://burtleburtle.net/bob/hash/index.html, both
   on speed and bucket distribution.  I haven't tried it against the
   function they just started using for Perl's hashes.  */

hashval_t
htab_hash_string (const void *p)
{
  const unsigned char *str = (const unsigned char *) p;
  hashval_t r = 0;
  unsigned char c;

  while ((c = *str++) != 0)
    r = r * 67 + c - 113;

  return r;
}

/* An equality function for null-terminated strings.  */
int
htab_eq_string (const void *a, const void *b)
{
  return strcmp ((const char *) a, (const char *) b) == 0;
}

/* DERIVED FROM:
--------------------------------------------------------------------
lookup2.c, by Bob Jenkins, December 1996, Public Domain.
hash(), hash2(), hash3, and mix() are externally useful functions.
Routines to test the hash are included if SELF_TEST is defined.
You can use this free for any purpose.  It has no warranty.
--------------------------------------------------------------------
*/

/*
--------------------------------------------------------------------
mix -- mix 3 32-bit values reversibly.
For every delta with one or two bit set, and the deltas of all three
  high bits or all three low bits, whether the original value of a,b,c
  is almost all zero or is uniformly distributed,
* If mix() is run forward or backward, at least 32 bits in a,b,c
  have at least 1/4 probability of changing.
* If mix() is run forward, every bit of c will change between 1/3 and
  2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
mix() was built out of 36 single-cycle latency instructions in a
  structure that could supported 2x parallelism, like so:
      a -= b;
      a -= c; x = (c>>13);
      b -= c; a ^= x;
      b -= a; x = (a<<8);
      c -= a; b ^= x;
      c -= b; x = (b>>13);
      ...
  Unfortunately, superscalar Pentiums and Sparcs can't take advantage
  of that parallelism.  They've also turned some of those single-cycle
  latency instructions into multi-cycle latency instructions.  Still,
  this is the fastest good hash I could find.  There were about 2^^68
  to choose from.  I only looked at a billion or so.
--------------------------------------------------------------------
*/
/* same, but slower, works on systems that might have 8 byte hashval_t's */
#define mix(a,b,c) \
{ \
  a -= b; a -= c; a ^= (c>>13); \
  b -= c; b -= a; b ^= (a<< 8); \
  c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
  a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
  b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
  c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
  a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
  b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
  c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
}

/*
--------------------------------------------------------------------
hash() -- hash a variable-length key into a 32-bit value
  k     : the key (the unaligned variable-length array of bytes)
  len   : the length of the key, counting by bytes
  level : can be any 4-byte value
Returns a 32-bit value.  Every bit of the key affects every bit of
the return value.  Every 1-bit and 2-bit delta achieves avalanche.
About 36+6len instructions.

The best hash table sizes are powers of 2.  There is no need to do
mod a prime (mod is sooo slow!).  If you need less than 32 bits,
use a bitmask.  For example, if you need only 10 bits, do
  h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.

If you are hashing n strings (ub1 **)k, do it like this:
  for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);

By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
code any way you wish, private, educational, or commercial.  It's free.

See http://burtleburtle.net/bob/hash/evahash.html
Use for hash table lookup, or anything where one collision in 2^32 is
acceptable.  Do NOT use for cryptographic purposes.
--------------------------------------------------------------------
*/

hashval_t
iterative_hash (const void *k_in /* the key */,
                register size_t  length /* the length of the key */,
                register hashval_t initval /* the previous hash, or
                                              an arbitrary value */)
{
  register const unsigned char *k = (const unsigned char *)k_in;
  register hashval_t a,b,c,len;

  /* Set up the internal state */
  len = length;
  a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
  c = initval;           /* the previous hash value */

  /*---------------------------------------- handle most of the key */
  /* Provide specialization for the aligned case for targets that cannot
     efficiently perform misaligned loads of a merged access.  */
  if ((((size_t)k)&3) == 0)
    while (len >= 12)
      {
	a += (k[0] | ((hashval_t)k[1]<<8) | ((hashval_t)k[2]<<16) | ((hashval_t)k[3]<<24));
	b += (k[4] | ((hashval_t)k[5]<<8) | ((hashval_t)k[6]<<16) | ((hashval_t)k[7]<<24));
	c += (k[8] | ((hashval_t)k[9]<<8) | ((hashval_t)k[10]<<16)| ((hashval_t)k[11]<<24));
	mix(a,b,c);
	k += 12; len -= 12;
      }
  else /* unaligned */
    while (len >= 12)
      {
	a += (k[0] | ((hashval_t)k[1]<<8) | ((hashval_t)k[2]<<16) | ((hashval_t)k[3]<<24));
	b += (k[4] | ((hashval_t)k[5]<<8) | ((hashval_t)k[6]<<16) | ((hashval_t)k[7]<<24));
	c += (k[8] | ((hashval_t)k[9]<<8) | ((hashval_t)k[10]<<16)| ((hashval_t)k[11]<<24));
	mix(a,b,c);
	k += 12; len -= 12;
      }

  /*------------------------------------- handle the last 11 bytes */
  c += length;
  switch(len)              /* all the case statements fall through */
    {
    case 11: c+=((hashval_t)k[10]<<24);	/* fall through */
    case 10: c+=((hashval_t)k[9]<<16);	/* fall through */
    case 9 : c+=((hashval_t)k[8]<<8);	/* fall through */
      /* the first byte of c is reserved for the length */
    case 8 : b+=((hashval_t)k[7]<<24);	/* fall through */
    case 7 : b+=((hashval_t)k[6]<<16);	/* fall through */
    case 6 : b+=((hashval_t)k[5]<<8);	/* fall through */
    case 5 : b+=k[4];			/* fall through */
    case 4 : a+=((hashval_t)k[3]<<24);	/* fall through */
    case 3 : a+=((hashval_t)k[2]<<16);	/* fall through */
    case 2 : a+=((hashval_t)k[1]<<8);	/* fall through */
    case 1 : a+=k[0];
      /* case 0: nothing left to add */
    }
  mix(a,b,c);
  /*-------------------------------------------- report the result */
  return c;
}

/* Returns a hash code for pointer P. Simplified version of evahash */

static hashval_t
hash_pointer (const void *p)
{
  intptr_t v = (intptr_t) p;
  unsigned a, b, c;

  a = b = 0x9e3779b9;
  a += v >> (sizeof (intptr_t) * CHAR_BIT / 2);
  b += v & (((intptr_t) 1 << (sizeof (intptr_t) * CHAR_BIT / 2)) - 1);
  c = 0x42135234;
  mix (a, b, c);
  return c;
}


================================================
FILE: compat/hashtab.h
================================================
/* An expandable hash tables datatype.
   Copyright (C) 1999-2025 Free Software Foundation, Inc.
   Contributed by Vladimir Makarov (vmakarov@cygnus.com).

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */

/* This package implements basic hash table functionality.  It is possible
   to search for an entry, create an entry and destroy an entry.

   Elements in the table are generic pointers.

   The size of the table is not fixed; if the occupancy of the table
   grows too high the hash table will be expanded.

   The abstract data implementation is based on generalized Algorithm D
   from Knuth's book "The art of computer programming".  Hash table is
   expanded by creation of new hash table and transferring elements from
   the old table to the new table.  */

#ifndef __HASHTAB_H__
#define __HASHTAB_H__

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "ansidecl.h"

/* The type for a hash code.  */
typedef unsigned int hashval_t;

/* Callback function pointer types.  */

/* Calculate hash of a table entry.  */
typedef hashval_t (*htab_hash) (const void *);

/* Compare a table entry with a possible entry.  The entry already in
   the table always comes first, so the second element can be of a
   different type (but in this case htab_find and htab_find_slot
   cannot be used; instead the variants that accept a hash value
   must be used).  */
typedef int (*htab_eq) (const void *, const void *);

/* Cleanup function called whenever a live element is removed from
   the hash table.  */
typedef void (*htab_del) (void *);

/* Function called by htab_traverse for each live element.  The first
   arg is the slot of the element (which can be passed to htab_clear_slot
   if desired), the second arg is the auxiliary pointer handed to
   htab_traverse.  Return 1 to continue scan, 0 to stop.  */
typedef int (*htab_trav) (void **, void *);

/* Memory-allocation function, with the same functionality as calloc().
   Iff it returns NULL, the hash table implementation will pass an error
   code back to the user, so if your code doesn't handle errors,
   best if you use xcalloc instead.  */
typedef void *(*htab_alloc) (size_t, size_t);

/* We also need a free() routine.  */
typedef void (*htab_free) (void *);

/* Memory allocation and deallocation; variants which take an extra
   argument.  */
typedef void *(*htab_alloc_with_arg) (void *, size_t, size_t);
typedef void (*htab_free_with_arg) (void *, void *);

/* This macro defines reserved value for empty table entry.  */

#define HTAB_EMPTY_ENTRY    ((void *) 0)

/* This macro defines reserved value for table entry which contained
   a deleted element. */

#define HTAB_DELETED_ENTRY  ((void *) 1)

/* Hash tables are of the following type.  The structure
   (implementation) of this type is not needed for using the hash
   tables.  All work with hash table should be executed only through
   functions mentioned below.  The size of this structure is subject to
   change.  */

struct htab {
  /* Pointer to hash function.  */
  htab_hash hash_f;

  /* Pointer to comparison function.  */
  htab_eq eq_f;

  /* Pointer to cleanup function.  */
  htab_del del_f;

  /* Table itself.  */
  void **entries;

  /* Current size (in entries) of the hash table.  */
  size_t size;

  /* Current number of elements including also deleted elements.  */
  size_t n_elements;

  /* Current number of deleted elements in the table.  */
  size_t n_deleted;

  /* The following member is used for debugging. Its value is number
     of all calls of `htab_find_slot' for the hash table. */
  unsigned int searches;

  /* The following member is used for debugging.  Its value is number
     of collisions fixed for time of work with the hash table. */
  unsigned int collisions;

  /* Pointers to allocate/free functions.  */
  htab_alloc alloc_f;
  htab_free free_f;

  /* Alternate allocate/free functions, which take an extra argument.  */
  void *alloc_arg;
  htab_alloc_with_arg alloc_with_arg_f;
  htab_free_with_arg free_with_arg_f;

  /* Current size (in entries) of the hash table, as an index into the
     table of primes.  */
  unsigned int size_prime_index;
};

typedef struct htab *htab_t;

/* An enum saying whether we insert into the hash table or not.  */
enum insert_option {NO_INSERT, INSERT};

/* The prototypes of the package functions. */

extern htab_t	htab_create_alloc  (size_t, htab_hash,
                                    htab_eq, htab_del,
                                    htab_alloc, htab_free);

extern htab_t	htab_create_alloc_ex (size_t, htab_hash,
                                      htab_eq, htab_del,
                                      void *, htab_alloc_with_arg,
                                      htab_free_with_arg);

extern htab_t  htab_create_typed_alloc (size_t, htab_hash, htab_eq, htab_del,
					htab_alloc, htab_alloc, htab_free);

/* Backward-compatibility functions.  */
extern htab_t htab_create (size_t, htab_hash, htab_eq, htab_del);
extern htab_t htab_try_create (size_t, htab_hash, htab_eq, htab_del);

extern void	htab_set_functions_ex (htab_t, htab_hash,
                                       htab_eq, htab_del,
                                       void *, htab_alloc_with_arg,
                                       htab_free_with_arg);

extern void	htab_delete (htab_t);
extern void	htab_empty (htab_t);

extern void *	htab_find (htab_t, const void *);
extern void **	htab_find_slot (htab_t, const void *, enum insert_option);
extern void *	htab_find_with_hash (htab_t, const void *, hashval_t);
extern void **	htab_find_slot_with_hash (htab_t, const void *,
					  hashval_t, enum insert_option);
extern void	htab_clear_slot	(htab_t, void **);
extern void	htab_remove_elt	(htab_t, const void *);
extern void	htab_remove_elt_with_hash (htab_t, const void *, hashval_t);

extern void	htab_traverse (htab_t, htab_trav, void *);
extern void	htab_traverse_noresize (htab_t, htab_trav, void *);

extern size_t	htab_size (htab_t);
extern size_t	htab_elements (htab_t);
extern double	htab_collisions	(htab_t);

/* A hash function for pointers.  */
extern htab_hash htab_hash_pointer;

/* An equality function for pointers.  */
extern htab_eq htab_eq_pointer;

/* A hash function for null-terminated strings.  */
extern hashval_t htab_hash_string (const void *);

/* An equality function for null-terminated strings.  */
extern int htab_eq_string (const void *, const void *);

/* An iterative hash function for arbitrary data.  */
extern hashval_t iterative_hash (const void *, size_t, hashval_t);
/* Shorthand for hashing something with an intrinsic size.  */
#define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT)

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __HASHTAB_H */


================================================
FILE: compat/mkstemps.c
================================================
/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc.
   This file is derived from mkstemp.c from the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
   Boston, MA 02110-1301, USA.  */
/*
 * This file was copied on 2013-08-03 from:
 * https://raw.github.com/mirrors/gcc/master/libiberty/mkstemps.c
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "compat.h"

#include <sys/types.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif

/* We need to provide a type for gcc_uint64_t.  */
#ifdef __GNUC__
__extension__ typedef unsigned long long gcc_uint64_t;
#else
typedef unsigned long gcc_uint64_t;
#endif

#ifndef TMP_MAX
#define TMP_MAX 16384
#endif

#ifndef O_BINARY
# define O_BINARY 0
#endif

/*

@deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len})

Generate a unique temporary file name from @var{pattern}.
@var{pattern} has the form:

@example
   @var{path}/ccXXXXXX@var{suffix}
@end example

@var{suffix_len} tells us how long @var{suffix} is (it can be zero
length).  The last six characters of @var{pattern} before @var{suffix}
must be @samp{XXXXXX}; they are replaced with a string that makes the
filename unique.  Returns a file descriptor open on the file for
reading and writing.

@end deftypefn

*/

int
compat_mkstemps (char *pattern, int suffix_len)
{
  static const char letters[]
    = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  static gcc_uint64_t value;
#ifdef HAVE_GETTIMEOFDAY
  struct timeval tv;
#endif
  char *XXXXXX;
  size_t len;
  int count;

  len = strlen (pattern);

  if ((int) len < 6 + suffix_len
      || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6))
    {
      return -1;
    }

  XXXXXX = &pattern[len - 6 - suffix_len];

#ifdef HAVE_GETTIMEOFDAY
  /* Get some more or less random data.  */
  gettimeofday (&tv, NULL);
  value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
#else
  value += getpid ();
#endif

  for (count = 0; count < TMP_MAX; ++count)
    {
      gcc_uint64_t v = value;
      int fd;

      /* Fill in the random bits.  */
      XXXXXX[0] = letters[v % 62];
      v /= 62;
      XXXXXX[1] = letters[v % 62];
      v /= 62;
      XXXXXX[2] = letters[v % 62];
      v /= 62;
      XXXXXX[3] = letters[v % 62];
      v /= 62;
      XXXXXX[4] = letters[v % 62];
      v /= 62;
      XXXXXX[5] = letters[v % 62];

      fd = open (pattern, O_BINARY|O_RDWR|O_CREAT|O_EXCL, 0600);
      if (fd >= 0)
	/* The file does not exist.  */
	return fd;
      if (errno != EEXIST
#ifdef EISDIR
	  && errno != EISDIR
#endif
	 )
	/* Fatal error (EPERM, ENOSPC etc).  Doesn't make sense to loop.  */
	break;

      /* This is a random value.  It is only necessary that the next
	 TMP_MAX values generated by adding 7777 to VALUE are different
	 with (module 2^32).  */
      value += 7777;
    }

  /* We return the null string if we can't find a unique file name.  */
  pattern[0] = '\0';
  return -1;
}


================================================
FILE: compat/setenv.c
================================================
/* Copyright (C) 1992, 1995, 1996, 1997, 2002, 2011 Free Software Foundation,
   Inc.
   This file based on setenv.c in the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
   Boston, MA 02110-1301, USA.  */

/*
 * This file was borrowed on 2013-08-08 from:
 * https://raw.github.com/mirrors/gcc/master/libiberty/setenv.c
 */

/*

@deftypefn Supplemental int setenv (const char *@var{name}, @
  const char *@var{value}, int @var{overwrite})
@deftypefnx Supplemental void unsetenv (const char *@var{name})

@code{setenv} adds @var{name} to the environment with value
@var{value}.  If the name was already present in the environment,
the new value will be stored only if @var{overwrite} is nonzero.
The companion @code{unsetenv} function removes @var{name} from the
environment.  This implementation is not safe for multithreaded code.

@end deftypefn

*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "compat.h"

#include <sys/types.h> /* For `size_t' */
#include <stdio.h>     /* For `NULL' */

#include <errno.h>
#if !defined(errno) && !defined(HAVE_DECL_ERRNO)
extern int errno;
#endif
#define __set_errno(ev) ((errno) = (ev))

#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#define __environ	environ
#ifndef HAVE_DECL_ENVIRON
extern char **environ;
#endif

/* LOCK and UNLOCK are defined as no-ops.  This makes the tig
 * implementation MT-Unsafe. */
#define LOCK
#define UNLOCK

/* Below this point, it's verbatim code from the glibc-2.0 implementation */

/* If this variable is not a null pointer we allocated the current
   environment.  */
static char **last_environ;


int
compat_setenv (const char *name, const char *value, int replace)
{
  register char **ep = 0;
  register size_t size;
  const size_t namelen = strlen (name);
  const size_t vallen = strlen (value) + 1;

  LOCK;

  size = 0;
  if (__environ != NULL)
    {
      for (ep = __environ; *ep != NULL; ++ep)
	if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
	  break;
	else
	  ++size;
    }

  if (__environ == NULL || *ep == NULL)
    {
      char **new_environ;
      if (__environ == last_environ && __environ != NULL)
	/* We allocated this space; we can extend it.  */
	new_environ = (char **) realloc (last_environ,
					 (size + 2) * sizeof (char *));
      else
	new_environ = (char **) malloc ((size + 2) * sizeof (char *));

      if (new_environ == NULL)
	{
	  UNLOCK;
	  return -1;
	}

      new_environ[size] = (char *) malloc (namelen + 1 + vallen);
      if (new_environ[size] == NULL)
	{
	  free ((char *) new_environ);
	  __set_errno (ENOMEM);
	  UNLOCK;
	  return -1;
	}

      if (__environ != last_environ)
	memcpy ((char *) new_environ, (char *) __environ,
		size * sizeof (char *));

      memcpy (new_environ[size], name, namelen);
      new_environ[size][namelen] = '=';
      memcpy (&new_environ[size][namelen + 1], value, vallen);

      new_environ[size + 1] = NULL;

      last_environ = __environ = new_environ;
    }
  else if (replace)
    {
      size_t len = strlen (*ep);
      if (len + 1 < namelen + 1 + vallen)
	{
	  /* The existing string is too short; malloc a new one.  */
	  char *new_string = (char *) malloc (namelen + 1 + vallen);
	  if (new_string == NULL)
	    {
	      UNLOCK;
	      return -1;
	    }
	  *ep = new_string;
	}
      memcpy (*ep, name, namelen);
      (*ep)[namelen] = '=';
      memcpy (&(*ep)[namelen + 1], value, vallen);
    }

  UNLOCK;

  return 0;
}

#if 0
void
compat_unsetenv (const char *name)
{
  const size_t len = strlen (name);
  char **ep;

  LOCK;

  for (ep = __environ; *ep; ++ep)
    if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
      {
	/* Found it.  Remove this pointer by moving later ones back.  */
	char **dp = ep;
	do
	  dp[0] = dp[1];
	while (*dp++);
	/* Continue the loop in case NAME appears again.  */
      }

  UNLOCK;
}
#endif


================================================
FILE: compat/strndup.c
================================================
/* Implement the strndup function.
   Copyright (C) 2005 Free Software Foundation, Inc.
   Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.

This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */

/*
 * This file was borrowed on 2014-05-05 and adapted from:
 * https://raw.github.com/mirrors/gcc/master/libiberty/strndup.c
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "compat.h"

#include <sys/types.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif

char *
compat_strndup (const char *s, size_t n)
{
  char *result;
  size_t len = strlen (s);

  if (n < len)
    len = n;

  result = (char *) malloc (len + 1);
  if (!result)
    return 0;

  result[len] = '\0';
  return (char *) memcpy (result, s, len);
}


================================================
FILE: compat/utf8proc.c
================================================
/* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */
/*
 *  Copyright (c) 2014-2021 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors.
 *  Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 */

/*
 *  This library contains derived data from a modified version of the
 *  Unicode data files.
 *
 *  The original data files are available at
 *  https://www.unicode.org/Public/UNIDATA/
 *
 *  Please notice the copyright statement in the file "utf8proc_data.c".
 */


/*
 *  File name:    utf8proc.c
 *
 *  Description:
 *  Implementation of libutf8proc.
 */


#include "utf8proc.h"

#ifndef SSIZE_MAX
#define SSIZE_MAX ((size_t)SIZE_MAX/2)
#endif
#ifndef UINT16_MAX
#  define UINT16_MAX 65535U
#endif

#include "utf8proc_data.c"


UTF8PROC_DLLEXPORT const utf8proc_int8_t utf8proc_utf8class[256] = {
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 };

#define UTF8PROC_HANGUL_SBASE 0xAC00
#define UTF8PROC_HANGUL_LBASE 0x1100
#define UTF8PROC_HANGUL_VBASE 0x1161
#define UTF8PROC_HANGUL_TBASE 0x11A7
#define UTF8PROC_HANGUL_LCOUNT 19
#define UTF8PROC_HANGUL_VCOUNT 21
#define UTF8PROC_HANGUL_TCOUNT 28
#define UTF8PROC_HANGUL_NCOUNT 588
#define UTF8PROC_HANGUL_SCOUNT 11172
/* END is exclusive */
#define UTF8PROC_HANGUL_L_START  0x1100
#define UTF8PROC_HANGUL_L_END    0x115A
#define UTF8PROC_HANGUL_L_FILLER 0x115F
#define UTF8PROC_HANGUL_V_START  0x1160
#define UTF8PROC_HANGUL_V_END    0x11A3
#define UTF8PROC_HANGUL_T_START  0x11A8
#define UTF8PROC_HANGUL_T_END    0x11FA
#define UTF8PROC_HANGUL_S_START  0xAC00
#define UTF8PROC_HANGUL_S_END    0xD7A4

/* Should follow semantic-versioning rules (semver.org) based on API
   compatibility.  (Note that the shared-library version number will
   be different, being based on ABI compatibility.): */
#define STRINGIZEx(x) #x
#define STRINGIZE(x) STRINGIZEx(x)
UTF8PROC_DLLEXPORT const char *utf8proc_version(void) {
  return STRINGIZE(UTF8PROC_VERSION_MAJOR) "." STRINGIZE(UTF8PROC_VERSION_MINOR) "." STRINGIZE(UTF8PROC_VERSION_PATCH) "";
}

UTF8PROC_DLLEXPORT const char *utf8proc_unicode_version(void) {
  return "17.0.0";
}

UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode) {
  switch (errcode) {
    case UTF8PROC_ERROR_NOMEM:
    return "Memory for processing UTF-8 data could not be allocated.";
    case UTF8PROC_ERROR_OVERFLOW:
    return "UTF-8 string is too long to be processed.";
    case UTF8PROC_ERROR_INVALIDUTF8:
    return "Invalid UTF-8 string";
    case UTF8PROC_ERROR_NOTASSIGNED:
    return "Unassigned Unicode code point found in UTF-8 string.";
    case UTF8PROC_ERROR_INVALIDOPTS:
    return "Invalid options for UTF-8 processing chosen.";
    default:
    return "An unknown error occurred while processing UTF-8 data.";
  }
}

#define utf_cont(ch)  (((ch) & 0xc0) == 0x80)
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate(
  const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *dst
) {
  utf8proc_int32_t uc;
  const utf8proc_uint8_t *end;

  *dst = -1;
  if (!strlen) return 0;
  end = str + ((strlen < 0) ? 4 : strlen);
  uc = *str++;
  if (uc < 0x80) {
    *dst = uc;
    return 1;
  }
  // Must be between 0xc2 and 0xf4 inclusive to be valid
  if ((utf8proc_uint32_t)(uc - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8;
  if (uc < 0xe0) {         // 2-byte sequence
     // Must have valid continuation character
     if (str >= end || !utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8;
     *dst = ((uc & 0x1f)<<6) | (*str & 0x3f);
     return 2;
  }
  if (uc < 0xf0) {        // 3-byte sequence
     if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1]))
        return UTF8PROC_ERROR_INVALIDUTF8;
     // Check for surrogate chars
     if (uc == 0xed && *str > 0x9f)
         return UTF8PROC_ERROR_INVALIDUTF8;
     uc = ((uc & 0xf)<<12) | ((*str & 0x3f)<<6) | (str[1] & 0x3f);
     if (uc < 0x800)
         return UTF8PROC_ERROR_INVALIDUTF8;
     *dst = uc;
     return 3;
  }
  // 4-byte sequence
  // Must have 3 valid continuation characters
  if ((str + 2 >= end) || !utf_cont(*str) || !utf_cont(str[1]) || !utf_cont(str[2]))
     return UTF8PROC_ERROR_INVALIDUTF8;
  // Make sure in correct range (0x10000 - 0x10ffff)
  if (uc == 0xf0) {
    if (*str < 0x90) return UTF8PROC_ERROR_INVALIDUTF8;
  } else if (uc == 0xf4) {
    if (*str > 0x8f) return UTF8PROC_ERROR_INVALIDUTF8;
  }
  *dst = ((uc & 7)<<18) | ((*str & 0x3f)<<12) | ((str[1] & 0x3f)<<6) | (str[2] & 0x3f);
  return 4;
}

UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t uc) {
    return (((utf8proc_uint32_t)uc)-0xd800 > 0x07ff) && ((utf8proc_uint32_t)uc < 0x110000);
}

UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) {
  if (uc < 0x00) {
    return 0;
  } else if (uc < 0x80) {
    dst[0] = (utf8proc_uint8_t) uc;
    return 1;
  } else if (uc < 0x800) {
    dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6));
    dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
    return 2;
  // Note: we allow encoding 0xd800-0xdfff here, so as not to change
  // the API, however, these are actually invalid in UTF-8
  } else if (uc < 0x10000) {
    dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12));
    dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
    dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
    return 3;
  } else if (uc < 0x110000) {
    dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18));
    dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F));
    dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
    dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
    return 4;
  } else return 0;
}

/* internal version used for inserting 0xff bytes between graphemes */
static utf8proc_ssize_t charbound_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) {
   if (uc < 0x00) {
      if (uc == -1) { /* internal value used for grapheme breaks */
        dst[0] = (utf8proc_uint8_t)0xFF;
        return 1;
      }
      return 0;
   } else if (uc < 0x80) {
      dst[0] = (utf8proc_uint8_t)uc;
      return 1;
   } else if (uc < 0x800) {
      dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6));
      dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
      return 2;
   } else if (uc < 0x10000) {
      dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12));
      dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
      dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
      return 3;
   } else if (uc < 0x110000) {
      dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18));
      dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F));
      dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
      dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
      return 4;
   } else return 0;
}

/* internal "unsafe" version that does not check whether uc is in range */
static const utf8proc_property_t *unsafe_get_property(utf8proc_int32_t uc) {
  /* ASSERT: uc >= 0 && uc < 0x110000 */
  return utf8proc_properties + (
    utf8proc_stage2table[
      utf8proc_stage1table[uc >> 8] + (uc & 0xFF)
    ]
  );
}

UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int32_t uc) {
  return uc < 0 || uc >= 0x110000 ? utf8proc_properties : unsafe_get_property(uc);
}

/* return whether there is a grapheme break between boundclasses lbc and tbc
   (according to the definition of extended grapheme clusters)

  Rule numbering refers to TR29 Version 29 (Unicode 9.0.0):
  http://www.unicode.org/reports/tr29/tr29-29.html

  CAVEATS:
   Please note that evaluation of GB10 (grapheme breaks between emoji zwj sequences)
   and GB 12/13 (regional indicator code points) require knowledge of previous characters
   and are thus not handled by this function. This may result in an incorrect break before
   an E_Modifier class codepoint and an incorrectly missing break between two
   REGIONAL_INDICATOR class code points if such support does not exist in the caller.

   See the special support in grapheme_break_extended, for required bookkeeping by the caller.
*/
static utf8proc_bool grapheme_break_simple(int lbc, int tbc) {
  return
    (lbc == UTF8PROC_BOUNDCLASS_START) ? true :       // GB1
    (lbc == UTF8PROC_BOUNDCLASS_CR &&                 // GB3
     tbc == UTF8PROC_BOUNDCLASS_LF) ? false :         // ---
    (lbc >= UTF8PROC_BOUNDCLASS_CR && lbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true :  // GB4
    (tbc >= UTF8PROC_BOUNDCLASS_CR && tbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true :  // GB5
    (lbc == UTF8PROC_BOUNDCLASS_L &&                  // GB6
     (tbc == UTF8PROC_BOUNDCLASS_L ||                 // ---
      tbc == UTF8PROC_BOUNDCLASS_V ||                 // ---
      tbc == UTF8PROC_BOUNDCLASS_LV ||                // ---
      tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false :      // ---
    ((lbc == UTF8PROC_BOUNDCLASS_LV ||                // GB7
      lbc == UTF8PROC_BOUNDCLASS_V) &&                // ---
     (tbc == UTF8PROC_BOUNDCLASS_V ||                 // ---
      tbc == UTF8PROC_BOUNDCLASS_T)) ? false :        // ---
    ((lbc == UTF8PROC_BOUNDCLASS_LVT ||               // GB8
      lbc == UTF8PROC_BOUNDCLASS_T) &&                // ---
     tbc == UTF8PROC_BOUNDCLASS_T) ? false :          // ---
    (tbc == UTF8PROC_BOUNDCLASS_EXTEND ||             // GB9
     tbc == UTF8PROC_BOUNDCLASS_ZWJ ||                // ---
     tbc == UTF8PROC_BOUNDCLASS_SPACINGMARK ||        // GB9a
     lbc == UTF8PROC_BOUNDCLASS_PREPEND) ? false :    // GB9b
    (lbc == UTF8PROC_BOUNDCLASS_E_ZWG &&              // GB11 (requires additional handling below)
     tbc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) ? false : // ----
    (lbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR &&          // GB12/13 (requires additional handling below)
     tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) ? false :  // ----
    true; // GB999
}

static utf8proc_bool grapheme_break_extended(int lbc, int tbc, int licb, int ticb, utf8proc_int32_t *state)
{
  if (state) {
    int state_bc, state_icb; /* boundclass and indic_conjunct_break state */
    if (*state == 0) { /* state initialization */
      state_bc = lbc;
      state_icb = licb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT ? licb : UTF8PROC_INDIC_CONJUNCT_BREAK_NONE;
    }
    else { /* lbc and licb are already encoded in *state */
      state_bc = *state & 0xff;  // 1st byte of state is bound class
      state_icb = *state >> 8;   // 2nd byte of state is indic conjunct break
    }

    utf8proc_bool break_permitted = grapheme_break_simple(state_bc, tbc) &&
       !(state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER
        && ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT); // GB9c

    // Special support for GB9c.  Don't break between two consonants
    // separated 1+ linker characters and 0+ extend characters in any order.
    // After a consonant, we enter LINKER state after at least one linker.
    if (ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT
        || state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT
        || state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND)
      state_icb = ticb;
    else if (state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER)
      state_icb = ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND ?
                  UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER : ticb;

    // Special support for GB 12/13 made possible by GB999. After two RI
    // class codepoints we want to force a break. Do this by resetting the
    // second RI's bound class to UTF8PROC_BOUNDCLASS_OTHER, to force a break
    // after that character according to GB999 (unless of course such a break is
    // forbidden by a different rule such as GB9).
    if (state_bc == tbc && tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR)
      state_bc = UTF8PROC_BOUNDCLASS_OTHER;
    // Special support for GB11 (emoji extend* zwj / emoji)
    else if (state_bc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) {
      if (tbc == UTF8PROC_BOUNDCLASS_EXTEND) // fold EXTEND codepoints into emoji
        state_bc = UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC;
      else if (tbc == UTF8PROC_BOUNDCLASS_ZWJ)
        state_bc = UTF8PROC_BOUNDCLASS_E_ZWG; // state to record emoji+zwg combo
      else
        state_bc = tbc;
    }
    else
      state_bc = tbc;

    *state = state_bc + (state_icb << 8);
    return break_permitted;
  }
  else
    return grapheme_break_simple(lbc, tbc);
}

UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful(
    utf8proc_int32_t c1, utf8proc_int32_t c2, utf8proc_int32_t *state) {

  const utf8proc_property_t *p1 = utf8proc_get_property(c1);
  const utf8proc_property_t *p2 = utf8proc_get_property(c2);
  return grapheme_break_extended(p1->boundclass,
                                 p2->boundclass,
                                 p1->indic_conjunct_break,
                                 p2->indic_conjunct_break,
                                 state);
}


UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break(
    utf8proc_int32_t c1, utf8proc_int32_t c2) {
  return utf8proc_grapheme_break_stateful(c1, c2, NULL);
}

static utf8proc_int32_t seqindex_decode_entry(const utf8proc_uint16_t **entry)
{
  utf8proc_int32_t entry_cp = **entry;
  if ((entry_cp & 0xF800) == 0xD800) {
    *entry = *entry + 1;
    entry_cp = ((entry_cp & 0x03FF) << 10) | (**entry & 0x03FF);
    entry_cp += 0x10000;
  }
  return entry_cp;
}

static utf8proc_int32_t seqindex_decode_index(const utf8proc_uint32_t seqindex)
{
  const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex];
  return seqindex_decode_entry(&entry);
}

static utf8proc_ssize_t seqindex_write_char_decomposed(utf8proc_uint16_t seqindex, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) {
  utf8proc_ssize_t written = 0;
  const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex & 0x3FFF];
  int len = seqindex >> 14;
  if (len >= 3) {
    len = *entry;
    entry++;
  }
  for (; len >= 0; entry++, len--) {
    utf8proc_int32_t entry_cp = seqindex_decode_entry(&entry);

    written += utf8proc_decompose_char(entry_cp, dst ? dst+written : dst,
      (bufsize > written) ? (bufsize - written) : 0, options,
    last_boundclass);
    if (written < 0) return UTF8PROC_ERROR_OVERFLOW;
  }
  return written;
}

UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c)
{
  utf8proc_int32_t cl = utf8proc_get_property(c)->lowercase_seqindex;
  return cl != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cl) : c;
}

UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c)
{
  utf8proc_int32_t cu = utf8proc_get_property(c)->uppercase_seqindex;
  return cu != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cu) : c;
}

UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c)
{
  utf8proc_int32_t cu = utf8proc_get_property(c)->titlecase_seqindex;
  return cu != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cu) : c;
}

UTF8PROC_DLLEXPORT int utf8proc_islower(utf8proc_int32_t c)
{
  const utf8proc_property_t *p = utf8proc_get_property(c);
  return p->lowercase_seqindex != p->uppercase_seqindex && p->lowercase_seqindex == UINT16_MAX;
}

UTF8PROC_DLLEXPORT int utf8proc_isupper(utf8proc_int32_t c)
{
  const utf8proc_property_t *p = utf8proc_get_property(c);
  return p->lowercase_seqindex != p->uppercase_seqindex && p->uppercase_seqindex == UINT16_MAX && p->category != UTF8PROC_CATEGORY_LT;
}

/* return a character width analogous to wcwidth (except portable and
   hopefully less buggy than most system wcwidth functions). */
UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) {
  return utf8proc_get_property(c)->charwidth;
}

UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_charwidth_ambiguous(utf8proc_int32_t c) {
  return utf8proc_get_property(c)->ambiguous_width;
}

UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) {
  return (utf8proc_category_t) utf8proc_get_property(c)->category;
}

UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
  static const char s[][3] = {"Cn","Lu","Ll","Lt","Lm","Lo","Mn","Mc","Me","Nd","Nl","No","Pc","Pd","Ps","Pe","Pi","Pf","Po","Sm","Sc","Sk","So","Zs","Zl","Zp","Cc","Cf","Cs","Co"};
  return s[utf8proc_category(c)];
}

#define utf8proc_decompose_lump(replacement_uc) \
  return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
  options & ~(unsigned int)UTF8PROC_LUMP, last_boundclass)

UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) {
  const utf8proc_property_t *property;
  utf8proc_propval_t category;
  utf8proc_int32_t hangul_sindex;
  if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED;
  property = unsafe_get_property(uc);
  category = property->category;
  hangul_sindex = uc - UTF8PROC_HANGUL_SBASE;
  if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
    if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) {
      utf8proc_int32_t hangul_tindex;
      if (bufsize >= 1) {
        dst[0] = UTF8PROC_HANGUL_LBASE +
          hangul_sindex / UTF8PROC_HANGUL_NCOUNT;
        if (bufsize >= 2) dst[1] = UTF8PROC_HANGUL_VBASE +
          (hangul_sindex % UTF8PROC_HANGUL_NCOUNT) / UTF8PROC_HANGUL_TCOUNT;
      }
      hangul_tindex = hangul_sindex % UTF8PROC_HANGUL_TCOUNT;
      if (!hangul_tindex) return 2;
      if (bufsize >= 3) dst[2] = UTF8PROC_HANGUL_TBASE + hangul_tindex;
      return 3;
    }
  }
  if (options & UTF8PROC_REJECTNA) {
    if (!category) return UTF8PROC_ERROR_NOTASSIGNED;
  }
  if (options & UTF8PROC_IGNORE) {
    if (property->ignorable) return 0;
  }
  if (options & UTF8PROC_STRIPNA) {
    if (!category) return 0;
  }
  if (options & UTF8PROC_LUMP) {
    if (category == UTF8PROC_CATEGORY_ZS) utf8proc_decompose_lump(0x0020);
    if (uc == 0x2018 || uc == 0x2019 || uc == 0x02BC || uc == 0x02C8)
      utf8proc_decompose_lump(0x0027);
    if (category == UTF8PROC_CATEGORY_PD || uc == 0x2212)
      utf8proc_decompose_lump(0x002D);
    if (uc == 0x2044 || uc == 0x2215) utf8proc_decompose_lump(0x002F);
    if (uc == 0x2236) utf8proc_decompose_lump(0x003A);
    if (uc == 0x2039 || uc == 0x2329 || uc == 0x3008)
      utf8proc_decompose_lump(0x003C);
    if (uc == 0x203A || uc == 0x232A || uc == 0x3009)
      utf8proc_decompose_lump(0x003E);
    if (uc == 0x2216) utf8proc_decompose_lump(0x005C);
    if (uc == 0x02C4 || uc == 0x02C6 || uc == 0x2038 || uc == 0x2303)
      utf8proc_decompose_lump(0x005E);
    if (category == UTF8PROC_CATEGORY_PC || uc == 0x02CD)
      utf8proc_decompose_lump(0x005F);
    if (uc == 0x02CB) utf8proc_decompose_lump(0x0060);
    if (uc == 0x2223) utf8proc_decompose_lump(0x007C);
    if (uc == 0x223C) utf8proc_decompose_lump(0x007E);
    if ((options & UTF8PROC_NLF2LS) && (options & UTF8PROC_NLF2PS)) {
      if (category == UTF8PROC_CATEGORY_ZL ||
          category == UTF8PROC_CATEGORY_ZP)
        utf8proc_decompose_lump(0x000A);
    }
  }
  if (options & UTF8PROC_STRIPMARK) {
    if (category == UTF8PROC_CATEGORY_MN ||
      category == UTF8PROC_CATEGORY_MC ||
      category == UTF8PROC_CATEGORY_ME) return 0;
  }
  if (options & UTF8PROC_CASEFOLD) {
    if (property->casefold_seqindex != UINT16_MAX) {
      return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass);
    }
  }
  if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
    if (property->decomp_seqindex != UINT16_MAX &&
        (!property->decomp_type || (options & UTF8PROC_COMPAT))) {
      return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass);
    }
  }
  if (options & UTF8PROC_CHARBOUND) {
    utf8proc_bool boundary;
    boundary = grapheme_break_extended(0, property->boundclass, 0, property->indic_conjunct_break,
                                       last_boundclass);
    if (boundary) {
      if (bufsize >= 1) dst[0] = -1; /* sentinel value for grapheme break */
      if (bufsize >= 2) dst[1] = uc;
      return 2;
    }
  }
  if (bufsize >= 1) *dst = uc;
  return 1;
}

UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
  const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
  utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options
) {
    return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL);
}

UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom(
  const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
  utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options,
  utf8proc_custom_func custom_func, void *custom_data
) {
  /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */
  utf8proc_ssize_t wpos = 0;
  if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE))
    return UTF8PROC_ERROR_INVALIDOPTS;
  if ((options & UTF8PROC_STRIPMARK) &&
      !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE))
    return UTF8PROC_ERROR_INVALIDOPTS;
  {
    utf8proc_int32_t uc;
    utf8proc_ssize_t rpos = 0;
    utf8proc_ssize_t decomp_result;
    int boundclass = UTF8PROC_BOUNDCLASS_START;
    while (1) {
      if (options & UTF8PROC_NULLTERM) {
        rpos += utf8proc_iterate(str + rpos, -1, &uc);
        /* checking of return value is not necessary,
           as 'uc' is < 0 in case of error */
        if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
        if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW;
        if (uc == 0) break;
      } else {
        if (rpos >= strlen) break;
        rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc);
        if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
      }
      if (custom_func != NULL) {
        uc = custom_func(uc, custom_data);   /* user-specified custom mapping */
      }
      decomp_result = utf8proc_decompose_char(
        uc, buffer ? buffer+wpos : buffer, (bufsize > wpos) ? (bufsize - wpos) : 0, options,
        &boundclass
      );
      if (decomp_result < 0) return decomp_result;
      wpos += decomp_result;
      /* prohibiting integer overflows due to too long strings: */
      if (wpos < 0 ||
          wpos > (utf8proc_ssize_t)(SSIZE_MAX/sizeof(utf8proc_int32_t)/2))
        return UTF8PROC_ERROR_OVERFLOW;
    }
  }
  if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) {
    utf8proc_ssize_t pos = 0;
    while (pos < wpos-1) {
      utf8proc_int32_t uc1, uc2;
      const utf8proc_property_t *property1, *property2;
      uc1 = buffer[pos];
      uc2 = buffer[pos+1];
      property1 = unsafe_get_property(uc1);
      property2 = unsafe_get_property(uc2);
      if (property1->combining_class > property2->combining_class &&
          property2->combining_class > 0) {
        buffer[pos] = uc2;
        buffer[pos+1] = uc1;
        if (pos > 0) pos--; else pos++;
      } else {
        pos++;
      }
    }
  }
  return wpos;
}

UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
  /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */
  if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) {
    utf8proc_ssize_t rpos;
    utf8proc_ssize_t wpos = 0;
    utf8proc_int32_t uc;
    for (rpos = 0; rpos < length; rpos++) {
      uc = buffer[rpos];
      if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++;
      if (uc == 0x000A || uc == 0x000D || uc == 0x0085 ||
          ((options & UTF8PROC_STRIPCC) && (uc == 0x000B || uc == 0x000C))) {
        if (options & UTF8PROC_NLF2LS) {
          if (options & UTF8PROC_NLF2PS) {
            buffer[wpos++] = 0x000A;
          } else {
            buffer[wpos++] = 0x2028;
          }
        } else {
          if (options & UTF8PROC_NLF2PS) {
            buffer[wpos++] = 0x2029;
          } else {
            buffer[wpos++] = 0x0020;
          }
        }
      } else if ((options & UTF8PROC_STRIPCC) &&
          (uc < 0x0020 || (uc >= 0x007F && uc < 0x00A0))) {
Download .txt
gitextract_jul00w11/

├── .bookignore
├── .github/
│   └── workflows/
│       ├── linux.yml
│       └── macos.yml
├── .gitignore
├── .mailmap
├── COPYING
├── INSTALL.adoc
├── Makefile
├── NEWS.adoc
├── README.adoc
├── appveyor.yml
├── autogen.sh
├── book.json
├── book.md
├── compat/
│   ├── ansidecl.h
│   ├── compat.h
│   ├── hashtab.c
│   ├── hashtab.h
│   ├── mkstemps.c
│   ├── setenv.c
│   ├── strndup.c
│   ├── utf8proc.c
│   ├── utf8proc.h
│   ├── utf8proc.license.md
│   ├── utf8proc_data.c
│   └── wordexp.c
├── config.make.in
├── configure.ac
├── contrib/
│   ├── bindings-v1.x.tigrc
│   ├── chocolate.theme.tigrc
│   ├── config.make
│   ├── config.make-CYGWIN_NT-6.1
│   ├── config.make-Darwin
│   ├── config.make-Linux
│   ├── git-flow.tigrc
│   ├── large-repo.tigrc
│   ├── tig-completion.bash
│   ├── tig-completion.zsh
│   ├── tig-pick
│   ├── tig.spec.in
│   └── vim.tigrc
├── doc/
│   ├── asciidoc.conf
│   ├── manual.adoc
│   ├── tig.1.adoc
│   ├── tigmanual.7.adoc
│   └── tigrc.5.adoc
├── include/
│   └── tig/
│       ├── apps.h
│       ├── argv.h
│       ├── blame.h
│       ├── blob.h
│       ├── diff.h
│       ├── display.h
│       ├── draw.h
│       ├── git.h
│       ├── graph.h
│       ├── grep.h
│       ├── help.h
│       ├── io.h
│       ├── keys.h
│       ├── line.h
│       ├── log.h
│       ├── main.h
│       ├── map.h
│       ├── options.h
│       ├── pager.h
│       ├── parse.h
│       ├── prompt.h
│       ├── refdb.h
│       ├── reflog.h
│       ├── refs.h
│       ├── repo.h
│       ├── request.h
│       ├── search.h
│       ├── stage.h
│       ├── stash.h
│       ├── status.h
│       ├── string.h
│       ├── tig.h
│       ├── tree.h
│       ├── types.h
│       ├── ui.h
│       ├── util.h
│       ├── view.h
│       └── watch.h
├── snap/
│   └── snapcraft.yaml
├── src/
│   ├── apps.c
│   ├── argv.c
│   ├── blame.c
│   ├── blob.c
│   ├── diff.c
│   ├── display.c
│   ├── draw.c
│   ├── graph-v1.c
│   ├── graph-v2.c
│   ├── graph.c
│   ├── grep.c
│   ├── help.c
│   ├── io.c
│   ├── keys.c
│   ├── line.c
│   ├── log.c
│   ├── main.c
│   ├── map.c
│   ├── options.c
│   ├── pager.c
│   ├── parse.c
│   ├── prompt.c
│   ├── refdb.c
│   ├── reflog.c
│   ├── refs.c
│   ├── repo.c
│   ├── request.c
│   ├── search.c
│   ├── stage.c
│   ├── stash.c
│   ├── status.c
│   ├── string.c
│   ├── tig.c
│   ├── tree.c
│   ├── types.c
│   ├── ui.c
│   ├── util.c
│   ├── view.c
│   └── watch.c
├── test/
│   ├── API.adoc
│   ├── README.adoc
│   ├── blame/
│   │   ├── blob-blame-test
│   │   ├── default-test
│   │   ├── initial-diff-test
│   │   ├── navigation-parent-test
│   │   ├── revargs-test
│   │   ├── start-on-line-test
│   │   └── stash-test
│   ├── blob/
│   │   └── wrap-lines-test
│   ├── diff/
│   │   ├── diff-context-test
│   │   ├── diff-highlight-color-test
│   │   ├── diff-highlight-test
│   │   ├── diff-stat-split-test
│   │   ├── diff-stat-test
│   │   ├── diff-stdin-test
│   │   ├── diff-wdiff-context-test
│   │   ├── editor-test
│   │   ├── line-number-test
│   │   ├── maximized-navigation-test
│   │   ├── open-after-split-test
│   │   ├── start-on-line-test
│   │   ├── submodule-editor-diffstat-test
│   │   ├── submodule-editor-test
│   │   ├── worktree-editor-test
│   │   └── wrap-lines-test
│   ├── files/
│   │   ├── refs-repo.tgz
│   │   ├── repo-authornamechange.tgz
│   │   ├── repo-one.tgz
│   │   ├── repo-two.tgz
│   │   └── scala-js-benchmarks.tgz
│   ├── graph/
│   │   ├── 00-simple-test
│   │   ├── 01-merge-from-left-test
│   │   ├── 02-duplicate-parent-test
│   │   ├── 03-octo-merge-test
│   │   ├── 04-missing-bar-test
│   │   ├── 05-extra-pipe-test
│   │   ├── 06-extra-bars-test
│   │   ├── 07-multi-collapse-test
│   │   ├── 08-multi-collapse-2-test
│   │   ├── 09-parallel-siblings-test
│   │   ├── 10-shorter-merge-than-branch-test
│   │   ├── 11-new-branch-in-middle-test
│   │   ├── 12-cross-over-collapse-test
│   │   ├── 13-collapse-parallel-branches-with-different-middle-branch-test
│   │   ├── 14-long-collapse-line-test
│   │   ├── 15-many-merges-test
│   │   ├── 16-changes-test
│   │   ├── 17-more-merges-test
│   │   ├── 18-tig-test
│   │   ├── 19-tig-all-test
│   │   ├── 20-tig-all-long-test
│   │   ├── 20-tig-all-long-test.in
│   │   ├── gh-490-heap-buffer-overflow-test
│   │   └── regression/
│   │       ├── horizontal-artifact-test
│   │       └── horizontal-bar-wrong-2-test
│   ├── grep/
│   │   ├── default-test
│   │   ├── editor-test
│   │   ├── refspec-test
│   │   └── start-on-line-test
│   ├── help/
│   │   ├── all-keybindings-test
│   │   ├── all-keybindings-test.expected
│   │   ├── default-test
│   │   └── user-command-test
│   ├── log/
│   │   ├── diff-stat-test
│   │   ├── log-graph-test
│   │   ├── pretty-format-test
│   │   ├── start-on-line-test
│   │   └── submodule-test
│   ├── main/
│   │   ├── all-arg-test
│   │   ├── author-name-change-test
│   │   ├── boundary-test
│   │   ├── branch-var-test
│   │   ├── commit-order-edge-case-test
│   │   ├── commit-order-edge-case-test.tgz
│   │   ├── commit-title-overflow-test
│   │   ├── date-test
│   │   ├── date-test.in
│   │   ├── default-test
│   │   ├── emoji-test
│   │   ├── escape-control-characters-test
│   │   ├── escape-control-characters-test.in
│   │   ├── filter-args-test
│   │   ├── git-alias-test
│   │   ├── goto-test
│   │   ├── graph-argument-test
│   │   ├── jump-ends-test
│   │   ├── mailmap-test
│   │   ├── main-options-test
│   │   ├── merge-test
│   │   ├── no-matching-commmits-test
│   │   ├── no-merges-test
│   │   ├── pretty-raw-test
│   │   ├── refresh-periodic-test
│   │   ├── refresh-test
│   │   ├── search-preload-test
│   │   ├── search-test
│   │   ├── show-changes-after-rename-test
│   │   ├── show-changes-test
│   │   ├── start-on-line-test
│   │   ├── stdin-test
│   │   ├── submodule-test
│   │   ├── unbind-default-quit-key-test
│   │   ├── untracked-test
│   │   ├── update-unstaged-changes-test
│   │   ├── util.sh
│   │   ├── vertical-lines-test
│   │   └── view-split-test
│   ├── prompt/
│   │   └── exec-test
│   ├── reflog/
│   │   └── default-test
│   ├── refs/
│   │   ├── branch-checkout-test
│   │   ├── branch-tag-test
│   │   ├── branch-var-test
│   │   ├── default-test
│   │   ├── filter-test
│   │   ├── refresh-test
│   │   ├── replace-test
│   │   ├── start-on-line-test
│   │   └── worktree-test
│   ├── regressions/
│   │   ├── github-1136-test
│   │   ├── github-370-test
│   │   ├── github-390-test
│   │   └── github-434-test
│   ├── script/
│   │   ├── comment-test
│   │   └── default-test
│   ├── stage/
│   │   ├── default-test
│   │   ├── gh-410-test
│   │   ├── maximized-unstaged-changes-test
│   │   ├── split-chunk-test
│   │   └── update-part-test
│   ├── stash/
│   │   └── start-on-line-test
│   ├── status/
│   │   ├── file-name-test
│   │   ├── file-var-test
│   │   ├── on-branch-test
│   │   ├── on-branch-tracking-info-test
│   │   ├── refresh-test
│   │   ├── repo-var-test
│   │   ├── start-on-line-test
│   │   ├── submodule-editor-test
│   │   ├── untracked-files-test
│   │   ├── worktree-editor-test
│   │   └── worktree-test
│   ├── tigrc/
│   │   ├── builtin-error-test
│   │   ├── builtin-save-test
│   │   ├── command-value-long-test
│   │   ├── compat-error-test
│   │   ├── contrib-tigrc-test
│   │   ├── env-vars-test
│   │   ├── escape-var-test
│   │   ├── parse-test
│   │   ├── quote-test
│   │   ├── save-option-test
│   │   ├── source-test
│   │   ├── tigrc-manpage-examples-test
│   │   ├── truncation-test
│   │   ├── view-column-test
│   │   ├── width-test
│   │   └── xdg-config-home-test
│   ├── tools/
│   │   ├── libgit.sh
│   │   ├── libtest.sh
│   │   ├── setup-conflict.sh
│   │   ├── show-results.sh
│   │   ├── test-graph.c
│   │   └── valgrind-Darwin.supp
│   └── tree/
│       ├── chdir-test
│       ├── default-test
│       ├── file-name-test
│       ├── submodule-editor-test
│       └── worktree-editor-test
├── tigrc
└── tools/
    ├── announcement.sh
    ├── aspell.dict
    ├── ax_lib_readline.m4
    ├── ax_require_defined.m4
    ├── ax_with_curses.m4
    ├── doc-gen.c
    ├── gcov.m4
    ├── header.h
    ├── iconv.m4
    ├── install.sh
    ├── make-builtin-config.sh
    ├── release.sh
    ├── travis.sh
    └── uninstall.sh
Download .txt
SYMBOL INDEX (1526 symbols across 84 files)

FILE: compat/compat.h
  type wordexp_t (line 54) | typedef struct

FILE: compat/hashtab.c
  function ceil_log2 (line 98) | unsigned int
  function choose_multiplier (line 108) | unsigned int
  type prime_ent (line 130) | struct prime_ent
  type prime_ent (line 138) | struct prime_ent
  function higher_prime_index (line 175) | static unsigned int
  function eq_pointer (line 202) | static int
  function hashval_t (line 236) | static inline hashval_t
  function hashval_t (line 264) | static inline hashval_t
  function hashval_t (line 273) | static inline hashval_t
  function htab_t (line 285) | htab_t
  function htab_t (line 296) | htab_t
  function htab_t (line 350) | htab_t
  function htab_set_functions_ex (line 384) | void
  function htab_t (line 401) | htab_t
  function htab_t (line 407) | htab_t
  function htab_delete (line 417) | void
  function htab_empty (line 443) | void
  function htab_expand (line 522) | static int
  type insert_option (line 640) | enum insert_option
  type insert_option (line 707) | enum insert_option
  function htab_remove_elt (line 717) | void
  function htab_remove_elt_with_hash (line 728) | void
  function htab_clear_slot (line 748) | void
  function htab_traverse_noresize (line 767) | void
  function htab_traverse (line 790) | void
  function htab_collisions (line 803) | double
  function hashval_t (line 837) | hashval_t
  function htab_eq_string (line 851) | int
  function hashval_t (line 934) | hashval_t
  function hashval_t (line 995) | static hashval_t

FILE: compat/hashtab.h
  type hashval_t (line 42) | typedef unsigned int hashval_t;
  type hashval_t (line 47) | typedef hashval_t (*htab_hash) (const void *);
  type htab (line 95) | struct htab {
  type htab (line 139) | struct htab
  type insert_option (line 142) | enum insert_option {NO_INSERT, INSERT}
  type insert_option (line 171) | enum insert_option
  type insert_option (line 174) | enum insert_option

FILE: compat/mkstemps.c
  type gcc_uint64_t (line 48) | __extension__ typedef unsigned long long gcc_uint64_t;
  type gcc_uint64_t (line 50) | typedef unsigned long gcc_uint64_t;
  function compat_mkstemps (line 82) | int

FILE: compat/setenv.c
  function compat_setenv (line 83) | int
  function compat_unsetenv (line 165) | void

FILE: compat/utf8proc.c
  function UTF8PROC_DLLEXPORT (line 99) | UTF8PROC_DLLEXPORT const char *utf8proc_version(void) {
  function UTF8PROC_DLLEXPORT (line 103) | UTF8PROC_DLLEXPORT const char *utf8proc_unicode_version(void) {
  function UTF8PROC_DLLEXPORT (line 107) | UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode) {
  function UTF8PROC_DLLEXPORT (line 125) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate(
  function UTF8PROC_DLLEXPORT (line 173) | UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32...
  function UTF8PROC_DLLEXPORT (line 177) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_...
  function utf8proc_ssize_t (line 204) | static utf8proc_ssize_t charbound_encode_char(utf8proc_int32_t uc, utf8p...
  function utf8proc_property_t (line 233) | static const utf8proc_property_t *unsafe_get_property(utf8proc_int32_t u...
  function UTF8PROC_DLLEXPORT (line 242) | UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8...
  function utf8proc_bool (line 261) | static utf8proc_bool grapheme_break_simple(int lbc, int tbc) {
  function utf8proc_bool (line 291) | static utf8proc_bool grapheme_break_extended(int lbc, int tbc, int licb,...
  function UTF8PROC_DLLEXPORT (line 345) | UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful(
  function UTF8PROC_DLLEXPORT (line 358) | UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break(
  function utf8proc_int32_t (line 363) | static utf8proc_int32_t seqindex_decode_entry(const utf8proc_uint16_t **...
  function utf8proc_int32_t (line 374) | static utf8proc_int32_t seqindex_decode_index(const utf8proc_uint32_t se...
  function utf8proc_ssize_t (line 380) | static utf8proc_ssize_t seqindex_write_char_decomposed(utf8proc_uint16_t...
  function UTF8PROC_DLLEXPORT (line 399) | UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c)
  function UTF8PROC_DLLEXPORT (line 405) | UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c)
  function UTF8PROC_DLLEXPORT (line 411) | UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c)
  function UTF8PROC_DLLEXPORT (line 417) | UTF8PROC_DLLEXPORT int utf8proc_islower(utf8proc_int32_t c)
  function UTF8PROC_DLLEXPORT (line 423) | UTF8PROC_DLLEXPORT int utf8proc_isupper(utf8proc_int32_t c)
  function UTF8PROC_DLLEXPORT (line 431) | UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) {
  function UTF8PROC_DLLEXPORT (line 435) | UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_charwidth_ambiguous(utf8proc_i...
  function UTF8PROC_DLLEXPORT (line 439) | UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_...
  function UTF8PROC_DLLEXPORT (line 443) | UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t...
  function UTF8PROC_DLLEXPORT (line 452) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int...
  function UTF8PROC_DLLEXPORT (line 540) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
  function UTF8PROC_DLLEXPORT (line 547) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom(
  function UTF8PROC_DLLEXPORT (line 614) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_in...
  function UTF8PROC_DLLEXPORT (line 731) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *...
  function UTF8PROC_DLLEXPORT (line 755) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
  function UTF8PROC_DLLEXPORT (line 761) | UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
  function UTF8PROC_DLLEXPORT (line 791) | UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t...
  function UTF8PROC_DLLEXPORT (line 798) | UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t...
  function UTF8PROC_DLLEXPORT (line 805) | UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_...
  function UTF8PROC_DLLEXPORT (line 812) | UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_...
  function UTF8PROC_DLLEXPORT (line 819) | UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8pr...

FILE: compat/utf8proc.h
  type utf8proc_int8_t (line 83) | typedef signed char utf8proc_int8_t;
  type utf8proc_uint8_t (line 84) | typedef unsigned char utf8proc_uint8_t;
  type utf8proc_int16_t (line 85) | typedef short utf8proc_int16_t;
  type utf8proc_uint16_t (line 86) | typedef unsigned short utf8proc_uint16_t;
  type utf8proc_int32_t (line 87) | typedef int utf8proc_int32_t;
  type utf8proc_uint32_t (line 88) | typedef unsigned int utf8proc_uint32_t;
  type __int64 (line 90) | typedef __int64 utf8proc_ssize_t;
  type utf8proc_size_t (line 91) | typedef unsigned __int64 utf8proc_size_t;
  type utf8proc_ssize_t (line 93) | typedef int utf8proc_ssize_t;
  type utf8proc_size_t (line 94) | typedef unsigned int utf8proc_size_t;
  type utf8proc_bool (line 98) | typedef unsigned char utf8proc_bool;
  type utf8proc_bool (line 105) | typedef bool utf8proc_bool;
  type utf8proc_int8_t (line 111) | typedef int8_t utf8proc_int8_t;
  type utf8proc_uint8_t (line 112) | typedef uint8_t utf8proc_uint8_t;
  type utf8proc_int16_t (line 113) | typedef int16_t utf8proc_int16_t;
  type utf8proc_uint16_t (line 114) | typedef uint16_t utf8proc_uint16_t;
  type utf8proc_int32_t (line 115) | typedef int32_t utf8proc_int32_t;
  type utf8proc_uint32_t (line 116) | typedef uint32_t utf8proc_uint32_t;
  type utf8proc_size_t (line 117) | typedef size_t utf8proc_size_t;
  type utf8proc_ssize_t (line 118) | typedef ptrdiff_t utf8proc_ssize_t;
  type utf8proc_bool (line 119) | typedef bool utf8proc_bool;
  type utf8proc_option_t (line 146) | typedef enum {
  type utf8proc_int16_t (line 233) | typedef utf8proc_int16_t utf8proc_propval_t;
  type utf8proc_property_t (line 236) | typedef struct utf8proc_property_struct {
  type utf8proc_category_t (line 319) | typedef enum {
  type utf8proc_bidi_class_t (line 353) | typedef enum {
  type utf8proc_decomp_type_t (line 380) | typedef enum {
  type utf8proc_boundclass_t (line 400) | typedef enum {
  type utf8proc_indic_conjunct_break_t (line 431) | typedef enum {
  type utf8proc_int32_t (line 443) | typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepo...

FILE: compat/wordexp.c
  function compat_wordfree (line 24) | void
  function compat_wordexp (line 31) | int

FILE: include/tig/apps.h
  type app_external (line 25) | struct app_external {
  type app_external (line 34) | struct app_external

FILE: include/tig/argv.h
  type argv_number (line 41) | typedef unsigned long argv_number;
  type argv_env (line 63) | struct argv_env {
  type argv_env (line 72) | struct argv_env
  type argv_flag (line 74) | enum argv_flag {
  type argv_env (line 80) | struct argv_env
  type argv_env (line 81) | struct argv_env
  type rev_flags (line 83) | struct rev_flags {
  type rev_flags (line 89) | struct rev_flags

FILE: include/tig/blame.h
  type view (line 19) | struct view
  function open_blame_view (line 21) | static inline void

FILE: include/tig/blob.h
  type view (line 19) | struct view
  type view (line 20) | struct view
  type open_flags (line 20) | enum open_flags

FILE: include/tig/diff.h
  type diff_state (line 19) | struct diff_state {
  type request (line 35) | enum request
  type view (line 35) | struct view
  type request (line 35) | enum request
  type line (line 35) | struct line
  type view (line 36) | struct view
  type diff_state (line 36) | struct diff_state
  type request (line 37) | enum request
  type view (line 37) | struct view
  type request (line 37) | enum request
  type line (line 37) | struct line
  type line (line 38) | struct line
  type view (line 38) | struct view
  type view (line 39) | struct view
  type line (line 39) | struct line
  type view (line 40) | struct view
  type diff_state (line 40) | struct diff_state
  type open_flags (line 40) | enum open_flags
  type view (line 41) | struct view
  type diff_state (line 41) | struct diff_state
  type status_code (line 42) | enum status_code
  type view (line 42) | struct view
  type diff_state (line 42) | struct diff_state
  type diff_state (line 43) | struct diff_state
  type view (line 45) | struct view
  type line (line 45) | struct line
  type view (line 46) | struct view
  type line (line 46) | struct line
  type view (line 48) | struct view
  function open_diff_view (line 50) | static inline void

FILE: include/tig/display.h
  type key (line 20) | struct key
  type view (line 35) | struct view
  type view (line 51) | struct view
  type vertical_split (line 53) | enum vertical_split
  type status_code (line 60) | enum status_code

FILE: include/tig/draw.h
  type align (line 23) | enum align {
  type view (line 28) | struct view
  type line_type (line 28) | enum line_type
  type view (line 29) | struct view
  type view (line 30) | struct view
  type line_type (line 30) | enum line_type
  type view (line 31) | struct view
  type line_type (line 31) | enum line_type
  type align (line 31) | enum align
  type view (line 32) | struct view
  type view_column (line 32) | struct view_column
  type view (line 33) | struct view
  type line (line 33) | struct line
  type view (line 35) | struct view
  type view (line 36) | struct view
  type view (line 37) | struct view
  type view (line 38) | struct view

FILE: include/tig/graph.h
  type graph (line 22) | struct graph
  type graph_symbol (line 23) | struct graph_symbol
  type graph_canvas (line 25) | struct graph_canvas {
  type graph (line 30) | struct graph
  type graph_symbol (line 30) | struct graph_symbol
  type graph (line 32) | struct graph {
  type graph (line 51) | struct graph
  type graph_display (line 51) | enum graph_display

FILE: include/tig/grep.h
  type view (line 19) | struct view
  type view (line 20) | struct view

FILE: include/tig/help.h
  type view (line 19) | struct view
  function open_help_view (line 21) | static inline void

FILE: include/tig/io.h
  type buffer (line 19) | struct buffer {
  type encoding (line 30) | struct encoding
  type encoding (line 32) | struct encoding
  type encoding (line 33) | struct encoding
  type buffer (line 33) | struct buffer
  type encoding (line 35) | struct encoding
  type encoding (line 35) | struct encoding
  type encoding (line 38) | struct encoding
  type io_flags (line 55) | enum io_flags {
  type io_type (line 60) | enum io_type {
  type io (line 69) | struct io {
  type status_code (line 81) | enum status_code
  type io (line 83) | struct io
  type io (line 84) | struct io
  type io (line 85) | struct io
  type io (line 86) | struct io
  type io (line 87) | struct io
  type io_type (line 87) | enum io_type
  type io (line 88) | struct io
  type io_type (line 88) | enum io_type
  type io (line 92) | struct io
  type io (line 93) | struct io
  type io (line 94) | struct io
  type io (line 95) | struct io
  type io (line 96) | struct io
  type io (line 97) | struct io
  type buffer (line 97) | struct buffer
  type io (line 98) | struct io
  type io (line 99) | struct io
  type io (line 100) | struct io
  type status_code (line 102) | enum status_code
  type io (line 102) | struct io
  type status_code (line 104) | enum status_code
  type io (line 104) | struct io
  type status_code (line 106) | enum status_code
  type io (line 106) | struct io
  type buffer (line 108) | struct buffer

FILE: include/tig/keys.h
  type keybinding (line 25) | struct keybinding
  type keymap (line 27) | struct keymap {
  type key (line 34) | struct key {
  function key_to_value (line 45) | static inline int
  function key_to_unicode (line 51) | static inline unsigned long
  function key_to_control (line 59) | static inline char
  type keymap (line 67) | struct keymap
  type key (line 70) | struct key
  type status_code (line 71) | enum status_code
  type key (line 71) | struct key
  type request (line 75) | enum request
  type keymap (line 75) | struct keymap
  type key (line 75) | struct key
  type status_code (line 76) | enum status_code
  type keymap (line 76) | struct keymap
  type request (line 76) | enum request
  type key (line 76) | struct key
  type keymap (line 78) | struct keymap
  type request (line 78) | enum request
  type run_request_flags (line 81) | struct run_request_flags {
  type run_request (line 90) | struct run_request {
  type run_request (line 96) | struct run_request
  type request (line 96) | enum request
  type status_code (line 97) | enum status_code
  type keymap (line 97) | struct keymap
  type key (line 97) | struct key
  type status_code (line 98) | enum status_code
  type run_request_flags (line 98) | struct run_request_flags
  type run_request (line 99) | struct run_request
  type keymap (line 101) | struct keymap
  type request (line 102) | enum request
  type request_info (line 103) | struct request_info
  type run_request (line 103) | struct run_request

FILE: include/tig/line.h
  type ref (line 18) | struct ref
  type line_type (line 107) | enum line_type {
  type line_info (line 113) | struct line_info {
  type line_rule (line 120) | struct line_rule {
  type line_type (line 129) | enum line_type
  type line_type (line 130) | enum line_type
  type ref (line 130) | struct ref
  type line_type (line 132) | enum line_type
  type line_info (line 134) | struct line_info
  type line_type (line 134) | enum line_type
  type line_info (line 135) | struct line_info
  type line_rule (line 135) | struct line_rule
  type line_rule (line 138) | struct line_rule
  function get_line_color (line 144) | static inline int
  function get_line_attr (line 150) | static inline int

FILE: include/tig/log.h
  type view (line 19) | struct view
  function open_log_view (line 21) | static inline void

FILE: include/tig/main.h
  type commit (line 21) | struct commit {
  type main_state (line 31) | struct main_state {
  type view (line 48) | struct view
  type line (line 48) | struct line
  type view_column_data (line 48) | struct view_column_data
  type view (line 49) | struct view
  type buffer (line 49) | struct buffer
  type request (line 50) | enum request
  type view (line 50) | struct view
  type request (line 50) | enum request
  type line (line 50) | struct line
  type view (line 51) | struct view
  type line (line 51) | struct line
  type view (line 52) | struct view
  type view (line 53) | struct view
  type line_type (line 53) | enum line_type
  type view (line 55) | struct view
  function open_main_view (line 57) | static inline void

FILE: include/tig/map.h
  type string_map_key_t (line 23) | typedef unsigned int string_map_key_t;
  type string_map_key_t (line 24) | typedef string_map_key_t (*string_map_hash_fn)(const void *value);
  type string_map (line 28) | struct string_map {
  type string_map (line 37) | struct string_map
  type string_map (line 38) | struct string_map
  type string_map (line 39) | struct string_map
  type string_map (line 40) | struct string_map
  type string_map (line 41) | struct string_map
  type string_map (line 42) | struct string_map
  type string_map (line 43) | struct string_map

FILE: include/tig/options.h
  type ref_format (line 25) | struct ref_format
  type view_column (line 26) | struct view_column
  type view_column (line 27) | struct view_column
  type graph_display (line 201) | enum graph_display
  type option_info (line 213) | struct option_info {
  type option_info (line 222) | struct option_info
  type option_info (line 222) | struct option_info
  type status_code (line 223) | enum status_code
  type option_info (line 223) | struct option_info
  type option_info (line 224) | struct option_info
  type view_column_type (line 224) | enum view_column_type
  type option_info (line 225) | struct option_info
  type status_code (line 226) | enum status_code
  type status_code (line 227) | enum status_code
  type status_code (line 228) | enum status_code
  type status_code (line 229) | enum status_code
  type status_code (line 230) | enum status_code
  type status_code (line 231) | enum status_code
  type option_info (line 232) | struct option_info

FILE: include/tig/pager.h
  type view (line 19) | struct view
  type line (line 19) | struct line
  type view_column_data (line 19) | struct view_column_data
  type view (line 20) | struct view
  type line_type (line 20) | enum line_type
  type line (line 20) | struct line
  type request (line 21) | enum request
  type view (line 21) | struct view
  type request (line 21) | enum request
  type line (line 21) | struct line
  type view (line 22) | struct view
  type line (line 22) | struct line
  type view (line 24) | struct view
  function open_pager_view (line 26) | static inline void

FILE: include/tig/parse.h
  type chunk_header_position (line 20) | struct chunk_header_position {
  type chunk_header (line 25) | struct chunk_header {
  type chunk_header (line 30) | struct chunk_header
  type blame_commit (line 33) | struct blame_commit {
  type blame_header (line 45) | struct blame_header {
  type blame_header (line 52) | struct blame_header
  type blame_commit (line 53) | struct blame_commit
  type ident (line 58) | struct ident
  type time (line 58) | struct time
  type ident (line 66) | struct ident
  function chunk_header_marker_length (line 68) | static inline unsigned int

FILE: include/tig/prompt.h
  type view (line 20) | struct view
  type input (line 21) | struct input
  type input_status (line 23) | enum input_status {
  type menu_item (line 31) | struct menu_item {
  type input_status (line 37) | enum input_status
  type input (line 37) | struct input
  type key (line 37) | struct key
  type input (line 39) | struct input {
  type input_status (line 47) | enum input_status
  type input (line 47) | struct input
  type key (line 47) | struct key
  type menu_item (line 52) | struct menu_item
  type request (line 54) | enum request
  type view (line 54) | struct view
  type request (line 55) | enum request
  type view (line 55) | struct view
  type request (line 56) | enum request
  type view (line 56) | struct view
  type run_request (line 56) | struct run_request

FILE: include/tig/refdb.h
  type argv_env (line 21) | struct argv_env
  type ref (line 23) | struct ref {
  type ref (line 38) | struct ref
  type ref (line 39) | struct ref
  type ref (line 40) | struct ref
  type status_code (line 42) | enum status_code
  type status_code (line 43) | enum status_code
  type ref (line 44) | struct ref
  type ref (line 44) | struct ref
  type argv_env (line 45) | struct argv_env
  type ref (line 45) | struct ref
  type ref (line 49) | struct ref
  type ref_format (line 52) | struct ref_format {
  type ref_format (line 57) | struct ref_format
  type ref_format (line 57) | struct ref_format
  type ref (line 57) | struct ref
  type status_code (line 58) | enum status_code
  type ref_format (line 58) | struct ref_format
  type status_code (line 59) | enum status_code
  type ref_format (line 59) | struct ref_format

FILE: include/tig/reflog.h
  type view (line 19) | struct view
  function open_reflog_view (line 21) | static inline void

FILE: include/tig/refs.h
  type view (line 19) | struct view
  function open_refs_view (line 21) | static inline void

FILE: include/tig/repo.h
  type repo_info (line 37) | struct repo_info {
  type repo_info (line 41) | struct repo_info
  type status_code (line 43) | enum status_code
  type status_code (line 44) | enum status_code
  type index_diff (line 46) | struct index_diff {
  type index_diff (line 52) | struct index_diff

FILE: include/tig/request.h
  type request_info (line 112) | struct request_info {
  type request (line 119) | enum request
  type request (line 120) | enum request
  type request_info (line 121) | struct request_info

FILE: include/tig/search.h
  type view (line 19) | struct view
  type view (line 20) | struct view
  type request (line 20) | enum request
  type view (line 21) | struct view
  type request (line 21) | enum request
  type view (line 22) | struct view
  type request (line 22) | enum request
  type view (line 23) | struct view

FILE: include/tig/stage.h
  type status (line 19) | struct status
  type view (line 21) | struct view
  type view (line 23) | struct view
  type status (line 23) | struct status
  type line_type (line 23) | enum line_type
  type open_flags (line 23) | enum open_flags

FILE: include/tig/stash.h
  type view (line 19) | struct view
  function open_stash_view (line 21) | static inline void

FILE: include/tig/status.h
  type status (line 20) | struct status {
  type status (line 34) | struct status
  type line_type (line 34) | enum line_type
  type view (line 35) | struct view
  type line (line 35) | struct line
  type status (line 36) | struct status
  type status (line 38) | struct status
  type line_type (line 38) | enum line_type
  type view (line 39) | struct view
  type status (line 39) | struct status
  type line_type (line 39) | enum line_type
  type line_type (line 42) | enum line_type
  type status (line 42) | struct status
  type view (line 45) | struct view
  type view (line 47) | struct view
  type open_flags (line 47) | enum open_flags

FILE: include/tig/string.h
  function ascii_toupper (line 40) | static inline int
  function ascii_tolower (line 48) | static inline int

FILE: include/tig/tree.h
  type view (line 21) | struct view
  function open_tree_view (line 23) | static inline void

FILE: include/tig/types.h
  type enum_map_entry (line 23) | struct enum_map_entry {
  type enum_map (line 29) | struct enum_map {
  type enum_map (line 52) | struct enum_map
  type enum_map_entry (line 54) | struct enum_map_entry

FILE: include/tig/util.h
  type status_code (line 31) | enum status_code {
  type status_code (line 37) | enum status_code
  type status_code (line 38) | enum status_code
  type status_code (line 39) | enum status_code
  function count_digits (line 46) | static inline int
  function apply_step (line 59) | static inline int
  type time (line 72) | struct time {
  type ident (line 77) | struct ident {
  type ident (line 83) | struct ident
  type timeval (line 85) | struct timeval
  type timezone (line 85) | struct timezone
  type time (line 86) | struct time
  type time (line 86) | struct time
  type ident (line 87) | struct ident
  type ident (line 87) | struct ident
  type time (line 89) | struct time
  type date (line 89) | enum date
  type file_size (line 90) | enum file_size
  type ident (line 91) | struct ident
  type author (line 91) | enum author
  type status_label (line 93) | enum status_label

FILE: include/tig/view.h
  type view_ops (line 26) | struct view_ops
  type box_cell (line 28) | struct box_cell {
  type box (line 33) | struct box {
  type line (line 39) | struct line {
  type view_flag (line 56) | enum view_flag {
  type position (line 82) | struct position {
  type sort_state (line 88) | struct sort_state {
  type view_column (line 93) | struct view_column {
  type view (line 102) | struct view {
  type open_flags (line 167) | enum open_flags {
  type view_column_data (line 185) | struct view_column_data {
  type view_ops (line 210) | struct view_ops {
  type view (line 243) | struct view
  type view (line 255) | struct view
  type view (line 256) | struct view
  type view (line 257) | struct view
  type view (line 258) | struct view
  type request (line 258) | enum request
  type view (line 259) | struct view
  type request (line 259) | enum request
  type view (line 260) | struct view
  type view_state (line 266) | struct view_state {
  type view_history (line 272) | struct view_history {
  type view_state (line 278) | struct view_state
  type view_history (line 278) | struct view_history
  type position (line 278) | struct position
  type view_history (line 279) | struct view_history
  type position (line 279) | struct position
  type view_history (line 280) | struct view_history
  type view (line 286) | struct view
  type view (line 286) | struct view
  type view (line 287) | struct view
  type view (line 288) | struct view
  type view (line 288) | struct view
  type open_flags (line 288) | enum open_flags
  type view (line 293) | struct view
  type view (line 293) | struct view
  type open_flags (line 293) | enum open_flags
  type view (line 294) | struct view
  type view (line 294) | struct view
  type open_flags (line 294) | enum open_flags
  type view (line 295) | struct view
  type open_flags (line 295) | enum open_flags
  type view (line 302) | struct view
  type view (line 303) | struct view
  type view_column (line 305) | struct view_column
  type view (line 305) | struct view
  type view_column_type (line 305) | enum view_column_type
  type view (line 306) | struct view
  type line (line 306) | struct line
  type view (line 307) | struct view
  type view (line 308) | struct view
  type view (line 309) | struct view
  type line (line 309) | struct line
  type status_code (line 310) | enum status_code
  type view_column (line 310) | struct view_column
  type status_code (line 311) | enum status_code
  type view_column_type (line 311) | enum view_column_type
  type status_code (line 312) | enum status_code
  type view_column (line 312) | struct view_column
  type view (line 313) | struct view
  type line (line 315) | struct line
  type view (line 316) | struct view
  type line (line 316) | struct line
  type line_type (line 316) | enum line_type
  type line_type (line 316) | enum line_type
  type request (line 333) | enum request
  type view (line 333) | struct view
  type request (line 333) | enum request
  function check_position (line 339) | static inline bool
  function clear_position (line 345) | static inline void
  type view (line 351) | struct view
  type status_code (line 352) | enum status_code
  type view (line 352) | struct view
  type open_flags (line 352) | enum open_flags
  type view (line 353) | struct view
  type view (line 354) | struct view
  type view (line 355) | struct view
  type line (line 362) | struct line
  type box (line 364) | struct box
  function box_text_length (line 369) | static inline size_t
  function box_sizeof (line 380) | static inline size_t
  type box (line 390) | struct box
  type line (line 392) | struct line
  type view (line 392) | struct view
  type line_type (line 392) | enum line_type
  type line (line 393) | struct line
  type view (line 393) | struct view
  type line_type (line 393) | enum line_type
  type line (line 394) | struct line
  type view (line 394) | struct view
  type line_type (line 394) | enum line_type
  type line (line 399) | struct line
  type view (line 399) | struct view
  type line_type (line 399) | enum line_type
  type line (line 400) | struct line
  type view (line 400) | struct view
  type line_type (line 400) | enum line_type
  type line (line 401) | struct line
  type view (line 401) | struct view
  type line_type (line 401) | enum line_type
  type line (line 402) | struct line
  type view (line 402) | struct view
  type line_type (line 402) | enum line_type
  type line (line 403) | struct line
  type view (line 404) | struct view
  type line (line 404) | struct line

FILE: include/tig/watch.h
  type watch_event (line 20) | enum watch_event {
  type watch_trigger (line 27) | enum watch_trigger {
  type watch (line 45) | struct watch {
  type watch (line 52) | struct watch
  type watch_trigger (line 52) | enum watch_trigger
  type watch (line 53) | struct watch
  type watch (line 54) | struct watch
  type watch_trigger (line 55) | enum watch_trigger
  type watch_event (line 55) | enum watch_event
  type watch_trigger (line 56) | enum watch_trigger
  type watch (line 56) | struct watch
  type watch_event (line 56) | enum watch_event
  type watch (line 57) | struct watch
  type watch_trigger (line 57) | enum watch_trigger

FILE: src/apps.c
  function app_oneline_buf (line 22) | static bool
  function app_git_exec_path (line 34) | static bool
  function app_diff_highlight_path_search (line 57) | static bool
  type app_external (line 97) | struct app_external
  type app_external (line 100) | struct app_external

FILE: src/argv.c
  function concat_argv (line 20) | static bool
  function argv_to_string_quoted (line 74) | bool
  function argv_to_string (line 80) | bool
  function split_argv_string (line 146) | static bool
  function argv_from_string_no_quotes (line 163) | bool
  function argv_from_string (line 169) | bool
  function argv_free (line 175) | void
  function argv_size (line 187) | size_t
  function argv_contains (line 198) | bool
  function argv_containsn (line 209) | bool
  function argv_appendn (line 222) | bool
  function argv_append (line 245) | bool
  function argv_append_array (line 251) | bool
  function argv_copy (line 262) | bool
  type format_context (line 278) | struct format_context
  type format_var (line 280) | struct format_var {
  type format_context (line 288) | struct format_context {
  type argv_env (line 298) | struct argv_env
  function format_expand_arg (line 302) | static bool
  function format_append_arg (line 343) | static bool
  function format_append_argv (line 372) | static bool
  function argv_string_formatter (line 387) | static bool
  function argv_number_formatter (line 402) | static bool
  function bool_formatter (line 410) | static bool
  function repo_str_formatter (line 418) | static bool
  function repo_ref_formatter (line 424) | static bool
  function repo_rev_formatter (line 430) | static bool
  function argv_format (line 436) | bool
  type format_context (line 447) | struct format_context
  function argv_find_rev_flag (line 496) | static inline bool
  function argv_parse_rev_flag (line 525) | bool
  type argv_env (line 621) | struct argv_env

FILE: src/blame.c
  type blame_history_state (line 30) | struct blame_history_state {
  type view_history (line 35) | struct view_history
  type blame_history_state (line 35) | struct blame_history_state
  type blame (line 37) | struct blame {
  type blame_state (line 43) | struct blame_state {
  function blame_update_file_name_visibility (line 56) | static void
  function blame_open (line 70) | static enum status_code
  type blame_commit (line 177) | struct blame_commit
  type view (line 178) | struct view
  type blame (line 183) | struct blame
  type blame_commit (line 193) | struct blame_commit
  type blame_commit (line 201) | struct blame_commit
  type view (line 202) | struct view
  type blame_state (line 202) | struct blame_state
  type blame_commit (line 204) | struct blame_commit
  function blame_read (line 216) | static bool
  function blame_get_column_data (line 274) | static bool
  function check_blame_commit (line 297) | static bool
  function setup_blame_parent_line (line 309) | static void
  function blame_go_forward (line 351) | static void
  function blame_go_back (line 386) | static void
  function blame_request (line 402) | static enum request
  function blame_select (line 488) | static void
  type view_ops (line 516) | struct view_ops
  type blame_state (line 520) | struct blame_state

FILE: src/blob.c
  type blob_state (line 24) | struct blob_state {
  function open_blob_view (line 29) | void
  function blob_open (line 63) | static enum status_code
  function blob_read (line 106) | static bool
  function blob_select (line 120) | static void
  function blob_request (line 132) | static enum request
  type view_ops (line 164) | struct view_ops
  type blob_state (line 168) | struct blob_state

FILE: src/diff.c
  function diff_open (line 25) | static enum status_code
  function diff_init_highlight (line 46) | enum status_code
  function diff_done_highlight (line 74) | bool
  type diff_stat_context (line 83) | struct diff_stat_context {
  function diff_common_add_cell (line 92) | static bool
  type line (line 109) | struct line
  type view (line 110) | struct view
  type line_type (line 110) | enum line_type
  type diff_stat_context (line 110) | struct diff_stat_context
  type line (line 114) | struct line
  type box (line 115) | struct box
  type box_cell (line 126) | struct box_cell
  function diff_common_add_cell_until (line 131) | static bool
  function diff_common_read_diff_stat_part (line 148) | static bool
  type line (line 163) | struct line
  type view (line 164) | struct view
  type diff_stat_context (line 166) | struct diff_stat_context
  type line (line 185) | struct line
  type view (line 186) | struct view
  function diff_common_read_diff_wdiff_group (line 217) | static bool
  function diff_common_read_diff_wdiff (line 269) | static bool
  function diff_common_highlight (line 288) | static bool
  function diff_common_read (line 305) | bool
  function diff_find_stat_entry (line 392) | static bool
  type line (line 401) | struct line
  type view (line 402) | struct view
  type line (line 402) | struct line
  function diff_common_enter (line 433) | enum request
  function diff_save_line (line 452) | void
  function diff_restore_line (line 467) | void
  function diff_read_describe (line 507) | static bool
  function diff_read (line 523) | static bool
  function diff_blame_line (line 586) | static bool
  function diff_get_lineno (line 625) | unsigned int
  function diff_trace_origin (line 656) | static enum request
  type view (line 728) | struct view
  type line (line 728) | struct line
  type line (line 730) | struct line
  function diff_common_edit (line 765) | enum request
  function diff_request (line 794) | static enum request
  function diff_common_select (line 822) | void
  function diff_select (line 869) | static void
  type view_ops (line 875) | struct view_ops
  type diff_state (line 879) | struct diff_state

FILE: src/display.c
  type view (line 32) | struct view
  type display_tty (line 39) | struct display_tty {
  type display_tty (line 45) | struct display_tty
  type io (line 47) | struct io
  function is_script_executing (line 49) | bool
  function open_script (line 55) | enum status_code
  function open_external_viewer (line 70) | bool
  function open_editor (line 129) | void
  function apply_horizontal_split (line 163) | static void
  function apply_vertical_split (line 173) | int
  function vertical_split_is_enabled (line 184) | bool
  function redraw_display_separator (line 192) | static void
  function create_or_move_display_separator (line 218) | static void create_or_move_display_separator(int height, int x)
  function remove_display_separator (line 231) | static void remove_display_separator(void)
  function resize_display (line 239) | void
  function redraw_display (line 317) | void
  function save_window_line (line 333) | static bool
  function save_window_vline (line 342) | static bool
  function save_display (line 356) | bool
  function save_view (line 406) | bool
  function update_status_window (line 477) | static bool
  function update_status (line 512) | void
  function update_status_with_context (line 522) | void
  function report (line 532) | void
  function report_clear (line 554) | void
  function done_display (line 570) | static void
  function set_terminal_modes (line 595) | static void
  function init_tty (line 605) | void
  function init_display (line 635) | void
  function read_script (line 694) | static bool
  function get_input_char (line 722) | int
  function update_views (line 747) | static bool
  function get_input (line 764) | int
  function enable_mouse (line 886) | void

FILE: src/draw.c
  type line_type (line 21) | enum line_type
  function set_view_attr (line 42) | static inline void
  function draw_chars (line 57) | static bool
  function draw_space (line 95) | static bool
  function draw_text_expanded (line 113) | static bool
  function draw_textn (line 135) | static inline bool
  function draw_text (line 141) | bool
  function draw_text_overflow (line 147) | static bool
  function PRINTF_LIKE (line 174) | bool PRINTF_LIKE(3, 4)
  function draw_field (line 210) | bool
  function draw_date (line 235) | static bool
  function draw_author (line 249) | static bool
  function draw_committer (line 262) | static bool
  function draw_id (line 275) | static bool
  function draw_filename (line 292) | static bool
  function draw_file_size (line 307) | static bool
  function draw_mode (line 318) | static bool
  function draw_lineno_custom (line 329) | static bool
  function draw_lineno (line 367) | bool
  function draw_ref (line 376) | static bool
  function draw_refs (line 385) | static bool
  function draw_status (line 406) | static bool
  function get_graph_color (line 419) | static inline enum line_type
  function draw_graph_utf8 (line 428) | static bool
  function draw_graph_ascii (line 436) | static bool
  function draw_graph_chtype (line 444) | static bool
  function draw_graph (line 452) | static bool
  function draw_commit_title (line 465) | static bool
  function view_column_draw (line 482) | bool
  function draw_view_line_search_result (line 620) | static void
  function draw_view_line (line 663) | bool
  function redraw_view_dirty (line 702) | void
  function redraw_view_from (line 723) | void
  function redraw_view (line 745) | void

FILE: src/graph-v1.c
  type graph_symbol (line 18) | struct graph_symbol {
  type graph_column (line 33) | struct graph_column {
  type graph_row (line 38) | struct graph_row {
  type graph_v1 (line 43) | struct graph_v1 {
  function get_free_graph_color (line 59) | static size_t get_free_graph_color(struct graph_v1 *graph)
  function done_graph (line 72) | static void
  function done_graph_rendering (line 80) | static void
  function graph_find_column_by_id (line 91) | static size_t
  type graph_column (line 107) | struct graph_column
  type graph_v1 (line 108) | struct graph_v1
  type graph_row (line 108) | struct graph_row
  type graph_column (line 110) | struct graph_column
  function graph_add_parent (line 128) | static bool
  function graph_needs_expansion (line 138) | static bool
  function graph_expand (line 148) | static bool
  function graph_needs_collapsing (line 160) | static bool
  function graph_collapse (line 167) | static bool
  function graph_reorder_parents (line 177) | static void
  function graph_canvas_append_symbol (line 198) | static void
  function graph_insert_parents (line 207) | static bool
  function graph_render_parents (line 300) | static bool
  function graph_is_merge (line 315) | static bool
  function graph_add_commit (line 321) | static bool
  type graph_symbol (line 351) | struct graph_symbol
  function chtype (line 389) | static const chtype *
  type graph_symbol (line 441) | struct graph_symbol
  function graph_foreach_symbol (line 476) | static void
  type graph (line 491) | struct graph
  type graph_v1 (line 494) | struct graph_v1
  type graph (line 495) | struct graph

FILE: src/graph-v2.c
  type graph_symbol (line 19) | struct graph_symbol {
  type graph_column (line 49) | struct graph_column {
  type graph_row (line 54) | struct graph_row {
  type colors (line 59) | struct colors {
  type graph_v2 (line 64) | struct graph_v2 {
  function intern_string_eq (line 84) | static int
  function hashval_t (line 90) | static hashval_t
  type id_color (line 113) | struct id_color {
  type id_color (line 118) | struct id_color
  type id_color (line 121) | struct id_color
  type id_color (line 121) | struct id_color
  function id_color_delete (line 131) | static void
  function id_color_eq (line 137) | static int
  function key_del (line 143) | static void
  function hashval_t (line 149) | static hashval_t
  function colors_add_id (line 155) | static void
  function colors_remove_id (line 169) | static void
  function colors_get_color (line 183) | static size_t
  function colors_get_free_color (line 197) | static size_t
  function colors_init (line 213) | static void
  function get_color (line 223) | static size_t
  function done_graph_rendering (line 244) | static void
  function done_graph (line 255) | static void
  function graph_find_column_by_id (line 271) | static size_t
  function graph_find_free_column (line 287) | static size_t
  type graph_column (line 300) | struct graph_column
  type graph_v2 (line 301) | struct graph_v2
  type graph_row (line 301) | struct graph_row
  type graph_column (line 303) | struct graph_column
  function graph_add_parent (line 323) | static bool
  function graph_needs_expansion (line 333) | static bool
  function graph_expand (line 339) | static bool
  function graph_needs_collapsing (line 356) | static bool
  function graph_collapse (line 363) | static bool
  function graph_canvas_append_symbol (line 375) | static void
  function graph_row_clear_commit (line 382) | static void
  function graph_insert_parents (line 394) | static void
  function commit_is_in_row (line 420) | static bool
  function graph_remove_collapsed_columns (line 435) | static void
  function graph_fill_empty_columns (line 466) | static void
  function graph_generate_next_row (line 479) | static void
  function commits_in_row (line 488) | static int
  function graph_commit_next_row (line 502) | static void
  function continued_down (line 522) | static bool
  function shift_left (line 534) | static bool
  function new_column (line 558) | static bool
  function continued_right (line 574) | static bool
  function continued_left (line 592) | static bool
  function parent_down (line 613) | static bool
  function parent_right (line 630) | static bool
  function flanked (line 651) | static bool
  function below_commit (line 672) | static bool
  function graph_generate_symbols (line 684) | static void
  function graph_render_parents (line 738) | static bool
  function graph_is_merge (line 762) | static bool
  function graph_add_commit (line 768) | static bool
  function graph_symbol_forks (line 796) | static bool
  function graph_symbol_cross_merge (line 811) | static bool
  function graph_symbol_vertical_merge (line 832) | static bool
  function graph_symbol_cross_over (line 856) | static bool
  function graph_symbol_turn_left (line 880) | static bool
  function graph_symbol_turn_down_cross_over (line 900) | static bool
  function graph_symbol_turn_down (line 921) | static bool
  function graph_symbol_merge (line 933) | static bool
  function graph_symbol_multi_merge (line 951) | static bool
  function graph_symbol_vertical_bar (line 963) | static bool
  function graph_symbol_horizontal_bar (line 990) | static bool
  function graph_symbol_multi_branch (line 1014) | static bool
  type graph_symbol (line 1038) | struct graph_symbol
  function chtype (line 1089) | static const chtype *
  type graph_symbol (line 1161) | struct graph_symbol
  function graph_foreach_symbol (line 1212) | static void
  type graph (line 1227) | struct graph
  type graph_v2 (line 1230) | struct graph_v2
  type graph (line 1231) | struct graph

FILE: src/graph.c
  type graph (line 17) | struct graph
  type graph (line 18) | struct graph
  type graph (line 20) | struct graph
  type graph_display (line 21) | enum graph_display

FILE: src/grep.c
  type grep_line (line 24) | struct grep_line {
  type grep_state (line 30) | struct grep_state {
  type grep_line (line 35) | struct grep_line
  type line (line 36) | struct line
  type grep_line (line 38) | struct grep_line
  function grep_get_column_data (line 47) | static bool
  function grep_select (line 76) | static void
  function grep_prompt (line 105) | static bool
  function open_grep_view (line 121) | void
  function grep_open (line 137) | static enum status_code
  function grep_request (line 165) | static enum request
  function grep_read (line 222) | static bool
  type view_ops (line 282) | struct view_ops
  type grep_state (line 286) | struct grep_state

FILE: src/help.c
  type menu_item (line 20) | struct menu_item
  type keymap (line 26) | struct keymap
  type keymap (line 29) | struct keymap
  type help_state (line 37) | struct help_state {
  type help (line 42) | struct help {
  function help_draw (line 54) | static bool
  function help_grep (line 114) | static bool
  type help_request_iterator (line 159) | struct help_request_iterator {
  function add_help_line (line 164) | static bool
  function help_keys_visitor (line 177) | static bool
  function help_collapse_expand_keys_visitor (line 216) | static bool
  function help_open (line 231) | static enum status_code
  function help_request (line 273) | static enum request
  function help_select (line 304) | static void
  type view_ops (line 309) | struct view_ops
  type help_state (line 313) | struct help_state

FILE: src/io.c
  type encoding (line 27) | struct encoding {
  type encoding (line 34) | struct encoding
  type encoding (line 35) | struct encoding
  type encoding (line 37) | struct encoding
  type encoding (line 40) | struct encoding
  function encoding_convert_string (line 67) | static bool
  function encoding_convert (line 112) | bool
  type buffer (line 122) | struct buffer
  type encoding (line 129) | struct encoding
  type encoding (line 130) | struct encoding
  function path_expand (line 166) | bool
  function path_search (line 197) | bool
  function io_init (line 242) | static void
  function io_open (line 249) | bool
  function io_kill (line 269) | bool
  function io_done (line 275) | bool
  function open_trace (line 306) | static int
  function io_trace (line 340) | bool
  function io_exec (line 364) | bool
  function io_run (line 457) | bool
  function io_complete (line 463) | static bool
  function io_run_bg (line 471) | bool
  function io_run_fg (line 477) | bool
  function io_run_append (line 483) | bool
  function io_eof (line 489) | bool
  function io_error (line 495) | int
  type io (line 502) | struct io
  function io_can_read (line 507) | bool
  function io_read (line 519) | ssize_t
  type buffer (line 536) | struct buffer
  function io_get_line (line 549) | static bool
  function io_get (line 613) | bool
  function io_write (line 619) | bool
  function io_printf (line 640) | bool
  function io_read_buf (line 655) | bool
  function io_run_buf (line 668) | bool
  function io_from_string (line 676) | bool
  function io_load_file (line 694) | static enum status_code
  function io_load_span (line 730) | enum status_code
  function io_load (line 737) | enum status_code
  function io_run_load (line 744) | enum status_code
  function io_fprintf (line 753) | bool

FILE: src/keys.c
  type keybinding (line 20) | struct keybinding {
  type keymap (line 26) | struct keymap
  type keymap (line 33) | struct keymap
  type keymap (line 36) | struct keymap
  type keymap (line 39) | struct keymap
  function update_keymap_visibility (line 51) | bool
  function keybinding_matches (line 68) | static bool
  function keybinding_equals (line 105) | static bool
  function del_keybinding (line 114) | static enum status_code
  function add_keybinding (line 139) | enum status_code
  function get_keybinding_in_keymap (line 180) | static enum request
  function get_keybinding (line 201) | enum request
  type key_mapping (line 231) | struct key_mapping {
  type key_mapping (line 236) | struct key_mapping
  type key_mapping (line 295) | struct key_mapping
  function parse_key_value (line 309) | static enum status_code
  function get_key_value (line 334) | enum status_code
  type key (line 388) | struct key
  function append_key (line 437) | static bool
  function append_keymap_request_keys (line 446) | static bool
  type keymap (line 465) | struct keymap
  type request (line 465) | enum request
  type run_request (line 492) | struct run_request
  function parse_run_request_flags (line 499) | enum status_code
  function add_run_request (line 532) | enum status_code
  type run_request (line 556) | struct run_request
  type request (line 557) | enum request
  type run_request (line 565) | struct run_request
  type key_visitor_state (line 593) | struct key_visitor_state {
  function foreach_key_visit (line 601) | static bool
  function foreach_key_request (line 645) | static bool
  function foreach_key_run_request (line 656) | static bool
  function foreach_key (line 687) | bool

FILE: src/line.c
  type line_rule (line 20) | struct line_rule
  type line_info (line 23) | struct line_info
  function get_line_type (line 29) | enum line_type
  function get_line_type_from_ref (line 50) | enum line_type
  type line_type (line 78) | enum line_type
  type line_info (line 84) | struct line_info
  type line_type (line 85) | enum line_type
  type line_info (line 87) | struct line_info
  type line_rule (line 88) | struct line_rule
  type line_info (line 102) | struct line_info
  type line_rule (line 105) | struct line_rule
  type line_rule (line 127) | struct line_rule
  type line_rule (line 128) | struct line_rule
  type line_type (line 130) | enum line_type
  type line_rule (line 137) | struct line_rule
  type line_info (line 150) | struct line_info
  type line_rule (line 151) | struct line_rule
  type line_rule (line 153) | struct line_rule
  type line_info (line 154) | struct line_info
  function foreach_line_rule (line 182) | bool
  function init_line_info_color_pair (line 197) | static void
  function init_colors (line 220) | void

FILE: src/log.c
  type log_state (line 21) | struct log_state {
  function log_copy_rev (line 33) | static inline void
  function log_select (line 43) | static void
  function log_open (line 66) | static enum status_code
  function log_request (line 85) | static enum request
  function log_read (line 109) | static bool
  type view_ops (line 158) | struct view_ops
  type log_state (line 162) | struct log_state

FILE: src/main.c
  type view_history (line 35) | struct view_history
  function main_status_exists (line 37) | bool
  type view (line 56) | struct view
  type main_state (line 56) | struct main_state
  function main_register_commit (line 58) | static void
  type commit (line 76) | struct commit
  type view (line 77) | struct view
  type line_type (line 77) | enum line_type
  type commit (line 77) | struct commit
  type main_state (line 80) | struct main_state
  type commit (line 82) | struct commit
  type line (line 84) | struct line
  function main_flush_commit (line 114) | static inline void
  function main_add_changes_commit (line 121) | static bool
  function main_check_index (line 158) | static bool
  function main_add_changes (line 190) | static bool
  function main_check_argv (line 217) | static bool
  function main_with_graph (line 267) | static enum graph_display
  function main_open (line 274) | static enum status_code
  function main_done (line 330) | void
  type ref (line 353) | struct ref
  type line (line 354) | struct line
  type commit (line 354) | struct commit
  type ref (line 356) | struct ref
  function main_get_column_data (line 364) | bool
  function main_add_reflog (line 390) | static bool
  function main_read (line 418) | bool
  function main_request (line 565) | enum request
  function main_select (line 646) | void
  type view_ops (line 675) | struct view_ops
  type main_state (line 679) | struct main_state

FILE: src/map.c
  function string_map_equal (line 22) | static int
  type string_map (line 32) | struct string_map
  type string_map (line 43) | struct string_map
  type string_map (line 54) | struct string_map
  type string_map (line 67) | struct string_map
  type string_map (line 79) | struct string_map
  function string_map_clear (line 92) | void
  type string_map_iterator (line 99) | struct string_map_iterator {
  function string_map_iterate (line 104) | static int
  function string_map_foreach (line 112) | void

FILE: src/options.c
  type option_info (line 38) | struct option_info
  type option_info (line 39) | struct option_info
  type option_info (line 68) | struct option_info
  function mark_option_seen (line 80) | static void
  type option_info (line 89) | struct option_info
  type view_column_type (line 90) | enum view_column_type
  type option_info (line 91) | struct option_info
  type enum_map_entry (line 175) | struct enum_map_entry
  type enum_map_entry (line 188) | struct enum_map_entry
  type graph_display (line 204) | enum graph_display
  type commit_order (line 206) | enum commit_order
  function update_options_from_argv (line 230) | void
  type enum_map_entry (line 313) | struct enum_map_entry
  type enum_map_entry (line 326) | struct enum_map_entry
  function parse_step (line 339) | enum status_code
  function parse_int (line 364) | enum status_code
  function set_color (line 377) | static bool
  function parse_color_name (line 392) | static enum status_code
  function find_remapped (line 456) | static int
  function option_color_command (line 475) | static enum status_code
  function parse_bool (line 556) | static enum status_code
  function parse_enum (line 566) | static enum status_code
  function parse_string (line 599) | static enum status_code
  function parse_encoding (line 617) | static enum status_code
  function parse_args (line 636) | static enum status_code
  function parse_option (line 644) | enum status_code
  function parse_view_settings (line 779) | static enum status_code
  function option_update (line 807) | static enum status_code
  function option_set_command (line 835) | static enum status_code
  function option_bind_command (line 901) | static enum status_code
  type status_code (line 1001) | enum status_code
  function option_source_command (line 1003) | static enum status_code
  function set_option (line 1028) | enum status_code
  type config_state (line 1046) | struct config_state {
  function read_option (line 1052) | static enum status_code
  function load_option_file (line 1091) | static enum status_code
  function load_options (line 1122) | enum status_code
  type option_info (line 1189) | struct option_info
  type author (line 1201) | enum author
  type enum_map (line 1202) | struct enum_map
  type ref_format (line 1255) | struct ref_format
  type view_column (line 1261) | struct view_column
  function save_option_settings (line 1274) | static bool
  function save_option_keybinding (line 1301) | static bool
  function save_option_keybindings (line 1332) | static bool
  function save_option_color_name (line 1341) | static bool
  function save_option_color_attr (line 1353) | static bool
  function save_option_color (line 1366) | static bool
  function save_option_colors (line 1391) | static bool
  function save_options (line 1400) | enum status_code
  function set_remote_branch (line 1424) | static void
  function set_repo_config_option (line 1439) | static void
  type line_info (line 1455) | struct line_info
  type line_info (line 1456) | struct line_info
  function set_git_color_option (line 1490) | static void
  function set_encoding (line 1527) | static void
  function read_repo_config_option (line 1536) | static enum status_code
  function load_git_config (line 1592) | enum status_code

FILE: src/pager.c
  function pager_get_column_data (line 29) | bool
  function add_pager_refs (line 37) | static void
  type line (line 71) | struct line
  type view (line 72) | struct view
  type line_type (line 72) | enum line_type
  type line (line 84) | struct line
  function pager_common_read (line 107) | bool
  function pager_read (line 137) | static bool
  function pager_request (line 156) | enum request
  function pager_select (line 188) | void
  function pager_open (line 202) | static enum status_code
  type view_ops (line 218) | struct view_ops
  type diff_state (line 222) | struct diff_state

FILE: src/parse.c
  function parse_size (line 18) | size_t
  function parse_timesec (line 36) | static void
  function parse_timezone (line 42) | static void
  function parse_author_line (line 59) | void
  function parse_number (line 95) | static bool
  function parse_blame_header (line 110) | bool
  function match_blame_header (line 129) | static bool
  function parse_blame_info (line 141) | bool
  function parse_ulong (line 206) | static bool
  function parse_chunk_header (line 226) | bool
  function parse_chunk_lineno (line 247) | bool
  type path_entry (line 265) | struct path_entry {
  type path_entry (line 276) | struct path_entry
  type ident (line 294) | struct ident
  type ident (line 298) | struct ident

FILE: src/prompt.c
  type input (line 30) | struct input
  type input_status (line 32) | enum input_status
  type key (line 34) | struct key
  function prompt_default_handler (line 109) | enum input_status
  function prompt_script_handler (line 129) | static enum input_status
  function prompt_yesno_handler (line 143) | static enum input_status
  function prompt_yesno (line 155) | bool
  type incremental_input (line 167) | struct incremental_input {
  function read_prompt_handler (line 173) | static enum input_status
  type incremental_input (line 193) | struct incremental_input
  type input (line 202) | struct input
  function readline_display (line 208) | static void
  function readline_getc (line 394) | static int
  function readline_display_matches (line 439) | static void
  function readline_init (line 457) | static void
  function sigint_absorb_handler (line 482) | static void sigint_absorb_handler(int sig) {
  function history_go_line (line 557) | static int
  function prompt_history_dedupe (line 566) | static void
  function prompt_teardown (line 595) | static void
  function prompt_init (line 605) | void
  function prompt_init (line 632) | void
  function prompt_menu (line 638) | bool
  type option_info (line 707) | struct option_info
  function find_arg (line 712) | static bool
  function prompt_toggle_option (line 723) | static enum status_code
  function prompt_toggle (line 847) | static enum status_code
  function prompt_option_flags (line 894) | static enum view_flag
  function prompt_update_display (line 924) | static void
  function run_prompt_command (line 943) | enum request
  function exec_run_request (line 1128) | enum request
  function open_prompt (line 1190) | enum request

FILE: src/refdb.c
  type ref (line 23) | struct ref
  function ref_compare (line 29) | int
  function ref_canonical_compare (line 37) | static int
  type ref_visitor_data (line 49) | struct ref_visitor_data {
  function foreach_ref_visitor (line 54) | static bool
  function foreach_ref (line 65) | void
  type ref (line 73) | struct ref
  type ref (line 79) | struct ref
  type ref (line 85) | struct ref
  type ref (line 88) | struct ref
  type ref (line 89) | struct ref
  function ref_list_contains_tag (line 98) | bool
  type ref_opt (line 110) | struct ref_opt {
  function add_ref_to_id_map (line 116) | static enum status_code
  function remove_ref_from_id_map (line 159) | static void
  function add_to_refs (line 182) | static enum status_code
  function read_ref (line 297) | static enum status_code
  function invalidate_refs (line 303) | static bool
  function cleanup_refs (line 313) | static bool
  function reload_refs (line 327) | static enum status_code
  function load_refs (line 374) | enum status_code
  function add_ref (line 386) | enum status_code
  function ref_update_env (line 394) | void
  function refs_contain_tag (line 424) | bool
  type ref_format (line 430) | struct ref_format
  type ref_format (line 431) | struct ref_format
  type ref (line 431) | struct ref
  type ref_format (line 433) | struct ref_format
  type ref_format (line 436) | struct ref_format
  function parse_ref_format_arg (line 451) | static enum status_code
  function parse_ref_formats (line 488) | enum status_code
  function format_ref_formats (line 509) | enum status_code

FILE: src/reflog.c
  function reflog_open (line 19) | static enum status_code
  function reflog_request (line 36) | static enum request
  type view_ops (line 63) | struct view_ops
  type main_state (line 67) | struct main_state

FILE: src/refs.c
  type reference (line 27) | struct reference {
  type ref (line 36) | struct ref
  type refs_filter (line 43) | enum refs_filter {
  function refs_get_column_data (line 51) | static bool
  function refs_request (line 70) | static enum request
  function refs_read (line 103) | static bool
  function refs_open_visitor (line 149) | static bool
  function refs_open (line 196) | static enum status_code
  function refs_select (line 257) | static void
  type view_ops (line 273) | struct view_ops

FILE: src/repo.c
  type repo_info_state (line 28) | struct repo_info_state {
  function read_repo_info (line 32) | static enum status_code
  function reload_repo_info (line 90) | static enum status_code
  function load_repo_info (line 99) | enum status_code
  function load_repo_head (line 113) | enum status_code
  type repo_info (line 132) | struct repo_info
  function update_index (line 138) | bool
  function index_diff (line 148) | bool

FILE: src/request.c
  type request_info (line 18) | struct request_info
  function get_request (line 26) | enum request
  type request (line 40) | enum request
  function foreach_request (line 50) | bool

FILE: src/search.c
  function grep_text (line 23) | bool
  function find_matches (line 34) | static bool
  type status_code (line 59) | enum status_code
  type view (line 59) | struct view
  type request (line 59) | enum request
  function setup_and_find_next (line 61) | static enum status_code
  function find_next_match_line (line 100) | static enum status_code
  function find_next_match (line 129) | static enum status_code
  function find_next (line 166) | void
  function find_next_merge_line (line 174) | static enum status_code
  function find_next_merge (line 211) | static enum status_code
  function find_merge (line 226) | void
  function reset_search (line 234) | void
  function search_view (line 242) | void

FILE: src/stage.c
  type status (line 30) | struct status
  type line_type (line 31) | enum line_type
  type update_t (line 33) | typedef enum
  function open_stage_view (line 40) | void
  type stage_state (line 54) | struct stage_state {
  function stage_diff_done (line 58) | static inline bool
  function stage_diff_write (line 66) | static bool
  function stage_diff_range_write (line 83) | static bool
  function stage_apply_line (line 117) | static bool
  function stage_apply_part (line 139) | static bool
  function stage_apply_chunk (line 193) | static bool
  function stage_update_files (line 239) | static bool
  function stage_update (line 263) | static bool
  function stage_revert (line 293) | static bool
  type line (line 317) | struct line
  type view (line 318) | struct view
  type chunk_header (line 318) | struct chunk_header
  type line (line 319) | struct line
  type line (line 319) | struct line
  type line (line 319) | struct line
  type box (line 321) | struct box
  type line (line 346) | struct line
  function stage_split_chunk (line 356) | static void
  function stage_exists (line 418) | static bool
  function stage_chunk_is_wrapped (line 432) | static bool
  function find_deleted_line_in_head (line 447) | static bool
  function stage_request (line 559) | static enum request
  function stage_select (line 698) | static void
  function stage_open (line 708) | static enum status_code
  function stage_read (line 787) | static bool
  type view_ops (line 821) | struct view_ops
  type stage_state (line 825) | struct stage_state

FILE: src/stash.c
  function stash_open (line 20) | static enum status_code
  function stash_select (line 55) | static void
  function stash_request (line 68) | static enum request
  type view_ops (line 99) | struct view_ops
  type main_state (line 103) | struct main_state

FILE: src/status.c
  function open_status_view (line 38) | void
  function status_has_none (line 49) | static inline bool
  function status_get_diff (line 58) | inline bool
  function status_run (line 88) | static bool
  function status_restore (line 201) | static void
  function status_branch_tracking_info (line 228) | static bool
  function status_update_onbranch (line 293) | static void
  function status_read_untracked (line 361) | static bool
  function status_open (line 379) | static enum status_code
  function status_get_column_data (line 410) | static bool
  function status_enter (line 467) | static enum request
  function status_exists (line 508) | bool
  function status_update_prepare (line 533) | static bool
  function status_update_write (line 557) | static bool
  function status_update_file (line 575) | bool
  function status_update_files (line 595) | bool
  function status_update (line 632) | static bool
  function status_revert (line 661) | bool
  function open_mergetool (line 706) | static void
  function status_request (line 714) | static enum request
  function status_stage_info_ (line 784) | bool
  function status_select (line 818) | static void
  type view_ops (line 865) | struct view_ops

FILE: src/string.c
  function string_isnumber (line 22) | bool
  function iscommit (line 35) | bool
  function suffixcmp (line 48) | int
  function string_ncopy_do (line 57) | void
  function string_copy_rev (line 67) | void
  function string_copy_rev_from_commit_line (line 82) | void
  function string_expand (line 91) | size_t
  function PRINTF_LIKE (line 137) | bool PRINTF_LIKE(4, 5)
  function strcmp_null (line 150) | int
  function strcmp_numeric (line 160) | int
  function unicode_width (line 191) | int
  function utf8_char_length (line 210) | unsigned char
  function utf8_to_unicode (line 219) | unsigned long
  function utf8_length (line 237) | size_t
  function utf8_width_of (line 290) | int
  function utf8_string_contains (line 301) | static bool
  function utf8_string_contains_uppercase (line 326) | bool

FILE: src/tig.c
  type menu_item (line 88) | struct menu_item
  function toggle_option (line 94) | static void
  function open_run_request (line 112) | static enum request
  function view_driver (line 129) | static bool
  function usage (line 385) | void
  function read_filter_args (line 391) | static enum status_code
  function filter_rev_parse (line 399) | static bool
  function filter_options (line 416) | static void
  function parse_options (line 471) | static enum request
  function open_pager_mode (line 584) | static enum request
  type view (line 613) | struct view
  type view (line 616) | struct view
  function handle_mouse_event (line 633) | static enum request
  function sigsegv_handler (line 691) | void
  function sighup_handler (line 720) | static void
  type key_combo (line 729) | struct key_combo {
  function key_combo_handler (line 737) | static enum input_status
  function read_key_combo (line 763) | static enum request
  function die_if_failed (line 772) | static inline void
  function hangup_children (line 779) | static void
  function handle_git_prefix (line 787) | static inline enum status_code
  function main (line 813) | int

FILE: src/tree.c
  type view_history (line 26) | struct view_history
  function pop_tree_stack_entry (line 28) | static void
  function push_tree_stack_entry (line 37) | static void
  type tree_entry (line 62) | struct tree_entry {
  type tree_state (line 74) | struct tree_state {
  type line (line 84) | struct line
  type tree_entry (line 86) | struct tree_entry
  function tree_compare_entry (line 89) | static int
  function tree_get_column_data (line 97) | static bool
  type line (line 122) | struct line
  type view (line 123) | struct view
  type line_type (line 123) | enum line_type
  type tree_entry (line 127) | struct tree_entry
  type line (line 128) | struct line
  function tree_read_date (line 143) | static bool
  function tree_read (line 224) | static bool
  function tree_draw (line 322) | static bool
  function open_blob_editor (line 335) | void
  function tree_request (line 362) | static enum request
  function tree_select (line 440) | static void
  function tree_open (line 464) | static enum status_code
  type view_ops (line 497) | struct view_ops
  type tree_state (line 501) | struct tree_state

FILE: src/types.c
  function string_enum_compare (line 21) | int
  function enum_name_copy (line 41) | bool
  function enum_name_prefixed (line 64) | bool
  type enum_map (line 78) | struct enum_map
  type enum_map (line 83) | struct enum_map
  function map_enum_do (line 96) | bool

FILE: src/ui.c
  type file_finder_line (line 22) | struct file_finder_line {
  type file_finder (line 29) | struct file_finder {
  function file_finder_read (line 44) | static bool
  function file_finder_done (line 82) | static void
  function file_finder_move (line 98) | static void
  function file_finder_draw_line (line 119) | static void
  function file_finder_draw (line 139) | static void
  function file_finder_line_matches (line 174) | static size_t
  function file_finder_update (line 189) | static void
  function file_finder_input_handler (line 226) | static enum input_status
  type file_finder (line 283) | struct file_finder

FILE: src/util.c
  type status_code (line 31) | enum status_code
  function error (line 44) | enum status_code
  function success (line 55) | enum status_code
  function warn (line 66) | void
  function die (line 79) | void TIG_NORETURN
  function time_now (line 100) | int
  function timecmp (line 122) | int
  type reldate (line 128) | struct reldate {
  type reldate (line 134) | struct reldate
  type time (line 145) | struct time
  type timeval (line 147) | struct timeval
  type time (line 181) | struct time
  type date (line 181) | enum date
  type tm (line 184) | struct tm
  type file_size (line 266) | enum file_size
  type ident (line 299) | struct ident
  function ident_compare (line 305) | int
  type ident (line 370) | struct ident
  type author (line 370) | enum author
  type status_label (line 404) | enum status_label

FILE: src/view.c
  function goto_view_line (line 28) | bool
  function do_scroll_view (line 53) | void
  function scroll_view (line 99) | void
  function move_view (line 191) | void
  function select_view_line (line 303) | void
  function goto_id (line 323) | void
  function view_history_is_empty (line 383) | static bool
  type view_state (line 389) | struct view_state
  type view_history (line 390) | struct view_history
  type position (line 390) | struct position
  type view_state (line 392) | struct view_state
  function pop_view_history_state (line 412) | bool
  function reset_view_history (line 432) | void
  function reset_view (line 443) | void
  function restore_view_position (line 469) | static bool
  function end_update (line 494) | void
  function setup_update (line 508) | static void
  function view_no_refresh (line 518) | static bool
  type view (line 528) | struct view
  type open_flags (line 528) | enum open_flags
  function view_exec (line 550) | bool
  function begin_update (line 574) | enum status_code
  function update_view (line 621) | bool
  function update_view_title (line 686) | void
  function split_view (line 742) | void
  function maximize_view (line 777) | void
  function load_view (line 800) | void
  function open_view (line 866) | void
  function open_argv (line 899) | void
  type view (line 917) | struct view
  function compare_view_column (line 926) | static int
  type view_column_type (line 981) | enum view_column_type
  function sort_view_compare (line 997) | static int
  function resort_view (line 1027) | void
  function sort_view (line 1042) | void
  type view (line 1064) | struct view
  type view_column_data (line 1064) | struct view_column_data
  type view_column (line 1065) | struct view_column
  function grep_refs (line 1135) | static bool
  function view_column_grep (line 1148) | bool
  function view_column_info_changed (line 1185) | bool
  function view_column_reset (line 1203) | void
  function parse_view_column_config_expr (line 1213) | static enum status_code
  function parse_view_column_option (line 1248) | static enum status_code
  function parse_view_column_config_exprs (line 1273) | static enum status_code
  function parse_view_column_type (line 1295) | static enum status_code
  type view (line 1311) | struct view
  type view (line 1314) | struct view
  function parse_view_column_config (line 1324) | enum status_code
  function parse_view_config (line 1348) | enum status_code
  function format_view_column_options (line 1402) | static enum status_code
  function format_view_column (line 1453) | static enum status_code
  function format_view_config (line 1474) | enum status_code
  type view_column (line 1500) | struct view_column
  type view (line 1501) | struct view
  type view_column_type (line 1501) | enum view_column_type
  type view_column (line 1503) | struct view_column
  function view_column_info_update (line 1513) | bool
  type line (line 1611) | struct line
  type view (line 1612) | struct view
  type line (line 1612) | struct line
  type line_type (line 1612) | enum line_type
  type line_type (line 1612) | enum line_type
  function forward_request_to_child (line 1623) | static inline bool
  function view_request (line 1630) | enum request
  type box (line 1662) | struct box
  function box_text_copy (line 1667) | void
  type line (line 1676) | struct line
  type view (line 1677) | struct view
  type line_type (line 1677) | enum line_type
  type line (line 1679) | struct line
  type line (line 1724) | struct line
  type view (line 1725) | struct view
  type line_type (line 1725) | enum line_type
  type line (line 1730) | struct line
  type view (line 1731) | struct view
  type line_type (line 1731) | enum line_type
  type line (line 1733) | struct line
  type line (line 1740) | struct line
  type view (line 1741) | struct view
  type line_type (line 1741) | enum line_type
  type line (line 1746) | struct line
  type view (line 1747) | struct view
  type line_type (line 1747) | enum line_type
  type box (line 1749) | struct box
  type line (line 1750) | struct line
  type line (line 1765) | struct line
  type view (line 1766) | struct view
  type line_type (line 1766) | enum line_type
  type line (line 1778) | struct line
  type view (line 1779) | struct view
  type line_type (line 1779) | enum line_type
  type line (line 1784) | struct line
  function append_line_format (line 1794) | bool
  type view (line 1849) | struct view
  type view (line 1854) | struct view

FILE: src/watch.c
  type watch (line 21) | struct watch
  function watch_register (line 23) | void
  function watch_unregister (line 36) | void
  type watch_handler (line 54) | struct watch_handler {
  function check_file_mtime (line 61) | static bool
  function watch_head_handler (line 80) | static enum watch_trigger
  function watch_stash_handler (line 96) | static enum watch_trigger
  function watch_index_handler (line 105) | static enum watch_trigger
  function watch_refs_handler (line 145) | static enum watch_trigger
  type watch_handler (line 161) | struct watch_handler
  function watch_no_refresh (line 168) | static bool
  function watch_apply_changes (line 176) | static void
  function watch_apply (line 202) | void
  function watch_update_event (line 208) | static enum watch_trigger
  function watch_unchanged_triggers (line 244) | static inline enum watch_trigger
  function watch_update_single (line 250) | enum watch_trigger
  function watch_update (line 258) | enum watch_trigger
  function watch_periodic (line 272) | int
  function watch_dirty (line 292) | bool

FILE: test/tools/test-graph.c
  type commit (line 26) | struct commit {
  type graph_symbol (line 33) | struct graph_symbol
  function print_symbol (line 35) | static bool
  function print_commit (line 44) | static void
  function main (line 51) | int

FILE: tools/doc-gen.c
  type doc_action_iterator (line 18) | struct doc_action_iterator {
  function doc_action_group_name_print (line 23) | static void
  function doc_action_table_print (line 32) | static void
  function doc_action_print (line 40) | static bool
  function doc_actions_print (line 62) | static void
  function main (line 71) | int
Condensed preview — 308 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,070K chars).
[
  {
    "path": ".bookignore",
    "chars": 297,
    "preview": "# Blacklist most files since documentation is co-located with the rest\n# of the source to avoid that GitBook copies them"
  },
  {
    "path": ".github/workflows/linux.yml",
    "chars": 892,
    "preview": "name: Linux\n\non: [push, pull_request]\n\njobs:\n  ci:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        compi"
  },
  {
    "path": ".github/workflows/macos.yml",
    "chars": 1779,
    "preview": "name: macOS\n\non: [push, pull_request]\n\njobs:\n  install:\n    runs-on: macos-latest\n    if: github.ref == 'refs/heads/mast"
  },
  {
    "path": ".gitignore",
    "chars": 454,
    "preview": "*.gcno\n*.gcda\n*.html\n*.o\n*.swp\n*~\n.deps\n/_book\n/config.make\n/node_modules/\naclocal.m4\nautom4te.cache\n/compile_commands/\n"
  },
  {
    "path": ".mailmap",
    "chars": 208,
    "preview": "Jonas Fonseca <jonas.fonseca@gmail.com> <fonseca@diku.dk>\nJonas Fonseca <jonas.fonseca@gmail.com> <jonas.fonseca@savoirf"
  },
  {
    "path": "COPYING",
    "chars": 18092,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
  },
  {
    "path": "INSTALL.adoc",
    "chars": 8407,
    "preview": "Installation instructions\n=========================\n:docext: adoc\n\nDownload a tarball from https://github.com/jonas/tig/"
  },
  {
    "path": "Makefile",
    "chars": 14890,
    "preview": "## Makefile for tig\n\n# The last tagged version. Can be overridden either by the version from\n# git or from the value of "
  },
  {
    "path": "NEWS.adoc",
    "chars": 62174,
    "preview": "Release notes\n=============\n\ntig-2.6.0\n---------\n\nBug fixes:\n\n - Initialise %(head) from command line arguments. (#1366)"
  },
  {
    "path": "README.adoc",
    "chars": 1870,
    "preview": "Tig: text-mode interface for Git\n================================\n:docext: adoc\n\nimage:https://github.com/jonas/tig/work"
  },
  {
    "path": "appveyor.yml",
    "chars": 570,
    "preview": "environment:\n  matrix:\n  - TARGET: cygwin64\n    ARCH: x86_64\n\ninstall:\n - appveyor DownloadFile https://cygwin.com/setup"
  },
  {
    "path": "autogen.sh",
    "chars": 517,
    "preview": "#!/bin/sh\n\nexport WARNINGS=\"all\"\nset -e\n\n# Ideally, we could just do this:\n#\n#${AUTORECONF:-autoreconf} -v -I tools\n#\n# "
  },
  {
    "path": "book.json",
    "chars": 283,
    "preview": "{\n  \"gitbook\": \"3.2.x\",\n  \"title\": \"Tig - Text-mode interface for Git\",\n  \"structure\": {\n     \"readme\": \"README.adoc\",\n "
  },
  {
    "path": "book.md",
    "chars": 309,
    "preview": "# Summary\n\n - [Installation](INSTALL.adoc)\n - [Release notes](NEWS.adoc)\n - [tig(1)](doc/tig.1.adoc)\n - [tigrc(5)](doc/t"
  },
  {
    "path": "compat/ansidecl.h",
    "chars": 11777,
    "preview": "/* Compiler compatibility macros\n   Copyright (C) 1991-2025 Free Software Foundation, Inc.\n   This file is part of the G"
  },
  {
    "path": "compat/compat.h",
    "chars": 1684,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n * Copyright (c) 2013 Drew Northup <n1xim.email@gmail"
  },
  {
    "path": "compat/hashtab.c",
    "chars": 29825,
    "preview": "/* An expandable hash tables datatype.\n   Copyright (C) 1999-2025 Free Software Foundation, Inc.\n   Contributed by Vladi"
  },
  {
    "path": "compat/hashtab.h",
    "chars": 7398,
    "preview": "/* An expandable hash tables datatype.\n   Copyright (C) 1999-2025 Free Software Foundation, Inc.\n   Contributed by Vladi"
  },
  {
    "path": "compat/mkstemps.c",
    "chars": 3881,
    "preview": "/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc.\n   This file is derived from mkstemp.c from"
  },
  {
    "path": "compat/setenv.c",
    "chars": 4647,
    "preview": "/* Copyright (C) 1992, 1995, 1996, 1997, 2002, 2011 Free Software Foundation,\n   Inc.\n   This file based on setenv.c in "
  },
  {
    "path": "compat/strndup.c",
    "chars": 1495,
    "preview": "/* Implement the strndup function.\n   Copyright (C) 2005 Free Software Foundation, Inc.\n   Written by Kaveh R. Ghazi <gh"
  },
  {
    "path": "compat/utf8proc.c",
    "chars": 32688,
    "preview": "/* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */\n/*\n *  Copyright (c) 2014-2021 Steven G. J"
  },
  {
    "path": "compat/utf8proc.h",
    "chars": 33793,
    "preview": "/*\n * Copyright (c) 2014-2021 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other cont"
  },
  {
    "path": "compat/utf8proc.license.md",
    "chars": 5125,
    "preview": "## utf8proc license ##\n\n**utf8proc** is a software package originally developed\nby Jan Behrens and the rest of the Publi"
  },
  {
    "path": "compat/utf8proc_data.c",
    "chars": 2360214,
    "preview": "static const utf8proc_uint16_t utf8proc_sequences[] = {\n  97, 98, 99, 100, 101, 102, 103, \n  104, 105, 106, 107, 108, 10"
  },
  {
    "path": "compat/wordexp.c",
    "chars": 1495,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "config.make.in",
    "chars": 858,
    "preview": "# -*- makefile-gmake -*-\n\nprefix = @prefix@\nexec_prefix = @exec_prefix@\nbindir = @bindir@\nmandir = @mandir@\ndocdir = @do"
  },
  {
    "path": "configure.ac",
    "chars": 2465,
    "preview": "AC_INIT([tig],[0],[jonas.fonseca@gmail.com],[tig])\n\nAC_LANG([C])\nAC_CONFIG_HEADERS([config.h])\nAC_CONFIG_SRCDIR(src)\n\ndn"
  },
  {
    "path": "contrib/bindings-v1.x.tigrc",
    "chars": 654,
    "preview": "# Bindings from before version 2.0\n#\n# To use these bindings copy the file to your HOME directory and include\n# it from "
  },
  {
    "path": "contrib/chocolate.theme.tigrc",
    "chars": 417,
    "preview": "color diff-stat\t\t\t95\tdefault\ncolor date\t\t\t172\tdefault\ncolor \"Merge: \"\t\t\tcyan\tdefault\ncolor graph-commit\t\tred\tdefault\ncol"
  },
  {
    "path": "contrib/config.make",
    "chars": 656,
    "preview": "# Example config.make.\n\n# Install files under /usr/local instead of under $HOME.\nprefix=/usr/local\n\n# Use ncursesw.\nLDLI"
  },
  {
    "path": "contrib/config.make-CYGWIN_NT-6.1",
    "chars": 489,
    "preview": "# Example configuration for Cygwin (`uname -s` = CYGWIN_NT-6.1)\n#\n# Use ncursesw.\n\nNCURSESW_LIBS = $(shell ncursesw6-con"
  },
  {
    "path": "contrib/config.make-Darwin",
    "chars": 1032,
    "preview": "# Example configuration for Darwin / macOS.\n\nifeq ($(origin HOMEBREW_PREFIX), undefined)\nHOMEBREW_PREFIX := $(shell brew"
  },
  {
    "path": "contrib/config.make-Linux",
    "chars": 136,
    "preview": "# Example configuration for Linux.\n#\n# Use ncursesw.\n\nTIG_NCURSES = -lncursesw\nTIG_CPPFLAGS = -DHAVE_NCURSESW_CURSES_H\n\n"
  },
  {
    "path": "contrib/git-flow.tigrc",
    "chars": 1988,
    "preview": "# Bindings for git-flow.\n#\n# Flow bindings start with the capital F and then follow the first character of\n# each operat"
  },
  {
    "path": "contrib/large-repo.tigrc",
    "chars": 701,
    "preview": "# Settings for speeding up Tig in large repositories\n#\n# To use these settings copy the file to your HOME directory and "
  },
  {
    "path": "contrib/tig-completion.bash",
    "chars": 3118,
    "preview": "# bash/zsh completion for tig\n#\n# Copyright (C) 2019 Roland Hieber, Pengutronix\n# Copyright (C) 2006-2026 Jonas fonseca\n"
  },
  {
    "path": "contrib/tig-completion.zsh",
    "chars": 827,
    "preview": "#compdef tig\n#\n# zsh completion wrapper for tig\n# ==============================\n#\n# You need to install this script to "
  },
  {
    "path": "contrib/tig-pick",
    "chars": 1302,
    "preview": "#!/bin/sh\n#\n# 'tig-pick' is a wrapper script that uses 'tig' to pick a Git commit from the\n# history. On success, The sc"
  },
  {
    "path": "contrib/tig.spec.in",
    "chars": 2528,
    "preview": "# -*- mode: rpm-spec-mode; encoding: utf-8; -*-\n# Pass '--without docs' to rpmbuild if you don't want the documentation "
  },
  {
    "path": "contrib/vim.tigrc",
    "chars": 1955,
    "preview": "# Vim-style keybindings for Tig\n#\n# To use these keybindings copy the file to your HOME directory and include\n# it from "
  },
  {
    "path": "doc/asciidoc.conf",
    "chars": 1543,
    "preview": "[macros]\n(?su)[\\\\]?(?P<name>manpage):(?P<target>\\S*?)\\[(?P<attrlist>.*?)\\]=\n\nifdef::backend-docbook[]\n[manpage-inlinemac"
  },
  {
    "path": "doc/manual.adoc",
    "chars": 25478,
    "preview": "ifndef::doctype-manpage[]\nThe Tig Manual\n==============\nJonas Fonseca <jonas.fonseca@gmail.com>\nendif::doctype-manpage[]"
  },
  {
    "path": "doc/tig.1.adoc",
    "chars": 10943,
    "preview": "tig(1)\n======\n:docext: adoc\n:sysconfdir: /etc\n\nNAME\n----\ntig - text-mode interface for Git\n\nSYNOPSIS\n--------\n[verse]\n__"
  },
  {
    "path": "doc/tigmanual.7.adoc",
    "chars": 325,
    "preview": "tigmanual(7)\n============\n\nNAME\n----\ntigmanual - text-mode interface for Git\n\nSYNOPSIS\n--------\n[verse]\ntig        [opti"
  },
  {
    "path": "doc/tigrc.5.adoc",
    "chars": 46691,
    "preview": "tigrc(5)\n========\n:docext: adoc\n\nNAME\n----\ntigrc - Tig configuration file\n\n\nSYNOPSIS\n--------\n[verse]\n__________________"
  },
  {
    "path": "include/tig/apps.h",
    "chars": 926,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/argv.h",
    "chars": 3057,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/blame.h",
    "chars": 837,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/blob.h",
    "chars": 777,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/diff.h",
    "chars": 2036,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/display.h",
    "chars": 2266,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/draw.h",
    "chars": 1603,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/git.h",
    "chars": 3105,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/graph.h",
    "chars": 1872,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/grep.h",
    "chars": 754,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/help.h",
    "chars": 919,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/io.h",
    "chars": 4158,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/keys.h",
    "chars": 3083,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/line.h",
    "chars": 4354,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/log.h",
    "chars": 827,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/main.h",
    "chars": 2048,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/map.h",
    "chars": 1990,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/options.h",
    "chars": 8350,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/pager.h",
    "chars": 1195,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/parse.h",
    "chars": 2343,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/prompt.h",
    "chars": 1682,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/refdb.h",
    "chars": 2379,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/reflog.h",
    "chars": 842,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/refs.h",
    "chars": 832,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/repo.h",
    "chars": 1436,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/request.h",
    "chars": 4177,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/search.h",
    "chars": 955,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/stage.h",
    "chars": 842,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/stash.h",
    "chars": 837,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/status.h",
    "chars": 1598,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/string.h",
    "chars": 4318,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/tig.h",
    "chars": 4690,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/tree.h",
    "chars": 911,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/types.h",
    "chars": 5153,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/ui.h",
    "chars": 707,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/util.h",
    "chars": 3075,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/view.h",
    "chars": 13058,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "include/tig/watch.h",
    "chars": 1990,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "snap/snapcraft.yaml",
    "chars": 727,
    "preview": "name: tig\nversion: git\nsummary: Text-mode interface for git\nlicense: GPL-2.0-or-later\ndescription: |\n  Tig is an ncurses"
  },
  {
    "path": "src/apps.c",
    "chars": 3650,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/argv.c",
    "chars": 13666,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/blame.c",
    "chars": 14324,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/blob.c",
    "chars": 4915,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/diff.c",
    "chars": 24192,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/display.c",
    "chars": 20112,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/draw.c",
    "chars": 19409,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/graph-v1.c",
    "chars": 11148,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/graph-v2.c",
    "chars": 26419,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/graph.c",
    "chars": 923,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/grep.c",
    "chars": 7083,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/help.c",
    "chars": 8457,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/io.c",
    "chars": 16222,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/keys.c",
    "chars": 17627,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/line.c",
    "chars": 6475,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/log.c",
    "chars": 4677,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/main.c",
    "chars": 18413,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/map.c",
    "chars": 2641,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/options.c",
    "chars": 42202,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/pager.c",
    "chars": 5678,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/parse.c",
    "chars": 7164,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/prompt.c",
    "chars": 28268,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/refdb.c",
    "chars": 12397,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/reflog.c",
    "chars": 2333,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/refs.c",
    "chars": 7902,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/repo.c",
    "chars": 5535,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/request.c",
    "chars": 1733,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/search.c",
    "chars": 6385,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/stage.c",
    "chars": 22373,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/stash.c",
    "chars": 3481,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/status.c",
    "chars": 21981,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/string.c",
    "chars": 7304,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/tig.c",
    "chars": 21189,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/tree.c",
    "chars": 12723,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/types.c",
    "chars": 2505,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/ui.c",
    "chars": 7541,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/util.c",
    "chars": 10090,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/view.c",
    "chars": 45368,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "src/watch.c",
    "chars": 7808,
    "preview": "/* Copyright (c) 2006-2026 Jonas Fonseca <jonas.fonseca@gmail.com>\n *\n * This program is free software; you can redistri"
  },
  {
    "path": "test/API.adoc",
    "chars": 1234,
    "preview": "Testing API\n-----------\n\nfile(filename, [content, ...]) [< content]::\n\ntig_script(name, content, [content, ...])::\n\nstep"
  },
  {
    "path": "test/README.adoc",
    "chars": 2552,
    "preview": "Test Overview\n=============\n\nAll tests can be run with `make test`. This will run all scripts that\nend with `-test` in t"
  },
  {
    "path": "test/blame/blob-blame-test",
    "chars": 2730,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=200\n\nin_work_dir create_repo_from_tgz \"$base_dir/files/scala-js-benc"
  },
  {
    "path": "test/blame/default-test",
    "chars": 7099,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\ntigrc <<EOF\nset vertical-split = no\nset line-graphics = ascii\nset blame-view-date-u"
  },
  {
    "path": "test/blame/initial-diff-test",
    "chars": 2341,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nsteps '\n\t:save-display initial-diff.screen\n\t:20 # Move to a deleted line.\n\t:view-bl"
  },
  {
    "path": "test/blame/navigation-parent-test",
    "chars": 2928,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=200\n\n# The test checks that pressing ',' in blame view correctly nav"
  },
  {
    "path": "test/blame/revargs-test",
    "chars": 4680,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nsteps '\n\t:save-display limit.screen\n\n\t:8\n\t:parent\n\t:save-display parent-of-4779f9b."
  },
  {
    "path": "test/blame/start-on-line-test",
    "chars": 4862,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=200\n\nin_work_dir create_repo_from_tgz \"$base_dir/files/scala-js-benc"
  },
  {
    "path": "test/blame/stash-test",
    "chars": 885,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\ntigrc <<EOF\nset blame-view = text\nEOF\n\nsteps '\n\t:view-stash\n\t:view-diff\n\t:move-last"
  },
  {
    "path": "test/blob/wrap-lines-test",
    "chars": 795,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=40\n\nsteps '\n\t:view-tree\n\t:/README.md\n\t:view-blob\n\t:save-display wrap"
  },
  {
    "path": "test/diff/diff-context-test",
    "chars": 6584,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nsteps '\n\t:save-display diff-default.screen\n\n\t:21\n\t]\n\t:save-display diff-u4.screen\n\n"
  },
  {
    "path": "test/diff/diff-highlight-color-test",
    "chars": 1640,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\ntest_require diff-highlight\n\nexport PATH=\"$(dirname -- \"$diff_highlight_path\"):$PAT"
  },
  {
    "path": "test/diff/diff-highlight-test",
    "chars": 1998,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nin_work_dir create_repo_from_tgz \"$base_dir/files/scala-js-benchmarks.tgz\"\n\nfile bi"
  },
  {
    "path": "test/diff/diff-stat-split-test",
    "chars": 4835,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=181\n\nsteps '\n\t:enter\n\t:save-display diff-stat.screen\n'\n\ntigrc <<EOF\n"
  },
  {
    "path": "test/diff/diff-stat-test",
    "chars": 3279,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=181\n\nsteps '\n\t:save-view view.data\n'\n\ntigrc <<EOF\nset line-graphics "
  },
  {
    "path": "test/diff/diff-stdin-test",
    "chars": 2752,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nsteps '\n\t:save-display diff.screen\n'\n\ngit_init\n\ntest_tig show <<EOF\ncommit 1b4c64b5"
  },
  {
    "path": "test/diff/diff-wdiff-context-test",
    "chars": 6272,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nsteps '\n\t:save-display diff-default.screen\n\n\t:21\n\t]\n\t:save-display diff-u4.screen\n\n"
  },
  {
    "path": "test/diff/editor-test",
    "chars": 11725,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport GIT_EDITOR=\\$EDITOR\n\ntigrc <<EOF\nset show-untracked = no\nset line-graphics ="
  },
  {
    "path": "test/diff/line-number-test",
    "chars": 404,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=40\nexport LINES=3\n\nsteps '\n\t:view-diff\n\t:move-last-line\n\t:!echo %(li"
  },
  {
    "path": "test/diff/maximized-navigation-test",
    "chars": 3198,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=12\n\nsteps '\n\t<Enter>\n\t:save-display split.screen\n\t:maximize\n\t:save-dis"
  },
  {
    "path": "test/diff/open-after-split-test",
    "chars": 2810,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=12\n\nsteps '\n\t<Enter>\n\t:save-display split.screen\n\t:next\n\t:save-display"
  },
  {
    "path": "test/diff/start-on-line-test",
    "chars": 1574,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nin_work_dir create_repo_from_tgz \"$base_dir/files/scala-js-benchmarks.tgz\"\n\nsteps '"
  },
  {
    "path": "test/diff/submodule-editor-diffstat-test",
    "chars": 1785,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=22\n\nexecutable exec-env <<EOF\n#!/bin/sh\n\n{\n\tprintf ' - pwd='; pwd\n\tfor"
  },
  {
    "path": "test/diff/submodule-editor-test",
    "chars": 13408,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexecutable exec-env <<EOF\n#!/bin/sh\n\n{\n\techo \"\\$TEST_CASE\"\n\tprintf ' - pwd='; pwd\n\t"
  },
  {
    "path": "test/diff/worktree-editor-test",
    "chars": 13382,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexecutable exec-env <<EOF\n#!/bin/sh\n\n{\n\techo \"\\$TEST_CASE\"\n\tprintf ' - pwd='; pwd\n\t"
  },
  {
    "path": "test/diff/wrap-lines-test",
    "chars": 1166,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=40\n\nsteps '\n\t:save-display wrapped.screen\n'\n\ntigrc <<EOF\nset line-gr"
  },
  {
    "path": "test/graph/00-simple-test",
    "chars": 377,
    "preview": "#!/bin/sh\n#\n# Graph test: simple\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit f e d\n    Merge branch 'branch3'\ncommit e b c\n  "
  },
  {
    "path": "test/graph/01-merge-from-left-test",
    "chars": 403,
    "preview": "#!/bin/sh\n#\n# Graph test: merge from left\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C\n    Commit A - Merge C into B\ncom"
  },
  {
    "path": "test/graph/02-duplicate-parent-test",
    "chars": 662,
    "preview": "#!/bin/sh\n#\n# Graph test: duplicate parent\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C\n    Commit A - Merge C into B\nco"
  },
  {
    "path": "test/graph/03-octo-merge-test",
    "chars": 416,
    "preview": "#!/bin/sh\n#\n# Graph test: octo merge\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C D\n    Commit A - Merges B, C, and D\nco"
  },
  {
    "path": "test/graph/04-missing-bar-test",
    "chars": 529,
    "preview": "#!/bin/sh\n#\n# Graph test: missing bar\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C\n    Commit A - Merge B and C\ncommit B"
  },
  {
    "path": "test/graph/05-extra-pipe-test",
    "chars": 427,
    "preview": "#!/bin/sh\n#\n# Graph test: extra pipe\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C\n    Commit A - merge B and C\ncommit C "
  },
  {
    "path": "test/graph/06-extra-bars-test",
    "chars": 3776,
    "preview": "#!/bin/sh\n#\n# Graph test: extra bars\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C\n    Commit A - merge B and C\ncommit C "
  },
  {
    "path": "test/graph/07-multi-collapse-test",
    "chars": 627,
    "preview": "#!/bin/sh\n#\n# Graph test: multi collapse\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C D E F\n    Commit A - merge B, C, D"
  },
  {
    "path": "test/graph/08-multi-collapse-2-test",
    "chars": 710,
    "preview": "#!/bin/sh\n#\n# Graph test: multi collapse 2\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A Z B C D E F\n    Commit A - merge Z, "
  },
  {
    "path": "test/graph/09-parallel-siblings-test",
    "chars": 701,
    "preview": "#!/bin/sh\n#\n# Graph test: parallel siblings\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A Z B C\n    Commit A - merge Z, B, an"
  },
  {
    "path": "test/graph/10-shorter-merge-than-branch-test",
    "chars": 863,
    "preview": "#!/bin/sh\n#\n# Graph test: shorter merge than branch\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A H B C D J E\n    Commit A - "
  },
  {
    "path": "test/graph/11-new-branch-in-middle-test",
    "chars": 682,
    "preview": "#!/bin/sh\n#\n# Graph test: new branch in middle\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C E\n    Commit A - merge B, C,"
  },
  {
    "path": "test/graph/12-cross-over-collapse-test",
    "chars": 663,
    "preview": "#!/bin/sh\n#\n# Graph test: cross over collapse\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B D E\n    Commit A - merge B, D, "
  },
  {
    "path": "test/graph/13-collapse-parallel-branches-with-different-middle-branch-test",
    "chars": 794,
    "preview": "#!/bin/sh\n#\n# Graph test: collapse parallel branches with different middle branch\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit"
  },
  {
    "path": "test/graph/14-long-collapse-line-test",
    "chars": 1497,
    "preview": "#!/bin/sh\n#\n# Graph test: long collapse line\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C D E F G\n    Commit A - merge B"
  },
  {
    "path": "test/graph/15-many-merges-test",
    "chars": 1388,
    "preview": "#!/bin/sh\n#\n# Graph test: many merges\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit P N O\n    Commit P - Merge O into N\ncommit "
  },
  {
    "path": "test/graph/16-changes-test",
    "chars": 555,
    "preview": "#!/bin/sh\n#\n# Graph test: changes\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit 0000000000000000000000000000000000000000 000000"
  },
  {
    "path": "test/graph/17-more-merges-test",
    "chars": 2587,
    "preview": "#!/bin/sh\n#\n# Graph test: more\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A B C D E\n    Commit A - merge B, C, D, and E\ncomm"
  },
  {
    "path": "test/graph/18-tig-test",
    "chars": 1054,
    "preview": "#!/bin/sh\n#\n# Graph test: tig\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit i h\n    Do not include merges in the announcement's"
  },
  {
    "path": "test/graph/19-tig-all-test",
    "chars": 14087,
    "preview": "#!/bin/sh\n#\n# Graph test: tig all\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit 9ba5aa1e29924175e52b79e8b255f1903aa73833 85e82d"
  },
  {
    "path": "test/graph/20-tig-all-long-test",
    "chars": 98286,
    "preview": "#!/bin/sh\n#\n# Graph test: tig all long\n\n. libtest.sh\n\ntest_graph < \"$source_dir/$test.in\"\n\nassert_equals stdout <<EOF\n∙ "
  },
  {
    "path": "test/graph/gh-490-heap-buffer-overflow-test",
    "chars": 226,
    "preview": "#!/bin/sh\n\n. libtest.sh\n\ntest_require address-sanitizer\ntest_setup\n\nsteps '\n\t:save-display screen\n\t:quit\n'\n\ngunzip --std"
  },
  {
    "path": "test/graph/regression/horizontal-artifact-test",
    "chars": 869,
    "preview": "#!/bin/sh\n#\n# Graph test: regression test for \"─╭\" instead of \" ╭\"\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A3 A1 A2\n    C"
  },
  {
    "path": "test/graph/regression/horizontal-bar-wrong-2-test",
    "chars": 752,
    "preview": "#!/bin/sh\n#\n# Graph test: regression test for \"─┬\" instead of \"──\"\n\n. libtest.sh\n\ntest_graph <<EOF\ncommit A4 A3\n    Comm"
  },
  {
    "path": "test/grep/default-test",
    "chars": 3733,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=16\n\ntigrc <<EOF\nset vertical-split = no\nset line-graphics = ascii\nEOF\n"
  },
  {
    "path": "test/grep/editor-test",
    "chars": 1172,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=16\n\ntigrc <<EOF\nset vertical-split = no\nset line-graphics = ascii\nEOF\n"
  },
  {
    "path": "test/grep/refspec-test",
    "chars": 1535,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=16\n\ntigrc <<EOF\nset vertical-split = no\nset line-graphics = ascii\nEOF\n"
  },
  {
    "path": "test/grep/start-on-line-test",
    "chars": 2199,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=100\n\nin_work_dir create_repo_from_tgz \"$base_dir/files/scala-js-benc"
  },
  {
    "path": "test/help/all-keybindings-test",
    "chars": 510,
    "preview": "#!/bin/sh\n\n. libtest.sh\n\nexport COLUMNS=100\nexport LINES=160\n\nsteps '\n\t:view-help\n\t:2\n\t:enter\n\t:enter\n\t:save-display hel"
  },
  {
    "path": "test/help/all-keybindings-test.expected",
    "chars": 8130,
    "preview": "Quick reference for tig keybindings:\n[-] Collapse all sections\n\n[-] generic bindings\nView switching\n                    "
  },
  {
    "path": "test/help/default-test",
    "chars": 5041,
    "preview": "#!/bin/sh\n\n. libtest.sh\n\nexport COLUMNS=100\n\nsteps '\n\t:view-help\n\t:save-display help-default.screen\n\n\t:/View manipulatio"
  },
  {
    "path": "test/help/user-command-test",
    "chars": 1773,
    "preview": "#!/bin/sh\n\n. libtest.sh\n\nexport COLUMNS=100\n\ntigrc <<EOF\nbind generic a !?@user-test-cmd\nbind generic b ?@user-test-cmd\n"
  },
  {
    "path": "test/log/diff-stat-test",
    "chars": 9448,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport COLUMNS=181\n\nsteps '\n\t:enter\n\t:save-display diff-stat.screen\n\t:view-next\n\t:r"
  },
  {
    "path": "test/log/log-graph-test",
    "chars": 1174,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nsteps '\n\t:save-display log-graph.screen\n'\n\nin_work_dir create_repo_from_tgz \"$base_"
  },
  {
    "path": "test/log/pretty-format-test",
    "chars": 3359,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=20\n\ntigrc <<EOF\n# Check compatibility with pretty format override\nset "
  },
  {
    "path": "test/log/start-on-line-test",
    "chars": 1658,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nin_work_dir create_repo_from_tgz \"$base_dir/files/scala-js-benchmarks.tgz\"\n\nsteps '"
  },
  {
    "path": "test/log/submodule-test",
    "chars": 3133,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=47\n\ntigrc <<EOF\nset vertical-split = no\nEOF\n\nsteps '\n\t:save-display lo"
  },
  {
    "path": "test/main/all-arg-test",
    "chars": 2499,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n. \"$source_dir/util.sh\"\n\nexport LINES=16\n\nsteps '\n\t:set line-graphics = ascii\n\t:exec"
  },
  {
    "path": "test/main/author-name-change-test",
    "chars": 512,
    "preview": "#!/bin/sh\n#\n# Test display and options specific to the main view.\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=5\n\ntigrc <<EOF"
  },
  {
    "path": "test/main/boundary-test",
    "chars": 801,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n. \"$source_dir/util.sh\"\n\nexport LINES=16\n\nsteps '\n\t:set line-graphics = ascii\n\t:save"
  },
  {
    "path": "test/main/branch-var-test",
    "chars": 1636,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=18\n\ntigrc <<EOF\nset line-graphics = ascii\nset refresh-mode = manual\nEO"
  },
  {
    "path": "test/main/commit-order-edge-case-test",
    "chars": 1501,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=10\n\ntigrc <<EOF\nset line-graphics = utf-8\nset main-view = date author "
  },
  {
    "path": "test/main/commit-title-overflow-test",
    "chars": 2866,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=51\n\ntigrc <<EOF\nset vertical-split = no\nset main-view\t= line-number:no"
  },
  {
    "path": "test/main/date-test",
    "chars": 16632,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport TEST_TIME_NOW=1441051553\nexport LINES=27\n\ntigrc <<EOF\nset vertical-split = n"
  },
  {
    "path": "test/main/date-test.in",
    "chars": 7729,
    "preview": "commit 91912eb97da4f6907015dab41ef9bba315730854\nauthor Kentaro Wada <www.kentaro.wada@example.com> 1440961292 +0900\ncomm"
  },
  {
    "path": "test/main/default-test",
    "chars": 6157,
    "preview": "#!/bin/sh\n#\n# Test display and options specific to the main view.\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=16\n\ntigrc <<EO"
  },
  {
    "path": "test/main/emoji-test",
    "chars": 2295,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\ncase \"$(uname -s)\" in CYGWIN*)\n\ttest_skip \"Emojis are not well supported on CYGWIN\""
  },
  {
    "path": "test/main/escape-control-characters-test",
    "chars": 1477,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=20\nexport COLUMNS=100\n\nsteps ':save-display screen'\n\ntest_tig --pretty"
  },
  {
    "path": "test/main/filter-args-test",
    "chars": 3582,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\n# git log's --exclude flag was added in git commit e7b432c521b0177e86eaecd2bd16906b"
  },
  {
    "path": "test/main/git-alias-test",
    "chars": 1277,
    "preview": "#!/bin/sh\n\n. libtest.sh\n. libgit.sh\n\nexport LINES=5\n\nbenchmarks_git=\"$output_dir/benchmarks.git\"\nbenchmarks_dir=\"$output"
  }
]

// ... and 108 more files (download for full content)

About this extraction

This page contains the full source code of the jonas/tig GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 308 files (3.8 MB), approximately 998.9k tokens, and a symbol index with 1526 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!