Index: tools/config.py
===================================================================
--- tools/config.py	(revision 9a0367fa3b9a9c76101f2153a0f10900ea972c2b)
+++ tools/config.py	(revision 27fb3d6f9efd0c4396c87c135ff58e0b7b2e6766)
@@ -35,5 +35,5 @@
 import re
 import commands
-import snack
+import xtui
 
 INPUT = sys.argv[1]
@@ -179,31 +179,34 @@
 	return ' '
 
-def subchoice(screen, name, choices):
+def subchoice(screen, name, choices, default):
 	"Return choice of choices"
 	
-	maxlen = 0
-	for choice in choices:
-		length = len(choice[0])
-		if (length > maxlen):
-			maxlen = length
+	maxkey = 0
+	for key, val in choices:
+		length = len(key)
+		if (length > maxkey):
+			maxkey = length
 	
 	options = []
-	for choice in choices:
-		options.append(" %-*s  %s " % (maxlen, choice[0], choice[1]))
-	
-	retval = snack.ListboxChoiceWindow(screen, name, 'Choose value', options)
-	
-	if (retval[0] == 'cancel'):
+	position = None
+	cnt = 0
+	for key, val in choices:
+		if ((default) and (key == default)):
+			position = cnt
+		
+		options.append(" %-*s  %s " % (maxkey, key, val))
+		cnt += 1
+	
+	(button, value) = xtui.choice_window(screen, name, 'Choose value', options, position)
+	
+	if (button == 'cancel'):
 		return None
 	
-	return choices[retval[1]][0]
+	return choices[value][0]
 
 def check_choices(defaults, ask_names):
 	"Check whether all accessible variables have a default"
 	
-	for row in ask_names:
-		varname = row[0]
-		cond = row[4]
-		
+	for varname, vartype, name, choices, cond in ask_names:
 		if ((cond) and (not check_condition(cond, defaults, ask_names))):
 			continue
@@ -223,9 +226,5 @@
 	outf.write('#########################################\n\n')
 	
-	for row in ask_names:
-		varname = row[0]
-		name = row[2]
-		cond = row[4]
-		
+	for varname, vartype, name, choices, cond in ask_names:
 		if ((cond) and (not check_condition(cond, defaults, ask_names))):
 			continue
@@ -259,5 +258,5 @@
 			return 0
 	
-	screen = snack.SnackScreen()
+	screen = xtui.screen_init()
 	try:
 		selname = None
@@ -268,11 +267,5 @@
 			position = None
 			cnt = 0
-			for row in ask_names:
-				
-				varname = row[0]
-				vartype = row[1]
-				name = row[2]
-				choices = row[3]
-				cond = row[4]
+			for varname, vartype, name, choices, cond in ask_names:
 				
 				if ((cond) and (not check_condition(cond, defaults, ask_names))):
@@ -312,31 +305,32 @@
 					raise RuntimeError("Unknown variable type: %s" % vartype)
 				
-				opt2row[cnt] = row
+				opt2row[cnt] = (varname, vartype, name, choices)
 				
 				cnt += 1
 			
-			retval = snack.ListboxChoiceWindow(screen, 'HelenOS configuration', 'Choose configuration option', options, default = position)
-			
-			if (retval[0] == 'cancel'):
+			(button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position)
+			
+			if (button == 'cancel'):
 				return 'Configuration canceled'
 			
-			row = opt2row[retval[1]]
-			if (row == None):
-				raise RuntimeError("Error selecting value: %s" % retval[1])
-			
-			selname = row[0]
-			seltype = row[1]
-			name = row[2]
-			choices = row[3]
-			
-			if (retval[0] == 'ok'):
+			if (not opt2row.has_key(value)):
+				raise RuntimeError("Error selecting value: %s" % value)
+			
+			(selname, seltype, name, choices) = opt2row[value]
+			
+			if (not defaults.has_key(selname)):
+					default = None
+			else:
+				default = defaults[selname]
+			
+			if (button == 'done'):
 				if (check_choices(defaults, ask_names)):
 					break
 				else:
-					snack.ButtonChoiceWindow(screen, 'Error', 'Some options have still undefined values.', ['Ok']);
+					xtui.error_dialog(screen, 'Error', 'Some options have still undefined values.')
 					continue
 			
 			if (seltype == 'choice'):
-				defaults[selname] = subchoice(screen, name, choices)
+				defaults[selname] = subchoice(screen, name, choices, default)
 			elif ((seltype == 'y/n') or (seltype == 'n/y')):
 				if (defaults[selname] == 'y'):
@@ -345,5 +339,5 @@
 					defaults[selname] = 'y'
 	finally:
-		screen.finish()
+		xtui.screen_done(screen)
 	
 	create_output(OUTPUT, defaults, ask_names)
Index: tools/xtui.py
===================================================================
--- tools/xtui.py	(revision 27fb3d6f9efd0c4396c87c135ff58e0b7b2e6766)
+++ tools/xtui.py	(revision 27fb3d6f9efd0c4396c87c135ff58e0b7b2e6766)
@@ -0,0 +1,252 @@
+#
+# Copyright (c) 2009 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+"""
+Text User Interface wrapper
+"""
+
+import sys
+import os
+
+def call_dlg(dlgcmd, *args, **kw):
+	"Wrapper for calling 'dialog' program"
+	
+	indesc, outdesc = os.pipe()
+	pid = os.fork()
+	if (not pid):
+		os.close(2)
+		os.dup(outdesc)
+		os.close(indesc)
+		
+		dlgargs = [dlgcmd]
+		for key, val in kw.items():
+			dlgargs.append('--' + key)
+			dlgargs.append(val)
+		
+		dlgargs += args
+		os.execlp(dlgcmd, *dlgargs)
+	
+	os.close(outdesc)
+	
+	try:
+		errout = os.fdopen(indesc, 'r')
+		data = errout.read()
+		errout.close()
+		pid, status = os.wait()
+	except:
+		# Reset terminal
+		os.system('reset')
+		raise
+	
+	if (not os.WIFEXITED(status)):
+		# Reset terminal
+		os.system('reset')
+		raise EOFError
+	
+	status = os.WEXITSTATUS(status)
+	if (status == 255):
+		raise EOFError
+	
+	return (status, data)
+
+try:
+	import snack
+	newt = True
+	dialog = False
+except ImportError:
+	newt = False
+	
+	dlgcmd = os.environ.get('DIALOG', 'dialog')
+	if (call_dlg(dlgcmd, '--print-maxsize')[0] != 0):
+		dialog = False
+	else:
+		dialog = True
+
+width_extra = 13
+height_extra = 11
+
+def width_fix(screen, width):
+	"Correct width to screen size"
+	
+	if (width + width_extra > screen.width):
+		width = screen.width - width_extra
+	
+	if (width <= 0):
+		width = screen.width
+	
+	return width
+
+def height_fix(screen, height):
+	"Correct height to screen size"
+	
+	if (height + height_extra > screen.height):
+		height = screen.height - height_extra
+	
+	if (height <= 0):
+		height = screen.height
+	
+	return height
+
+def screen_init():
+	"Initialize the screen"
+	
+	if (newt):
+		return snack.SnackScreen()
+	
+	return None
+
+def screen_done(screen):
+	"Cleanup the screen"
+	
+	if (newt):
+		screen.finish()
+
+def choice_window(screen, title, text, options, position):
+	"Create options menu"
+	
+	maxopt = 0
+	for option in options:
+		length = len(option)
+		if (length > maxopt):
+			maxopt = length
+	
+	width = maxopt
+	height = len(options)
+	
+	if (newt):
+		width = width_fix(screen, width + width_extra)
+		height = height_fix(screen, height)
+		
+		buttonbar = snack.ButtonBar(screen, ('Done', 'Cancel'))
+		textbox = snack.TextboxReflowed(width, text)
+		listbox = snack.Listbox(height, scroll = True, returnExit = 1)
+		
+		cnt = 0
+		for option in options:
+			listbox.append(option, cnt)
+			cnt += 1
+		
+		if (position != None):
+			listbox.setCurrent(position)
+		
+		grid = snack.GridForm(screen, title, 1, 3)
+		grid.add(textbox, 0, 0)
+		grid.add(listbox, 0, 1, padding = (0, 1, 0, 1))
+		grid.add(buttonbar, 0, 2, growx = 1)
+		
+		retval = grid.runOnce()
+		
+		return (buttonbar.buttonPressed(retval), listbox.current())
+	elif (dialog):
+		args = []
+		cnt = 0
+		for option in options:
+			args.append(str(cnt + 1))
+			args.append(option)
+			
+			cnt += 1
+		
+		kw = {}
+		if (position != None):
+			kw['default-item'] = str(position + 1)
+		
+		status, data = call_dlg(dlgcmd, '--title', title, '--extra-button', '--extra-label', 'Done', '--menu', text, str(height + height_extra), str(width + width_extra), str(cnt), *args, **kw)
+		
+		if (status == 1):
+			return ('cancel', None)
+		
+		try:
+			choice = int(data) - 1
+		except ValueError:
+			return ('cancel', None)
+		
+		if (status == 0):
+			return (None, choice)
+		
+		return ('done', choice)
+	
+	sys.stdout.write("\n *** %s *** \n%s\n\n" % (title, text))
+	
+	maxcnt = len(str(len(options)))
+	cnt = 0
+	for option in options:
+		sys.stdout.write("%*s. %s\n" % (maxcnt, cnt + 1, option))
+		cnt += 1
+	
+	sys.stdout.write("\n%*s. Done\n" % (maxcnt, '0'))
+	sys.stdout.write("%*s. Quit\n\n" % (maxcnt, 'q'))
+	
+	while True:
+		if (position != None):
+			sys.stdout.write("Selection[%s]: " % str(position + 1))
+		else:
+			sys.stdout.write("Selection: ")
+		inp = sys.stdin.readline()
+		
+		if (not inp):
+			raise EOFError
+		
+		if (not inp.strip()):
+			if (position != None):
+				return (None, position)
+			continue
+		
+		if (inp.strip() == 'q'):
+			return ('cancel', None)
+		
+		try:
+			choice = int(inp.strip())
+		except ValueError:
+			continue
+		
+		if (choice == 0):
+			return ('done', 0)
+		
+		if (choice < 1) or (choice > len(options)):
+			continue
+		
+		return (None, choice - 1)
+
+def error_dialog(screen, title, msg):
+	"Print error dialog"
+	
+	width = len(msg)
+	
+	if (newt):
+		width = width_fix(screen, width)
+		
+		buttonbar = snack.ButtonBar(screen, ['Ok'])
+		textbox = snack.TextboxReflowed(width, msg)
+		
+		grid = snack.GridForm(screen, title, 1, 2)
+		grid.add(textbox, 0, 0, padding = (0, 0, 0, 1))
+		grid.add(buttonbar, 0, 1, growx = 1)
+		grid.runOnce()
+	elif (dialog):
+		call_dlg(dlgcmd, '--title', title, '--msgbox', msg, '6', str(width + width_extra))
+	
+	sys.stdout.write("\n%s: %s\n" % (title, msg))
