Toolchains

Toolchains for all supported devices.

343 Commits   8 Branches   37 Tags   |
Index: 3pp/dialog/1.3-20181107/Makefile
===================================================================
--- 3pp/dialog/1.3-20181107/Makefile	(nonexistent)
+++ 3pp/dialog/1.3-20181107/Makefile	(revision 258)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(TOOLCHAIN_HOST)
+
+include ../../../../build-system/config.mk
+
+SOURCE_REQUIRES = build-system/3pp/sources/packages/dialog
+
+
+# ======= __END_OF_REQUIRES__ =======
+
+
+tar_gz_archive  = $(BUILDSYSTEM)/3pp/sources/packages/dialog/dialog-1.3-20181107.tgz
+src_dir         = dialog-1.3-20181107
+build_dir       = $(TARGET_BUILD_DIR)/built
+
+src_done        = $(TARGET_BUILD_DIR)/.source-done
+SRC_DIR         = $(TARGET_BUILD_DIR)/dialog-1.3-20181107
+SRC_ARCHIVE     = $(tar_gz_archive)
+
+DIALOGRC        = $(BUILDSYSTEM)/3pp/sources/packages/dialog/dialogrc
+
+PATCHES = PATCHES
+
+build_target    = $(TARGET_BUILD_DIR)/.built
+install_target  = $(TARGET_BUILD_DIR)/.installed
+
+environment     =
+extra_configure_switches  = --libdir=/usr/lib
+extra_configure_switches += --mandir=/usr/share/man
+extra_configure_switches += --without-shared
+extra_configure_switches += --with-ncursesw
+
+BUILD_TARGETS = $(install_target)
+
+include ../../../../build-system/core.mk
+
+$(src_done): $(SRC_ARCHIVE) $(PATCHES_DEP)
+	$(UNPACK_SRC_ARCHIVE)
+	$(APPLY_PATCHES)
+	@touch $@
+
+$(build_target): $(src_done)
+	@mkdir -p $(build_dir)
+	@cd $(build_dir) && $(environment) ../$(src_dir)/configure \
+	  --prefix=/ \
+	  $(extra_configure_switches)
+	@$(environment) $(MAKE) -C $(build_dir) all
+	@touch $@
+
+$(install_target): $(build_target)
+	@echo -e "\n======= Installing DIALOG binary =======\n"
+	@mkdir -p $(BUILDSYSTEM)/{etc,sbin} && \
+	  cp -a $(DIALOGRC) $(BUILDSYSTEM)/etc && \
+	  cp -a $(build_dir)/dialog $(BUILDSYSTEM)/sbin && \
+	  echo "DIALOG := $(BUILDSYSTEM)/sbin/dialog" >> $(BUILDSYSTEM)/sbin/.config
+	@touch $@
Index: 3pp/dialog/1.3-20181107/PATCHES
===================================================================
--- 3pp/dialog/1.3-20181107/PATCHES	(nonexistent)
+++ 3pp/dialog/1.3-20181107/PATCHES	(revision 258)
@@ -0,0 +1,2 @@
+
+../../sources/packages/dialog/patches/dialog-1.3-20181107.patch -p0
Index: 3pp/gnattools/7.2.0/Makefile
===================================================================
--- 3pp/gnattools/7.2.0/Makefile	(revision 257)
+++ 3pp/gnattools/7.2.0/Makefile	(nonexistent)
@@ -1,90 +0,0 @@
-
-COMPONENT_TARGETS  = $(TOOLCHAIN_HOST)
-
-include ../../../../build-system/config.mk
-
-
-SOURCE_REQUIRES  = build-system/3pp/sources/GNU
-
-# ======= __END_OF_REQUIRES__ =======
-
-tar_xz_archive        = $(BUILDSYSTEM)/3pp/sources/GNU/gcc/gcc-7.2.0/gcc-7.2.0.tar.xz
-tar_xz_archive_gmp    = $(BUILDSYSTEM)/3pp/sources/GNU/gmp/gmp-6.1.2.tar.xz
-tar_xz_archive_mpfr   = $(BUILDSYSTEM)/3pp/sources/GNU/mpfr/mpfr-4.0.1.tar.xz
-tar_gz_archive_mpc    = $(BUILDSYSTEM)/3pp/sources/GNU/mpc/mpc-1.1.0.tar.gz
-SRC_ARCHIVE           = $(tar_xz_archive)
-SRC_DIR               = $(TARGET_BUILD_DIR)/gcc-7.2.0
-src_dir_name          = gcc-7.2.0
-src_done              = $(TARGET_BUILD_DIR)/.source-done
-gmp_src_done          = $(TARGET_BUILD_DIR)/.gmp-source-done
-mpfr_src_done         = $(TARGET_BUILD_DIR)/.mpfr-source-done
-mpc_src_done          = $(TARGET_BUILD_DIR)/.mpc-source-done
-
-PATCHES        = PATCHES
-
-build_dir             = $(TARGET_BUILD_DIR)/build
-
-
-build_target   = $(TARGET_BUILD_DIR)/.built
-install_target = $(TARGET_BUILD_DIR)/.installed
-
-
-BUILD_TARGETS  = $(build_target)
-BUILD_TARGETS += $(install_target)
-
-
-include ../../../../build-system/core.mk
-
-
-JOBS = -j$(NUMPROCS)
-
-environment  = CC="$(CCACHE)/usr/bin/gcc"
-environment += CC_FOR_BUILD="$(CCACHE)/usr/bin/gcc"
-environment += CXX_FOR_BUILD="$(CCACHE)/usr/bin/g++"
-
-
-GNATTOOLS_DEST_DIR = $(BUILDSYSTEM)/gnattools/7.2.0/usr
-
-extra_configure_switches  = --disable-bootstrap
-extra_configure_switches += --enable-languages=c,c++,ada
-
-
-$(src_done): $(SRC_ARCHIVE) $(PATCHES_DEP)
-	$(UNPACK_SRC_ARCHIVE)
-	$(APPLY_PATCHES)
-	@touch $@
-
-$(gmp_src_done): $(src_done)
-	@echo "Expanding $(tar_xz_archive_gmp)"
-	@tar xJf $(tar_xz_archive_gmp) -C $(TARGET_BUILD_DIR)
-	@cd $(SRC_DIR); ln -sf ../gmp-6.1.2 gmp
-	@touch $@
-
-$(mpfr_src_done): $(src_done)
-	@echo "Expanding $(tar_xz_archive_mpfr)"
-	@tar xJf $(tar_xz_archive_mpfr) -C $(TARGET_BUILD_DIR)
-	@cd $(SRC_DIR); ln -sf ../mpfr-4.0.1 mpfr
-	@touch $@
-
-$(mpc_src_done): $(src_done)
-	@echo "Expanding $(tar_gz_archive_mpc)"
-	@tar xzf $(tar_gz_archive_mpc) -C $(TARGET_BUILD_DIR)
-	@cd $(SRC_DIR); ln -sf ../mpc-1.1.0 mpc
-	@touch $@
-
-$(build_target): $(src_done) $(gmp_src_done) $(mpfr_src_done) $(mpc_src_done)
-	@mkdir -p $(build_dir)
-	@cd $(build_dir) && $(environment) ../$(src_dir_name)/configure \
-	  --prefix=$(GNATTOOLS_DEST_DIR)                  \
-	  --build=$(shell $(BUILDSYSTEM)/canonical-build) \
-	  --datadir=$(GNATTOOLS_DEST_DIR)/share           \
-	  --infodir=$(GNATTOOLS_DEST_DIR)/share/info      \
-	  --mandir=$(GNATTOOLS_DEST_DIR)/share/man        \
-	  $(extra_configure_switches)
-	@cd $(build_dir) && make $(JOBS)
-	@touch $@
-
-$(install_target): $(build_target)
-	@cd $(build_dir) && make install
-	@rm -f $(GNATTOOLS_DEST_DIR)/share/info/dir
-	@touch $@
Index: 3pp/gnattools/7.3.0/Makefile
===================================================================
--- 3pp/gnattools/7.3.0/Makefile	(nonexistent)
+++ 3pp/gnattools/7.3.0/Makefile	(revision 258)
@@ -0,0 +1,90 @@
+
+COMPONENT_TARGETS  = $(TOOLCHAIN_HOST)
+
+include ../../../../build-system/config.mk
+
+
+SOURCE_REQUIRES  = build-system/3pp/sources/GNU
+
+# ======= __END_OF_REQUIRES__ =======
+
+tar_xz_archive        = $(BUILDSYSTEM)/3pp/sources/GNU/gcc/gcc-7.3.0/gcc-7.3.0.tar.xz
+tar_xz_archive_gmp    = $(BUILDSYSTEM)/3pp/sources/GNU/gmp/gmp-6.1.2.tar.xz
+tar_xz_archive_mpfr   = $(BUILDSYSTEM)/3pp/sources/GNU/mpfr/mpfr-4.0.1.tar.xz
+tar_gz_archive_mpc    = $(BUILDSYSTEM)/3pp/sources/GNU/mpc/mpc-1.1.0.tar.gz
+SRC_ARCHIVE           = $(tar_xz_archive)
+SRC_DIR               = $(TARGET_BUILD_DIR)/gcc-7.3.0
+src_dir_name          = gcc-7.3.0
+src_done              = $(TARGET_BUILD_DIR)/.source-done
+gmp_src_done          = $(TARGET_BUILD_DIR)/.gmp-source-done
+mpfr_src_done         = $(TARGET_BUILD_DIR)/.mpfr-source-done
+mpc_src_done          = $(TARGET_BUILD_DIR)/.mpc-source-done
+
+PATCHES        = PATCHES
+
+build_dir             = $(TARGET_BUILD_DIR)/build
+
+
+build_target   = $(TARGET_BUILD_DIR)/.built
+install_target = $(TARGET_BUILD_DIR)/.installed
+
+
+BUILD_TARGETS  = $(build_target)
+BUILD_TARGETS += $(install_target)
+
+
+include ../../../../build-system/core.mk
+
+
+JOBS = -j$(NUMPROCS)
+
+environment  = CC="$(CCACHE)/usr/bin/gcc"
+environment += CC_FOR_BUILD="$(CCACHE)/usr/bin/gcc"
+environment += CXX_FOR_BUILD="$(CCACHE)/usr/bin/g++"
+
+
+GNATTOOLS_DEST_DIR = $(BUILDSYSTEM)/gnattools/7.3.0/usr
+
+extra_configure_switches  = --disable-bootstrap
+extra_configure_switches += --enable-languages=c,c++,ada
+
+
+$(src_done): $(SRC_ARCHIVE) $(PATCHES_DEP)
+	$(UNPACK_SRC_ARCHIVE)
+	$(APPLY_PATCHES)
+	@touch $@
+
+$(gmp_src_done): $(src_done)
+	@echo "Expanding $(tar_xz_archive_gmp)"
+	@tar xJf $(tar_xz_archive_gmp) -C $(TARGET_BUILD_DIR)
+	@cd $(SRC_DIR); ln -sf ../gmp-6.1.2 gmp
+	@touch $@
+
+$(mpfr_src_done): $(src_done)
+	@echo "Expanding $(tar_xz_archive_mpfr)"
+	@tar xJf $(tar_xz_archive_mpfr) -C $(TARGET_BUILD_DIR)
+	@cd $(SRC_DIR); ln -sf ../mpfr-4.0.1 mpfr
+	@touch $@
+
+$(mpc_src_done): $(src_done)
+	@echo "Expanding $(tar_gz_archive_mpc)"
+	@tar xzf $(tar_gz_archive_mpc) -C $(TARGET_BUILD_DIR)
+	@cd $(SRC_DIR); ln -sf ../mpc-1.1.0 mpc
+	@touch $@
+
+$(build_target): $(src_done) $(gmp_src_done) $(mpfr_src_done) $(mpc_src_done)
+	@mkdir -p $(build_dir)
+	@cd $(build_dir) && $(environment) ../$(src_dir_name)/configure \
+	  --prefix=$(GNATTOOLS_DEST_DIR)                  \
+	  --build=$(shell $(BUILDSYSTEM)/canonical-build) \
+	  --datadir=$(GNATTOOLS_DEST_DIR)/share           \
+	  --infodir=$(GNATTOOLS_DEST_DIR)/share/info      \
+	  --mandir=$(GNATTOOLS_DEST_DIR)/share/man        \
+	  $(extra_configure_switches)
+	@cd $(build_dir) && make $(JOBS)
+	@touch $@
+
+$(install_target): $(build_target)
+	@cd $(build_dir) && make install
+	@rm -f $(GNATTOOLS_DEST_DIR)/share/info/dir
+	@touch $@
Index: 3pp/gnattools/7.3.0/PATCHES
===================================================================
Index: 3pp/sources/GNU/gcc/gcc-7.2.0/Makefile
===================================================================
--- 3pp/sources/GNU/gcc/gcc-7.2.0/Makefile	(revision 257)
+++ 3pp/sources/GNU/gcc/gcc-7.2.0/Makefile	(nonexistent)
@@ -1,39 +0,0 @@
-
-COMPONENT_TARGETS = $(TOOLCHAIN_NOARCH)
-
-include ../../../../../../build-system/config.mk
-
-url         = $(DOWNLOAD_SERVER)/sources/GNU/gcc/gcc-$(version)
-
-version     = 7.2.0
-
-tarballs    = $(addsuffix .tar.xz, $(addprefix gcc-, $(version)))
-sha1s       = $(addsuffix .sha1sum, $(tarballs))
-
-BUILD_TARGETS = $(tarballs) $(sha1s)
-
-include ../../../../../../build-system/core.mk
-
-.PHONY: download_clean
-
-$(tarballs):
-	@echo -e "\n======= Downloading source tarballs =======" ; \
-	 for tarball in $(tarballs) ; do \
-	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) -i & \
-	 done ; wait
-
-$(sha1s): $(tarballs)
-	@for sha in $@ ; do \
-	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
-	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) -i & wait %1 ; \
-	   touch $$sha ; \
-	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
-	   sha1sum --check $$sha ; ret="$$?" ; \
-	   if [ "$$ret" == "1" ]; then \
-	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
-	     exit 1 ; \
-	   fi ; \
-	 done
-
-download_clean:
-	@rm -f $(tarballs) $(sha1s)
Index: 3pp/sources/GNU/gcc/gcc-7.3.0/Makefile
===================================================================
--- 3pp/sources/GNU/gcc/gcc-7.3.0/Makefile	(nonexistent)
+++ 3pp/sources/GNU/gcc/gcc-7.3.0/Makefile	(revision 258)
@@ -0,0 +1,39 @@
+
+COMPONENT_TARGETS = $(TOOLCHAIN_NOARCH)
+
+include ../../../../../../build-system/config.mk
+
+url         = $(DOWNLOAD_SERVER)/sources/GNU/gcc/gcc-$(version)
+
+version     = 7.3.0
+
+tarballs    = $(addsuffix .tar.xz, $(addprefix gcc-, $(version)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+include ../../../../../../build-system/core.mk
+
+.PHONY: download_clean
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) -i & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) -i & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: 3pp/sources/packages/Makefile
===================================================================
--- 3pp/sources/packages/Makefile	(nonexistent)
+++ 3pp/sources/packages/Makefile	(revision 258)
@@ -0,0 +1,14 @@
+
+COMPONENT_TARGETS = $(TOOLCHAIN_NOARCH)
+
+SOURCE_REQUIRES += ALL_DIRS
+
+# ======= __END_OF_REQUIRES__ =======
+
+include ../../../../build-system/core.mk
+
+
+download_clean:
+	@true
+
+.PHONY: download_clean
Index: 3pp/sources/packages/dialog/Makefile
===================================================================
--- 3pp/sources/packages/dialog/Makefile	(nonexistent)
+++ 3pp/sources/packages/dialog/Makefile	(revision 258)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(TOOLCHAIN_NOARCH)
+
+
+include ../../../../../build-system/config.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/packages/a/dialog
+
+versions    = 1.3-20181107
+pkgname     = dialog
+suffix      = tgz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/dialog-1.3-20181107.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) -i & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) -i & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-1.3-20181107-patch ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: 3pp/sources/packages/dialog/create-1.3-20181107-patch/create.patch.sh
===================================================================
--- 3pp/sources/packages/dialog/create-1.3-20181107-patch/create.patch.sh	(nonexistent)
+++ 3pp/sources/packages/dialog/create-1.3-20181107-patch/create.patch.sh	(revision 258)
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+VERSION=1.3-20181107
+
+tar --files-from=file.list -xzvf ../dialog-$VERSION.tgz
+mv dialog-$VERSION dialog-$VERSION-orig
+
+cp -rf ./dialog-$VERSION-new ./dialog-$VERSION
+
+diff -b --unified -Nr  dialog-$VERSION-orig  dialog-$VERSION > dialog-$VERSION.patch
+
+mv dialog-$VERSION.patch ../patches
+
+rm -rf ./dialog-$VERSION
+rm -rf ./dialog-$VERSION-orig

Property changes on: 3pp/sources/packages/dialog/create-1.3-20181107-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/checklist.c
===================================================================
--- 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/checklist.c	(nonexistent)
+++ 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/checklist.c	(revision 258)
@@ -0,0 +1,698 @@
+/*
+ *  $Id: checklist.c,v 1.160 2018/06/19 22:57:01 tom Exp $
+ *
+ *  checklist.c -- implements the checklist box
+ *
+ *  Copyright 2000-2016,2018	Thomas E. Dickey
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License, version 2.1
+ *  as published by the Free Software Foundation.
+ *
+ *  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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to
+ *	Free Software Foundation, Inc.
+ *	51 Franklin St., Fifth Floor
+ *	Boston, MA 02110, USA.
+ *
+ *  An earlier version of this program lists as authors:
+ *	Savio Lam (lam836@cs.cuhk.hk)
+ *	Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
+ *	Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
+ */
+
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#define MIN_HIGH  4
+
+typedef struct {
+    /* the outer-window */
+    WINDOW *dialog;
+    int box_y;
+    int box_x;
+    int check_x;
+    int item_x;
+    int checkflag;
+    int use_height;
+    int use_width;
+    /* the inner-window */
+    WINDOW *list;
+    DIALOG_LISTITEM *items;
+    int item_no;
+    const char *states;
+} ALL_DATA;
+
+/*
+ * Print list item.  The 'selected' parameter is true if 'choice' is the
+ * current item.  That one is colored differently from the other items.
+ */
+static void
+print_item(ALL_DATA * data,
+	   WINDOW *win,
+	   DIALOG_LISTITEM * item,
+	   const char *states,
+	   int choice,
+	   int selected)
+{
+    chtype save = dlg_get_attrs(win);
+    int i;
+    bool both = (!dialog_vars.no_tags && !dialog_vars.no_items);
+    bool first = TRUE;
+    int climit = (getmaxx(win) - data->check_x + 1);
+    const char *show = (dialog_vars.no_items
+			? item->name
+			: item->text);
+
+    /* Clear 'residue' of last item */
+    dlg_attrset(win, menubox_attr);
+    (void) wmove(win, choice, 0);
+    for (i = 0; i < data->use_width; i++)
+	(void) waddch(win, ' ');
+
+    (void) wmove(win, choice, data->check_x);
+    dlg_attrset(win, selected ? check_selected_attr : check_attr);
+    (void) wprintw(win,
+		   (data->checkflag == FLAG_CHECK) ? "[%c]" : "(%c)",
+		   states[item->state]);
+    dlg_attrset(win, menubox_attr);
+    (void) waddch(win, ' ');
+
+    if (both) {
+	dlg_print_listitem(win, item->name, climit, first, selected);
+	first = FALSE;
+    }
+
+    (void) wmove(win, choice, data->item_x);
+    dlg_print_listitem(win, show, climit, first, selected);
+
+    if (selected) {
+	dlg_item_help(item->help);
+    }
+    dlg_attrset(win, save);
+}
+
+static void
+print_list(ALL_DATA * data, int choice, int scrollamt, int max_choice)
+{
+    int i;
+    int cur_y, cur_x;
+
+    getyx(data->dialog, cur_y, cur_x);
+    for (i = 0; i < max_choice; i++) {
+	print_item(data,
+		   data->list,
+		   &data->items[i + scrollamt],
+		   data->states,
+		   i, i == choice);
+    }
+    (void) wnoutrefresh(data->list);
+
+    dlg_draw_scrollbar(data->dialog,
+		       (long) (scrollamt),
+		       (long) (scrollamt),
+		       (long) (scrollamt + max_choice),
+		       (long) (data->item_no),
+		       data->box_x + data->check_x,
+		       data->box_x + data->use_width,
+		       data->box_y,
+		       data->box_y + data->use_height + 1,
+		       menubox_border2_attr,
+		       menubox_border_attr);
+
+    (void) wmove(data->dialog, cur_y, cur_x);
+}
+
+static bool
+check_hotkey(DIALOG_LISTITEM * items, int choice)
+{
+    bool result = FALSE;
+
+    if (dlg_match_char(dlg_last_getc(),
+		       (dialog_vars.no_tags
+			? items[choice].text
+			: items[choice].name))) {
+	result = TRUE;
+    }
+    return result;
+}
+
+/*
+ * This is an alternate interface to 'checklist' which allows the application
+ * to read the list item states back directly without putting them in the
+ * output buffer.  It also provides for more than two states over which the
+ * check/radio box can display.
+ */
+int
+dlg_checklist(const char *title,
+	      const char *cprompt,
+	      int height,
+	      int width,
+	      int list_height,
+	      int item_no,
+	      DIALOG_LISTITEM * items,
+	      const char *states,
+	      int flag,
+	      int *current_item)
+{
+    /* *INDENT-OFF* */
+    static DLG_KEYS_BINDING binding[] = {
+	HELPKEY_BINDINGS,
+	ENTERKEY_BINDINGS,
+	DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
+	DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
+	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
+	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
+	DLG_KEYS_DATA( DLGK_ITEM_FIRST, KEY_HOME ),
+	DLG_KEYS_DATA( DLGK_ITEM_LAST,	KEY_END ),
+	DLG_KEYS_DATA( DLGK_ITEM_LAST,	KEY_LL ),
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	'+' ),
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	KEY_DOWN ),
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  CHR_NEXT ),
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,	'-' ),
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,	KEY_UP ),
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,  CHR_PREVIOUS ),
+	DLG_KEYS_DATA( DLGK_PAGE_NEXT,	KEY_NPAGE ),
+	DLG_KEYS_DATA( DLGK_PAGE_NEXT,	DLGK_MOUSE(KEY_NPAGE) ),
+	DLG_KEYS_DATA( DLGK_PAGE_PREV,	KEY_PPAGE ),
+	DLG_KEYS_DATA( DLGK_PAGE_PREV,	DLGK_MOUSE(KEY_PPAGE) ),
+	TOGGLEKEY_BINDINGS,
+	END_KEYS_BINDING
+    };
+    /* *INDENT-ON* */
+
+#ifdef KEY_RESIZE
+    int old_height = height;
+    int old_width = width;
+#endif
+    ALL_DATA all;
+    int i, j, key2, found, x, y, cur_x, cur_y;
+    int key = 0, fkey;
+    int button = dialog_state.visit_items ? -1 : dlg_default_button();
+    int choice = dlg_default_listitem(items);
+    int scrollamt = 0;
+    int max_choice;
+    int was_mouse;
+    int use_width, list_width, name_width, text_width;
+    int result = DLG_EXIT_UNKNOWN;
+    int num_states;
+    WINDOW *dialog;
+    char *prompt;
+    const char **buttons = dlg_ok_labels();
+    const char *widget_name;
+
+    DLG_TRACE(("# %s args:\n", flag ? "checklist" : "radiolist"));
+    DLG_TRACE2S("title", title);
+    DLG_TRACE2S("message", cprompt);
+    DLG_TRACE2N("height", height);
+    DLG_TRACE2N("width", width);
+    DLG_TRACE2N("lheight", list_height);
+    DLG_TRACE2N("llength", item_no);
+    /* FIXME dump the items[][] too */
+    DLG_TRACE2S("states", states);
+    DLG_TRACE2N("flag", flag);
+    DLG_TRACE2N("current", *current_item);
+
+    dialog_state.plain_buttons = TRUE;
+
+    memset(&all, 0, sizeof(all));
+    all.items = items;
+    all.item_no = item_no;
+
+    dlg_does_output();
+
+    /*
+     * If this is a radiobutton list, ensure that no more than one item is
+     * selected initially.  Allow none to be selected, since some users may
+     * wish to provide this flavor.
+     */
+    if (flag == FLAG_RADIO) {
+	bool first = TRUE;
+
+	for (i = 0; i < item_no; i++) {
+	    if (items[i].state) {
+		if (first) {
+		    first = FALSE;
+		} else {
+		    items[i].state = 0;
+		}
+	    }
+	}
+	widget_name = "radiolist";
+    } else {
+	widget_name = "checklist";
+    }
+#ifdef KEY_RESIZE
+  retry:
+#endif
+
+    prompt = dlg_strclone(cprompt);
+    dlg_tab_correct_str(prompt);
+
+    all.use_height = list_height;
+    use_width = dlg_calc_list_width(item_no, items) + 10;
+    use_width = MAX(26, use_width);
+    if (all.use_height == 0) {
+	/* calculate height without items (4) */
+	dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, use_width);
+	dlg_calc_listh(&height, &all.use_height, item_no);
+    } else {
+	dlg_auto_size(title, prompt,
+		      &height, &width,
+		      MIN_HIGH + all.use_height, use_width);
+    }
+    dlg_button_layout(buttons, &width);
+    dlg_print_size(height, width);
+    dlg_ctl_size(height, width);
+
+    /* we need at least two states */
+    if (states == 0 || strlen(states) < 2)
+	states = " *";
+    num_states = (int) strlen(states);
+    all.states = states;
+
+    all.checkflag = flag;
+
+    x = dlg_box_x_ordinate(width);
+    y = dlg_box_y_ordinate(height);
+
+    dialog = dlg_new_window(height, width, y, x);
+    all.dialog = dialog;
+    dlg_register_window(dialog, widget_name, binding);
+    dlg_register_buttons(dialog, widget_name, buttons);
+
+    dlg_mouse_setbase(x, y);
+
+    dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
+    dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
+    dlg_draw_title(dialog, title);
+
+    dlg_attrset(dialog, dialog_attr);
+    dlg_print_autowrap(dialog, prompt, height, width);
+
+    all.use_width = width - 6;
+    getyx(dialog, cur_y, cur_x);
+    all.box_y = cur_y + 1;
+    all.box_x = (width - all.use_width) / 2 - 1;
+
+    /*
+     * After displaying the prompt, we know how much space we really have.
+     * Limit the list to avoid overwriting the ok-button.
+     */
+    if (all.use_height + MIN_HIGH > height - cur_y)
+	all.use_height = height - MIN_HIGH - cur_y;
+    if (all.use_height <= 0)
+	all.use_height = 1;
+
+    max_choice = MIN(all.use_height, item_no);
+    max_choice = MAX(max_choice, 1);
+
+    /* create new window for the list */
+    all.list = dlg_sub_window(dialog, all.use_height, all.use_width,
+			      y + all.box_y + 1, x + all.box_x + 1);
+
+    /* draw a box around the list items */
+    dlg_draw_box(dialog, all.box_y, all.box_x,
+		 all.use_height + 2 * MARGIN,
+		 all.use_width + 2 * MARGIN,
+		 menubox_border_attr, menubox_border2_attr);
+
+    text_width = 0;
+    name_width = 0;
+    /* Find length of longest item to center checklist */
+    for (i = 0; i < item_no; i++) {
+	text_width = MAX(text_width, dlg_count_columns(items[i].text));
+	name_width = MAX(name_width, dlg_count_columns(items[i].name));
+    }
+
+    /* If the name+text is wider than the list is allowed, then truncate
+     * one or both of them.  If the name is no wider than 1/4 of the list,
+     * leave it intact.
+     */
+    use_width = (all.use_width - 6);
+    if (dialog_vars.no_tags) {
+	list_width = MIN(all.use_width, text_width);
+    } else if (dialog_vars.no_items) {
+	list_width = MIN(all.use_width, name_width);
+    } else {
+	if (text_width >= 0
+	    && name_width >= 0
+	    && use_width > 0
+	    && text_width + name_width > use_width) {
+	    int need = (int) (0.25 * use_width);
+	    if (name_width > need) {
+		int want = (int) (use_width * ((double) name_width) /
+				  (text_width + name_width));
+		name_width = (want > need) ? want : need;
+	    }
+	    text_width = use_width - name_width;
+	}
+	list_width = (text_width + name_width);
+    }
+
+    all.check_x = (use_width - list_width) / 2;
+    all.item_x = ((dialog_vars.no_tags
+		   ? 0
+		   : (dialog_vars.no_items
+		      ? 0
+		      : (2 + name_width)))
+		  + all.check_x + 4);
+
+    /* ensure we are scrolled to show the current choice */
+    scrollamt = MIN(scrollamt, max_choice + item_no - 1);
+    if (choice >= (max_choice + scrollamt - 1)) {
+	scrollamt = MAX(0, choice - max_choice + 1);
+	choice = max_choice - 1;
+    }
+    print_list(&all, choice, scrollamt, max_choice);
+
+    /* register the new window, along with its borders */
+    dlg_mouse_mkbigregion(all.box_y + 1, all.box_x,
+			  all.use_height, all.use_width + 2,
+			  KEY_MAX, 1, 1, 1 /* by lines */ );
+
+    dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
+
+    dlg_trace_win(dialog);
+    while (result == DLG_EXIT_UNKNOWN) {
+	if (button < 0)		/* --visit-items */
+	    wmove(dialog, all.box_y + choice + 1, all.box_x + all.check_x + 2);
+
+	key = dlg_mouse_wgetch(dialog, &fkey);
+	if (dlg_result_key(key, fkey, &result))
+	    break;
+
+	was_mouse = (fkey && is_DLGK_MOUSE(key));
+	if (was_mouse)
+	    key -= M_EVENT;
+
+	if (was_mouse && (key >= KEY_MAX)) {
+	    getyx(dialog, cur_y, cur_x);
+	    i = (key - KEY_MAX);
+	    if (i < max_choice) {
+		choice = (key - KEY_MAX);
+		print_list(&all, choice, scrollamt, max_choice);
+
+		key = DLGK_TOGGLE;	/* force the selected item to toggle */
+	    } else {
+		beep();
+		continue;
+	    }
+	    fkey = FALSE;
+	} else if (was_mouse && key >= KEY_MIN) {
+	    key = dlg_lookup_key(dialog, key, &fkey);
+	}
+
+	/*
+	 * A space toggles the item status.  We handle either a checklist
+	 * (any number of items can be selected) or radio list (zero or one
+	 * items can be selected).
+	 */
+	if (key == DLGK_TOGGLE) {
+	    int current = scrollamt + choice;
+	    int next = items[current].state + 1;
+
+	    if (next >= num_states)
+		next = 0;
+
+	    if (flag == FLAG_CHECK) {	/* checklist? */
+		getyx(dialog, cur_y, cur_x);
+		items[current].state = next;
+		print_item(&all, all.list,
+			   &items[scrollamt + choice],
+			   states,
+			   choice, TRUE);
+		(void) wnoutrefresh(all.list);
+		(void) wmove(dialog, cur_y, cur_x);
+	    } else {		/* radiolist */
+		for (i = 0; i < item_no; i++) {
+		    if (i != current) {
+			items[i].state = 0;
+		    }
+		}
+		if (items[current].state) {
+		    getyx(dialog, cur_y, cur_x);
+		    items[current].state = next ? next : 1;
+		    print_item(&all, all.list,
+			       &items[current],
+			       states,
+			       choice, TRUE);
+		    (void) wnoutrefresh(all.list);
+		    (void) wmove(dialog, cur_y, cur_x);
+		} else {
+		    items[current].state = 1;
+		    print_list(&all, choice, scrollamt, max_choice);
+		}
+	    }
+	    continue;		/* wait for another key press */
+	}
+
+	/*
+	 * Check if key pressed matches first character of any item tag in
+	 * list.  If there is more than one match, we will cycle through
+	 * each one as the same key is pressed repeatedly.
+	 */
+	found = FALSE;
+	if (!fkey) {
+	    if (button < 0 || !dialog_state.visit_items) {
+		for (j = scrollamt + choice + 1; j < item_no; j++) {
+		    if (check_hotkey(items, j)) {
+			found = TRUE;
+			i = j - scrollamt;
+			break;
+		    }
+		}
+		if (!found) {
+		    for (j = 0; j <= scrollamt + choice; j++) {
+			if (check_hotkey(items, j)) {
+			    found = TRUE;
+			    i = j - scrollamt;
+			    break;
+			}
+		    }
+		}
+		if (found)
+		    dlg_flush_getc();
+	    } else if ((j = dlg_char_to_button(key, buttons)) >= 0) {
+		button = j;
+		ungetch('\n');
+		continue;
+	    }
+	}
+
+	/*
+	 * A single digit (1-9) positions the selection to that line in the
+	 * current screen.
+	 */
+	if (!found
+	    && (key <= '9')
+	    && (key > '0')
+	    && (key - '1' < max_choice)) {
+	    found = TRUE;
+	    i = key - '1';
+	}
+
+	if (!found) {
+	    if (fkey) {
+		found = TRUE;
+		switch (key) {
+		case DLGK_ITEM_FIRST:
+		    i = -scrollamt;
+		    break;
+		case DLGK_ITEM_LAST:
+		    i = item_no - 1 - scrollamt;
+		    break;
+		case DLGK_PAGE_PREV:
+		    if (choice)
+			i = 0;
+		    else if (scrollamt != 0)
+			i = -MIN(scrollamt, max_choice);
+		    else
+			continue;
+		    break;
+		case DLGK_PAGE_NEXT:
+		    i = MIN(choice + max_choice, item_no - scrollamt - 1);
+		    break;
+		case DLGK_ITEM_PREV:
+		    i = choice - 1;
+		    if (choice == 0 && scrollamt == 0)
+			continue;
+		    break;
+		case DLGK_ITEM_NEXT:
+		    i = choice + 1;
+		    if (scrollamt + choice >= item_no - 1)
+			continue;
+		    break;
+		default:
+		    found = FALSE;
+		    break;
+		}
+	    }
+	}
+
+	if (found) {
+	    if (i != choice) {
+		getyx(dialog, cur_y, cur_x);
+		if (i < 0 || i >= max_choice) {
+		    if (i < 0) {
+			scrollamt += i;
+			choice = 0;
+		    } else {
+			choice = max_choice - 1;
+			scrollamt += (i - max_choice + 1);
+		    }
+		    print_list(&all, choice, scrollamt, max_choice);
+		} else {
+		    choice = i;
+		    print_list(&all, choice, scrollamt, max_choice);
+		}
+	    }
+	    continue;		/* wait for another key press */
+	}
+
+	if (fkey) {
+	    switch (key) {
+	    case DLGK_ENTER:
+		result = dlg_enter_buttoncode(button);
+		break;
+	    case DLGK_FIELD_PREV:
+		button = dlg_prev_button(buttons, button);
+		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
+				 FALSE, width);
+		break;
+	    case DLGK_FIELD_NEXT:
+		button = dlg_next_button(buttons, button);
+		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
+				 FALSE, width);
+		break;
+#ifdef KEY_RESIZE
+	    case KEY_RESIZE:
+		dlg_will_resize(dialog);
+		/* reset data */
+		height = old_height;
+		width = old_width;
+		free(prompt);
+		dlg_clear();
+		dlg_del_window(dialog);
+		dlg_mouse_free_regions();
+		/* repaint */
+		goto retry;
+#endif
+	    default:
+		if (was_mouse) {
+		    if ((key2 = dlg_ok_buttoncode(key)) >= 0) {
+			result = key2;
+			break;
+		    }
+		    beep();
+		}
+	    }
+	} else {
+	    beep();
+	}
+    }
+
+    dlg_del_window(dialog);
+    dlg_mouse_free_regions();
+    free(prompt);
+    *current_item = (scrollamt + choice);
+    return result;
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * The `flag' parameter is used to select between radiolist and checklist.
+ */
+int
+dialog_checklist(const char *title,
+		 const char *cprompt,
+		 int height,
+		 int width,
+		 int list_height,
+		 int item_no,
+		 char **items,
+		 int flag)
+{
+    int result;
+    int i, j;
+    DIALOG_LISTITEM *listitems;
+    bool separate_output = ((flag == FLAG_CHECK)
+			    && (dialog_vars.separate_output));
+    bool show_status = FALSE;
+    int current = 0;
+    char *help_result;
+
+    listitems = dlg_calloc(DIALOG_LISTITEM, (size_t) item_no + 1);
+    assert_ptr(listitems, "dialog_checklist");
+
+    for (i = j = 0; i < item_no; ++i) {
+	listitems[i].name = items[j++];
+	listitems[i].text = (dialog_vars.no_items
+			     ? dlg_strempty()
+			     : items[j++]);
+	listitems[i].state = !dlg_strcmp(items[j++], "on");
+	listitems[i].help = ((dialog_vars.item_help)
+			     ? items[j++]
+			     : dlg_strempty());
+    }
+    dlg_align_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no);
+
+    result = dlg_checklist(title,
+			   cprompt,
+			   height,
+			   width,
+			   list_height,
+			   item_no,
+			   listitems,
+			   NULL,
+			   flag,
+			   &current);
+
+    switch (result) {
+    case DLG_EXIT_OK:		/* FALLTHRU */
+    case DLG_EXIT_EXTRA:
+	show_status = TRUE;
+	break;
+    case DLG_EXIT_HELP:
+	dlg_add_help_listitem(&result, &help_result, &listitems[current]);
+	if ((show_status = dialog_vars.help_status)) {
+	    if (separate_output) {
+		dlg_add_string(help_result);
+		dlg_add_separator();
+	    } else {
+		dlg_add_quoted(help_result);
+	    }
+	} else {
+	    dlg_add_string(help_result);
+	}
+	break;
+    }
+
+    if (show_status) {
+	for (i = 0; i < item_no; i++) {
+	    if (listitems[i].state) {
+		if (separate_output) {
+		    dlg_add_string(listitems[i].name);
+		    dlg_add_separator();
+		} else {
+		    if (dlg_need_separator())
+			dlg_add_separator();
+		    if (flag == FLAG_CHECK)
+			dlg_add_quoted(listitems[i].name);
+		    else
+			dlg_add_string(listitems[i].name);
+		}
+	    }
+	}
+	dlg_add_last_key(separate_output);
+    }
+
+    dlg_free_columns(&listitems[0].text, (int) sizeof(DIALOG_LISTITEM), item_no);
+    free(listitems);
+    return result;
+}
Index: 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/fselect.c
===================================================================
--- 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/fselect.c	(nonexistent)
+++ 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/fselect.c	(revision 258)
@@ -0,0 +1,941 @@
+/*
+ *  $Id: fselect.c,v 1.102 2018/06/21 23:28:04 tom Exp $
+ *
+ *  fselect.c -- implements the file-selector box
+ *
+ *  Copyright 2000-2017,2018	Thomas E. Dickey
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License, version 2.1
+ *  as published by the Free Software Foundation.
+ *
+ *  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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to
+ *	Free Software Foundation, Inc.
+ *	51 Franklin St., Fifth Floor
+ *	Boston, MA 02110, USA.
+ */
+
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+# if defined(_FILE_OFFSET_BITS) && defined(HAVE_STRUCT_DIRENT64)
+#  if !defined(_LP64) && (_FILE_OFFSET_BITS == 64)
+#   define      DIRENT  struct dirent64
+#  else
+#   define      DIRENT  struct dirent
+#  endif
+# else
+#  define       DIRENT  struct dirent
+# endif
+
+#define EXT_WIDE 1
+#define HDR_HIGH 1
+#define BTN_HIGH (1 + 2 * MARGIN)	/* Ok/Cancel, also input-box */
+#define MIN_HIGH (HDR_HIGH - MARGIN + (BTN_HIGH * 2) + 4 * MARGIN)
+#define MIN_WIDE (2 * MAX(dlg_count_columns(d_label), dlg_count_columns(f_label)) + 6 * MARGIN + 2 * EXT_WIDE)
+
+#define MOUSE_D (KEY_MAX + 0)
+#define MOUSE_F (KEY_MAX + 10000)
+#define MOUSE_T (KEY_MAX + 20000)
+
+typedef enum {
+    sDIRS = -3
+    ,sFILES = -2
+    ,sTEXT = -1
+} STATES;
+
+typedef struct {
+    WINDOW *par;		/* parent window */
+    WINDOW *win;		/* this window */
+    int length;			/* length of the data[] array */
+    int offset;			/* index of first item on screen */
+    int choice;			/* index of the selection */
+    int mousex;			/* base of mouse-code return-values */
+    unsigned allocd;
+    char **data;
+} LIST;
+
+typedef struct {
+    int length;
+    char **data;
+} MATCH;
+
+static void
+init_list(LIST * list, WINDOW *par, WINDOW *win, int mousex)
+{
+    list->par = par;
+    list->win = win;
+    list->length = 0;
+    list->offset = 0;
+    list->choice = 0;
+    list->mousex = mousex;
+    list->allocd = 0;
+    list->data = 0;
+    dlg_mouse_mkbigregion(getbegy(win), getbegx(win),
+			  getmaxy(win), getmaxx(win),
+			  mousex, 1, 1, 1 /* by lines */ );
+}
+
+static char *
+leaf_of(char *path)
+{
+    char *leaf = strrchr(path, '/');
+    if (leaf != 0)
+	leaf++;
+    else
+	leaf = path;
+    return leaf;
+}
+
+static char *
+data_of(LIST * list)
+{
+    if (list != 0
+	&& list->data != 0)
+	return list->data[list->choice];
+    return 0;
+}
+
+static void
+free_list(LIST * list, int reinit)
+{
+    int n;
+
+    if (list->data != 0) {
+	for (n = 0; list->data[n] != 0; n++)
+	    free(list->data[n]);
+	free(list->data);
+	list->data = 0;
+    }
+    if (reinit)
+	init_list(list, list->par, list->win, list->mousex);
+}
+
+static void
+add_to_list(LIST * list, char *text)
+{
+    unsigned need;
+
+    need = (unsigned) (list->length + 1);
+    if (need + 1 > list->allocd) {
+	list->allocd = 2 * (need + 1);
+	if (list->data == 0) {
+	    list->data = dlg_malloc(char *, list->allocd);
+	} else {
+	    list->data = dlg_realloc(char *, list->allocd, list->data);
+	}
+	assert_ptr(list->data, "add_to_list");
+    }
+    list->data[list->length++] = dlg_strclone(text);
+    list->data[list->length] = 0;
+}
+
+static void
+keep_visible(LIST * list)
+{
+    int high = getmaxy(list->win);
+
+    if (list->choice < list->offset) {
+	list->offset = list->choice;
+    }
+    if (list->choice - list->offset >= high)
+	list->offset = list->choice - high + 1;
+}
+
+#define Value(c) (int)((c) & 0xff)
+
+static int
+find_choice(char *target, LIST * list)
+{
+    int n;
+    int choice = list->choice;
+    int len_1, len_2, cmp_1, cmp_2;
+
+    if (*target == 0) {
+	list->choice = 0;
+    } else {
+	/* find the match with the longest length.  If more than one has the
+	 * same length, choose the one with the closest match of the final
+	 * character.
+	 */
+	len_1 = 0;
+	cmp_1 = 256;
+	for (n = 0; n < list->length; n++) {
+	    char *a = target;
+	    char *b = list->data[n];
+
+	    len_2 = 0;
+	    while ((*a != 0) && (*b != 0) && (*a == *b)) {
+		a++;
+		b++;
+		len_2++;
+	    }
+	    cmp_2 = Value(*a) - Value(*b);
+	    if (cmp_2 < 0)
+		cmp_2 = -cmp_2;
+	    if ((len_2 > len_1)
+		|| (len_1 == len_2 && cmp_2 < cmp_1)) {
+		len_1 = len_2;
+		cmp_1 = cmp_2;
+		list->choice = n;
+	    }
+	}
+    }
+    if (choice != list->choice) {
+	keep_visible(list);
+    }
+    return (choice != list->choice);
+}
+
+static void
+display_list(LIST * list)
+{
+    int n;
+    int x;
+    int y;
+    int top;
+    int bottom;
+
+    if (list->win != 0) {
+	dlg_attr_clear(list->win, getmaxy(list->win), getmaxx(list->win), item_attr);
+	for (n = list->offset; n < list->length && list->data[n]; n++) {
+	    y = n - list->offset;
+	    if (y >= getmaxy(list->win))
+		break;
+	    (void) wmove(list->win, y, 0);
+	    if (n == list->choice)
+		dlg_attrset(list->win, item_selected_attr);
+	    (void) waddstr(list->win, list->data[n]);
+	    dlg_attrset(list->win, item_attr);
+	}
+	dlg_attrset(list->win, item_attr);
+
+	getparyx(list->win, y, x);
+
+	top = y - 1;
+	bottom = y + getmaxy(list->win);
+	dlg_draw_scrollbar(list->par,
+			   (long) list->offset,
+			   (long) list->offset,
+			   (long) (list->offset + getmaxy(list->win)),
+			   (long) (list->length),
+			   x + 1,
+			   x + getmaxx(list->win),
+			   top,
+			   bottom,
+			   menubox_border2_attr,
+			   menubox_border_attr);
+
+	(void) wmove(list->win, list->choice - list->offset, 0);
+	(void) wnoutrefresh(list->win);
+    }
+}
+
+/* FIXME: see arrows.c
+ * This workaround is used to allow two lists to have scroll-tabs at the same
+ * time, by reassigning their return-values to be different.  Just for
+ * readability, we use the names of keys with similar connotations, though all
+ * that is really required is that they're distinct, so we can put them in a
+ * switch statement.
+ */
+static void
+fix_arrows(LIST * list)
+{
+    int x;
+    int y;
+    int top;
+    int right;
+    int bottom;
+
+    if (list->win != 0) {
+	getparyx(list->win, y, x);
+	top = y - 1;
+	right = getmaxx(list->win);
+	bottom = y + getmaxy(list->win);
+
+	mouse_mkbutton(top, x, right,
+		       ((list->mousex == MOUSE_D)
+			? KEY_PREVIOUS
+			: KEY_PPAGE));
+	mouse_mkbutton(bottom, x, right,
+		       ((list->mousex == MOUSE_D)
+			? KEY_NEXT
+			: KEY_NPAGE));
+    }
+}
+
+static bool
+show_list(char *target, LIST * list, bool keep)
+{
+    bool changed = keep || find_choice(target, list);
+    display_list(list);
+    return changed;
+}
+
+/*
+ * Highlight the closest match to 'target' in the given list, setting offset
+ * to match.
+ */
+static bool
+show_both_lists(char *input, LIST * d_list, LIST * f_list, bool keep)
+{
+    char *leaf = leaf_of(input);
+
+    return show_list(leaf, d_list, keep) || show_list(leaf, f_list, keep);
+}
+
+/*
+ * Move up/down in the given list
+ */
+static bool
+change_list(int choice, LIST * list)
+{
+    if (data_of(list) != 0) {
+	int last = list->length - 1;
+
+	choice += list->choice;
+	if (choice < 0)
+	    choice = 0;
+	if (choice > last)
+	    choice = last;
+	list->choice = choice;
+	keep_visible(list);
+	display_list(list);
+	return TRUE;
+    }
+    return FALSE;
+}
+
+static void
+scroll_list(int direction, LIST * list)
+{
+    if (data_of(list) != 0) {
+	int length = getmaxy(list->win);
+	if (change_list(direction * length, list))
+	    return;
+    }
+    beep();
+}
+
+static int
+compar(const void *a, const void *b)
+{
+    return strcmp(*(const char *const *) a, *(const char *const *) b);
+}
+
+static void
+match(char *name, LIST * d_list, LIST * f_list, MATCH * match_list)
+{
+    char *test = leaf_of(name);
+    size_t test_len = strlen(test);
+    char **matches = dlg_malloc(char *, (size_t) (d_list->length + f_list->length));
+    size_t data_len = 0;
+    int i;
+    for (i = 2; i < d_list->length; i++) {
+	if (strncmp(test, d_list->data[i], test_len) == 0) {
+	    matches[data_len++] = d_list->data[i];
+	}
+    }
+    for (i = 0; i < f_list->length; i++) {
+	if (strncmp(test, f_list->data[i], test_len) == 0) {
+	    matches[data_len++] = f_list->data[i];
+	}
+    }
+    matches = dlg_realloc(char *, data_len + 1, matches);
+    match_list->data = matches;
+    match_list->length = (int) data_len;
+}
+
+static void
+free_match(MATCH * match_list)
+{
+    free(match_list->data);
+    match_list->length = 0;
+}
+
+static int
+complete(char *name, LIST * d_list, LIST * f_list, char **buff_ptr)
+{
+    MATCH match_list;
+    char *test;
+    size_t test_len;
+    size_t i;
+    int j;
+    char *buff;
+
+    match(name, d_list, f_list, &match_list);
+    if (match_list.length == 0) {
+	*buff_ptr = NULL;
+	return 0;
+    }
+
+    test = match_list.data[0];
+    test_len = strlen(test);
+    buff = dlg_malloc(char, test_len + 2);
+    if (match_list.length == 1) {
+	strcpy(buff, test);
+	i = test_len;
+	if (test == data_of(d_list)) {
+	    buff[test_len] = '/';
+	    i++;
+	}
+    } else {
+	for (i = 0; i < test_len; i++) {
+	    char test_char = test[i];
+	    if (test_char == '\0')
+		break;
+	    for (j = 0; j < match_list.length; j++) {
+		if (match_list.data[j][i] != test_char) {
+		    break;
+		}
+	    }
+	    if (j == match_list.length) {
+		(buff)[i] = test_char;
+	    } else
+		break;
+	}
+	buff = dlg_realloc(char, i + 1, buff);
+    }
+    free_match(&match_list);
+    buff[i] = '\0';
+    *buff_ptr = buff;
+    return (i != 0);
+}
+
+static bool
+fill_lists(char *current, char *input, LIST * d_list, LIST * f_list, bool keep)
+{
+    bool result = TRUE;
+    bool rescan = FALSE;
+    DIR *dp;
+    DIRENT *de;
+    struct stat sb;
+    int n;
+    char path[MAX_LEN + 1];
+    char *leaf;
+
+    /* check if we've updated the lists */
+    for (n = 0; current[n] && input[n]; n++) {
+	if (current[n] != input[n])
+	    break;
+    }
+
+    if (current[n] == input[n]) {
+	result = FALSE;
+	rescan = (n == 0 && d_list->length == 0);
+    } else if (strchr(current + n, '/') == 0
+	       && strchr(input + n, '/') == 0) {
+	result = show_both_lists(input, d_list, f_list, keep);
+    } else {
+	rescan = TRUE;
+    }
+
+    if (rescan) {
+	size_t have = strlen(input);
+
+	if (have > MAX_LEN)
+	    have = MAX_LEN;
+	memcpy(current, input, have);
+	current[have] = '\0';
+
+	/* refill the lists */
+	free_list(d_list, TRUE);
+	free_list(f_list, TRUE);
+	memcpy(path, current, have);
+	path[have] = '\0';
+	if ((leaf = strrchr(path, '/')) != 0) {
+	    *++leaf = 0;
+	} else {
+	    strcpy(path, "./");
+	    leaf = path + strlen(path);
+	}
+	DLG_TRACE(("opendir '%s'\n", path));
+	if ((dp = opendir(path)) != 0) {
+	    while ((de = readdir(dp)) != 0) {
+		size_t len = NAMLEN(de);
+		if (len == 0 || (len + have + 2) >= MAX_LEN)
+		    continue;
+		memcpy(leaf, de->d_name, len);
+		leaf[len] = '\0';
+		if (stat(path, &sb) == 0) {
+		    if ((sb.st_mode & S_IFMT) == S_IFDIR)
+			add_to_list(d_list, leaf);
+		    else if (f_list->win)
+			add_to_list(f_list, leaf);
+		}
+	    }
+	    (void) closedir(dp);
+	    /* sort the lists */
+	    if (d_list->data != 0 && d_list->length > 1) {
+		qsort(d_list->data,
+		      (size_t) d_list->length,
+		      sizeof(d_list->data[0]),
+		      compar);
+	    }
+	    if (f_list->data != 0 && f_list->length > 1) {
+		qsort(f_list->data,
+		      (size_t) f_list->length,
+		      sizeof(f_list->data[0]),
+		      compar);
+	    }
+	}
+
+	(void) show_both_lists(input, d_list, f_list, FALSE);
+	d_list->offset = d_list->choice;
+	f_list->offset = f_list->choice;
+	result = TRUE;
+    }
+    return result;
+}
+
+static bool
+usable_state(int state, LIST * dirs, LIST * files)
+{
+    bool result;
+
+    switch (state) {
+    case sDIRS:
+	result = (dirs->win != 0) && (data_of(dirs) != 0);
+	break;
+    case sFILES:
+	result = (files->win != 0) && (data_of(files) != 0);
+	break;
+    default:
+	result = TRUE;
+	break;
+    }
+    return result;
+}
+
+#define which_list() ((state == sFILES) \
+			? &f_list \
+			: ((state == sDIRS) \
+			  ? &d_list \
+			  : 0))
+#define NAVIGATE_BINDINGS \
+	DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ), \
+	DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), \
+	DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), \
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  KEY_DOWN ), \
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  CHR_NEXT ), \
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  KEY_NEXT ), \
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,  CHR_PREVIOUS ), \
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,  KEY_UP ), \
+	DLG_KEYS_DATA( DLGK_PAGE_NEXT,  KEY_NPAGE ), \
+	DLG_KEYS_DATA( DLGK_PAGE_PREV,  KEY_PPAGE )
+
+/*
+ * Display a dialog box for entering a filename
+ */
+static int
+dlg_fselect(const char *title, const char *path, int height, int width, int dselect)
+{
+    /* *INDENT-OFF* */
+    static DLG_KEYS_BINDING binding[] = {
+	HELPKEY_BINDINGS,
+	ENTERKEY_BINDINGS,
+	NAVIGATE_BINDINGS,
+	TOGGLEKEY_BINDINGS,
+	END_KEYS_BINDING
+    };
+    static DLG_KEYS_BINDING binding2[] = {
+	INPUTSTR_BINDINGS,
+	HELPKEY_BINDINGS,
+	ENTERKEY_BINDINGS,
+	NAVIGATE_BINDINGS,
+	TOGGLEKEY_BINDINGS,
+	END_KEYS_BINDING
+    };
+    /* *INDENT-ON* */
+
+#ifdef KEY_RESIZE
+    int old_height = height;
+    int old_width = width;
+    bool resized = FALSE;
+#endif
+    int tbox_y, tbox_x, tbox_width, tbox_height;
+    int dbox_y, dbox_x, dbox_width, dbox_height;
+    int fbox_y, fbox_x, fbox_width, fbox_height;
+    int show_buttons = TRUE;
+    int offset = 0;
+    int key = 0;
+    int fkey = FALSE;
+    int code;
+    int result = DLG_EXIT_UNKNOWN;
+    int state = dialog_vars.default_button >= 0 ? dlg_default_button() : sTEXT;
+    int button;
+    bool first = (state == sTEXT);
+    bool first_trace = TRUE;
+    char *input;
+    char *completed;
+    char current[MAX_LEN + 1];
+    WINDOW *dialog = 0;
+    WINDOW *w_text = 0;
+    WINDOW *w_work = 0;
+    const char **buttons = dlg_ok_labels();
+    const char *d_label = _("Directories");
+    const char *f_label = _("Files");
+    char *partial = 0;
+    int min_wide = MIN_WIDE;
+    int min_items = height ? 0 : 4;
+    LIST d_list, f_list;
+
+    DLG_TRACE(("# %s args:\n", dselect ? "dselect" : "fselect"));
+    DLG_TRACE2S("title", title);
+    DLG_TRACE2S("path", path);
+    DLG_TRACE2N("height", height);
+    DLG_TRACE2N("width", width);
+
+    dlg_does_output();
+
+    /* Set up the initial value */
+    input = dlg_set_result(path);
+    offset = (int) strlen(input);
+    *current = 0;
+
+    dlg_button_layout(buttons, &min_wide);
+
+#ifdef KEY_RESIZE
+  retry:
+#endif
+    dlg_auto_size(title, (char *) 0, &height, &width, 6, 25);
+    height += MIN_HIGH + min_items;
+    if (width < min_wide)
+	width = min_wide;
+    dlg_print_size(height, width);
+    dlg_ctl_size(height, width);
+
+    dialog = dlg_new_window(height + 1, width,
+			    dlg_box_y_ordinate(height),
+			    dlg_box_x_ordinate(width));
+    dlg_register_window(dialog, "fselect", binding);
+    dlg_register_buttons(dialog, "fselect", buttons);
+
+    dlg_mouse_setbase(0, 0);
+
+    dlg_draw_box2(dialog, 0, 0, height + 1, width, dialog_attr, border_attr, border2_attr);
+    dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
+    dlg_draw_title(dialog, title);
+
+    dlg_attrset(dialog, dialog_attr);
+
+    /* Draw the input field box */
+    tbox_height = 1;
+    tbox_width = width - (4 * MARGIN + 2);
+    tbox_y = height - (BTN_HIGH * 2) + MARGIN + 1;
+    tbox_x = (width - tbox_width) / 2;
+
+    w_text = derwin(dialog, tbox_height, tbox_width, tbox_y, tbox_x);
+    if (w_text == 0) {
+	result = DLG_EXIT_ERROR;
+	goto finish;
+    }
+
+    (void) keypad(w_text, TRUE);
+    dlg_draw_box(dialog, tbox_y - MARGIN, tbox_x - MARGIN,
+		 (2 * MARGIN + 1), tbox_width + (MARGIN + EXT_WIDE),
+		 menubox_border_attr, menubox_border2_attr);
+    dlg_mouse_mkbigregion(getbegy(dialog) + tbox_y - MARGIN,
+			  getbegx(dialog) + tbox_x - MARGIN,
+			  1 + (2 * MARGIN),
+			  tbox_width + (MARGIN + EXT_WIDE),
+			  MOUSE_T, 1, 1, 3 /* doesn't matter */ );
+
+    dlg_register_window(w_text, "fselect2", binding2);
+
+    /* Draw the directory listing box */
+    if (dselect)
+	dbox_width = (width - (6 * MARGIN));
+    else
+	dbox_width = (width - (6 * MARGIN + 2 * EXT_WIDE)) / 2;
+    dbox_height = height - MIN_HIGH;
+    dbox_y = (2 * MARGIN + 2);
+    dbox_x = tbox_x;
+
+    w_work = derwin(dialog, dbox_height, dbox_width, dbox_y, dbox_x);
+    if (w_work == 0) {
+	result = DLG_EXIT_ERROR;
+	goto finish;
+    }
+
+    (void) keypad(w_work, TRUE);
+    (void) mvwaddstr(dialog, dbox_y - (MARGIN + 1), dbox_x - MARGIN, d_label);
+    dlg_draw_box(dialog,
+		 dbox_y - MARGIN, dbox_x - MARGIN,
+		 dbox_height + (MARGIN + 1), dbox_width + (MARGIN + 1),
+		 menubox_border_attr, menubox_border2_attr);
+    init_list(&d_list, dialog, w_work, MOUSE_D);
+
+    if (!dselect) {
+	/* Draw the filename listing box */
+	fbox_height = dbox_height;
+	fbox_width = dbox_width;
+	fbox_y = dbox_y;
+	fbox_x = tbox_x + dbox_width + (2 * MARGIN);
+
+	w_work = derwin(dialog, fbox_height, fbox_width, fbox_y, fbox_x);
+	if (w_work == 0) {
+	    result = DLG_EXIT_ERROR;
+	    goto finish;
+	}
+
+	(void) keypad(w_work, TRUE);
+	(void) mvwaddstr(dialog, fbox_y - (MARGIN + 1), fbox_x - MARGIN, f_label);
+	dlg_draw_box(dialog,
+		     fbox_y - MARGIN, fbox_x - MARGIN,
+		     fbox_height + (MARGIN + 1), fbox_width + (MARGIN + 1),
+		     menubox_border_attr, menubox_border2_attr);
+	init_list(&f_list, dialog, w_work, MOUSE_F);
+    } else {
+	memset(&f_list, 0, sizeof(f_list));
+    }
+
+    while (result == DLG_EXIT_UNKNOWN) {
+
+	if (fill_lists(current, input, &d_list, &f_list, state < sTEXT))
+	    show_buttons = TRUE;
+
+#ifdef KEY_RESIZE
+	if (resized) {
+	    resized = FALSE;
+	    dlg_show_string(w_text, input, offset, inputbox_attr,
+			    0, 0, tbox_width, FALSE, first);
+	}
+#endif
+
+	/*
+	 * The last field drawn determines where the cursor is shown:
+	 */
+	if (show_buttons) {
+	    show_buttons = FALSE;
+	    button = (state < 0) ? 0 : state;
+	    dlg_draw_buttons(dialog, height - 1, 0, buttons, button, FALSE, width);
+	}
+
+	if (first_trace) {
+	    first_trace = FALSE;
+	    dlg_trace_win(dialog);
+	}
+
+	if (state < 0) {
+	    switch (state) {
+	    case sTEXT:
+		dlg_set_focus(dialog, w_text);
+		break;
+	    case sFILES:
+		dlg_set_focus(dialog, f_list.win);
+		break;
+	    case sDIRS:
+		dlg_set_focus(dialog, d_list.win);
+		break;
+	    }
+	}
+
+	if (first) {
+	    (void) wrefresh(dialog);
+	} else {
+	    fix_arrows(&d_list);
+	    fix_arrows(&f_list);
+	    key = dlg_mouse_wgetch((state == sTEXT) ? w_text : dialog, &fkey);
+	    if (dlg_result_key(key, fkey, &result))
+		break;
+	}
+
+	if (key == DLGK_TOGGLE) {
+	    key = DLGK_SELECT;
+	    fkey = TRUE;
+	}
+
+	if (fkey) {
+	    switch (key) {
+	    case DLGK_MOUSE(KEY_PREVIOUS):
+		state = sDIRS;
+		scroll_list(-1, which_list());
+		continue;
+	    case DLGK_MOUSE(KEY_NEXT):
+		state = sDIRS;
+		scroll_list(1, which_list());
+		continue;
+	    case DLGK_MOUSE(KEY_PPAGE):
+		state = sFILES;
+		scroll_list(-1, which_list());
+		continue;
+	    case DLGK_MOUSE(KEY_NPAGE):
+		state = sFILES;
+		scroll_list(1, which_list());
+		continue;
+	    case DLGK_PAGE_PREV:
+		scroll_list(-1, which_list());
+		continue;
+	    case DLGK_PAGE_NEXT:
+		scroll_list(1, which_list());
+		continue;
+	    case DLGK_ITEM_PREV:
+		if (change_list(-1, which_list()))
+		    continue;
+		/* FALLTHRU */
+	    case DLGK_FIELD_PREV:
+		show_buttons = TRUE;
+		do {
+		    state = dlg_prev_ok_buttonindex(state, sDIRS);
+		} while (!usable_state(state, &d_list, &f_list));
+		continue;
+	    case DLGK_ITEM_NEXT:
+		if (change_list(1, which_list()))
+		    continue;
+		/* FALLTHRU */
+	    case DLGK_FIELD_NEXT:
+		show_buttons = TRUE;
+		do {
+		    state = dlg_next_ok_buttonindex(state, sDIRS);
+		} while (!usable_state(state, &d_list, &f_list));
+		continue;
+	    case DLGK_SELECT:
+		completed = 0;
+		if (partial != 0) {
+		    free(partial);
+		    partial = 0;
+		}
+		if (state == sFILES && !dselect) {
+		    completed = data_of(&f_list);
+		} else if (state == sDIRS) {
+		    completed = data_of(&d_list);
+		} else {
+		    if (complete(input, &d_list, &f_list, &partial)) {
+			completed = partial;
+		    }
+		}
+		if (completed != 0) {
+		    state = sTEXT;
+		    show_buttons = TRUE;
+		    strcpy(leaf_of(input), completed);
+		    offset = (int) strlen(input);
+		    dlg_show_string(w_text, input, offset, inputbox_attr,
+				    0, 0, tbox_width, 0, first);
+		    if (partial != NULL) {
+			free(partial);
+			partial = 0;
+		    }
+		    continue;
+		} else {	/* if (state < sTEXT) */
+		    (void) beep();
+		    continue;
+		}
+		/* FALLTHRU */
+	    case DLGK_ENTER:
+		result = (state > 0) ? dlg_enter_buttoncode(state) : DLG_EXIT_OK;
+		continue;
+#ifdef KEY_RESIZE
+	    case KEY_RESIZE:
+		dlg_will_resize(dialog);
+		/* reset data */
+		height = old_height;
+		width = old_width;
+		show_buttons = TRUE;
+		*current = 0;
+		resized = TRUE;
+		/* repaint */
+		dlg_clear();
+		dlg_del_window(dialog);
+		refresh();
+		dlg_mouse_free_regions();
+		goto retry;
+#endif
+	    default:
+		if (key >= DLGK_MOUSE(MOUSE_T)) {
+		    state = sTEXT;
+		    continue;
+		} else if (key >= DLGK_MOUSE(MOUSE_F)) {
+		    if (f_list.win != 0) {
+			state = sFILES;
+			f_list.choice = (key - DLGK_MOUSE(MOUSE_F)) + f_list.offset;
+			display_list(&f_list);
+		    }
+		    continue;
+		} else if (key >= DLGK_MOUSE(MOUSE_D)) {
+		    if (d_list.win != 0) {
+			state = sDIRS;
+			d_list.choice = (key - DLGK_MOUSE(MOUSE_D)) + d_list.offset;
+			display_list(&d_list);
+		    }
+		    continue;
+		} else if (is_DLGK_MOUSE(key)
+			   && (code = dlg_ok_buttoncode(key - M_EVENT)) >= 0) {
+		    result = code;
+		    continue;
+		}
+		break;
+	    }
+	}
+
+	if (state < 0) {	/* Input box selected if we're editing */
+	    int edit = dlg_edit_string(input, &offset, key, fkey, first);
+
+	    if (edit) {
+		dlg_show_string(w_text, input, offset, inputbox_attr,
+				0, 0, tbox_width, 0, first);
+		first = FALSE;
+		state = sTEXT;
+	    }
+	} else if (state >= 0 &&
+		   (code = dlg_char_to_button(key, buttons)) >= 0) {
+	    result = dlg_ok_buttoncode(code);
+	    break;
+	}
+    }
+
+    dlg_unregister_window(w_text);
+    dlg_del_window(dialog);
+    dlg_mouse_free_regions();
+    free_list(&d_list, FALSE);
+    free_list(&f_list, FALSE);
+
+  finish:
+    if (partial != 0)
+	free(partial);
+    return result;
+}
+
+/*
+ * Display a dialog box for entering a filename
+ */
+int
+dialog_fselect(const char *title, const char *path, int height, int width)
+{
+    return dlg_fselect(title, path, height, width, FALSE);
+}
+
+/*
+ * Display a dialog box for entering a directory
+ */
+int
+dialog_dselect(const char *title, const char *path, int height, int width)
+{
+    return dlg_fselect(title, path, height, width, TRUE);
+}
Index: 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/menubox.c
===================================================================
--- 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/menubox.c	(nonexistent)
+++ 3pp/sources/packages/dialog/create-1.3-20181107-patch/dialog-1.3-20181107-new/menubox.c	(revision 258)
@@ -0,0 +1,801 @@
+/*
+ *  $Id: menubox.c,v 1.159 2018/06/21 23:28:56 tom Exp $
+ *
+ *  menubox.c -- implements the menu box
+ *
+ *  Copyright 2000-2016,2018	Thomas E. Dickey
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public Licens, version 2.1e
+ *  as published by the Free Software Foundation.
+ *
+ *  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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to
+ *	Free Software Foundation, Inc.
+ *	51 Franklin St., Fifth Floor
+ *	Boston, MA 02110, USA.
+ *
+ *  An earlier version of this program lists as authors
+ *	Savio Lam (lam836@cs.cuhk.hk)
+ */
+
+#include <dialog.h>
+#include <dlg_keys.h>
+
+typedef enum {
+    Unselected = 0,
+    Selected,
+    Editing
+} Mode;
+
+typedef struct {
+    /* the outer-window */
+    WINDOW *dialog;
+    int box_y;
+    int box_x;
+    int tag_x;
+    int item_x;
+    int menu_height;
+    int menu_width;
+    /* the inner-window */
+    WINDOW *menu;
+    DIALOG_LISTITEM *items;
+    int item_no;
+} ALL_DATA;
+
+#define MIN_HIGH  4
+
+#define INPUT_ROWS     3	/* rows per inputmenu entry */
+
+#define RowHeight(i) (is_inputmenu ? ((i) * INPUT_ROWS) : ((i) * 1))
+#define ItemToRow(i) (is_inputmenu ? ((i) * INPUT_ROWS + 1) : (i))
+#define RowToItem(i) (is_inputmenu ? ((i) / INPUT_ROWS + 0) : (i))
+
+/*
+ * Print menu item
+ */
+static void
+print_item(ALL_DATA * data,
+	   WINDOW *win,
+	   DIALOG_LISTITEM * item,
+	   int choice,
+	   Mode selected,
+	   bool is_inputmenu)
+{
+    chtype save = dlg_get_attrs(win);
+    int n;
+    int climit = (data->item_x - data->tag_x - GUTTER);
+    int my_width = data->menu_width;
+    int my_x = data->item_x;
+    int my_y = ItemToRow(choice);
+    bool both = (!dialog_vars.no_tags && !dialog_vars.no_items);
+    bool first = TRUE;
+    chtype bordchar;
+    const char *show = (dialog_vars.no_items
+			? item->name
+			: item->text);
+
+    switch (selected) {
+    default:
+    case Unselected:
+	bordchar = item_attr;
+	break;
+    case Selected:
+	bordchar = item_selected_attr;
+	break;
+    case Editing:
+	bordchar = dialog_attr;
+	break;
+    }
+
+    /* Clear 'residue' of last item and mark current current item */
+    if (is_inputmenu) {
+	dlg_attrset(win, (selected != Unselected) ? item_selected_attr : item_attr);
+	for (n = my_y - 1; n < my_y + INPUT_ROWS - 1; n++) {
+	    wmove(win, n, 0);
+	    wprintw(win, "%*s", my_width, " ");
+	}
+    } else {
+	dlg_attrset(win, menubox_attr);
+	wmove(win, my_y, 0);
+	wprintw(win, "%*s", my_width, " ");
+    }
+
+    /* highlight first char of the tag to be special */
+    if (both) {
+	(void) wmove(win, my_y, data->tag_x);
+	dlg_print_listitem(win, item->name, climit, first, selected);
+	first = FALSE;
+    }
+
+    /* Draw the input field box (only for inputmenu) */
+    (void) wmove(win, my_y, my_x);
+    if (is_inputmenu) {
+	my_width -= 1;
+	dlg_draw_box(win, my_y - 1, my_x, INPUT_ROWS, my_width - my_x - data->tag_x,
+		     bordchar,
+		     bordchar);
+	my_width -= 1;
+	++my_x;
+    }
+
+    /* print actual item */
+    wmove(win, my_y, my_x);
+    dlg_print_listitem(win, show, my_width - my_x, first, selected);
+
+    if (selected) {
+	dlg_item_help(item->help);
+    }
+    dlg_attrset(win, save);
+}
+
+/*
+ * Allow the user to edit the text of a menu entry.
+ */
+static int
+input_menu_edit(ALL_DATA * data,
+		DIALOG_LISTITEM * items,
+		int choice,
+		char **resultp)
+{
+    chtype save = dlg_get_attrs(data->menu);
+    char *result;
+    int offset = 0;
+    int key = 0, fkey = 0;
+    bool first = TRUE;
+    /* see above */
+    bool is_inputmenu = TRUE;
+    int y = ItemToRow(choice);
+    int code = TRUE;
+    int max_len = dlg_max_input(MAX((int) strlen(items->text) + 1, MAX_LEN));
+
+    result = dlg_malloc(char, (size_t) max_len);
+    assert_ptr(result, "input_menu_edit");
+
+    /* original item is used to initialize the input string. */
+    result[0] = '\0';
+    strcpy(result, items->text);
+
+    print_item(data, data->menu, items, choice, Editing, TRUE);
+
+    /* taken out of inputbox.c - but somewhat modified */
+    for (;;) {
+	if (!first)
+	    key = dlg_mouse_wgetch(data->menu, &fkey);
+	if (dlg_edit_string(result, &offset, key, fkey, first)) {
+	    dlg_show_string(data->menu, result, offset, inputbox_attr,
+			    y,
+			    data->item_x + 1,
+			    data->menu_width - data->item_x - 3,
+			    FALSE, first);
+	    first = FALSE;
+	} else if (key == ESC || key == TAB) {
+	    code = FALSE;
+	    break;
+	} else {
+	    break;
+	}
+    }
+    print_item(data, data->menu, items, choice, Selected, TRUE);
+    dlg_attrset(data->menu, save);
+
+    *resultp = result;
+    return code;
+}
+
+static int
+handle_button(int code, DIALOG_LISTITEM * items, int choice)
+{
+    char *help_result;
+
+    switch (code) {
+    case DLG_EXIT_OK:		/* FALLTHRU */
+    case DLG_EXIT_EXTRA:
+	dlg_add_string(items[choice].name);
+	break;
+    case DLG_EXIT_HELP:
+	dlg_add_help_listitem(&code, &help_result, &items[choice]);
+	dlg_add_string(help_result);
+	break;
+    }
+    return code;
+}
+
+int
+dlg_renamed_menutext(DIALOG_LISTITEM * items, int current, char *newtext)
+{
+    if (dialog_vars.input_result)
+	dialog_vars.input_result[0] = '\0';
+    dlg_add_result("RENAMED ");
+    dlg_add_string(items[current].name);
+    dlg_add_result(" ");
+    dlg_add_string(newtext);
+    return DLG_EXIT_EXTRA;
+}
+
+int
+dlg_dummy_menutext(DIALOG_LISTITEM * items, int current, char *newtext)
+{
+    (void) items;
+    (void) current;
+    (void) newtext;
+    return DLG_EXIT_ERROR;
+}
+
+static void
+print_menu(ALL_DATA * data, int choice, int scrollamt, int max_choice, bool is_inputmenu)
+{
+    int i;
+
+    for (i = 0; i < max_choice; i++) {
+	print_item(data,
+		   data->menu,
+		   &data->items[i + scrollamt],
+		   i,
+		   (i == choice) ? Selected : Unselected,
+		   is_inputmenu);
+    }
+
+    /* Clean bottom lines */
+    if (is_inputmenu) {
+	int spare_lines, x_count;
+	spare_lines = data->menu_height % INPUT_ROWS;
+	dlg_attrset(data->menu, menubox_attr);
+	for (; spare_lines; spare_lines--) {
+	    wmove(data->menu, data->menu_height - spare_lines, 0);
+	    for (x_count = 0; x_count < data->menu_width;
+		 x_count++) {
+		waddch(data->menu, ' ');
+	    }
+	}
+    }
+
+    (void) wnoutrefresh(data->menu);
+
+    dlg_draw_scrollbar(data->dialog,
+		       scrollamt,
+		       scrollamt,
+		       scrollamt + max_choice,
+		       data->item_no,
+		       data->box_x,
+		       data->box_x + data->menu_width,
+		       data->box_y,
+		       data->box_y + data->menu_height + 1,
+		       menubox_border2_attr,
+		       menubox_border_attr);
+}
+
+static bool
+check_hotkey(DIALOG_LISTITEM * items, int choice)
+{
+    bool result = FALSE;
+
+    if (dlg_match_char(dlg_last_getc(),
+		       (dialog_vars.no_tags
+			? items[choice].text
+			: items[choice].name))) {
+	result = TRUE;
+    }
+    return result;
+}
+
+/*
+ * This is an alternate interface to 'menu' which allows the application
+ * to read the list item states back directly without putting them in the
+ * output buffer.
+ */
+int
+dlg_menu(const char *title,
+	 const char *cprompt,
+	 int height,
+	 int width,
+	 int menu_height,
+	 int item_no,
+	 DIALOG_LISTITEM * items,
+	 int *current_item,
+	 DIALOG_INPUTMENU rename_menutext)
+{
+    /* *INDENT-OFF* */
+    static DLG_KEYS_BINDING binding[] = {
+	HELPKEY_BINDINGS,
+	ENTERKEY_BINDINGS,
+	TOGGLEKEY_BINDINGS,
+	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	KEY_RIGHT ),
+	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	TAB ),
+	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_BTAB ),
+	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_LEFT ),
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	'+' ),
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,	KEY_DOWN ),
+	DLG_KEYS_DATA( DLGK_ITEM_NEXT,  CHR_NEXT ),
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,	'-' ),
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,	KEY_UP ),
+	DLG_KEYS_DATA( DLGK_ITEM_PREV,  CHR_PREVIOUS ),
+	DLG_KEYS_DATA( DLGK_PAGE_FIRST,	KEY_HOME ),
+	DLG_KEYS_DATA( DLGK_PAGE_LAST,	KEY_END ),
+	DLG_KEYS_DATA( DLGK_PAGE_LAST,	KEY_LL ),
+	DLG_KEYS_DATA( DLGK_PAGE_NEXT,	KEY_NPAGE ),
+	DLG_KEYS_DATA( DLGK_PAGE_PREV,	KEY_PPAGE ),
+	END_KEYS_BINDING
+    };
+    static DLG_KEYS_BINDING binding2[] = {
+	INPUTSTR_BINDINGS,
+	HELPKEY_BINDINGS,
+	ENTERKEY_BINDINGS,
+	END_KEYS_BINDING
+    };
+    /* *INDENT-ON* */
+
+#ifdef KEY_RESIZE
+    int old_LINES = LINES;
+    int old_COLS = COLS;
+    int old_height = height;
+    int old_width = width;
+#endif
+    ALL_DATA all;
+    int i, j, x, y, cur_x, cur_y;
+    int key = 0, fkey;
+    int button = dialog_state.visit_items ? -1 : dlg_default_button();
+    int choice = dlg_default_listitem(items);
+    int result = DLG_EXIT_UNKNOWN;
+    int scrollamt = 0;
+    int max_choice;
+    int found;
+    int use_width, name_width, text_width, list_width;
+    WINDOW *dialog, *menu;
+    char *prompt = 0;
+    const char **buttons = dlg_ok_labels();
+    bool is_inputmenu = ((rename_menutext != 0)
+			 && (rename_menutext != dlg_dummy_menutext));
+
+    DLG_TRACE(("# menubox args:\n"));
+    DLG_TRACE2S("title", title);
+    DLG_TRACE2S("message", cprompt);
+    DLG_TRACE2N("height", height);
+    DLG_TRACE2N("width", width);
+    DLG_TRACE2N("lheight", menu_height);
+    DLG_TRACE2N("llength", item_no);
+    /* FIXME dump the items[][] too */
+    DLG_TRACE2N("current", *current_item);
+    DLG_TRACE2N("rename", rename_menutext != 0);
+
+    dialog_state.plain_buttons = TRUE;
+
+    all.items = items;
+    all.item_no = item_no;
+
+    dlg_does_output();
+
+#ifdef KEY_RESIZE
+  retry:
+#endif
+
+    prompt = dlg_strclone(cprompt);
+    dlg_tab_correct_str(prompt);
+
+    all.menu_height = menu_height;
+    use_width = dlg_calc_list_width(item_no, items) + 10;
+    use_width = MAX(26, use_width);
+    if (all.menu_height == 0) {
+	/* calculate height without items (4) */
+	dlg_auto_size(title, prompt, &height, &width, MIN_HIGH, use_width);
+	dlg_calc_listh(&height, &all.menu_height, item_no);
+    } else {
+	dlg_auto_size(title, prompt,
+		      &height, &width,
+		      MIN_HIGH + all.menu_height, use_width);
+    }
+    dlg_button_layout(buttons, &width);
+    dlg_print_size(height, width);
+    dlg_ctl_size(height, width);
+
+    x = dlg_box_x_ordinate(width);
+    y = dlg_box_y_ordinate(height);
+
+    dialog = dlg_new_window(height, width, y, x);
+    all.dialog = dialog;
+
+    dlg_register_window(dialog, "menubox", binding);
+    dlg_register_buttons(dialog, "menubox", buttons);
+
+    dlg_mouse_setbase(x, y);
+
+    dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
+    dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
+    dlg_draw_title(dialog, title);
+
+    dlg_attrset(dialog, dialog_attr);
+    dlg_print_autowrap(dialog, prompt, height, width);
+
+    all.menu_width = width - 6;
+    getyx(dialog, cur_y, cur_x);
+    all.box_y = cur_y + 1;
+    all.box_x = (width - all.menu_width) / 2 - 1;
+
+    /*
+     * After displaying the prompt, we know how much space we really have.
+     * Limit the list to avoid overwriting the ok-button.
+     */
+    if (all.menu_height + MIN_HIGH > height - cur_y)
+	all.menu_height = height - MIN_HIGH - cur_y;
+    if (all.menu_height <= 0)
+	all.menu_height = 1;
+
+    /* Find out maximal number of displayable items at once. */
+    max_choice = MIN(all.menu_height,
+		     RowHeight(item_no));
+    if (is_inputmenu)
+	max_choice /= INPUT_ROWS;
+
+    /* create new window for the menu */
+    menu = dlg_sub_window(dialog, all.menu_height, all.menu_width,
+			  y + all.box_y + 1,
+			  x + all.box_x + 1);
+    all.menu = menu;
+
+    dlg_register_window(menu, "menu", binding2);
+    dlg_register_buttons(menu, "menu", buttons);
+
+    /* draw a box around the menu items */
+    dlg_draw_box(dialog,
+		 all.box_y, all.box_x,
+		 all.menu_height + 2, all.menu_width + 2,
+		 menubox_border_attr, menubox_border2_attr);
+
+    name_width = 0;
+    text_width = 0;
+
+    /* Find length of longest item to center menu  *
+     * only if --menu was given, using --inputmenu *
+     * won't be centered.                         */
+    for (i = 0; i < item_no; i++) {
+	name_width = MAX(name_width, dlg_count_columns(items[i].name));
+	text_width = MAX(text_width, dlg_count_columns(items[i].text));
+    }
+
+    /* If the name+text is wider than the list is allowed, then truncate
+     * one or both of them.  If the name is no wider than 30% of the list,
+     * leave it intact.
+     *
+     * FIXME: the gutter width and name/list ratio should be configurable.
+     */
+    use_width = (all.menu_width - GUTTER);
+    if (dialog_vars.no_tags) {
+	list_width = MIN(use_width, text_width);
+    } else if (dialog_vars.no_items) {
+	list_width = MIN(use_width, name_width);
+    } else {
+	if (text_width >= 0
+	    && name_width >= 0
+	    && use_width > 0
+	    && text_width + name_width > use_width) {
+	    int need = (int) (0.30 * use_width);
+	    if (name_width > need) {
+		int want = (int) (use_width
+				  * ((double) name_width)
+				  / (text_width + name_width));
+		name_width = (want > need) ? want : need;
+	    }
+	    text_width = use_width - name_width;
+	}
+	list_width = (text_width + name_width);
+    }
+
+    all.tag_x = (is_inputmenu
+		 ? 0
+		 : (use_width - list_width) / 2);
+    all.item_x = ((dialog_vars.no_tags
+		   ? 0
+		   : (dialog_vars.no_items
+		      ? 0
+		      : (GUTTER + name_width)))
+		  + all.tag_x);
+
+    if (choice - scrollamt >= max_choice) {
+	scrollamt = choice - (max_choice - 1);
+	choice = max_choice - 1;
+    }
+
+    print_menu(&all, choice, scrollamt, max_choice, is_inputmenu);
+
+    /* register the new window, along with its borders */
+    dlg_mouse_mkbigregion(all.box_y + 1, all.box_x,
+			  all.menu_height + 2, all.menu_width + 2,
+			  KEY_MAX, 1, 1, 1 /* by lines */ );
+
+    dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
+
+    dlg_trace_win(dialog);
+    while (result == DLG_EXIT_UNKNOWN) {
+	if (button < 0)		/* --visit-items */
+	    wmove(dialog,
+		  all.box_y + ItemToRow(choice) + 1,
+		  all.box_x + all.tag_x + 1);
+
+	key = dlg_mouse_wgetch(dialog, &fkey);
+	if (dlg_result_key(key, fkey, &result))
+	    break;
+
+	found = FALSE;
+	if (fkey) {
+	    /*
+	     * Allow a mouse-click on a box to switch selection to that box.
+	     * Handling a button click is a little more complicated, since we
+	     * push a KEY_ENTER back onto the input stream so we'll put the
+	     * cursor at the right place before handling the "keypress".
+	     */
+	    if (key >= DLGK_MOUSE(KEY_MAX)) {
+		key -= DLGK_MOUSE(KEY_MAX);
+		i = RowToItem(key);
+		if (i < max_choice) {
+		    found = TRUE;
+		} else {
+		    beep();
+		    continue;
+		}
+	    } else if (is_DLGK_MOUSE(key)
+		       && dlg_ok_buttoncode(key - M_EVENT) >= 0) {
+		button = (key - M_EVENT);
+		ungetch('\n');
+		continue;
+	    }
+	} else {
+	    /*
+	     * Check if key pressed matches first character of any item tag in
+	     * list.  If there is more than one match, we will cycle through
+	     * each one as the same key is pressed repeatedly.
+	     */
+	    if (button < 0 || !dialog_state.visit_items) {
+		for (j = scrollamt + choice + 1; j < item_no; j++) {
+		    if (check_hotkey(items, j)) {
+			found = TRUE;
+			i = j - scrollamt;
+			break;
+		    }
+		}
+		if (!found) {
+		    for (j = 0; j <= scrollamt + choice; j++) {
+			if (check_hotkey(items, j)) {
+			    found = TRUE;
+			    i = j - scrollamt;
+			    break;
+			}
+		    }
+		}
+		if (found)
+		    dlg_flush_getc();
+	    } else if ((j = dlg_char_to_button(key, buttons)) >= 0) {
+		button = j;
+		ungetch('\n');
+		continue;
+	    }
+
+	    /*
+	     * A single digit (1-9) positions the selection to that line in the
+	     * current screen.
+	     */
+	    if (!found
+		&& (key <= '9')
+		&& (key > '0')
+		&& (key - '1' < max_choice)) {
+		found = TRUE;
+		i = key - '1';
+	    }
+	}
+
+	if (!found && fkey) {
+	    found = TRUE;
+	    switch (key) {
+	    case DLGK_PAGE_FIRST:
+		i = -scrollamt;
+		break;
+	    case DLGK_PAGE_LAST:
+		i = item_no - 1 - scrollamt;
+		break;
+	    case DLGK_MOUSE(KEY_PPAGE):
+	    case DLGK_PAGE_PREV:
+		if (choice)
+		    i = 0;
+		else if (scrollamt != 0)
+		    i = -MIN(scrollamt, max_choice);
+		else
+		    continue;
+		break;
+	    case DLGK_MOUSE(KEY_NPAGE):
+	    case DLGK_PAGE_NEXT:
+		i = MIN(choice + max_choice, item_no - scrollamt - 1);
+		break;
+	    case DLGK_ITEM_PREV:
+		i = choice - 1;
+		if (choice == 0 && scrollamt == 0)
+		    continue;
+		break;
+	    case DLGK_ITEM_NEXT:
+		i = choice + 1;
+		if (scrollamt + choice >= item_no - 1)
+		    continue;
+		break;
+	    default:
+		found = FALSE;
+		break;
+	    }
+	}
+
+	if (found) {
+	    if (i != choice) {
+		getyx(dialog, cur_y, cur_x);
+		if (i < 0 || i >= max_choice) {
+		    if (i < 0) {
+			scrollamt += i;
+			choice = 0;
+		    } else {
+			choice = max_choice - 1;
+			scrollamt += (i - max_choice + 1);
+		    }
+		    print_menu(&all, choice, scrollamt, max_choice, is_inputmenu);
+		} else {
+		    choice = i;
+		    print_menu(&all, choice, scrollamt, max_choice, is_inputmenu);
+		    (void) wmove(dialog, cur_y, cur_x);
+		    wrefresh(dialog);
+		}
+	    }
+	    continue;		/* wait for another key press */
+	}
+
+	if (fkey) {
+	    switch (key) {
+	    case DLGK_FIELD_PREV:
+		button = dlg_prev_button(buttons, button);
+		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
+				 FALSE, width);
+		break;
+	    case DLGK_FIELD_NEXT:
+		button = dlg_next_button(buttons, button);
+		dlg_draw_buttons(dialog, height - 2, 0, buttons, button,
+				 FALSE, width);
+		break;
+	    case DLGK_TOGGLE:
+	    case DLGK_ENTER:
+		if (is_inputmenu)
+		    result = dlg_ok_buttoncode(button);
+		else
+		    result = dlg_enter_buttoncode(button);
+
+		/*
+		 * If dlg_menu() is called from dialog_menu(), we want to
+		 * capture the results into dialog_vars.input_result.
+		 */
+		if (result == DLG_EXIT_ERROR) {
+		    result = DLG_EXIT_UNKNOWN;
+		} else if (is_inputmenu
+			   || rename_menutext == dlg_dummy_menutext) {
+		    result = handle_button(result,
+					   items,
+					   scrollamt + choice);
+		}
+
+		/*
+		 * If we have a rename_menutext function, interpret the Extra
+		 * button as a request to rename the menu's text.  If that
+		 * function doesn't return "Unknown", we will exit from this
+		 * function.  Usually that is done for dialog_menu(), so the
+		 * shell script can use the updated value.  If it does return
+		 * "Unknown", update the list item only.  A direct caller of
+		 * dlg_menu() can free the renamed value - we cannot.
+		 */
+		if (is_inputmenu && result == DLG_EXIT_EXTRA) {
+		    char *tmp;
+
+		    if (input_menu_edit(&all,
+					&items[scrollamt + choice],
+					choice,
+					&tmp)) {
+			result = rename_menutext(items, scrollamt + choice, tmp);
+			if (result == DLG_EXIT_UNKNOWN) {
+			    items[scrollamt + choice].text = tmp;
+			} else {
+			    free(tmp);
+			}
+		    } else {
+			result = DLG_EXIT_UNKNOWN;
+			print_item(&all,
+				   menu,
+				   &items[scrollamt + choice],
+				   choice,
+				   Selected,
+				   is_inputmenu);
+			(void) wnoutrefresh(menu);
+			free(tmp);
+		    }
+
+		    if (result == DLG_EXIT_UNKNOWN) {
+			dlg_draw_buttons(dialog, height - 2, 0,
+					 buttons, button, FALSE, width);
+		    }
+		}
+		break;
+#ifdef KEY_RESIZE
+	    case KEY_RESIZE:
+		dlg_will_resize(dialog);
+		/* reset data */
+#define resizeit(name, NAME) \
+		name = ((NAME >= old_##NAME) \
+			? (NAME - (old_##NAME - old_##name)) \
+			: old_##name)
+		resizeit(height, LINES);
+		resizeit(width, COLS);
+		free(prompt);
+		dlg_clear();
+		dlg_del_window(dialog);
+		dlg_mouse_free_regions();
+		/* repaint */
+		goto retry;
+#endif
+	    default:
+		flash();
+		break;
+	    }
+	}
+    }
+
+    dlg_mouse_free_regions();
+    dlg_unregister_window(menu);
+    dlg_del_window(dialog);
+    free(prompt);
+
+    *current_item = scrollamt + choice;
+    return result;
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int
+dialog_menu(const char *title,
+	    const char *cprompt,
+	    int height,
+	    int width,
+	    int menu_height,
+	    int item_no,
+	    char **items)
+{
+    int result;
+    int choice;
+    int i, j;
+    DIALOG_LISTITEM *listitems;
+
+    listitems = dlg_calloc(DIALOG_LISTITEM, (size_t) item_no + 1);
+    assert_ptr(listitems, "dialog_menu");
+
+    for (i = j = 0; i < item_no; ++i) {
+	listitems[i].name = items[j++];
+	listitems[i].text = (dialog_vars.no_items
+			     ? dlg_strempty()
+			     : items[j++]);
+	listitems[i].help = ((dialog_vars.item_help)
+			     ? items[j++]
+			     : dlg_strempty());
+    }
+    dlg_align_columns(&listitems[0].text, sizeof(DIALOG_LISTITEM), item_no);
+
+    result = dlg_menu(title,
+		      cprompt,
+		      height,
+		      width,
+		      menu_height,
+		      item_no,
+		      listitems,
+		      &choice,
+		      (dialog_vars.input_menu
+		       ? dlg_renamed_menutext
+		       : dlg_dummy_menutext));
+
+    dlg_free_columns(&listitems[0].text, sizeof(DIALOG_LISTITEM), item_no);
+    free(listitems);
+    return result;
+}
Index: 3pp/sources/packages/dialog/create-1.3-20181107-patch/file.list
===================================================================
--- 3pp/sources/packages/dialog/create-1.3-20181107-patch/file.list	(nonexistent)
+++ 3pp/sources/packages/dialog/create-1.3-20181107-patch/file.list	(revision 258)
@@ -0,0 +1,3 @@
+dialog-1.3-20181107/checklist.c
+dialog-1.3-20181107/fselect.c
+dialog-1.3-20181107/menubox.c
Index: 3pp/sources/packages/dialog/dialogrc
===================================================================
--- 3pp/sources/packages/dialog/dialogrc	(nonexistent)
+++ 3pp/sources/packages/dialog/dialogrc	(revision 258)
@@ -0,0 +1,144 @@
+#
+# Run-time configuration file for dialog, matches Radix color scheme.
+#
+# Types of values:
+#
+# Number     -  <number>
+# String     -  "string"
+# Boolean    -  <ON|OFF>
+# Attribute  -  (foreground,background,highlight?)
+
+# Set aspect-ration.
+aspect = 0
+
+# Set separator (for multiple widgets output).
+separate_widget = ""
+
+# Set tab-length (for textbox tab-conversion).
+tab_len = 0
+
+# Make tab-traversal for checklist, etc., include the list.
+visit_items = OFF
+
+# Shadow dialog boxes? This also turns on color.
+use_shadow = ON
+
+# Turn color support ON or OFF
+use_colors = ON
+
+# Screen color
+screen_color = (WHITE,BLACK,ON)
+
+# Shadow color
+shadow_color = (BLACK,BLACK,OFF)
+
+# Dialog box color
+dialog_color = (BLACK,WHITE,OFF)
+
+# Dialog box title color
+title_color = (RED,WHITE,ON)
+
+# Dialog box border color
+border_color = (WHITE,WHITE,ON)
+
+
+# Active button color
+button_active_color = (WHITE,BLUE,ON)
+
+# Inactive button color
+button_inactive_color = (BLACK,WHITE,OFF)
+
+# Active button key color
+button_key_active_color = (YELLOW,BLUE,ON)
+
+# Inactive button key color
+button_key_inactive_color = (RED,WHITE,ON)
+
+# Active button label color
+button_label_active_color = (WHITE,BLUE,ON)
+
+# Inactive button label color
+button_label_inactive_color = (BLACK,WHITE,ON)
+
+# Input box color
+inputbox_color = (BLUE,WHITE,ON)
+
+# Input box border color
+inputbox_border_color = (WHITE,WHITE,ON)
+
+# Search box color
+searchbox_color = (YELLOW,WHITE,ON)
+
+# Search box title color
+searchbox_title_color = (WHITE,WHITE,ON)
+
+# Search box border color
+searchbox_border_color = (RED,WHITE,OFF)
+
+# File position indicator color
+position_indicator_color = (RED,WHITE,ON)
+
+# Menu box color
+menubox_color = dialog_color
+
+# Menu box border color
+menubox_border_color = border_color
+
+# Item color
+item_color = dialog_color
+
+# Selected item color
+item_selected_color = (BLUE,WHITE,ON)
+
+# Tag color
+tag_color = (BLACK,WHITE,ON)
+
+# Selected tag color
+tag_selected_color = (BLUE,WHITE,ON)
+
+# Tag key color
+tag_key_color = (MAGENTA,WHITE,ON)
+
+# Selected tag key color
+tag_key_selected_color = (RED,WHITE,ON)
+
+# Check box color
+check_color = dialog_color
+
+# Selected check box color
+check_selected_color = (RED,WHITE,ON)
+
+
+# Up arrow color
+uarrow_color = (BLUE,WHITE,ON)
+
+# Down arrow color
+darrow_color = uarrow_color
+
+
+# Item help-text color
+itemhelp_color = shadow_color
+
+# Active form text color
+form_active_text_color = inputbox_color
+
+# Form text color
+form_text_color = (BLACK,WHITE,ON)
+
+# Readonly form item color
+form_item_readonly_color = (CYAN,WHITE,ON)
+
+# Dialog box gauge color
+gauge_color = (BLUE,WHITE,ON)
+
+# Dialog box border2 color
+border2_color = dialog_color
+
+# Input box border2 color
+inputbox_border2_color = border2_color
+
+# Search box border2 color
+searchbox_border2_color = border2_color
+
+# Menu box border2 color
+menubox_border2_color = border2_color
Index: 3pp/sources/packages/dialog/patches/README
===================================================================
--- 3pp/sources/packages/dialog/patches/README	(nonexistent)
+++ 3pp/sources/packages/dialog/patches/README	(revision 258)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+   dialog-1.3-20181107.patch   - Some enhance the appearance of dialogs.
+
+ * end */
Index: Makefile
===================================================================
--- Makefile	(revision 257)
+++ Makefile	(revision 258)
@@ -4,7 +4,8 @@
 
 include config.mk
 
-REQUIRES += build-system/3pp/gnattools/7.2.0
+REQUIRES  = build-system/3pp/dialog/1.3-20181107
+REQUIRES += build-system/3pp/gnattools/7.3.0
 
 # ======= __END_OF_REQUIRES__ =======
 
@@ -11,11 +12,13 @@
 
 config_makefile = targets-config.mk
 
+BUILD_TARGETS = $(config_makefile)
+
 CLEANUP_FILES += $(config_makefile)
 CLEANUP_FILES += $(CURDIR)/gnattools
+CLEANUP_FILES += $(CURDIR)/sbin
+CLEANUP_FILES += $(CURDIR)/etc
 
-BUILD_TARGETS = $(config_makefile)
-
 # CORE Makefile:
 
 include core.mk
Index: canonical-build
===================================================================
--- canonical-build	(revision 257)
+++ canonical-build	(revision 258)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
 UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
Index: config.mk
===================================================================
--- config.mk	(revision 257)
+++ config.mk	(revision 258)
@@ -12,7 +12,8 @@
 
 CACHED_CC_OUTPUT     = /opt/extra/ccache
 
-TOOLCHAINS_BASE_PATH = /opt/toolchain
+TOOLCHAINS_BASE_PATH = /opt/toolchains
+
 TOOLCHAINS_VERSION   = 1.0.0
 
 
@@ -60,6 +61,16 @@
 ####### Additional Available Toolchains:
 #######
 
+# All ARM 32-bit series with Newlib
+TOOLCHAIN_ARM32_NEWLIB = arm32-newlib
+
+ARM32_NEWLIB_ARCH = arm-none-eabi
+ARM32_NEWLIB_DIR  = arm-NONE-eabi-newlib
+ARM32_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(ARM32_NEWLIB_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+ARM32_NEWLIB_SPEC = All ARM 32-bit series newlib toolchain
+
+
 # AT91SAM7S
 TOOLCHAIN_AT91SAM7S_NEWLIB = at91sam7s-newlib
 
@@ -66,6 +77,8 @@
 AT91SAM7S_NEWLIB_ARCH = arm-at91sam7s-eabi
 AT91SAM7S_NEWLIB_DIR  = arm-AT91SAM7S-eabi-newlib
 AT91SAM7S_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(AT91SAM7S_NEWLIB_DIR)
+###                    |---Toolchain-spec-handy-ruler----------------|
+AT91SAM7S_NEWLIB_SPEC = Atmel AT91SAM7S newlib toolchain
 
 
 # LPC17XX-UCLIBC
@@ -74,6 +87,8 @@
 LPC17XX_UCLIBC_ARCH = arm-lpc17xx-uclinuxeabi
 LPC17XX_UCLIBC_DIR  = arm-LPC17XX-uclinuxeabi
 LPC17XX_UCLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(LPC17XX_UCLIBC_DIR)
+###                  |---Toolchain-spec-handy-ruler----------------|
+LPC17XX_UCLIBC_SPEC = NXP LPC17xx uclibc toolchain
 
 
 # IMX6-GLIBC
@@ -82,6 +97,8 @@
 IMX6_GLIBC_ARCH = arm-imx6-linux-gnueabihf
 IMX6_GLIBC_DIR  = arm-IMX6-linux-glibc
 IMX6_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(IMX6_GLIBC_DIR)
+###              |---Toolchain-spec-handy-ruler----------------|
+IMX6_GLIBC_SPEC = Freescale i.MX6 GNU Libc toolchain
 
 
 # OMAP543X-GLIBC
@@ -90,22 +107,10 @@
 OMAP543X_GLIBC_ARCH = arm-omap543x-linux-gnueabihf
 OMAP543X_GLIBC_DIR  = arm-OMAP543X-linux-glibc
 OMAP543X_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(OMAP543X_GLIBC_DIR)
+###                  |---Toolchain-spec-handy-ruler----------------|
+OMAP543X_GLIBC_SPEC = Texas OMAP543x GNU Libc toolchain
 
 
-# AllWinner A10
-TOOLCHAIN_A1X_NEWLIB = a1x-newlib
-
-A1X_NEWLIB_ARCH = arm-a1x-eabi
-A1X_NEWLIB_DIR  = arm-A1X-eabi-newlib
-A1X_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(A1X_NEWLIB_DIR)
-
-# AllWinner A20
-TOOLCHAIN_A2X_NEWLIB = a2x-newlib
-
-A2X_NEWLIB_ARCH = arm-a2x-eabi
-A2X_NEWLIB_DIR  = arm-A2X-eabi-newlib
-A2X_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(A2X_NEWLIB_DIR)
-
 # AllWinner A10-GLIBC
 TOOLCHAIN_A1X_GLIBC = a1x-glibc
 
@@ -112,8 +117,9 @@
 A1X_GLIBC_ARCH = arm-a1x-linux-gnueabihf
 A1X_GLIBC_DIR  = arm-A1X-linux-glibc
 A1X_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(A1X_GLIBC_DIR)
+###             |---Toolchain-spec-handy-ruler----------------|
+A1X_GLIBC_SPEC = Allwinner A1x GNU Libc toolchain
 
-
 # AllWinner A20-GLIBC
 TOOLCHAIN_A2X_GLIBC = a2x-glibc
 
@@ -120,15 +126,39 @@
 A2X_GLIBC_ARCH = arm-a2x-linux-gnueabihf
 A2X_GLIBC_DIR  = arm-A2X-linux-glibc
 A2X_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(A2X_GLIBC_DIR)
+###             |---Toolchain-spec-handy-ruler----------------|
+A2X_GLIBC_SPEC = Allwinner A2x GNU Libc toolchain
 
 
-# Amlogic S8XX
-TOOLCHAIN_S8XX_NEWLIB = s8xx-newlib
+# AllWinner H3-GLIBC
+TOOLCHAIN_H3_GLIBC = h3-glibc
 
-S8XX_NEWLIB_ARCH = arm-s8xx-eabi
-S8XX_NEWLIB_DIR  = arm-S8XX-eabi-newlib
-S8XX_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(S8XX_NEWLIB_DIR)
+H3_GLIBC_ARCH = arm-h3-linux-gnueabihf
+H3_GLIBC_DIR  = arm-H3-linux-glibc
+H3_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(H3_GLIBC_DIR)
+###            |---Toolchain-spec-handy-ruler----------------|
+H3_GLIBC_SPEC = Allwinner H3 GNU Libc toolchain
 
+
+# AllWinner H5-NEWLIB
+TOOLCHAIN_H5_NEWLIB = h5-newlib
+
+H5_NEWLIB_ARCH = aarch64-h5-elf
+H5_NEWLIB_DIR  = aarch64-H5-elf-newlib
+H5_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(H5_NEWLIB_DIR)
+###             |---Toolchain-spec-handy-ruler----------------|
+H5_NEWLIB_SPEC = Allwinner H5 newlib toolchain
+
+# AllWinner H5-GLIBC
+TOOLCHAIN_H5_GLIBC = h5-glibc
+
+H5_GLIBC_ARCH = aarch64-h5-linux-gnu
+H5_GLIBC_DIR  = aarch64-H5-linux-glibc
+H5_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(H5_GLIBC_DIR)
+###            |---Toolchain-spec-handy-ruler----------------|
+H5_GLIBC_SPEC = Allwinner H5 GNU Libc toolchain
+
+
 # Amlogic S8XX-GLIBC
 TOOLCHAIN_S8XX_GLIBC = s8xx-glibc
 
@@ -135,6 +165,8 @@
 S8XX_GLIBC_ARCH = arm-s8xx-linux-gnueabihf
 S8XX_GLIBC_DIR  = arm-S8XX-linux-glibc
 S8XX_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(S8XX_GLIBC_DIR)
+###              |---Toolchain-spec-handy-ruler----------------|
+S8XX_GLIBC_SPEC = Amlogic S8xx GNU Libc toolchain
 
 
 # Amlogic S9XX (especially for u-boot firmware)
@@ -143,6 +175,8 @@
 A9XX_NEWLIB_ARCH = arm-a9xx-eabi
 A9XX_NEWLIB_DIR  = arm-A9XX-eabi-newlib
 A9XX_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(A9XX_NEWLIB_DIR)
+###               |---Toolchain-spec-handy-ruler----------------|
+A9XX_NEWLIB_SPEC = Amlogic S9xx Cortex-m3 newlib toolchain
 
 # Amlogic S9XX
 TOOLCHAIN_S9XX_NEWLIB = s9xx-newlib
@@ -150,6 +184,8 @@
 S9XX_NEWLIB_ARCH = aarch64-s9xx-elf
 S9XX_NEWLIB_DIR  = aarch64-S9XX-elf-newlib
 S9XX_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(S9XX_NEWLIB_DIR)
+###               |---Toolchain-spec-handy-ruler----------------|
+S9XX_NEWLIB_SPEC = Amlogic S9xx newlib toolchain
 
 # Amlogic S9XX-GLIBC
 TOOLCHAIN_S9XX_GLIBC = s9xx-glibc
@@ -157,6 +193,8 @@
 S9XX_GLIBC_ARCH = aarch64-s9xx-linux-gnu
 S9XX_GLIBC_DIR  = aarch64-S9XX-linux-glibc
 S9XX_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(S9XX_GLIBC_DIR)
+###              |---Toolchain-spec-handy-ruler----------------|
+S9XX_GLIBC_SPEC = Amlogic S9xx GNU Libc toolchain
 
 # Amlogic A9XX-GLIBC
 TOOLCHAIN_A9XX_GLIBC = a9xx-glibc
@@ -164,8 +202,56 @@
 A9XX_GLIBC_ARCH = armv8l-a9xx-linux-gnueabihf
 A9XX_GLIBC_DIR  = armv8l-A9XX-linux-glibc
 A9XX_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(A9XX_GLIBC_DIR)
+###              |---Toolchain-spec-handy-ruler----------------|
+A9XX_GLIBC_SPEC = Amlogic S9xx armv8l GNU Libc toolchain
 
 
+# Rockchip A33XX-NEWLIB (ARMv6-M Cortex-m0)
+TOOLCHAIN_A33XX_NEWLIB = a33xx-newlib
+
+A33XX_NEWLIB_ARCH = arm-a33xx-eabi
+A33XX_NEWLIB_DIR  = arm-A33XX-eabi-newlib
+A33XX_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(A33XX_NEWLIB_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+A33XX_NEWLIB_SPEC = Rockchip RK33xx Cortex-m0 newlib toolchain
+
+# Rockchip RK33XX-NEWLIB
+TOOLCHAIN_RK33XX_NEWLIB = rk33xx-newlib
+
+RK33XX_NEWLIB_ARCH = aarch64-rk33xx-elf
+RK33XX_NEWLIB_DIR  = aarch64-RK33XX-elf-newlib
+RK33XX_NEWLIB_PATH = $(TOOLCHAINS_BASE_PATH)/$(RK33XX_NEWLIB_DIR)
+###                 |---Toolchain-spec-handy-ruler----------------|
+RK33XX_NEWLIB_SPEC = Rockchip RK33xx newlib toolchain
+
+# Rockchip RK33XX-GLIBC
+TOOLCHAIN_RK33XX_GLIBC = rk33xx-glibc
+
+RK33XX_GLIBC_ARCH = aarch64-rk33xx-linux-gnu
+RK33XX_GLIBC_DIR  = aarch64-RK33XX-linux-glibc
+RK33XX_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(RK33XX_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+RK33XX_GLIBC_SPEC = Rockchip RK33xx GNU Libc toolchain
+
+# Rockchip RK339X-GLIBC
+TOOLCHAIN_RK339X_GLIBC = rk339x-glibc
+
+RK339X_GLIBC_ARCH = aarch64-rk339x-linux-gnu
+RK339X_GLIBC_DIR  = aarch64-RK339X-linux-glibc
+RK339X_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(RK339X_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+RK339X_GLIBC_SPEC = Rockchip RK339x GNU Libc toolchain
+
+# Rockchip A33XX-GLIBC
+TOOLCHAIN_A33XX_GLIBC = a33xx-glibc
+
+A33XX_GLIBC_ARCH = armv8l-a33xx-linux-gnueabihf
+A33XX_GLIBC_DIR  = armv8l-A33XX-linux-glibc
+A33XX_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(A33XX_GLIBC_DIR)
+###               |---Toolchain-spec-handy-ruler----------------|
+A33XX_GLIBC_SPEC = Rockchip RK33xx armv8l GNU Libc toolchain
+
+
 # Rockchip RK328X-GLIBC
 TOOLCHAIN_RK328X_GLIBC = rk328x-glibc
 
@@ -172,6 +258,8 @@
 RK328X_GLIBC_ARCH = arm-rk328x-linux-gnueabihf
 RK328X_GLIBC_DIR  = arm-RK328X-linux-glibc
 RK328X_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(RK328X_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+RK328X_GLIBC_SPEC = Rockchip RK328x GNU Libc toolchain
 
 
 # JZ47XX-GLIBC
@@ -180,6 +268,8 @@
 JZ47XX_GLIBC_ARCH = mipsel-jz47xx-linux-gnu
 JZ47XX_GLIBC_DIR  = mipsel-JZ47XX-linux-glibc
 JZ47XX_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(JZ47XX_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+JZ47XX_GLIBC_SPEC = Ingenic MIPS jz47xx GNU Libc toolchain
 
 
 # P5600-GLIBC
@@ -188,6 +278,8 @@
 P5600_GLIBC_ARCH = mipsel-p5600-linux-gnu
 P5600_GLIBC_DIR  = mipsel-P5600-linux-glibc
 P5600_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(P5600_GLIBC_DIR)
+###               |---Toolchain-spec-handy-ruler----------------|
+P5600_GLIBC_SPEC = Baikal MIPS p5600 core GNU Libc toolchain
 
 
 # POWER8-GLIBC
@@ -196,6 +288,8 @@
 POWER8_GLIBC_ARCH = ppc64-power8-linux-gnu
 POWER8_GLIBC_DIR  = ppc64-POWER8-linux-glibc
 POWER8_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(POWER8_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+POWER8_GLIBC_SPEC = Openpower POWER8 MSB GNU Libc toolchain
 
 # POWER9-GLIBC
 TOOLCHAIN_POWER9_GLIBC = power9-glibc
@@ -203,6 +297,8 @@
 POWER9_GLIBC_ARCH = ppc64-power9-linux-gnu
 POWER9_GLIBC_DIR  = ppc64-POWER9-linux-glibc
 POWER9_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(POWER9_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+POWER9_GLIBC_SPEC = Openpower POWER9 MSB GNU Libc toolchain
 
 
 # POWER8LE-GLIBC
@@ -211,6 +307,8 @@
 POWER8LE_GLIBC_ARCH = ppc64le-power8-linux-gnu
 POWER8LE_GLIBC_DIR  = ppc64le-POWER8-linux-glibc
 POWER8LE_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(POWER8LE_GLIBC_DIR)
+###                  |---Toolchain-spec-handy-ruler----------------|
+POWER8LE_GLIBC_SPEC = Openpower POWER8 LSB GNU Libc toolchain
 
 # POWER9LE-GLIBC
 TOOLCHAIN_POWER9LE_GLIBC = power9le-glibc
@@ -218,6 +316,8 @@
 POWER9LE_GLIBC_ARCH = ppc64le-power9-linux-gnu
 POWER9LE_GLIBC_DIR  = ppc64le-POWER9-linux-glibc
 POWER9LE_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(POWER9LE_GLIBC_DIR)
+###                  |---Toolchain-spec-handy-ruler----------------|
+POWER9LE_GLIBC_SPEC = Openpower POWER9 LSB GNU Libc toolchain
 
 
 # R1000-GLIBC
@@ -226,6 +326,8 @@
 R1000_GLIBC_ARCH = sparc64-r1000-linux-gnu
 R1000_GLIBC_DIR  = sparc64-R1000-linux-glibc
 R1000_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(R1000_GLIBC_DIR)
+###               |---Toolchain-spec-handy-ruler----------------|
+R1000_GLIBC_SPEC = MCST SPARC MSB GNU Libc toolchain
 
 
 # X86_64-GLIBC
@@ -234,6 +336,8 @@
 X86_64_GLIBC_ARCH = x86_64-radix-linux-gnu
 X86_64_GLIBC_DIR  = x86_64-PC-linux-glibc
 X86_64_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(X86_64_GLIBC_DIR)
+###                |---Toolchain-spec-handy-ruler----------------|
+X86_64_GLIBC_SPEC = Intel x86_64 GNU Libc toolchain
 
 
 # I686-GLIBC
@@ -242,6 +346,8 @@
 I686_GLIBC_ARCH = i686-radix-linux-gnu
 I686_GLIBC_DIR  = i686-PC-linux-glibc
 I686_GLIBC_PATH = $(TOOLCHAINS_BASE_PATH)/$(I686_GLIBC_DIR)
+###              |---Toolchain-spec-handy-ruler----------------|
+I686_GLIBC_SPEC = Intel i686 GNU Libc toolchain
 
 
 
Index: configure-targets
===================================================================
--- configure-targets	(nonexistent)
+++ configure-targets	(revision 258)
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+CWD=`pwd`
+
+BUILDSYSTEM=${BUILDSYSTEM:-$CWD}
+
+CONFIG=${CONFIG:-targets-config.mk}
+CONSTANTS=${CONSTANTS:-config.mk}
+
+if [ ! -r $CONFIG ] ; then
+  echo "$0: ERROR: There is no $CONFIG file for configuring target HW."
+  echo ""
+  exit 1
+fi
+
+: ${DIALOG=$BUILDSYSTEM/sbin/dialog}
+: ${DIALOGRC=$BUILDSYSTEM/etc/dialogrc}
+
+export DIALOGRC
+
+: ${DIALOG_OK=0}
+: ${DIALOG_CANCEL=1}
+: ${DIALOG_HELP=2}
+: ${DIALOG_EXTRA=3}
+: ${DIALOG_ITEM_HELP=4}
+: ${DIALOG_ESC=255}
+
+: ${SIG_NONE=0}
+: ${SIG_HUP=1}
+: ${SIG_INT=2}
+: ${SIG_QUIT=3}
+: ${SIG_KILL=9}
+: ${SIG_TERM=15}
+
+
+umask 002
+if [ ! -z "$TMPDIR" ] ; then mkdir -p $TMPDIR ; fi
+TMP=$(mkdir -p /tmp/radix && mktemp -d -p /tmp/radix build-system.XXXXXXXX) || { echo "Cannot create '/tmp/...' directory" ; exit 92; }
+trap "rm -rf $TMP" 0 $SIG_NONE $SIG_HUP $SIG_INT $SIG_QUIT $SIG_TERM
+
+
+hwlist=`cat $CONFIG | grep "^BUILD_.*[ \t]*=.*" | sed "s,^BUILD_\(.*\)[ \t]*=.*,\1," | tr 'A-Z' 'a-z' | tr '\n' ' ' | sed 's/host//g' | tr -s ' ' | sed 's/^[ \t]//' | sed 's/[ \t]$//'`
+
+for hw in $hwlist ; do
+  hh=`echo $hw | tr 'a-z' 'A-Z'`
+  spec=`cat $CONSTANTS | grep "^${hh}_SPEC[ \t]*=.*" | sed "s,^${hh}_SPEC[ \t]*=[ \t]*\(.*\),\1," | sed "s,\\\\\,,g"`
+  enabled=`cat $CONFIG | grep "^BUILD_${hh}[ \t]*=.*" | sed "s,^BUILD_${hh}[ \t]*=[ \t]*\(.*\),\1,"`
+  if [ "$enabled" == "true" ] ; then
+    en="on"
+  else
+    en="off"
+  fi
+  echo "\"$hw\" \"$spec\" \"$en\"" >> $TMP/sel$$
+done
+
+$DIALOG --colors \
+        --backtitle "\Z7Build System\Zn" \
+        --title " \Z1SELECTING TOOLCHAINS TO BUILD\Zn " \
+        --clear \
+        --checklist "\n\
+\Zb\Z4Please confirm the toolchains you want to build\Zn\ZB.\n\n\
+Use the UP/DOWN keys to scroll through the list, and the SPACE key\n\
+to deselect any items you don't want to build.\n\n\
+Press ENTER when you are done." \
+21 72 8 \
+        --file $TMP/sel$$  2> $TMP/ret$$
+
+retval=$?
+
+case $retval in
+  $DIALOG_OK)
+    enabled="`cat $TMP/ret$$`"
+    for hw in $hwlist ; do
+      hh=`echo $hw | tr 'a-z' 'A-Z'`
+      sed -i "s,^\(BUILD_${hh}[ \t]*=[ \t]*\).*,\1false," $CONFIG
+    done
+    for hw in $enabled ; do
+      hh=`echo $hw | tr 'a-z' 'A-Z'`
+      sed -i "s,^\(BUILD_${hh}[ \t]*=[ \t]*\).*,\1true," $CONFIG
+    done
+    ;;
+esac

Property changes on: configure-targets
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: core.mk
===================================================================
--- core.mk	(revision 257)
+++ core.mk	(revision 258)
@@ -298,7 +298,7 @@
 	@$(MAKE) local_clean
 
 
-__quick_targets := help local_clean downloads_clean targets-config.mk $(HACK_TARGETS)
+__quick_targets := help configure_targets local_clean downloads_clean targets-config.mk $(HACK_TARGETS)
 
 
 #
@@ -361,16 +361,16 @@
 ifeq ($(filter %_clean,$(MAKECMDGOALS)),)
 ifeq ($(__final__),)
 	@echo ""
-	@shtool echo -e "%B################################################################%b"
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B#######%b %BStart of building source requires for '%b$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))%B':%b"
-	@shtool echo -e "%B#######%b"
+	@echo -e "################################################################"
+	@echo -e "#######"
+	@echo -e "####### Start of building source requires for '$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))':"
+	@echo -e "#######"
 	@$(BUILDSYSTEM)/build_src_requires $(TOP_BUILD_DIR_ABS)
 	@__final__= TREE_RULE=local_all $(MAKE) TOOLCHAIN=$(TOOLCHAIN_NOARCH) FLAVOUR= -f .src_requires
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B#######%b %BEnd of building source requires for '%b$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))%B':%b"
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B################################################################%b"
+	@echo -e "#######"
+	@echo -e "####### End of building source requires for '$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))'."
+	@echo -e "#######"
+	@echo -e "################################################################"
 	@echo ""
 	@touch $@
 	@touch .src_requires_depend
@@ -384,15 +384,15 @@
 ifneq ($(shell pwd),$(TOP_BUILD_DIR_ABS))
 ifeq ($(shell pwd | grep $(TOP_BUILD_DIR_ABS)/$(SRC_PACKAGE_DIR))$(shell pwd | grep $(BUILDSYSTEM)/3pp/sources),)
 ifeq ($(shell pwd | grep $(BUILDSYSTEM)),)
-	@shtool echo -e "%B################################################################%b"
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B#######%b %BStart to Check the BUILDSYSTEM is ready:%b"
-	@shtool echo -e "%B#######%b"
+	@echo -e "################################################################"
+	@echo -e "#######"
+	@echo -e "####### Start to Check the BUILDSYSTEM is ready:"
+	@echo -e "#######"
 	@( cd $(BUILDSYSTEM) ; __final__= $(MAKE) TOOLCHAIN=$(TOOLCHAIN_HOST) FLAVOUR= all )
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B#######%b %BEnd of checking the BUILDSYSTEM.%b"
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B################################################################%b"
+	@echo -e "#######"
+	@echo -e "####### End of checking the BUILDSYSTEM."
+	@echo -e "#######"
+	@echo -e "################################################################"
 endif
 endif
 endif
@@ -426,16 +426,62 @@
 
 .downloads_clean:
 	@echo ""
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B#######%b %BCleaning Up all downloaded sources...%b"
-	@shtool echo -e "%B#######%b"
+	@echo -e "#######"
+	@echo -e "####### Cleaning Up all downloaded sources..."
+	@echo -e "#######"
 	@$(BUILDSYSTEM)/downloads_clean $(addprefix ., $(TOOLCHAIN_NOARCH)) $(BUILDSYSTEM)/3pp/sources
 ifneq ($(wildcard $(TOP_BUILD_DIR_ABS)/$(SRC_PACKAGE_DIR)),)
 	@$(BUILDSYSTEM)/downloads_clean $(addprefix ., $(TOOLCHAIN_NOARCH)) $(TOP_BUILD_DIR_ABS)/$(SRC_PACKAGE_DIR)
 endif
 
+help:
+	@echo ""
+	@echo -e "You can build and install software using command line such as follow:"
+	@echo ""
+	@echo -e "   $$ [TOOLCHAIN_VERSION=version] [TOOLCHAIN=toolchain] [FLAVOUR=flavour] make [goal]"
+	@echo ""
+	@echo -e "The following MAKE goals are available:"
+	@echo ""
+	@echo -e "   all                - perform make build and install software in the all"
+	@echo -e "                        required directories which defined by REQUIRES"
+	@echo -e "                        variable in the local Makefile;"
+	@echo -e "   local_all          - build and install software prepared onlu by local"
+	@echo -e "                        Makefile;"
+	@echo -e "   dist_clean,"
+	@echo -e "   local_dist_clean   - remove distribution packages from target directory"
+	@echo -e "                        defined by PRODUCTS_DEST_DIR variable. Note that"
+	@echo -e "                        is depends from targets defined by COMPONENT_TARGETS"
+	@echo -e "                        variable or command line;"
+	@echo -e "   clean,"
+	@echo -e "   local_clean        - clean up all built targets by this Makefile;"
+	@echo ""
+	@echo -e "   If the one from above goals has prefix 'local_' then this goal affects only"
+	@echo -e "   current directory.  Otherwise this goal will be performed for all required"
+	@echo -e "   directories which defined by REQUIRES variable."
+	@echo ""
+	@echo -e "   configure_targets  - select toolchains you want to built."
+	@echo -e "                        This command edits the targets-config.mk file;"
+	@echo ""
+	@echo -e "   tree_clean         - clean up whole sourses tree excluding downloaded"
+	@echo -e "                        source tarballs;"
+	@echo -e "   downloads_clean    - remove all sourse tarball from 'sourses' directory;"
+	@echo ""
+	@echo -e "Local Makefile is prepared for following target toolchains:"
+	@echo ""
+	@for toolchain in $(COMPONENT_TARGETS) ; do \
+	  echo -e "   $$toolchain"; \
+	 done
+	@echo ""
+	@echo -e "Enjoy."
+	@echo ""
 
+configure_targets: $(BUILDSYSTEM)/targets-config.mk
+	@BUILDSYSTEM=$(BUILDSYSTEM)              \
+	 CONFIG=$(BUILDSYSTEM)/targets-config.mk \
+	 CONSTANTS=$(BUILDSYSTEM)/config.mk \
+	 $(BUILDSYSTEM)/configure-targets
 
+
 #######
 ####### Source archive and patch handling
 #######
@@ -482,9 +528,22 @@
 # 	@touch $@
 
 
+################################################################
+#######
+####### Include files with references to BUILD-SYSTEM scripts:
+#######
 
+-include $(BUILDSYSTEM)/sbin/.config
 
+#######
+####### References to BUILD-SYSTEM scripts.
+#######
 ################################################################
+
+
+
+
+################################################################
 #
 # No '__final__' target selected:
 # ==============================
@@ -643,23 +702,23 @@
 .tree_all: $(TARGET_BUILD_DIR)/.requires
 ifneq ($(shell pwd),$(TOP_BUILD_DIR_ABS))
 ifeq ($(shell pwd | grep $(TOP_BUILD_DIR_ABS)/$(SRC_PACKAGE_DIR))$(shell pwd | grep $(BUILDSYSTEM)/3pp/sources),)
-	@shtool echo -e "%B################################################################%b"
-	@shtool echo -e "%B#######%b"
+	@echo -e "################################################################"
+	@echo -e "#######"
 ifeq ($(shell pwd),$(BUILDSYSTEM))
-	@shtool echo -e "%B#######%b %BStart of building requires for '%b$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))%B':%b"
+	@echo -e "####### Start of building requires for '$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))':"
 else
-	@shtool echo -e "%B#######%b %BStart of building requires for %bTOOLCHAIN=%B$(TOOLCHAIN) %bFLAVOUR=%B$(FLAVOUR) in '%b$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))%B':%b"
+	@echo -e "####### Start of building requires for TOOLCHAIN=$(TOOLCHAIN) FLAVOUR=$(FLAVOUR) in '$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))':"
 endif
-	@shtool echo -e "%B#######%b"
+	@echo -e "#######"
 ifeq ($(shell pwd),$(BUILDSYSTEM))
 	@__final__=true TREE_RULE=local_all $(MAKE) TOOLCHAIN=$(TOOLCHAIN_HOST) FLAVOUR= -f $(TARGET_BUILD_DIR)/.requires
 else
 	@__final__=true TREE_RULE=local_all $(MAKE) TOOLCHAIN=$(TOOLCHAIN) FLAVOUR= -f $(TARGET_BUILD_DIR)/.requires
 endif
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B#######%b %BEnd of building requires for '%b$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))%B':%b"
-	@shtool echo -e "%B#######%b"
-	@shtool echo -e "%B################################################################%b"
+	@echo -e "#######"
+	@echo -e "####### End of building requires for '$(subst $(TOP_BUILD_DIR_ABS)/,,$(CURDIR))'."
+	@echo -e "#######"
+	@echo -e "################################################################"
 endif
 endif
 
@@ -751,8 +810,6 @@
 endif
 
 
-
-
 -include .src_requires_depend
 -include $(TARGET_BUILD_DIR)/.requires_depend
 
@@ -773,7 +830,8 @@
 .PHONY: all local_all .clean local_clean clean
 .PHONY: .install
 
-.PHONY:  downloads_clean
+.PHONY: help
+.PHONY: downloads_clean
 .PHONY: .downloads_clean
 
 .SUFFIXES:
Index: targets-config.mk.template
===================================================================
--- targets-config.mk.template	(revision 257)
+++ targets-config.mk.template	(revision 258)
@@ -3,21 +3,24 @@
 BUILD_HOST = true
 
 
-# a1x-newlib:
-BUILD_A1X_NEWLIB = true
+# arm-none-eabi-newlib:
+BUILD_ARM32_NEWLIB = true
 
-# a2x-newlib:
-BUILD_A2X_NEWLIB = true
+# a33xx-newlib:
+BUILD_A33XX_NEWLIB = true
 
-# s8xx-newlib:
-BUILD_S8XX_NEWLIB = true
-
 # a9xx-newlib:
 BUILD_A9XX_NEWLIB = true
 
+# h5-newlib:
+BUILD_H5_NEWLIB = true
+
 # s9xx-newlib:
 BUILD_S9XX_NEWLIB = true
 
+# rk33xx-newlib:
+BUILD_RK33XX_NEWLIB = true
+
 # at91sam7s-newlib:
 BUILD_AT91SAM7S_NEWLIB = true
 
@@ -32,6 +35,27 @@
 # a2x-glibc:
 BUILD_A2X_GLIBC = true
 
+# h3-glibc:
+BUILD_H3_GLIBC = true
+
+# h5-glibc:
+BUILD_H5_GLIBC = true
+
+# imx6-glibc:
+BUILD_IMX6_GLIBC = true
+
+# jz47xx-glibc:
+BUILD_JZ47XX_GLIBC = true
+
+# p5600-glibc:
+BUILD_P5600_GLIBC = true
+
+# omap543x-glibc:
+BUILD_OMAP543X_GLIBC = true
+
+# rk328x-glibc:
+BUILD_RK328X_GLIBC = true
+
 # s8xx-glibc:
 BUILD_S8XX_GLIBC = true
 
@@ -41,21 +65,15 @@
 # a9xx-glibc:
 BUILD_A9XX_GLIBC = true
 
-# rk328x-glibc:
-BUILD_RK328X_GLIBC = true
+# rk33xx-glibc:
+BUILD_RK33XX_GLIBC = true
 
-# imx6-glibc:
-BUILD_IMX6_GLIBC = true
+# rk339x-glibc:
+BUILD_RK339X_GLIBC = true
 
-# omap543x-glibc:
-BUILD_OMAP543X_GLIBC = true
+# a33xx-glibc:
+BUILD_A33XX_GLIBC = true
 
-# jz47xx-glibc:
-BUILD_JZ47XX_GLIBC = true
-
-# p5600-glibc:
-BUILD_P5600_GLIBC = true
-
 # power8-glibc:
 BUILD_POWER8_GLIBC = true
 
Index: tree_clean
===================================================================
--- tree_clean	(revision 257)
+++ tree_clean	(revision 258)
@@ -61,6 +61,7 @@
   chomp $cwd;
 
   return if( ! -f "$cwd/Makefile" );
+  return if( $dir =~ m/sources/ );
 
   # needs dist clean:
   if( -f "$cwd/.dist" ) { push @dist_clean_dirs_all, $cwd; }
@@ -127,6 +128,8 @@
 }
 @clean_dirs = reverse( keys %seen );
 
+push @clean_dirs, "$top_dir/build-system";
+
 $dist_clean_count = @dist_clean_dirs;
 $clean_count = @clean_dirs;