Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Feb 2006 02:07:10 -0800 (PST)
From:      Seth Kingsley <sethk@magnesium.net>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/93853: [PATCH]: Add country-specific keymap selection to sysinstall
Message-ID:  <20060226100710.68F47DA8D7@toxic.magnesium.net>
Resent-Message-ID: <200602261010.k1QAA4AW060145@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         93853
>Category:       bin
>Synopsis:       [PATCH]: Add country-specific keymap selection to sysinstall
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Feb 26 10:10:04 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Seth Kingsley
>Release:        FreeBSD 5.4-STABLE i386
>Organization:
>Environment:
System: FreeBSD toxic.magnesium.net 5.4-STABLE FreeBSD 5.4-STABLE #6: Wed Jul 6 13:04:10 PDT 2005 root@toxic.magnesium.net:/data/world/obj/data/world/src/sys/TOXIC i386

>Description:
	The patch below adds country-specific keymap selection to sysinstall.
	Later, the country setting will also be used as a hint when selecting
	a timezone.

	The default country selection is "United States", and if the user
	doesn't select a different item, no alternate keymap is loaded.
	Otherwise, the user is given a choice of keymaps, with the default
	being the ISO keymap for their country, if available.  This also means
	that the user will only have to hit Enter one additional time when
	starting sysinstall to get the the pre-existing behavior.

	The country menu is presented just before the main menu, and bypassed
	if an action was specified on the command-line.  Any install.cfg
	script that ends with "shutdown" will also bypass this menu, since
	sysinstall will exit before it reaches the main menu.

>How-To-Repeat:
	N/A

>Fix:

Index: Makefile
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/Makefile,v
retrieving revision 1.136
diff -u -d -p -r1.136 Makefile
--- Makefile	15 Dec 2005 01:04:50 -0000	1.136
+++ Makefile	26 Feb 2006 08:18:56 -0000
@@ -12,7 +12,7 @@ SRCS=	anonFTP.c cdrom.c command.c config
 	label.c main.c makedevs.c media.c menus.c misc.c modules.c \
 	mouse.c msg.c network.c nfs.c options.c package.c \
 	system.c tape.c tcpip.c termcap.c ttys.c ufs.c user.c \
-	variable.c ${_wizard} keymap.h
+	variable.c ${_wizard} keymap.h countries.h
 
 CFLAGS+= -DUSE_GZIP=1
 .if ${MACHINE} == "pc98"
@@ -24,7 +24,7 @@ DPADD=	${LIBDIALOG} ${LIBNCURSES} ${LIBU
 LDADD=	-ldialog -lncurses -lutil -ldisk -lftpio
 
 CLEANFILES=	makedevs.c rtermcap
-CLEANFILES+=	keymap.tmp keymap.h
+CLEANFILES+=	keymap.tmp keymap.h countries.tmp countries.h
 
 .if exists(${.CURDIR}/../../share/termcap/termcap.src)
 RTERMCAP=	TERMCAP=${.CURDIR}/../../share/termcap/termcap.src ./rtermcap
@@ -99,4 +99,25 @@ keymap.h:
 	( echo "	{ 0 }"; echo "};" ; echo "" ) >> keymap.tmp
 	mv keymap.tmp keymap.h
 
+countries.h: ${.CURDIR}/../../share/misc/iso3166
+	rm -f countries.tmp
+	awk 'BEGIN { \
+	    FS = "\t"; \
+	    num = 1; \
+	    print "DMenu MenuCountry = {"; \
+	    print "    DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS,"; \
+	    print "    \"Country Selection\","; \
+	    print "    \"Please choose a country, region, or group.\\n\""; \
+	    print "    \"Select an item using [SPACE] or [ENTER].\","; \
+	    printf "    NULL,\n    NULL,\n    { "; \
+	} \
+	/^[[:space:]]*#/ {next;} \
+	{if (num > 1) {printf "      ";} \
+	    print "{ \"" num "\", \"" $$4 "\"" \
+	    ", dmenuVarCheck, dmenuSetCountryVariable" \
+	    ", NULL, VAR_COUNTRY \"=" tolower($$1) "\" },"; \
+	    ++num;} \
+	END {print "      { NULL } }\n};\n";}' < ${.ALLSRC} > countries.tmp
+	mv countries.tmp ${.TARGET}
+
 .include <bsd.prog.mk>
Index: config.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/config.c,v
retrieving revision 1.234
diff -u -d -p -r1.234 config.c
--- config.c	21 Jul 2005 03:32:29 -0000	1.234
+++ config.c	26 Feb 2006 08:18:57 -0000
@@ -506,6 +506,21 @@ configNTP(dialogMenuItem *self)
 }
 
 int
+configCountry(dialogMenuItem *self)
+{
+    int choice, scroll, curr, max;
+
+    WINDOW *w = savescr();
+
+    dialog_clear_norefresh();
+    dmenuSetDefaultItem(&MenuCountry, NULL, NULL, VAR_COUNTRY "=" DEFAULT_COUNTRY,
+	    &choice, &scroll, &curr, &max);
+    dmenuOpen(&MenuCountry, &choice, &scroll, &curr, &max, FALSE);
+
+    return DITEM_SUCCESS;
+}
+
+int
 configUsers(dialogMenuItem *self)
 {
     WINDOW *w = savescr();
Index: dmenu.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/dmenu.c,v
retrieving revision 1.45
diff -u -d -p -r1.45 dmenu.c
--- dmenu.c	17 Sep 2003 03:45:30 -0000	1.45
+++ dmenu.c	26 Feb 2006 08:19:00 -0000
@@ -35,6 +35,7 @@
  */
 
 #include "sysinstall.h"
+#include <sys/param.h>
 #include <errno.h>
 
 #define MAX_MENU		15
@@ -111,6 +112,21 @@ dmenuSetVariables(dialogMenuItem *tmp)
 }
 
 int
+dmenuSetCountryVariable(dialogMenuItem *tmp)
+{
+    variable_set((char *)tmp->data, FALSE);
+#ifdef WITH_SYSCONS
+    /* Don't prompt the user for a keymap if they're using the default locale. */
+    if (!strcmp(variable_get(VAR_COUNTRY), DEFAULT_COUNTRY))
+	return;
+
+    return keymapMenuSelect(tmp);
+#else
+    return DITEM_SUCCESS;
+#endif
+}
+
+int
 dmenuSetKmapVariable(dialogMenuItem *tmp)
 {
     char *lang;
@@ -264,6 +280,60 @@ menu_height(DMenu *menu, int n)
     return n > max ? max : n;
 }
 
+/* Find a menu item that matches any field. */
+int
+dmenuFindItem(DMenu *menu, const char *prompt, const char *title, void *data)
+{
+    dialogMenuItem *items = menu->items;
+    int i;
+
+    for (i = 0; items[i].prompt; ++i)
+	if ((prompt && !strcmp(items[i].prompt, prompt)) ||
+		(title && !strcmp(items[i].title, title)) ||
+		(data && items[i].data == data))
+	    return i;
+
+    return -1;
+}
+
+/* Set the default item for a menu by index and scroll to it. */
+void
+dmenuSetDefaultIndex(DMenu *menu, int *choice, int *scroll, int *curr, int *max)
+{
+    int nitem;
+    int height;
+
+    *curr = *max = 0;
+
+    for (nitem = 0; menu->items[nitem].prompt; ++nitem);
+
+    height = menu_height(menu, nitem);
+    if (*choice > height)
+    {
+	*scroll = MIN(nitem - height, *choice);
+	*choice = *choice - *scroll;
+    }
+    else
+	*scroll = 0;
+}
+
+/* Set the default menu item that matches any field and scroll to it. */
+Boolean
+dmenuSetDefaultItem(DMenu *menu, const char *prompt, const char *title, void *data,
+		    int *choice, int *scroll, int *curr, int *max)
+{
+    if ((*choice = dmenuFindItem(menu, prompt, title, data)) != -1)
+    {
+	dmenuSetDefaultIndex(menu, choice, scroll, curr, max);
+	return TRUE;
+    }
+    else
+    {
+	*choice = *scroll = *curr = *max = 0;
+	return FALSE;
+    }
+}
+
 /* Traverse over an internal menu */
 Boolean
 dmenuOpen(DMenu *menu, int *choice, int *scroll, int *curr, int *max, Boolean buttons)
Index: keymap.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/keymap.c,v
retrieving revision 1.6
diff -u -d -p -r1.6 keymap.c
--- keymap.c	8 Oct 2000 21:33:51 -0000	1.6
+++ keymap.c	26 Feb 2006 08:19:04 -0000
@@ -50,6 +50,73 @@ struct keymapInfo {
  * the language name only.
  */
 
+
+static int
+keymapSetDefault(const char *prefix)
+{
+    dialogMenuItem *items = MenuSysconsKeymap.items;
+    int i;
+    size_t plen = strlen(prefix);
+
+    for (i = 0; items[i].data; ++i)
+	if (!strncmp(prefix, items[i].data, plen))
+	    return i;
+
+    return -1;
+}
+
+int
+keymapMenuSelect(dialogMenuItem *self)
+{
+    static const struct {
+	const char *country, *lang;
+    } map[] = {
+	{"dk", "danish"},
+	{"ee", "estonian"},
+	{"fi", "finnish"},
+	{"de", "german"},
+	{"is", "icelandic"},
+	{"no", "norwegian"},
+	{"pl", "pl_PL"},
+	{"es", "spanish"},
+	{"se", "swedish"},
+	{"ch", "swiss"},
+	{"gb", "uk"},
+	{NULL, NULL}
+    };
+    const char *country, *lang;
+    int i;
+    int choice, scroll, curr, max;
+    char prefix[16 + 1];
+
+    if ((country = variable_get(VAR_COUNTRY)) != NULL)
+    {
+	lang = NULL;
+	for (i = 0; map[i].country; ++i)
+	    if (!strcmp(country, map[i].country))
+	    {
+		lang = map[i].lang;
+		break;
+	    }
+
+	if (!lang)
+	    lang = country;
+
+	snprintf(prefix, sizeof(prefix), "keymap=%s.iso", lang);
+	if ((choice = keymapSetDefault(prefix)) == -1)
+	{
+	    snprintf(prefix, sizeof(prefix), "keymap=%s", lang);
+	    if ((choice = keymapSetDefault(prefix)) == -1)
+		choice = 0;
+	}
+
+	dmenuSetDefaultIndex(&MenuSysconsKeymap, &choice, &scroll, &curr, &max);
+	return dmenuOpen(&MenuSysconsKeymap, &choice, &scroll, &curr, &max, FALSE);
+    }
+    else
+	return dmenuOpenSimple(&MenuSysconsKeymap, FALSE);
+}
+
 /*
  * Return values:
  *
Index: main.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/main.c,v
retrieving revision 1.72
diff -u -d -p -r1.72 main.c
--- main.c	15 Dec 2005 01:04:50 -0000	1.72
+++ main.c	26 Feb 2006 08:19:05 -0000
@@ -158,6 +158,9 @@ main(int argc, char **argv)
 	systemShutdown(status);
     }
 
+    /* Get user's country and keymap */
+    configCountry(NULL);
+
     /* Begin user dialog at outer menu */
     dialog_clear();
     while (1) {
Index: menus.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/menus.c,v
retrieving revision 1.413
diff -u -d -p -r1.413 menus.c
--- menus.c	15 Jan 2006 23:15:41 -0000	1.413
+++ menus.c	26 Feb 2006 08:19:09 -0000
@@ -203,6 +203,7 @@ DMenu MenuIndex = {
     NULL,
     { { " Anon FTP",		"Configure anonymous FTP logins.",	dmenuVarCheck, configAnonFTP, NULL, "anon_ftp" },
       { " Commit",		"Commit any pending actions (dangerous!)", NULL, installCustomCommit },
+      { " Country",		"Set the system's country",		NULL, configCountry },
 #ifdef WITH_SYSCONS
       { " Console settings",	"Customize system console behavior.",	NULL, dmenuSubmenu, NULL, &MenuSyscons },
 #endif
@@ -273,7 +274,7 @@ DMenu MenuIndex = {
 #ifndef PC98
       { " Syscons, Font",	"The console screen font.",	  NULL, dmenuSubmenu, NULL, &MenuSysconsFont },
 #endif
-      { " Syscons, Keymap",	"The console keymap configuration menu.", NULL, dmenuSubmenu, NULL, &MenuSysconsKeymap },
+      { " Syscons, Keymap",	"The console keymap configuration menu.", NULL, keymapMenuSelect },
       { " Syscons, Keyrate",	"The console key rate configuration menu.", NULL, dmenuSubmenu, NULL, &MenuSysconsKeyrate },
       { " Syscons, Saver",	"The console screen saver configuration menu.",	NULL, dmenuSubmenu, NULL, &MenuSysconsSaver },
 #ifndef PC98
@@ -291,6 +292,9 @@ DMenu MenuIndex = {
       { NULL } },
 };
 
+/* The country menu */
+#include "countries.h"
+
 /* The initial installation menu */
 DMenu MenuInitial = {
     DMENU_NORMAL_TYPE,
@@ -310,7 +314,7 @@ DMenu MenuInitial = {
       { "Configure",	"Do post-install configuration of FreeBSD",	NULL, dmenuSubmenu, NULL, &MenuConfigure },
       { "Doc",	"Installation instructions, README, etc.",	NULL, dmenuSubmenu, NULL, &MenuDocumentation },
 #ifdef WITH_SYSCONS
-      { "Keymap",	"Select keyboard type",				NULL, dmenuSubmenu, NULL, &MenuSysconsKeymap },
+      { "Keymap",	"Select keyboard type",				NULL, keymapMenuSelect },
 #endif
       { "Options",	"View/Set various installation options",	NULL, optionsEditor },
       { "Fixit",	"Repair mode with CDROM/DVD/floppy or start shell",	NULL, dmenuSubmenu, NULL, &MenuFixit },
Index: sysinstall.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/sysinstall/sysinstall.h,v
retrieving revision 1.267
diff -u -d -p -r1.267 sysinstall.h
--- sysinstall.h	27 Jan 2006 21:00:31 -0000	1.267
+++ sysinstall.h	26 Feb 2006 08:19:13 -0000
@@ -97,6 +97,7 @@
 #define VAR_BOOTMGR			"bootManager"
 #define VAR_BROWSER_BINARY		"browserBinary"
 #define VAR_BROWSER_PACKAGE		"browserPackage"
+#define VAR_COUNTRY			"country"
 #define VAR_CPIO_VERBOSITY		"cpioVerbose"
 #define VAR_DEBUG			"debug"
 #define VAR_DESKSTYLE			"_deskStyle"
@@ -198,6 +199,11 @@
 #define VAR_TERM			"TERM"
 #define VAR_CONSTERM                    "_consterm"
 
+#ifdef PC98
+#define DEFAULT_COUNTRY		"jp"
+#else
+#define DEFAULT_COUNTRY		"us"
+#endif
 #define DEFAULT_TAPE_BLOCKSIZE	"20"
 
 /* One MB worth of blocks */
@@ -414,6 +420,7 @@ extern unsigned int	SrcDists;		/* Which 
 extern unsigned int	XOrgDists;		/* Which X.Org dists we want			*/
 extern int		BootMgr;		/* Which boot manager to use 			*/
 extern int		StatusLine;		/* Where to print our status messages		*/
+extern DMenu		MenuCountry;		/* Country menu				*/
 extern DMenu		MenuInitial;		/* Initial installation menu			*/
 extern DMenu		MenuFixit;		/* Fixit repair menu				*/
 #if defined(__i386__) || defined(__amd64__)
@@ -522,6 +529,7 @@ extern int	configNTP(dialogMenuItem *sel
 #ifdef __alpha__
 extern int	configOSF1(dialogMenuItem *self);
 #endif
+extern int	configCountry(dialogMenuItem *self);
 extern int	configUsers(dialogMenuItem *self);
 extern int	configRouter(dialogMenuItem *self);
 extern int	configPCNFSD(dialogMenuItem *self);
@@ -605,11 +613,16 @@ extern int	dmenuSystemCommandBox(dialogM
 extern int	dmenuExit(dialogMenuItem *tmp);
 extern int	dmenuISetVariable(dialogMenuItem *tmp);
 extern int	dmenuSetVariable(dialogMenuItem *tmp);
+extern int	dmenuSetCountryVariable(dialogMenuItem *tmp);
 extern int	dmenuSetKmapVariable(dialogMenuItem *tmp);
 extern int	dmenuSetVariables(dialogMenuItem *tmp);
 extern int	dmenuToggleVariable(dialogMenuItem *tmp);
 extern int	dmenuSetFlag(dialogMenuItem *tmp);
 extern int	dmenuSetValue(dialogMenuItem *tmp);
+extern int	dmenuFindItem(DMenu *menu, const char *prompt, const char *title, void *data);
+extern void	dmenuSetDefaultIndex(DMenu *menu, int *choice, int *scroll, int *curr, int *max);
+extern int	dmenuSetDefaultItem(DMenu *menu, const char *prompt, const char *title, void *data,
+				    int *choice, int *scroll, int *curr, int *max);
 extern Boolean	dmenuOpen(DMenu *menu, int *choice, int *scroll, int *curr, int *max, Boolean buttons);
 extern Boolean	dmenuOpenSimple(DMenu *menu, Boolean buttons);
 extern int	dmenuVarCheck(dialogMenuItem *item);
@@ -677,6 +690,7 @@ extern Boolean	copySelf(void);
 extern int	kget(char *out);
 
 /* keymap.c */
+extern int	keymapMenuSelect(dialogMenuItem *self);
 extern int	loadKeymap(const char *lang);
 
 /* label.c */

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060226100710.68F47DA8D7>