#!/usr/bin/env python3

# Copyright (c) 2019, Ulf Magnusson
# SPDX-License-Identifier: ISC

"""
Overview
========

A Tkinter-based menuconfig implementation, based around a treeview control and
a help display. The interface should feel familiar to people used to qconf
('make xconfig'). Compatible with both Python 2 and Python 3.

The display can be toggled between showing the full tree and showing just a
single menu (like menuconfig.py). Only single-menu mode distinguishes between
symbols defined with 'config' and symbols defined with 'menuconfig'.

A show-all mode is available that shows invisible items in red.

Supports both mouse and keyboard controls. The following keyboard shortcuts are
available:

  Ctrl-S   : Save configuration
  Ctrl-O   : Open configuration
  Ctrl-A   : Toggle show-all mode
  Ctrl-N   : Toggle show-name mode
  Ctrl-M   : Toggle single-menu mode
  Ctrl-F, /: Open jump-to dialog
  ESC      : Close

Running
=======

guiconfig.py can be run either as a standalone executable or by calling the
menuconfig() function with an existing Kconfig instance. The second option is a
bit inflexible in that it will still load and save .config, etc.

When run in standalone mode, the top-level Kconfig file to load can be passed
as a command-line argument. With no argument, it defaults to "Kconfig".

The KCONFIG_CONFIG environment variable specifies the .config file to load (if
it exists) and save. If KCONFIG_CONFIG is unset, ".config" is used.

When overwriting a configuration file, the old version is saved to
<filename>.old (e.g. .config.old).

$srctree is supported through Kconfiglib.
"""

# Note: There's some code duplication with menuconfig.py below, especially for
# the help text. Maybe some of it could be moved into kconfiglib.py or a shared
# helper script, but OTOH it's pretty nice to have things standalone and
# customizable.

import errno
import os
import sys

_PY2 = sys.version_info[0] < 3

if _PY2:
    # Python 2
    from Tkinter import *
    import ttk
    import tkFont as font
    import tkFileDialog as filedialog
    import tkMessageBox as messagebox
else:
    # Python 3
    from tkinter import *
    import tkinter.ttk as ttk
    import tkinter.font as font
    from tkinter import filedialog, messagebox

from kconfiglib import Symbol, Choice, MENU, COMMENT, MenuNode, \
                       BOOL, TRISTATE, STRING, INT, HEX, \
                       AND, OR, \
                       expr_str, expr_value, split_expr, \
                       standard_sc_expr_str, \
                       TRI_TO_STR, TYPE_TO_STR, \
                       standard_kconfig, standard_config_filename


# If True, use GIF image data embedded in this file instead of separate GIF
# files. See _load_images().
_USE_EMBEDDED_IMAGES = True


# Help text for the jump-to dialog
_JUMP_TO_HELP = """\
Type one or more strings/regexes and press Enter to list items that match all
of them. Python's regex flavor is used (see the 're' module). Double-clicking
an item will jump to it. Item values can be toggled directly within the dialog.\
"""


def _main():
    menuconfig(standard_kconfig(__doc__))


# Global variables used below:
#
#   _root:
#     The Toplevel instance for the main window
#
#   _tree:
#     The Treeview in the main window
#
#   _jump_to_tree:
#     The Treeview in the jump-to dialog. None if the jump-to dialog isn't
#     open. Doubles as a flag.
#
#   _jump_to_matches:
#     List of Nodes shown in the jump-to dialog
#
#   _menupath:
#     The Label that shows the menu path of the selected item
#
#   _backbutton:
#     The button shown in single-menu mode for jumping to the parent menu
#
#   _status_label:
#     Label with status text shown at the bottom of the main window
#     ("Modified", "Saved to ...", etc.)
#
#   _id_to_node:
#     We can't use Node objects directly as Treeview item IDs, so we use their
#     id()s instead. This dictionary maps Node id()s back to Nodes. (The keys
#     are actually str(id(node)), just to simplify lookups.)
#
#   _cur_menu:
#     The current menu. Ignored outside single-menu mode.
#
#   _show_all_var/_show_name_var/_single_menu_var:
#     Tkinter Variable instances bound to the corresponding checkboxes
#
#   _show_all/_single_menu:
#     Plain Python bools that track _show_all_var and _single_menu_var, to
#     speed up and simplify things a bit
#
#   _conf_filename:
#     File to save the configuration to
#
#   _minconf_filename:
#     File to save minimal configurations to
#
#   _conf_changed:
#     True if the configuration has been changed. If False, we don't bother
#     showing the save-and-quit dialog.
#
#     We reset this to False whenever the configuration is saved.
#
#   _*_img:
#     PhotoImage instances for images


def menuconfig(kconf):
    """
    Launches the configuration interface, returning after the user exits.

    kconf:
      Kconfig instance to be configured
    """
    global _kconf
    global _conf_filename
    global _minconf_filename
    global _jump_to_tree
    global _cur_menu

    _kconf = kconf

    _jump_to_tree = None

    _create_id_to_node()

    _create_ui()

    # Filename to save configuration to
    _conf_filename = standard_config_filename()

    # Load existing configuration and check if it's outdated
    _set_conf_changed(_load_config())

    # Filename to save minimal configuration to
    _minconf_filename = "defconfig"

    # Current menu in single-menu mode
    _cur_menu = _kconf.top_node

    # Any visible items in the top menu?
    if not _shown_menu_nodes(kconf.top_node):
        # Nothing visible. Start in show-all mode and try again.
        _show_all_var.set(True)
        if not _shown_menu_nodes(kconf.top_node):
            # Give up and show an error. It's nice to be able to assume that
            # the tree is non-empty in the rest of the code.
            _root.wait_visibility()
            messagebox.showerror(
                "Error",
                "Empty configuration -- nothing to configure.\n\n"
                "Check that environment variables are set properly.")
            _root.destroy()
            return

    # Build the initial tree
    _update_tree()

    # Select the first item and focus the Treeview, so that keyboard controls
    # work immediately
    _select(_tree, _tree.get_children()[0])
    _tree.focus_set()

    # Make geometry information available for centering the window. This
    # indirectly creates the window, so hide it so that it's never shown at the
    # old location.
    _root.withdraw()
    _root.update_idletasks()

    # Center the window
    _root.geometry("+{}+{}".format(
        (_root.winfo_screenwidth() - _root.winfo_reqwidth())//2,
        (_root.winfo_screenheight() - _root.winfo_reqheight())//2))

    # Show it
    _root.deiconify()

    # Prevent the window from being automatically resized. Otherwise, it
    # changes size when scrollbars appear/disappear before the user has
    # manually resized it.
    _root.geometry(_root.geometry())

    _root.mainloop()


def _load_config():
    # Loads any existing .config file. See the Kconfig.load_config() docstring.
    #
    # Returns True if .config is missing or outdated. We always prompt for
    # saving the configuration in that case.

    print(_kconf.load_config())
    if not os.path.exists(_conf_filename):
        # No .config
        return True

    return _needs_save()


def _needs_save():
    # Returns True if a just-loaded .config file is outdated (would get
    # modified when saving)

    if _kconf.missing_syms:
        # Assignments to undefined symbols in the .config
        return True

    for sym in _kconf.unique_defined_syms:
        if sym.user_value is None:
            if sym.config_string:
                # Unwritten symbol
                return True
        elif sym.orig_type in (BOOL, TRISTATE):
            if sym.tri_value != sym.user_value:
                # Written bool/tristate symbol, new value
                return True
        elif sym.str_value != sym.user_value:
            # Written string/int/hex symbol, new value
            return True

    # No need to prompt for save
    return False


def _create_id_to_node():
    global _id_to_node

    _id_to_node = {str(id(node)): node for node in _kconf.node_iter()}


def _create_ui():
    # Creates the main window UI

    global _root
    global _tree

    # Create the root window. This initializes Tkinter and makes e.g.
    # PhotoImage available, so do it early.
    _root = Tk()

    _load_images()
    _init_misc_ui()
    _fix_treeview_issues()

    _create_top_widgets()
    # Create the pane with the Kconfig tree and description text
    panedwindow, _tree = _create_kconfig_tree_and_desc(_root)
    panedwindow.grid(column=0, row=1, sticky="nsew")
    _create_status_bar()

    _root.columnconfigure(0, weight=1)
    # Only the pane with the Kconfig tree and description grows vertically
    _root.rowconfigure(1, weight=1)

    # Start with show-name disabled
    _do_showname()

    _tree.bind("<Left>", _tree_left_key)
    _tree.bind("<Right>", _tree_right_key)
    # Note: Binding this for the jump-to tree as well would cause issues due to
    # the Tk bug mentioned in _tree_open()
    _tree.bind("<<TreeviewOpen>>", _tree_open)
    # add=True to avoid overriding the description text update
    _tree.bind("<<TreeviewSelect>>", _update_menu_path, add=True)

    _root.bind("<Control-s>", _save)
    _root.bind("<Control-o>", _open)
    _root.bind("<Control-a>", _toggle_showall)
    _root.bind("<Control-n>", _toggle_showname)
    _root.bind("<Control-m>", _toggle_tree_mode)
    _root.bind("<Control-f>", _jump_to_dialog)
    _root.bind("/", _jump_to_dialog)
    _root.bind("<Escape>", _on_quit)


def _load_images():
    # Loads GIF images, creating the global _*_img PhotoImage variables.
    # Base64-encoded images embedded in this script are used if
    # _USE_EMBEDDED_IMAGES is True, and separate image files in the same
    # directory as the script otherwise.
    #
    # Using a global variable indirectly prevents the image from being
    # garbage-collected. Passing an image to a Tkinter function isn't enough to
    # keep it alive.

    def load_image(name, data):
        var_name = "_{}_img".format(name)

        if _USE_EMBEDDED_IMAGES:
            globals()[var_name] = PhotoImage(data=data, format="gif")
        else:
            globals()[var_name] = PhotoImage(
                file=os.path.join(os.path.dirname(__file__), name + ".gif"),
                format="gif")

    # Note: Base64 data can be put on the clipboard with
    #   $ base64 -w0 foo.gif | xclip

    load_image("icon", "R0lGODlhMAAwAPEDAAAAAADQAO7u7v///yH5BAUKAAMALAAAAAAwADAAAAL/nI+gy+2Pokyv2jazuZxryQjiSJZmyXxHeLbumH6sEATvW8OLNtf5bfLZRLFITzgEipDJ4mYxYv6A0ubuqYhWk66tVTE4enHer7jcKvt0LLUw6P45lvEprT6c0+v7OBuqhYdHohcoqIbSAHc4ljhDwrh1UlgSydRCWWlp5wiYZvmSuSh4IzrqV6p4cwhkCsmY+nhK6uJ6t1mrOhuJqfu6+WYiCiwl7HtLjNSZZZis/MeM7NY3TaRKS40ooDeoiVqIultsrav92bi9c3a5KkkOsOJZpSS99m4k/0zPng4Gks9JSbB+8DIcoQfnjwpZCHv5W+ip4aQrKrB0uOikYhiMCBw1/uPoQUMBADs=")
    load_image("n_bool", "R0lGODdhEAAQAPAAAAgICP///ywAAAAAEAAQAAACIISPacHtvp5kcb5qG85hZ2+BkyiRF8BBaEqtrKkqslEAADs=")
    load_image("y_bool", "R0lGODdhEAAQAPEAAAgICADQAP///wAAACwAAAAAEAAQAAACMoSPacLtvlh4YrIYsst2cV19AvaVF9CUXBNJJoum7ymrsKuCnhiupIWjSSjAFuWhSCIKADs=")
    load_image("n_tri", "R0lGODlhEAAQAPD/AAEBAf///yH5BAUKAAIALAAAAAAQABAAAAInlI+pBrAKQnCPSUlXvFhznlkfeGwjKZhnJ65h6nrfi6h0st2QXikFADs=")
    load_image("m_tri", "R0lGODlhEAAQAPEDAAEBAeQMuv///wAAACH5BAUKAAMALAAAAAAQABAAAAI5nI+pBrAWAhPCjYhiAJQCnWmdoElHGVBoiK5M21ofXFpXRIrgiecqxkuNciZIhNOZFRNI24PhfEoLADs=")
    load_image("y_tri", "R0lGODlhEAAQAPEDAAICAgDQAP///wAAACH5BAUKAAMALAAAAAAQABAAAAI0nI+pBrAYBhDCRRUypfmergmgZ4xjMpmaw2zmxk7cCB+pWiVqp4MzDwn9FhGZ5WFjIZeGAgA7")
    load_image("m_my", "R0lGODlhEAAQAPEDAAAAAOQMuv///wAAACH5BAUKAAMALAAAAAAQABAAAAI5nIGpxiAPI2ghxFinq/ZygQhc94zgZopmOLYf67anGr+oZdp02emfV5n9MEHN5QhqICETxkABbQ4KADs=")
    load_image("y_my", "R0lGODlhEAAQAPH/AAAAAADQAAPRA////yH5BAUKAAQALAAAAAAQABAAAAM+SArcrhCMSSuIM9Q8rxxBWIXawIBkmWonupLd565Um9G1PIs59fKmzw8WnAlusBYR2SEIN6DmAmqBLBxYSAIAOw==")
    load_image("n_locked", "R0lGODlhEAAQAPABAAAAAP///yH5BAUKAAEALAAAAAAQABAAAAIgjB8AyKwN04pu0vMutpqqz4Hih4ydlnUpyl2r23pxUAAAOw==")
    load_image("m_locked", "R0lGODlhEAAQAPD/AAAAAOQMuiH5BAUKAAIALAAAAAAQABAAAAIylC8AyKwN04ohnGcqqlZmfXDWI26iInZoyiore05walolV39ftxsYHgL9QBBMBGFEFAAAOw==")
    load_image("y_locked", "R0lGODlhEAAQAPD/AAAAAADQACH5BAUKAAIALAAAAAAQABAAAAIylC8AyKzNgnlCtoDTwvZwrHydIYpQmR3KWq4uK74IOnp0HQPmnD3cOVlUIAgKsShkFAAAOw==")
    load_image("not_selected", "R0lGODlhEAAQAPD/AAAAAP///yH5BAUKAAIALAAAAAAQABAAAAIrlA2px6IBw2IpWglOvTYhzmUbGD3kNZ5QqrKn2YrqigCxZoMelU6No9gdCgA7")
    load_image("selected", "R0lGODlhEAAQAPD/AAAAAP///yH5BAUKAAIALAAAAAAQABAAAAIzlA2px6IBw2IpWglOvTah/kTZhimASJomiqonlLov1qptHTsgKSEzh9H8QI0QzNPwmRoFADs=")
    load_image("edit", "R0lGODlhEAAQAPIFAAAAAKOLAMuuEPvXCvrxvgAAAAAAAAAAACH5BAUKAAUALAAAAAAQABAAAANCWLqw/gqMBp8cszJxcwVC2FEOEIAi5kVBi3IqWZhuCGMyfdpj2e4pnK+WAshmvxeAcETWlsxPkkBtsqBMa8TIBSQAADs=")


def _fix_treeview_issues():
    # Fixes some Treeview issues

    global _treeview_rowheight

    style = ttk.Style()

    # The treeview rowheight isn't adjusted automatically on high-DPI displays,
    # so do it ourselves. The font will probably always be TkDefaultFont, but
    # play it safe and look it up.

    _treeview_rowheight = font.Font(font=style.lookup("Treeview", "font")) \
        .metrics("linespace") + 2

    style.configure("Treeview", rowheight=_treeview_rowheight)

    # Work around regression in https://core.tcl.tk/tk/tktview?name=509cafafae,
    # which breaks tag background colors

    for option in "foreground", "background":
        # Filter out any styles starting with ("!disabled", "!selected", ...).
        # style.map() returns an empty list for missing options, so this should
        # be future-safe.
        style.map(
            "Treeview",
            **{option: [elm for elm in style.map("Treeview", query_opt=option)
                        if elm[:2] != ("!disabled", "!selected")]})


def _init_misc_ui():
    # Does misc. UI initialization, like setting the title, icon, and theme

    _root.title(_kconf.mainmenu_text)
    # iconphoto() isn't available in Python 2's Tkinter
    _root.tk.call("wm", "iconphoto", _root._w, "-default", _icon_img)
    # Reducing the width of the window to 1 pixel makes it move around, at
    # least on GNOME. Prevent weird stuff like that.
    _root.minsize(128, 128)
    _root.protocol("WM_DELETE_WINDOW", _on_quit)

    # Use the 'clam' theme on *nix if it's available. It looks nicer than the
    # 'default' theme.
    if _root.tk.call("tk", "windowingsystem") == "x11":
        style = ttk.Style()
        if "clam" in style.theme_names():
            style.theme_use("clam")


def _create_top_widgets():
    # Creates the controls above the Kconfig tree in the main window

    global _show_all_var
    global _show_name_var
    global _single_menu_var
    global _menupath
    global _backbutton

    topframe = ttk.Frame(_root)
    topframe.grid(column=0, row=0, sticky="ew")

    ttk.Button(topframe, text="Save", command=_save) \
        .grid(column=0, row=0, sticky="ew", padx=".05c", pady=".05c")

    ttk.Button(topframe, text="Save as...", command=_save_as) \
        .grid(column=1, row=0, sticky="ew")

    ttk.Button(topframe, text="Save minimal (advanced)...",
               command=_save_minimal) \
        .grid(column=2, row=0, sticky="ew", padx=".05c")

    ttk.Button(topframe, text="Open...", command=_open) \
        .grid(column=3, row=0)

    ttk.Button(topframe, text="Jump to...", command=_jump_to_dialog) \
        .grid(column=4, row=0, padx=".05c")

    _show_name_var = BooleanVar()
    ttk.Checkbutton(topframe, text="Show name", command=_do_showname,
                    variable=_show_name_var) \
        .grid(column=0, row=1, sticky="nsew", padx=".05c", pady="0 .05c",
              ipady=".2c")

    _show_all_var = BooleanVar()
    ttk.Checkbutton(topframe, text="Show all", command=_do_showall,
                    variable=_show_all_var) \
        .grid(column=1, row=1, sticky="nsew", pady="0 .05c")

    # Allow the show-all and single-menu status to be queried via plain global
    # Python variables, which is faster and simpler

    def show_all_updated(*_):
        global _show_all
        _show_all = _show_all_var.get()

    _trace_write(_show_all_var, show_all_updated)
    _show_all_var.set(False)

    _single_menu_var = BooleanVar()
    ttk.Checkbutton(topframe, text="Single-menu mode", command=_do_tree_mode,
                    variable=_single_menu_var) \
        .grid(column=2, row=1, sticky="nsew", padx=".05c", pady="0 .05c")

    _backbutton = ttk.Button(topframe, text="<--", command=_leave_menu,
                             state="disabled")
    _backbutton.grid(column=0, row=4, sticky="nsew", padx=".05c", pady="0 .05c")

    def tree_mode_updated(*_):
        global _single_menu
        _single_menu = _single_menu_var.get()

        if _single_menu:
            _backbutton.grid()
        else:
            _backbutton.grid_remove()

    _trace_write(_single_menu_var, tree_mode_updated)
    _single_menu_var.set(False)

    # Column to the right of the buttons that the menu path extends into, so
    # that it can grow wider than the buttons
    topframe.columnconfigure(5, weight=1)

    _menupath = ttk.Label(topframe)
    _menupath.grid(column=0, row=3, columnspan=6, sticky="w", padx="0.05c",
                   pady="0 .05c")


def _create_kconfig_tree_and_desc(parent):
    # Creates a Panedwindow with a Treeview that shows Kconfig nodes and a Text
    # that shows a description of the selected node. Returns a tuple with the
    # Panedwindow and the Treeview. This code is shared between the main window
    # and the jump-to dialog.

    panedwindow = ttk.Panedwindow(parent, orient=VERTICAL)

    tree_frame, tree = _create_kconfig_tree(panedwindow)
    desc_frame, desc = _create_kconfig_desc(panedwindow)

    panedwindow.add(tree_frame, weight=1)
    panedwindow.add(desc_frame)

    def tree_select(_):
        # The Text widget does not allow editing the text in its disabled
        # state. We need to temporarily enable it.
        desc["state"] = "normal"

        sel = tree.selection()
        if not sel:
            desc.delete("1.0", "end")
            desc["state"] = "disabled"
            return

        # Text.replace() is not available in Python 2's Tkinter
        desc.delete("1.0", "end")
        desc.insert("end", _info_str(_id_to_node[sel[0]]))

        desc["state"] = "disabled"

    tree.bind("<<TreeviewSelect>>", tree_select)
    tree.bind("<1>", _tree_click)
    tree.bind("<Double-1>", _tree_double_click)
    tree.bind("<Return>", _tree_enter)
    tree.bind("<KP_Enter>", _tree_enter)
    tree.bind("<space>", _tree_toggle)
    tree.bind("n", _tree_set_val(0))
    tree.bind("m", _tree_set_val(1))
    tree.bind("y", _tree_set_val(2))

    return panedwindow, tree


def _create_kconfig_tree(parent):
    # Creates a Treeview for showing Kconfig nodes

    frame = ttk.Frame(parent)

    tree = ttk.Treeview(frame, selectmode="browse", height=20,
                        columns=("name",))
    tree.heading("#0", text="Option", anchor="w")
    tree.heading("name", text="Name", anchor="w")

    tree.tag_configure("n-bool", image=_n_bool_img)
    tree.tag_configure("y-bool", image=_y_bool_img)
    tree.tag_configure("m-tri", image=_m_tri_img)
    tree.tag_configure("n-tri", image=_n_tri_img)
    tree.tag_configure("m-tri", image=_m_tri_img)
    tree.tag_configure("y-tri", image=_y_tri_img)
    tree.tag_configure("m-my", image=_m_my_img)
    tree.tag_configure("y-my", image=_y_my_img)
    tree.tag_configure("n-locked", image=_n_locked_img)
    tree.tag_configure("m-locked", image=_m_locked_img)
    tree.tag_configure("y-locked", image=_y_locked_img)
    tree.tag_configure("not-selected", image=_not_selected_img)
    tree.tag_configure("selected", image=_selected_img)
    tree.tag_configure("edit", image=_edit_img)
    tree.tag_configure("invisible", foreground="red")

    tree.grid(column=0, row=0, sticky="nsew")

    _add_vscrollbar(frame, tree)

    frame.columnconfigure(0, weight=1)
    frame.rowconfigure(0, weight=1)

    # Create items for all menu nodes. These can be detached/moved later.
    # Micro-optimize this a bit.
    insert = tree.insert
    id_ = id
    Symbol_ = Symbol
    for node in _kconf.node_iter():
        item = node.item
        insert("", "end", iid=id_(node),
               values=item.name if item.__class__ is Symbol_ else "")

    return frame, tree


def _create_kconfig_desc(parent):
    # Creates a Text for showing the description of the selected Kconfig node

    frame = ttk.Frame(parent)

    desc = Text(frame, height=12, wrap="none", borderwidth=0,
                state="disabled")
    desc.grid(column=0, row=0, sticky="nsew")

    # Work around not being to Ctrl-C/V text from a disabled Text widget, with a
    # tip found in https://stackoverflow.com/questions/3842155/is-there-a-way-to-make-the-tkinter-text-widget-read-only
    desc.bind("<1>", lambda _: desc.focus_set())

    _add_vscrollbar(frame, desc)

    frame.columnconfigure(0, weight=1)
    frame.rowconfigure(0, weight=1)

    return frame, desc


def _add_vscrollbar(parent, widget):
    # Adds a vertical scrollbar to 'widget' that's only shown as needed

    vscrollbar = ttk.Scrollbar(parent, orient="vertical",
                               command=widget.yview)
    vscrollbar.grid(column=1, row=0, sticky="ns")

    def yscrollcommand(first, last):
        # Only show the scrollbar when needed. 'first' and 'last' are
        # strings.
        if float(first) <= 0.0 and float(last) >= 1.0:
            vscrollbar.grid_remove()
        else:
            vscrollbar.grid()

        vscrollbar.set(first, last)

    widget["yscrollcommand"] = yscrollcommand


def _create_status_bar():
    # Creates the status bar at the bottom of the main window

    global _status_label

    _status_label = ttk.Label(_root, anchor="e", padding="0 0 0.4c 0")
    _status_label.grid(column=0, row=3, sticky="ew")


def _set_status(s):
    # Sets the text in the status bar to 's'

    _status_label["text"] = s


def _set_conf_changed(changed):
    # Updates the status re. whether there are unsaved changes

    global _conf_changed

    _conf_changed = changed
    if changed:
        _set_status("Modified")


def _update_tree():
    # Updates the Kconfig tree in the main window by first detaching all nodes
    # and then updating and reattaching them. The tree structure might have
    # changed.

    # If a selected/focused item is detached and later reattached, it stays
    # selected/focused. That can give multiple selections even though
    # selectmode=browse. Save and later restore the selection and focus as a
    # workaround.
    old_selection = _tree.selection()
    old_focus = _tree.focus()

    # Detach all tree items before re-stringing them. This is relatively fast,
    # luckily.
    _tree.detach(*_id_to_node.keys())

    if _single_menu:
        _build_menu_tree()
    else:
        _build_full_tree(_kconf.top_node)

    _tree.selection_set(old_selection)
    _tree.focus(old_focus)


def _build_full_tree(menu):
    # Updates the tree starting from menu.list, in full-tree mode. To speed
    # things up, only open menus are updated. The menu-at-a-time logic here is
    # to deal with invisible items that can show up outside show-all mode (see
    # _shown_full_nodes()).

    for node in _shown_full_nodes(menu):
        _add_to_tree(node, _kconf.top_node)

        # _shown_full_nodes() includes nodes from menus rooted at symbols, so
        # we only need to check "real" menus/choices here
        if node.list and not isinstance(node.item, Symbol):
            if _tree.item(id(node), "open"):
                _build_full_tree(node)
            else:
                # We're just probing here, so _shown_menu_nodes() will work
                # fine, and might be a bit faster
                shown = _shown_menu_nodes(node)
                if shown:
                    # Dummy element to make the open/closed toggle appear
                    _tree.move(id(shown[0]), id(shown[0].parent), "end")


def _shown_full_nodes(menu):
    # Returns the list of menu nodes shown in 'menu' (a menu node for a menu)
    # for full-tree mode. A tricky detail is that invisible items need to be
    # shown if they have visible children.

    def rec(node):
        res = []

        while node:
            if _visible(node) or _show_all:
                res.append(node)
                if node.list and isinstance(node.item, Symbol):
                    # Nodes from menu created from dependencies
                    res += rec(node.list)

            elif node.list and isinstance(node.item, Symbol):
                # Show invisible symbols (defined with either 'config' and
                # 'menuconfig') if they have visible children. This can happen
                # for an m/y-valued symbol with an optional prompt
                # ('prompt "foo" is COND') that is currently disabled.
                shown_children = rec(node.list)
                if shown_children:
                    res.append(node)
                    res += shown_children

            node = node.next

        return res

    return rec(menu.list)


def _build_menu_tree():
    # Updates the tree in single-menu mode. See _build_full_tree() as well.

    for node in _shown_menu_nodes(_cur_menu):
        _add_to_tree(node, _cur_menu)


def _shown_menu_nodes(menu):
    # Used for single-menu mode. Similar to _shown_full_nodes(), but doesn't
    # include children of symbols defined with 'menuconfig'.

    def rec(node):
        res = []

        while node:
            if _visible(node) or _show_all:
                res.append(node)
                if node.list and not node.is_menuconfig:
                    res += rec(node.list)

            elif node.list and isinstance(node.item, Symbol):
                shown_children = rec(node.list)
                if shown_children:
                    # Invisible item with visible children
                    res.append(node)
                    if not node.is_menuconfig:
                        res += shown_children

            node = node.next

        return res

    return rec(menu.list)


def _visible(node):
    # Returns True if the node should appear in the menu (outside show-all
    # mode)

    return node.prompt and expr_value(node.prompt[1]) and not \
        (node.item == MENU and not expr_value(node.visibility))


def _add_to_tree(node, top):
    # Adds 'node' to the tree, at the end of its menu. We rely on going through
    # the nodes linearly to get the correct order. 'top' holds the menu that
    # corresponds to the top-level menu, and can vary in single-menu mode.

    parent = node.parent
    _tree.move(id(node), "" if parent is top else id(parent), "end")
    _tree.item(
        id(node),
        text=_node_str(node),
        # The _show_all test avoids showing invisible items in red outside
        # show-all mode, which could look confusing/broken. Invisible symbols
        # are shown outside show-all mode if an invisible symbol has visible
        # children in an implicit menu.
        tags=_img_tag(node) if _visible(node) or not _show_all else
            _img_tag(node) + " invisible")


def _node_str(node):
    # Returns the string shown to the right of the image (if any) for the node

    if node.prompt:
        if node.item == COMMENT:
            s = "*** {} ***".format(node.prompt[0])
        else:
            s = node.prompt[0]

        if isinstance(node.item, Symbol):
            sym = node.item

            # Print "(NEW)" next to symbols without a user value (from e.g. a
            # .config), but skip it for choice symbols in choices in y mode,
            # and for symbols of UNKNOWN type (which generate a warning though)
            if sym.user_value is None and sym.type and not \
                (sym.choice and sym.choice.tri_value == 2):

                s += " (NEW)"

    elif isinstance(node.item, Symbol):
        # Symbol without prompt (can show up in show-all)
        s = "<{}>".format(node.item.name)

    else:
        # Choice without prompt. Use standard_sc_expr_str() so that it shows up
        # as '<choice (name if any)>'.
        s = standard_sc_expr_str(node.item)


    if isinstance(node.item, Symbol):
        sym = node.item
        if sym.orig_type == STRING:
            s += ": " + sym.str_value
        elif sym.orig_type in (INT, HEX):
            s = "({}) {}".format(sym.str_value, s)

    elif isinstance(node.item, Choice) and node.item.tri_value == 2:
        # Print the prompt of the selected symbol after the choice for
        # choices in y mode
        sym = node.item.selection
        if sym:
            for sym_node in sym.nodes:
                # Use the prompt used at this choice location, in case the
                # choice symbol is defined in multiple locations
                if sym_node.parent is node and sym_node.prompt:
                    s += " ({})".format(sym_node.prompt[0])
                    break
            else:
                # If the symbol isn't defined at this choice location, then
                # just use whatever prompt we can find for it
                for sym_node in sym.nodes:
                    if sym_node.prompt:
                        s += " ({})".format(sym_node.prompt[0])
                        break

    # In single-menu mode, print "--->" next to nodes that have menus that can
    # potentially be entered. Print "----" if the menu is empty. We don't allow
    # those to be entered.
    if _single_menu and node.is_menuconfig:
        s += "  --->" if _shown_menu_nodes(node) else "  ----"

    return s


def _img_tag(node):
    # Returns the tag for the image that should be shown next to 'node', or the
    # empty string if it shouldn't have an image

    item = node.item

    if item in (MENU, COMMENT) or not item.orig_type:
        return ""

    if item.orig_type in (STRING, INT, HEX):
        return "edit"

    # BOOL or TRISTATE

    if _is_y_mode_choice_sym(item):
        # Choice symbol in y-mode choice
        return "selected" if item.choice.selection is item else "not-selected"

    if len(item.assignable) <= 1:
        # Pinned to a single value
        return "" if isinstance(item, Choice) else item.str_value + "-locked"

    if item.type == BOOL:
        return item.str_value + "-bool"

    # item.type == TRISTATE
    if item.assignable == (1, 2):
        return item.str_value + "-my"
    return item.str_value + "-tri"


def _is_y_mode_choice_sym(item):
    # The choice mode is an upper bound on the visibility of choice symbols, so
    # we can check the choice symbols' own visibility to see if the choice is
    # in y mode
    return isinstance(item, Symbol) and item.choice and item.visibility == 2


def _tree_click(event):
    # Click on the Kconfig Treeview

    tree = event.widget
    if tree.identify_element(event.x, event.y) == "image":
        item = tree.identify_row(event.y)
        # Select the item before possibly popping up a dialog for
        # string/int/hex items, so that its help is visible
        _select(tree, item)
        _change_node(_id_to_node[item], tree.winfo_toplevel())
        return "break"


def _tree_double_click(event):
    # Double-click on the Kconfig treeview

    # Do an extra check to avoid weirdness when double-clicking in the tree
    # heading area
    if not _in_heading(event):
        return _tree_enter(event)


def _in_heading(event):
    # Returns True if 'event' took place in the tree heading

    tree = event.widget
    return hasattr(tree, "identify_region") and \
        tree.identify_region(event.x, event.y) in ("heading", "separator")


def _tree_enter(event):
    # Enter press or double-click within the Kconfig treeview. Prefer to
    # open/close/enter menus, but toggle the value if that's not possible.

    tree = event.widget
    sel = tree.focus()
    if sel:
        node = _id_to_node[sel]

        if tree.get_children(sel):
            _tree_toggle_open(sel)
        elif _single_menu_mode_menu(node, tree):
            _enter_menu_and_select_first(node)
        else:
            _change_node(node, tree.winfo_toplevel())

        return "break"


def _tree_toggle(event):
    # Space press within the Kconfig treeview. Prefer to toggle the value, but
    # open/close/enter the menu if that's not possible.

    tree = event.widget
    sel = tree.focus()
    if sel:
        node = _id_to_node[sel]

        if _changeable(node):
            _change_node(node, tree.winfo_toplevel())
        elif _single_menu_mode_menu(node, tree):
            _enter_menu_and_select_first(node)
        elif tree.get_children(sel):
            _tree_toggle_open(sel)

        return "break"


def _tree_left_key(_):
    # Left arrow key press within the Kconfig treeview

    if _single_menu:
        # Leave the current menu in single-menu mode
        _leave_menu()
        return "break"

    # Otherwise, default action


def _tree_right_key(_):
    # Right arrow key press within the Kconfig treeview

    sel = _tree.focus()
    if sel:
        node = _id_to_node[sel]
        # If the node can be entered in single-menu mode, do it
        if _single_menu_mode_menu(node, _tree):
            _enter_menu_and_select_first(node)
            return "break"

    # Otherwise, default action


def _single_menu_mode_menu(node, tree):
    # Returns True if single-menu mode is on and 'node' is an (interface)
    # menu that can be entered

    return _single_menu and tree is _tree and node.is_menuconfig and \
           _shown_menu_nodes(node)


def _changeable(node):
    # Returns True if 'node' is a Symbol/Choice whose value can be changed

    sc = node.item

    if not isinstance(sc, (Symbol, Choice)):
        return False

    # This will hit for invisible symbols, which appear in show-all mode and
    # when an invisible symbol has visible children (which can happen e.g. for
    # symbols with optional prompts)
    if not (node.prompt and expr_value(node.prompt[1])):
        return False

    return sc.orig_type in (STRING, INT, HEX) or len(sc.assignable) > 1 \
           or _is_y_mode_choice_sym(sc)


def _tree_toggle_open(item):
    # Opens/closes the Treeview item 'item'

    if _tree.item(item, "open"):
        _tree.item(item, open=False)
    else:
        node = _id_to_node[item]
        if not isinstance(node.item, Symbol):
            # Can only get here in full-tree mode
            _build_full_tree(node)
        _tree.item(item, open=True)


def _tree_set_val(tri_val):
    def tree_set_val(event):
        # n/m/y press within the Kconfig treeview

        # Sets the value of the currently selected item to 'tri_val', if that
        # value can be assigned

        sel = event.widget.focus()
        if sel:
            sc = _id_to_node[sel].item
            if isinstance(sc, (Symbol, Choice)) and tri_val in sc.assignable:
                _set_val(sc, tri_val)

    return tree_set_val


def _tree_open(_):
    # Lazily populates the Kconfig tree when menus are opened in full-tree mode

    if _single_menu:
        # Work around https://core.tcl.tk/tk/tktview?name=368fa4561e
        # ("ttk::treeview open/closed indicators can be toggled while hidden").
        # Clicking on the hidden indicator will call _build_full_tree() in
        # single-menu mode otherwise.
        return

    node = _id_to_node[_tree.focus()]
    # _shown_full_nodes() includes nodes from menus rooted at symbols, so we
    # only need to check "real" menus and choices here
    if not isinstance(node.item, Symbol):
        _build_full_tree(node)


def _update_menu_path(_):
    # Updates the displayed menu path when nodes are selected in the Kconfig
    # treeview

    sel = _tree.selection()
    _menupath["text"] = _menu_path_info(_id_to_node[sel[0]]) if sel else ""


def _item_row(item):
    # Returns the row number 'item' appears on within the Kconfig treeview,
    # starting from the top of the tree. Used to preserve scrolling.
    #
    # ttkTreeview.c in the Tk sources defines a RowNumber() function that does
    # the same thing, but it's not exposed.

    row = 0

    while True:
        prev = _tree.prev(item)
        if prev:
            item = prev
            row += _n_rows(item)
        else:
            item = _tree.parent(item)
            if not item:
                return row
            row += 1


def _n_rows(item):
    # _item_row() helper. Returns the number of rows occupied by 'item' and #
    # its children.

    rows = 1

    if _tree.item(item, "open"):
        for child in _tree.get_children(item):
            rows += _n_rows(child)

    return rows


def _attached(item):
    # Heuristic for checking if a Treeview item is attached. Doesn't seem to be
    # good APIs for this. Might fail for super-obscure cases with tiny trees,
    # but you'd just get a small scroll mess-up.

    return bool(_tree.next(item) or _tree.prev(item) or _tree.parent(item))


def _change_node(node, parent):
    # Toggles/changes the value of 'node'. 'parent' is the parent window
    # (either the main window or the jump-to dialog), in case we need to pop up
    # a dialog.

    if not _changeable(node):
        return

    # sc = symbol/choice
    sc = node.item

    if sc.type in (INT, HEX, STRING):
        s = _set_val_dialog(node, parent)

        # Tkinter can return 'unicode' strings on Python 2, which Kconfiglib
        # can't deal with. UTF-8-encode the string to work around it.
        if _PY2 and isinstance(s, unicode):
            s = s.encode("utf-8", "ignore")

        if s is not None:
            _set_val(sc, s)

    elif len(sc.assignable) == 1:
        # Handles choice symbols for choices in y mode, which are a special
        # case: .assignable can be (2,) while .tri_value is 0.
        _set_val(sc, sc.assignable[0])

    else:
        # Set the symbol to the value after the current value in
        # sc.assignable, with wrapping
        val_index = sc.assignable.index(sc.tri_value)
        _set_val(sc, sc.assignable[(val_index + 1) % len(sc.assignable)])


def _set_val(sc, val):
    # Wrapper around Symbol/Choice.set_value() for updating the menu state and
    # _conf_changed

    # Use the string representation of tristate values. This makes the format
    # consistent for all symbol types.
    if val in TRI_TO_STR:
        val = TRI_TO_STR[val]

    if val != sc.str_value:
        sc.set_value(val)
        _set_conf_changed(True)

        # Update the tree and try to preserve the scroll. Do a cheaper variant
        # than in the show-all case, that might mess up the scroll slightly in
        # rare cases, but is fast and flicker-free.

        stayput = _loc_ref_item()  # Item to preserve scroll for
        old_row = _item_row(stayput)

        _update_tree()

        # If the reference item disappeared (can happen if the change was done
        # from the jump-to dialog), then avoid messing with the scroll and hope
        # for the best
        if _attached(stayput):
            _tree.yview_scroll(_item_row(stayput) - old_row, "units")

        if _jump_to_tree:
            _update_jump_to_display()


def _set_val_dialog(node, parent):
    # Pops up a dialog for setting the value of the string/int/hex
    # symbol at node 'node'. 'parent' is the parent window.

    def ok(_=None):
        # No 'nonlocal' in Python 2
        global _entry_res

        s = entry.get()
        if sym.type == HEX and not s.startswith(("0x", "0X")):
            s = "0x" + s

        if _check_valid(dialog, entry, sym, s):
            _entry_res = s
            dialog.destroy()

    def cancel(_=None):
        global _entry_res
        _entry_res = None
        dialog.destroy()

    sym = node.item

    dialog = Toplevel(parent)
    dialog.title("Enter {} value".format(TYPE_TO_STR[sym.type]))
    dialog.resizable(False, False)
    dialog.transient(parent)
    dialog.protocol("WM_DELETE_WINDOW", cancel)

    ttk.Label(dialog, text=node.prompt[0] + ":") \
        .grid(column=0, row=0, columnspan=2, sticky="w", padx=".3c",
              pady=".2c .05c")

    entry = ttk.Entry(dialog, width=30)
    # Start with the previous value in the editbox, selected
    entry.insert(0, sym.str_value)
    entry.selection_range(0, "end")
    entry.grid(column=0, row=1, columnspan=2, sticky="ew", padx=".3c")
    entry.focus_set()

    range_info = _range_info(sym)
    if range_info:
        ttk.Label(dialog, text=range_info) \
            .grid(column=0, row=2, columnspan=2, sticky="w", padx=".3c",
                  pady=".2c 0")

    ttk.Button(dialog, text="OK", command=ok) \
        .grid(column=0, row=4 if range_info else 3, sticky="e", padx=".3c",
              pady=".4c")

    ttk.Button(dialog, text="Cancel", command=cancel) \
        .grid(column=1, row=4 if range_info else 3, padx="0 .3c")

    # Give all horizontal space to the grid cell with the OK button, so that
    # Cancel moves to the right
    dialog.columnconfigure(0, weight=1)

    _center_on_root(dialog)

    # Hack to scroll the entry so that the end of the text is shown, from
    # https://stackoverflow.com/questions/29334544/why-does-tkinters-entry-xview-moveto-fail.
    # Related Tk ticket: https://core.tcl.tk/tk/info/2513186fff
    def scroll_entry(_):
        _root.update_idletasks()
        entry.unbind("<Expose>")
        entry.xview_moveto(1)
    entry.bind("<Expose>", scroll_entry)

    # The dialog must be visible before we can grab the input
    dialog.wait_visibility()
    dialog.grab_set()

    dialog.bind("<Return>", ok)
    dialog.bind("<KP_Enter>", ok)
    dialog.bind("<Escape>", cancel)

    # Wait for the user to be done with the dialog
    parent.wait_window(dialog)

    # Regrab the input in the parent
    parent.grab_set()

    return _entry_res


def _center_on_root(dialog):
    # Centers 'dialog' on the root window. It often ends up at some bad place
    # like the top-left corner of the screen otherwise. See the menuconfig()
    # function, which has similar logic.

    dialog.withdraw()
    _root.update_idletasks()

    dialog_width = dialog.winfo_reqwidth()
    dialog_height = dialog.winfo_reqheight()

    screen_width = _root.winfo_screenwidth()
    screen_height = _root.winfo_screenheight()

    x = _root.winfo_rootx() + (_root.winfo_width() - dialog_width)//2
    y = _root.winfo_rooty() + (_root.winfo_height() - dialog_height)//2

    # Clamp so that no part of the dialog is outside the screen
    if x + dialog_width > screen_width:
        x = screen_width - dialog_width
    elif x < 0:
        x = 0
    if y + dialog_height > screen_height:
        y = screen_height - dialog_height
    elif y < 0:
        y = 0

    dialog.geometry("+{}+{}".format(x, y))

    dialog.deiconify()


def _check_valid(dialog, entry, sym, s):
    # Returns True if the string 's' is a well-formed value for 'sym'.
    # Otherwise, pops up an error and returns False.

    if sym.type not in (INT, HEX):
        # Anything goes for non-int/hex symbols
        return True

    base = 10 if sym.type == INT else 16
    try:
        int(s, base)
    except ValueError:
        messagebox.showerror(
            "Bad value",
            "'{}' is a malformed {} value".format(
                s, TYPE_TO_STR[sym.type]),
            parent=dialog)
        entry.focus_set()
        return False

    for low_sym, high_sym, cond in sym.ranges:
        if expr_value(cond):
            low_s = low_sym.str_value
            high_s = high_sym.str_value

            if not int(low_s, base) <= int(s, base) <= int(high_s, base):
                messagebox.showerror(
                    "Value out of range",
                    "{} is outside the range {}-{}".format(s, low_s, high_s),
                    parent=dialog)
                entry.focus_set()
                return False

            break

    return True


def _range_info(sym):
    # Returns a string with information about the valid range for the symbol
    # 'sym', or None if 'sym' doesn't have a range

    if sym.type in (INT, HEX):
        for low, high, cond in sym.ranges:
            if expr_value(cond):
                return "Range: {}-{}".format(low.str_value, high.str_value)

    return None


def _save(_=None):
    # Tries to save the configuration

    if _try_save(_kconf.write_config, _conf_filename, "configuration"):
        _set_conf_changed(False)

    _tree.focus_set()


def _save_as():
    # Pops up a dialog for saving the configuration to a specific location

    global _conf_filename

    filename = _conf_filename
    while True:
        filename = filedialog.asksaveasfilename(
            title="Save configuration as",
            initialdir=os.path.dirname(filename),
            initialfile=os.path.basename(filename),
            parent=_root)

        if not filename:
            break

        if _try_save(_kconf.write_config, filename, "configuration"):
            _conf_filename = filename
            break

    _tree.focus_set()


def _save_minimal():
    # Pops up a dialog for saving a minimal configuration (defconfig) to a
    # specific location

    global _minconf_filename

    filename = _minconf_filename
    while True:
        filename = filedialog.asksaveasfilename(
            title="Save minimal configuration as",
            initialdir=os.path.dirname(filename),
            initialfile=os.path.basename(filename),
            parent=_root)

        if not filename:
            break

        if _try_save(_kconf.write_min_config, filename,
                     "minimal configuration"):

            _minconf_filename = filename
            break

    _tree.focus_set()


def _open(_=None):
    # Pops up a dialog for loading a configuration

    global _conf_filename

    if _conf_changed and \
        not messagebox.askokcancel(
            "Unsaved changes",
            "You have unsaved changes. Load new configuration anyway?"):

        return

    filename = _conf_filename
    while True:
        filename = filedialog.askopenfilename(
            title="Open configuration",
            initialdir=os.path.dirname(filename),
            initialfile=os.path.basename(filename),
            parent=_root)

        if not filename:
            break

        if _try_load(filename):
            # Maybe something fancier could be done here later to try to
            # preserve the scroll

            _conf_filename = filename
            _set_conf_changed(_needs_save())

            if _single_menu and not _shown_menu_nodes(_cur_menu):
                # Turn on show-all if we're in single-menu mode and would end
                # up with an empty menu
                _show_all_var.set(True)

            _update_tree()

            break

    _tree.focus_set()


def _toggle_showname(_):
    # Toggles show-name mode on/off

    _show_name_var.set(not _show_name_var.get())
    _do_showname()


def _do_showname():
    # Updates the UI for the current show-name setting

    # Columns do not automatically shrink/expand, so we have to update
    # column widths ourselves

    tree_width = _tree.winfo_width()

    if _show_name_var.get():
        _tree["displaycolumns"] = ("name",)
        _tree["show"] = "tree headings"
        name_width = tree_width//3
        _tree.column("#0", width=max(tree_width - name_width, 1))
        _tree.column("name", width=name_width)
    else:
        _tree["displaycolumns"] = ()
        _tree["show"] = "tree"
        _tree.column("#0", width=tree_width)

    _tree.focus_set()


def _toggle_showall(_):
    # Toggles show-all mode on/off

    _show_all_var.set(not _show_all)
    _do_showall()


def _do_showall():
    # Updates the UI for the current show-all setting

    # Don't allow turning off show-all if we'd end up with no visible nodes
    if _nothing_shown():
        _show_all_var.set(True)
        return

    # Save scroll information. old_scroll can end up negative here, if the
    # reference item isn't shown (only invisible items on the screen, and
    # show-all being turned off).

    stayput = _vis_loc_ref_item()
    # Probe the middle of the first row, to play it safe. identify_row(0) seems
    # to return the row before the top row.
    old_scroll = _item_row(stayput) - \
        _item_row(_tree.identify_row(_treeview_rowheight//2))

    _update_tree()

    if _show_all:
        # Deep magic: Unless we call update_idletasks(), the scroll adjustment
        # below is restricted to the height of the old tree, instead of the
        # height of the new tree. Since the tree with show-all on is guaranteed
        # to be taller, and we want the maximum range, we only call it when
        # turning show-all on.
        #
        # Strictly speaking, something similar ought to be done when changing
        # symbol values, but it causes annoying flicker, and in 99% of cases
        # things work anyway there (with usually minor scroll mess-ups in the
        # 1% case).
        _root.update_idletasks()

    # Restore scroll
    _tree.yview(_item_row(stayput) - old_scroll)

    _tree.focus_set()


def _nothing_shown():
    # _do_showall() helper. Returns True if no nodes would get
    # shown with the current show-all setting. Also handles the
    # (obscure) case when there are no visible nodes in the entire
    # tree, meaning guiconfig was automatically started in
    # show-all mode, which mustn't be turned off.

    return not _shown_menu_nodes(
        _cur_menu if _single_menu else _kconf.top_node)


def _toggle_tree_mode(_):
    # Toggles single-menu mode on/off

    _single_menu_var.set(not _single_menu)
    _do_tree_mode()


def _do_tree_mode():
    # Updates the UI for the current tree mode (full-tree or single-menu)

    loc_ref_node = _id_to_node[_loc_ref_item()]

    if not _single_menu:
        # _jump_to() -> _enter_menu() already updates the tree, but
        # _jump_to() -> load_parents() doesn't, because it isn't always needed.
        # We always need to update the tree here, e.g. to add/remove "--->".
        _update_tree()

    _jump_to(loc_ref_node)
    _tree.focus_set()


def _enter_menu_and_select_first(menu):
    # Enters the menu 'menu' and selects the first item. Used in single-menu
    # mode.

    _enter_menu(menu)
    _select(_tree, _tree.get_children()[0])


def _enter_menu(menu):
    # Enters the menu 'menu'. Used in single-menu mode.

    global _cur_menu

    _cur_menu = menu
    _update_tree()

    _backbutton["state"] = "disabled" if menu is _kconf.top_node else "normal"


def _leave_menu():
    # Leaves the current menu. Used in single-menu mode.

    global _cur_menu

    if _cur_menu is not _kconf.top_node:
        old_menu = _cur_menu

        _cur_menu = _parent_menu(_cur_menu)
        _update_tree()

        _select(_tree, id(old_menu))

        if _cur_menu is _kconf.top_node:
            _backbutton["state"] = "disabled"

    _tree.focus_set()


def _select(tree, item):
    # Selects, focuses, and see()s 'item' in 'tree'

    tree.selection_set(item)
    tree.focus(item)
    tree.see(item)


def _loc_ref_item():
    # Returns a Treeview item that can serve as a reference for the current
    # scroll location. We try to make this item stay on the same row on the
    # screen when updating the tree.

    # If the selected item is visible, use that
    sel = _tree.selection()
    if sel and _tree.bbox(sel[0]):
        return sel[0]

    # Otherwise, use the middle item on the screen. If it doesn't exist, the
    # tree is probably really small, so use the first item in the entire tree.
    return _tree.identify_row(_tree.winfo_height()//2) or \
        _tree.get_children()[0]


def _vis_loc_ref_item():
    # Like _loc_ref_item(), but finds a visible item around the reference item.
    # Used when changing show-all mode, where non-visible (red) items will
    # disappear.

    item = _loc_ref_item()

    vis_before = _vis_before(item)
    if vis_before and _tree.bbox(vis_before):
        return vis_before

    vis_after = _vis_after(item)
    if vis_after and _tree.bbox(vis_after):
        return vis_after

    return vis_before or vis_after


def _vis_before(item):
    # _vis_loc_ref_item() helper. Returns the first visible (not red) item,
    # searching backwards from 'item'.

    while item:
        if not _tree.tag_has("invisible", item):
            return item

        prev = _tree.prev(item)
        item = prev if prev else _tree.parent(item)

    return None


def _vis_after(item):
    # _vis_loc_ref_item() helper. Returns the first visible (not red) item,
    # searching forwards from 'item'.

    while item:
        if not _tree.tag_has("invisible", item):
            return item

        next = _tree.next(item)
        if next:
            item = next
        else:
            item = _tree.parent(item)
            if not item:
                break
            item = _tree.next(item)

    return None


def _on_quit(_=None):
    # Called when the user wants to exit

    if not _conf_changed:
        _quit("No changes to save (for '{}')".format(_conf_filename))
        return

    while True:
        ync = messagebox.askyesnocancel("Quit", "Save changes?")
        if ync is None:
            return

        if not ync:
            _quit("Configuration ({}) was not saved".format(_conf_filename))
            return

        if _try_save(_kconf.write_config, _conf_filename, "configuration"):
            # _try_save() already prints the "Configuration saved to ..."
            # message
            _quit()
            return


def _quit(msg=None):
    # Quits the application

    # Do not call sys.exit() here, in case we're being run from a script
    _root.destroy()
    if msg:
        print(msg)


def _try_save(save_fn, filename, description):
    # Tries to save a configuration file. Pops up an error and returns False on
    # failure.
    #
    # save_fn:
    #   Function to call with 'filename' to save the file
    #
    # description:
    #   String describing the thing being saved

    try:
        # save_fn() returns a message to print
        msg = save_fn(filename)
        _set_status(msg)
        print(msg)
        return True
    except EnvironmentError as e:
        messagebox.showerror(
            "Error saving " + description,
            "Error saving {} to '{}': {} (errno: {})"
            .format(description, e.filename, e.strerror,
                    errno.errorcode[e.errno]))
        return False


def _try_load(filename):
    # Tries to load a configuration file. Pops up an error and returns False on
    # failure.
    #
    # filename:
    #   Configuration file to load

    try:
        msg = _kconf.load_config(filename)
        _set_status(msg)
        print(msg)
        return True
    except EnvironmentError as e:
        messagebox.showerror(
            "Error loading configuration",
            "Error loading '{}': {} (errno: {})"
            .format(filename, e.strerror, errno.errorcode[e.errno]))
        return False


def _jump_to_dialog(_=None):
    # Pops up a dialog for jumping directly to a particular node. Symbol values
    # can also be changed within the dialog.
    #
    # Note: There's nothing preventing this from doing an incremental search
    # like menuconfig.py does, but currently it's a bit jerky for large Kconfig
    # trees, at least when inputting the beginning of the search string. We'd
    # need to somehow only update the tree items that are shown in the Treeview
    # to fix it.

    global _jump_to_tree

    def search(_=None):
        _update_jump_to_matches(msglabel, entry.get())

    def jump_to_selected(event=None):
        # Jumps to the selected node and closes the dialog

        # Ignore double clicks on the image and in the heading area
        if event and (tree.identify_element(event.x, event.y) == "image" or
                      _in_heading(event)):
            return

        sel = tree.selection()
        if not sel:
            return

        node = _id_to_node[sel[0]]

        if node not in _shown_menu_nodes(_parent_menu(node)):
            _show_all_var.set(True)
            if not _single_menu:
                # See comment in _do_tree_mode()
                _update_tree()

        _jump_to(node)

        dialog.destroy()

    def tree_select(_):
        jumpto_button["state"] = "normal" if tree.selection() else "disabled"


    dialog = Toplevel(_root)
    dialog.geometry("+{}+{}".format(
        _root.winfo_rootx() + 50, _root.winfo_rooty() + 50))
    dialog.title("Jump to symbol/choice/menu/comment")
    dialog.minsize(128, 128)  # See _create_ui()
    dialog.transient(_root)

    ttk.Label(dialog, text=_JUMP_TO_HELP) \
        .grid(column=0, row=0, columnspan=2, sticky="w", padx=".1c",
              pady=".1c")

    entry = ttk.Entry(dialog)
    entry.grid(column=0, row=1, sticky="ew", padx=".1c", pady=".1c")
    entry.focus_set()

    entry.bind("<Return>", search)
    entry.bind("<KP_Enter>", search)

    ttk.Button(dialog, text="Search", command=search) \
        .grid(column=1, row=1, padx="0 .1c", pady="0 .1c")

    msglabel = ttk.Label(dialog)
    msglabel.grid(column=0, row=2, sticky="w", pady="0 .1c")

    panedwindow, tree = _create_kconfig_tree_and_desc(dialog)
    panedwindow.grid(column=0, row=3, columnspan=2, sticky="nsew")

    # Clear tree
    tree.set_children("")

    _jump_to_tree = tree

    jumpto_button = ttk.Button(dialog, text="Jump to selected item",
                               state="disabled", command=jump_to_selected)
    jumpto_button.grid(column=0, row=4, columnspan=2, sticky="ns", pady=".1c")

    dialog.columnconfigure(0, weight=1)
    # Only the pane with the Kconfig tree and description grows vertically
    dialog.rowconfigure(3, weight=1)

    # See the menuconfig() function
    _root.update_idletasks()
    dialog.geometry(dialog.geometry())

    # The dialog must be visible before we can grab the input
    dialog.wait_visibility()
    dialog.grab_set()

    tree.bind("<Double-1>", jump_to_selected)
    tree.bind("<Return>", jump_to_selected)
    tree.bind("<KP_Enter>", jump_to_selected)
    # add=True to avoid overriding the description text update
    tree.bind("<<TreeviewSelect>>", tree_select, add=True)

    dialog.bind("<Escape>", lambda _: dialog.destroy())

    # Wait for the user to be done with the dialog
    _root.wait_window(dialog)

    _jump_to_tree = None

    _tree.focus_set()


def _update_jump_to_matches(msglabel, search_string):
    # Searches for nodes matching the search string and updates
    # _jump_to_matches. Puts a message in 'msglabel' if there are no matches,
    # or regex errors.

    global _jump_to_matches

    _jump_to_tree.selection_set(())

    try:
        # We could use re.IGNORECASE here instead of lower(), but this is
        # faster for regexes like '.*debug$' (though the '.*' is redundant
        # there). Those probably have bad interactions with re.search(), which
        # matches anywhere in the string.
        regex_searches = [re.compile(regex).search
                          for regex in search_string.lower().split()]
    except re.error as e:
        msg = "Bad regular expression"
        # re.error.msg was added in Python 3.5
        if hasattr(e, "msg"):
            msg += ": " + e.msg
        msglabel["text"] = msg
        # Clear tree
        _jump_to_tree.set_children("")
        return

    _jump_to_matches = []
    add_match = _jump_to_matches.append

    for node in _sorted_sc_nodes():
        # Symbol/choice
        sc = node.item

        for search in regex_searches:
            # Both the name and the prompt might be missing, since
            # we're searching both symbols and choices

            # Does the regex match either the symbol name or the
            # prompt (if any)?
            if not (sc.name and search(sc.name.lower()) or
                    node.prompt and search(node.prompt[0].lower())):

                # Give up on the first regex that doesn't match, to
                # speed things up a bit when multiple regexes are
                # entered
                break

        else:
            add_match(node)

    # Search menus and comments

    for node in _sorted_menu_comment_nodes():
        for search in regex_searches:
            if not search(node.prompt[0].lower()):
                break
        else:
            add_match(node)

    msglabel["text"] = "" if _jump_to_matches else "No matches"

    _update_jump_to_display()

    if _jump_to_matches:
        item = id(_jump_to_matches[0])
        _jump_to_tree.selection_set(item)
        _jump_to_tree.focus(item)


def _update_jump_to_display():
    # Updates the images and text for the items in _jump_to_matches, and sets
    # them as the items of _jump_to_tree

    # Micro-optimize a bit
    item = _jump_to_tree.item
    id_ = id
    node_str = _node_str
    img_tag = _img_tag
    visible = _visible
    for node in _jump_to_matches:
        item(id_(node),
             text=node_str(node),
             tags=img_tag(node) if visible(node) else
                 img_tag(node) + " invisible")

    _jump_to_tree.set_children("", *map(id, _jump_to_matches))


def _jump_to(node):
    # Jumps directly to 'node' and selects it

    if _single_menu:
        _enter_menu(_parent_menu(node))
    else:
        _load_parents(node)

    _select(_tree, id(node))


# Obscure Python: We never pass a value for cached_nodes, and it keeps pointing
# to the same list. This avoids a global.
def _sorted_sc_nodes(cached_nodes=[]):
    # Returns a sorted list of symbol and choice nodes to search. The symbol
    # nodes appear first, sorted by name, and then the choice nodes, sorted by
    # prompt and (secondarily) name.

    if not cached_nodes:
        # Add symbol nodes
        for sym in sorted(_kconf.unique_defined_syms,
                          key=lambda sym: sym.name):
            # += is in-place for lists
            cached_nodes += sym.nodes

        # Add choice nodes

        choices = sorted(_kconf.unique_choices,
                         key=lambda choice: choice.name or "")

        cached_nodes += sorted(
            [node for choice in choices for node in choice.nodes],
            key=lambda node: node.prompt[0] if node.prompt else "")

    return cached_nodes


def _sorted_menu_comment_nodes(cached_nodes=[]):
    # Returns a list of menu and comment nodes to search, sorted by prompt,
    # with the menus first

    if not cached_nodes:
        def prompt_text(mc):
            return mc.prompt[0]

        cached_nodes += sorted(_kconf.menus, key=prompt_text)
        cached_nodes += sorted(_kconf.comments, key=prompt_text)

    return cached_nodes


def _load_parents(node):
    # Menus are lazily populated as they're opened in full-tree mode, but
    # jumping to an item needs its parent menus to be populated. This function
    # populates 'node's parents.

    # Get all parents leading up to 'node', sorted with the root first
    parents = []
    cur = node.parent
    while cur is not _kconf.top_node:
        parents.append(cur)
        cur = cur.parent
    parents.reverse()

    for i, parent in enumerate(parents):
        if not _tree.item(id(parent), "open"):
            # Found a closed menu. Populate it and all the remaining menus
            # leading up to 'node'.
            for parent in parents[i:]:
                # We only need to populate "real" menus/choices. Implicit menus
                # are populated when their parents menus are entered.
                if not isinstance(parent.item, Symbol):
                    _build_full_tree(parent)
            return


def _parent_menu(node):
    # Returns the menu node of the menu that contains 'node'. In addition to
    # proper 'menu's, this might also be a 'menuconfig' symbol or a 'choice'.
    # "Menu" here means a menu in the interface.

    menu = node.parent
    while not menu.is_menuconfig:
        menu = menu.parent
    return menu


def _trace_write(var, fn):
    # Makes fn() be called whenever the Tkinter Variable 'var' changes value

    # trace_variable() is deprecated according to the docstring,
    # which recommends trace_add()
    if hasattr(var, "trace_add"):
        var.trace_add("write", fn)
    else:
        var.trace_variable("w", fn)


def _info_str(node):
    # Returns information about the menu node 'node' as a string.
    #
    # The helper functions are responsible for adding newlines. This allows
    # them to return "" if they don't want to add any output.

    if isinstance(node.item, Symbol):
        sym = node.item

        return (
            _name_info(sym) +
            _help_info(sym) +
            _direct_dep_info(sym) +
            _defaults_info(sym) +
            _select_imply_info(sym) +
            _kconfig_def_info(sym)
        )

    if isinstance(node.item, Choice):
        choice = node.item

        return (
            _name_info(choice) +
            _help_info(choice) +
            'Mode: {}\n\n'.format(choice.str_value) +
            _choice_syms_info(choice) +
            _direct_dep_info(choice) +
            _defaults_info(choice) +
            _kconfig_def_info(choice)
        )

    # node.item in (MENU, COMMENT)
    return _kconfig_def_info(node)


def _name_info(sc):
    # Returns a string with the name of the symbol/choice. Choices are shown as
    # <choice (name if any)>.

    return (sc.name if sc.name else standard_sc_expr_str(sc)) + "\n\n"


def _value_info(sym):
    # Returns a string showing 'sym's value

    # Only put quotes around the value for string symbols
    return "Value: {}\n".format(
        '"{}"'.format(sym.str_value)
        if sym.orig_type == STRING
        else sym.str_value)


def _choice_syms_info(choice):
    # Returns a string listing the choice symbols in 'choice'. Adds
    # "(selected)" next to the selected one.

    s = "Choice symbols:\n"

    for sym in choice.syms:
        s += "  - " + sym.name
        if sym is choice.selection:
            s += " (selected)"
        s += "\n"

    return s + "\n"


def _help_info(sc):
    # Returns a string with the help text(s) of 'sc' (Symbol or Choice).
    # Symbols and choices defined in multiple locations can have multiple help
    # texts.

    s = ""

    for node in sc.nodes:
        if node.help is not None:
            s += node.help + "\n\n"

    return s


def _direct_dep_info(sc):
    # Returns a string describing the direct dependencies of 'sc' (Symbol or
    # Choice). The direct dependencies are the OR of the dependencies from each
    # definition location. The dependencies at each definition location come
    # from 'depends on' and dependencies inherited from parent items.

    return "" if sc.direct_dep is _kconf.y else \
        'Direct dependencies (={}):\n{}\n' \
        .format(TRI_TO_STR[expr_value(sc.direct_dep)],
                _split_expr_info(sc.direct_dep, 2))


def _defaults_info(sc):
    # Returns a string describing the defaults of 'sc' (Symbol or Choice)

    if not sc.defaults:
        return ""

    s = "Default"
    if len(sc.defaults) > 1:
        s += "s"
    s += ":\n"

    for val, cond in sc.orig_defaults:
        s += "  - "
        if isinstance(sc, Symbol):
            s += _expr_str(val)

            # Skip the tristate value hint if the expression is just a single
            # symbol. _expr_str() already shows its value as a string.
            #
            # This also avoids showing the tristate value for string/int/hex
            # defaults, which wouldn't make any sense.
            if isinstance(val, tuple):
                s += '  (={})'.format(TRI_TO_STR[expr_value(val)])
        else:
            # Don't print the value next to the symbol name for choice
            # defaults, as it looks a bit confusing
            s += val.name
        s += "\n"

        if cond is not _kconf.y:
            s += "    Condition (={}):\n{}" \
                 .format(TRI_TO_STR[expr_value(cond)],
                         _split_expr_info(cond, 4))

    return s + "\n"


def _split_expr_info(expr, indent):
    # Returns a string with 'expr' split into its top-level && or || operands,
    # with one operand per line, together with the operand's value. This is
    # usually enough to get something readable for long expressions. A fancier
    # recursive thingy would be possible too.
    #
    # indent:
    #   Number of leading spaces to add before the split expression.

    if len(split_expr(expr, AND)) > 1:
        split_op = AND
        op_str = "&&"
    else:
        split_op = OR
        op_str = "||"

    s = ""
    for i, term in enumerate(split_expr(expr, split_op)):
        s += "{}{} {}".format(indent*" ",
                              "  " if i == 0 else op_str,
                              _expr_str(term))

        # Don't bother showing the value hint if the expression is just a
        # single symbol. _expr_str() already shows its value.
        if isinstance(term, tuple):
            s += "  (={})".format(TRI_TO_STR[expr_value(term)])

        s += "\n"

    return s


def _select_imply_info(sym):
    # Returns a string with information about which symbols 'select' or 'imply'
    # 'sym'. The selecting/implying symbols are grouped according to which
    # value they select/imply 'sym' to (n/m/y).

    def sis(expr, val, title):
        # sis = selects/implies
        sis = [si for si in split_expr(expr, OR) if expr_value(si) == val]
        if not sis:
            return ""

        res = title
        for si in sis:
            res += "  - {}\n".format(split_expr(si, AND)[0].name)
        return res + "\n"

    s = ""

    if sym.rev_dep is not _kconf.n:
        s += sis(sym.rev_dep, 2,
                 "Symbols currently y-selecting this symbol:\n")
        s += sis(sym.rev_dep, 1,
                 "Symbols currently m-selecting this symbol:\n")
        s += sis(sym.rev_dep, 0,
                 "Symbols currently n-selecting this symbol (no effect):\n")

    if sym.weak_rev_dep is not _kconf.n:
        s += sis(sym.weak_rev_dep, 2,
                 "Symbols currently y-implying this symbol:\n")
        s += sis(sym.weak_rev_dep, 1,
                 "Symbols currently m-implying this symbol:\n")
        s += sis(sym.weak_rev_dep, 0,
                 "Symbols currently n-implying this symbol (no effect):\n")

    return s


def _kconfig_def_info(item):
    # Returns a string with the definition of 'item' in Kconfig syntax,
    # together with the definition location(s) and their include and menu paths

    nodes = [item] if isinstance(item, MenuNode) else item.nodes

    s = "Kconfig definition{}, with parent deps. propagated to 'depends on'\n" \
        .format("s" if len(nodes) > 1 else "")
    s += (len(s) - 1)*"="

    for node in nodes:
        s += "\n\n" \
             "At {}:{}\n" \
             "{}" \
             "Menu path: {}\n\n" \
             "{}" \
             .format(node.filename, node.linenr,
                     _include_path_info(node),
                     _menu_path_info(node),
                     node.custom_str(_name_and_val_str))

    return s


def _include_path_info(node):
    if not node.include_path:
        # In the top-level Kconfig file
        return ""

    return "Included via {}\n".format(
        " -> ".join("{}:{}".format(filename, linenr)
                    for filename, linenr in node.include_path))


def _menu_path_info(node):
    # Returns a string describing the menu path leading up to 'node'

    path = ""

    while node.parent is not _kconf.top_node:
        node = node.parent

        # Promptless choices might appear among the parents. Use
        # standard_sc_expr_str() for them, so that they show up as
        # '<choice (name if any)>'.
        path = " -> " + (node.prompt[0] if node.prompt else
                         standard_sc_expr_str(node.item)) + path

    return "(Top)" + path


def _name_and_val_str(sc):
    # Custom symbol/choice printer that shows symbol values after symbols

    # Show the values of non-constant (non-quoted) symbols that don't look like
    # numbers. Things like 123 are actually symbol references, and only work as
    # expected due to undefined symbols getting their name as their value.
    # Showing the symbol value for those isn't helpful though.
    if isinstance(sc, Symbol) and not sc.is_constant and not _is_num(sc.name):
        if not sc.nodes:
            # Undefined symbol reference
            return "{}(undefined/n)".format(sc.name)

        return '{}(={})'.format(sc.name, sc.str_value)

    # For other items, use the standard format
    return standard_sc_expr_str(sc)


def _expr_str(expr):
    # Custom expression printer that shows symbol values
    return expr_str(expr, _name_and_val_str)


def _is_num(name):
    # Heuristic to see if a symbol name looks like a number, for nicer output
    # when printing expressions. Things like 16 are actually symbol names, only
    # they get their name as their value when the symbol is undefined.

    try:
        int(name)
    except ValueError:
        if not name.startswith(("0x", "0X")):
            return False

        try:
            int(name, 16)
        except ValueError:
            return False

    return True


if __name__ == "__main__":
    _main()
