Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
539
cde/programs/dtlogin/vglang.c
Normal file
539
cde/programs/dtlogin/vglang.c
Normal file
@@ -0,0 +1,539 @@
|
||||
/* $TOG: vglang.c /main/7 1998/03/04 19:28:18 mgreess $ */
|
||||
/* *
|
||||
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
|
||||
* (c) Copyright 1993, 1994 International Business Machines Corp. *
|
||||
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
|
||||
* (c) Copyright 1993, 1994 Novell, Inc. *
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
**
|
||||
** File: ui.c
|
||||
**
|
||||
** Project: Common Desktop Environment
|
||||
**
|
||||
** Description: common ui code for login manager
|
||||
**
|
||||
**
|
||||
****************************************************************************
|
||||
************************************<+>*************************************/
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* Includes
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vg.h"
|
||||
#include "vgmsg.h"
|
||||
#include <Xm/CascadeBG.h>
|
||||
#include <Xm/RowColumn.h>
|
||||
#include <Xm/ToggleBG.h>
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* GetLangName
|
||||
*
|
||||
* Convert an actual locale name to a meaningful language name which will
|
||||
* be shown in the language menu. This function may be platform dependent.
|
||||
***************************************************************************/
|
||||
|
||||
static char *
|
||||
GetLangName( char *label )
|
||||
{
|
||||
/*
|
||||
* Default implementation is to use langName resource. Language names can be
|
||||
* set in Dtlogin file as follows. (In this case, en_US is a locale name which
|
||||
* can be set to LANG environment variable.
|
||||
*
|
||||
* Dtlogin*en_US*languageName: English (ISO8859-1)
|
||||
*/
|
||||
char rmname[50];
|
||||
char rmclass[50];
|
||||
char *rmtype;
|
||||
XrmValue rmvalue;
|
||||
|
||||
sprintf(rmname, "Dtlogin*%s*languageName", label);
|
||||
sprintf(rmclass, "Dtlogin*%s*LanguageName", label);
|
||||
if(XrmGetResource(XtDatabase(dpyinfo.dpy), rmname, rmclass, &rmtype,
|
||||
&rmvalue)) {
|
||||
return(rmvalue.addr);
|
||||
}
|
||||
else
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#if defined (ENABLE_DYNAMIC_LANGLIST)
|
||||
/***************************************************************************
|
||||
*
|
||||
* Methods for dynamic language list
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* _enumLangCmdStart() - start enumeration of languages and descriptions
|
||||
*
|
||||
* The command specified by Dtlogin*languageListCmd command returns
|
||||
* the list of locales and a translated description of each.
|
||||
*/
|
||||
static void *
|
||||
_enumLangCmdStart(void)
|
||||
{
|
||||
if (appInfo.languageListCmd)
|
||||
{
|
||||
return((void *)popen(appInfo.languageListCmd, "r"));
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* _enumLangCmdNext() - get next language description pair
|
||||
* note: *lang and *desc must be freed by free()
|
||||
*
|
||||
* Read the next locale and description from pipe. Default description
|
||||
* comes from system, but user may override with Xresources description.
|
||||
*/
|
||||
static Boolean
|
||||
_enumLangCmdNext(
|
||||
void *state,
|
||||
char **lang,
|
||||
char **desc)
|
||||
{
|
||||
char buf[200];
|
||||
Boolean rc = False;
|
||||
|
||||
if (fgets(buf, sizeof(buf), (FILE *)state) != NULL)
|
||||
{
|
||||
/*
|
||||
* The buf format is "locale desc ...\n". For example:
|
||||
*
|
||||
* pl_PL Polish ISO8859-2
|
||||
* pt_BR Portuguese (Brazil) ISO8859-1
|
||||
*/
|
||||
char *loclang = strtok(buf, " "); /* lang name from system */
|
||||
char *locdesc = strtok(NULL, "\n"); /* description from system */
|
||||
char *userdesc; /* user provided description from Xresources */
|
||||
|
||||
if ((userdesc = GetLangName(loclang)) != NULL)
|
||||
{
|
||||
locdesc = userdesc; /* use user provided description */
|
||||
}
|
||||
|
||||
*lang = strdup(loclang);
|
||||
*desc = strdup(locdesc);
|
||||
rc = True;
|
||||
}
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* _enumLangCmdEnd() - end enumeration of language names and descriptions
|
||||
*
|
||||
* Close pipe.
|
||||
*/
|
||||
static void
|
||||
_enumLangCmdEnd(
|
||||
void *state)
|
||||
{
|
||||
pclose((FILE *)state);
|
||||
}
|
||||
#endif /* ENABLE_DYNAMIC_LANGLIST */
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* Methods for language list of type 'LANGLIST'
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#define DELIM " \t" /* delimiters in language list */
|
||||
|
||||
struct _enumState
|
||||
{
|
||||
char *dupstr;
|
||||
char *tokstr;
|
||||
};
|
||||
|
||||
/*
|
||||
* _enumLanglistStart() - start enumeration of languages and descriptions
|
||||
*
|
||||
* Dtlogin sets up the LANGLIST env var which contains the list
|
||||
* of locale names to display in the language menus.
|
||||
*/
|
||||
static void *
|
||||
_enumLanglistStart(void)
|
||||
{
|
||||
char *p;
|
||||
struct _enumState *state = malloc(sizeof(struct _enumState));
|
||||
|
||||
if (state)
|
||||
{
|
||||
if ((p = (char *)getenv(LANGLIST)) == NULL )
|
||||
{
|
||||
free(state);
|
||||
state = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->dupstr = strdup(p);
|
||||
state->tokstr = state->dupstr;
|
||||
}
|
||||
}
|
||||
|
||||
return((void *)state);
|
||||
}
|
||||
|
||||
/*
|
||||
* _enumLanglistNext() - get next language description pair
|
||||
* note: *lang and *desc must be freed by free()
|
||||
*
|
||||
* Get next locale from LANGLIST and get possible description from
|
||||
* Xresources.
|
||||
*/
|
||||
static Boolean
|
||||
_enumLanglistNext(
|
||||
void *state,
|
||||
char **lang,
|
||||
char **desc)
|
||||
{
|
||||
Boolean rc = False;
|
||||
struct _enumState *enumstate = (struct _enumState *)state;
|
||||
char *loclang, *locdesc;
|
||||
|
||||
loclang = strtok(enumstate->tokstr, DELIM);
|
||||
if (enumstate->tokstr)
|
||||
{
|
||||
enumstate->tokstr = NULL;
|
||||
}
|
||||
|
||||
if (loclang != NULL)
|
||||
{
|
||||
if ((locdesc = GetLangName(loclang)) == NULL)
|
||||
{
|
||||
locdesc = loclang;
|
||||
}
|
||||
|
||||
*lang = strdup(loclang);
|
||||
*desc = strdup(locdesc);
|
||||
|
||||
rc = True;
|
||||
}
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* _enumLanglistEnd() - end enumeration of language names and descriptions
|
||||
*
|
||||
* Free memory.
|
||||
*/
|
||||
static void
|
||||
_enumLanglistEnd(
|
||||
void *state)
|
||||
{
|
||||
struct _enumState *enumstate = (struct _enumState *)state;
|
||||
|
||||
free(enumstate->dupstr);
|
||||
free((char *)state);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* Methods for language list
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
struct _enumObject
|
||||
{
|
||||
Boolean (*methodNext)();
|
||||
void (*methodEnd)();
|
||||
void *enumstate;
|
||||
};
|
||||
|
||||
/*
|
||||
* _enumLangStart() - start enumeration of languages and descriptions
|
||||
*
|
||||
* ENABLE_DYNAMIC_LANGLIST defined
|
||||
* Enumerate LANGLIST. If unsucessful, try 'LangCmd'. LANGLIST will only
|
||||
* be set if user specified Dtlogin*languageList.
|
||||
*
|
||||
* ENABLE_DYNAMIC_LANGLIST undefined
|
||||
* Enumerate LANGLIST.
|
||||
*
|
||||
*/
|
||||
static void *
|
||||
_enumLangStart(void)
|
||||
{
|
||||
char *p;
|
||||
struct _enumObject *state = malloc(sizeof(struct _enumObject));
|
||||
|
||||
if (state)
|
||||
{
|
||||
state->enumstate = _enumLanglistStart();
|
||||
if (state->enumstate != NULL)
|
||||
{
|
||||
state->methodNext = _enumLanglistNext;
|
||||
state->methodEnd = _enumLanglistEnd;
|
||||
}
|
||||
|
||||
#if defined (ENABLE_DYNAMIC_LANGLIST)
|
||||
if (state->enumstate == NULL)
|
||||
{
|
||||
state->enumstate = _enumLangCmdStart();
|
||||
if (state->enumstate != NULL)
|
||||
{
|
||||
state->methodNext = _enumLangCmdNext;
|
||||
state->methodEnd = _enumLangCmdEnd;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_DYNAMIC_LANGLIST */
|
||||
|
||||
if (state->enumstate == NULL)
|
||||
{
|
||||
free(state);
|
||||
state = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return((void *)state);
|
||||
}
|
||||
|
||||
/*
|
||||
* _enumLangNext() - get next language description pair
|
||||
* note: *lang and *desc must be freed by free()
|
||||
*/
|
||||
static Boolean
|
||||
_enumLangNext(
|
||||
void *state,
|
||||
char **lang,
|
||||
char **desc)
|
||||
{
|
||||
Boolean rc;
|
||||
struct _enumObject *object = (struct _enumObject *)state;
|
||||
|
||||
rc = (*object->methodNext)(object->enumstate, lang, desc);
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* _enumLangEnd() - end enumeration of language names and descriptions
|
||||
*/
|
||||
static void
|
||||
_enumLangEnd(
|
||||
void *state)
|
||||
{
|
||||
struct _enumObject *object = (struct _enumObject *)state;
|
||||
|
||||
(*object->methodEnd)(object->enumstate);
|
||||
|
||||
free((char *)state);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* MakeLangMenu
|
||||
*
|
||||
* Widgets: lang_menu
|
||||
*
|
||||
* The language menu contains the list of locales available to the
|
||||
* the desktop session. This may be a subset of the actual installed
|
||||
* locales. The list of locales to display in the language menu can
|
||||
* be provided by the sysadmin, or determined by the login manager.
|
||||
*
|
||||
* * Sysadmin provided language list
|
||||
*
|
||||
* A sysadmin can set the Dtlogin.languageList resource to set the list
|
||||
* of languages. The dtlogin process provides this list to dtgreet
|
||||
* in the LANGLIST environment variable. This has priority.
|
||||
*
|
||||
* * Login manager determined language list
|
||||
*
|
||||
* If the sysadm does not set Dtlogin.languageList, ie. LANGLIST unset,
|
||||
* the login manager will generate the list. There are two methods for
|
||||
* doing this, one of which is selected at compile time with the
|
||||
* ENABLE_DYNAMIC_LANGLIST define.
|
||||
*
|
||||
* * dynamic list (ENABLE_DYNAMIC_LANGLIST defined)
|
||||
*
|
||||
* This method executes the command specified by the
|
||||
* Dtlogin*languageListCmd resource. The default is
|
||||
* /usr/dt/bin/dtlslocale. The languageListCmd command is expected
|
||||
* to write to stdout a series of language names and descriptions:
|
||||
*
|
||||
* lang_name description
|
||||
* lang_name description
|
||||
* ...
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* En_US English (United States) - IBM-850
|
||||
* Fr_BE French (Belgium) - IBM-850
|
||||
*
|
||||
* Also, since languageListCmd is run under dtgreet's locale, a
|
||||
* localized description can be returned.
|
||||
*
|
||||
* * static list (ENABLE_DYNAMIC_LANGLIST undefined)
|
||||
*
|
||||
* This method has dtlogin querying the system and generating
|
||||
* the language list to be provided to dtgreet via the LANGLIST
|
||||
* environment variable. In this case dtlogin takes care to use the
|
||||
* sysadmin provided list if necessary.
|
||||
*
|
||||
* * Language descriptions
|
||||
*
|
||||
* The sysadmin can set the Dtlogin*<lang>.languageName resource to
|
||||
* provide a descriptive name for a particular language. If languageName
|
||||
* unset, the value used depends on ENABLE_DYNAMIC_LANGLIST. If
|
||||
* ENABLE_DYNAMIC_LANGLIST set, the value used is the descriptive text
|
||||
* provided by languageListCmd. If ENABLE_DYNAMIC_LANGLIST unset, the value
|
||||
* used is simply the locale name.
|
||||
*
|
||||
* * Default language
|
||||
*
|
||||
* The sysadmin can set the Dtlogin*language resource to specify the
|
||||
* default language in the language menu.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#define MAX_LANG_ITEMS 16 /* maximum number of items in one lang menu */
|
||||
#define MAX_NAME_LEN 128 /* maximum length of a language name */
|
||||
|
||||
struct Langlist {
|
||||
char *lang; /* lang name ie En_US, Ja_JP */
|
||||
char *desc; /* lang description ie English */
|
||||
};
|
||||
|
||||
/*
|
||||
* compareLangDesc() - compare language descriptions in qsort()
|
||||
*/
|
||||
static int
|
||||
compareLangDesc(
|
||||
const void *first,
|
||||
const void *second)
|
||||
{
|
||||
return(strcmp(((struct Langlist *)first)->desc,
|
||||
((struct Langlist *)second)->desc));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MakeLangMenu( void )
|
||||
{
|
||||
register int i, k;
|
||||
char cblab[MAX_NAME_LEN]; /* pushbutton label */
|
||||
int nlang; /* total number of languages */
|
||||
int nlangMenus; /* number of language sub-menus */
|
||||
int maxitems; /* max no. of items in sub-lang menu*/
|
||||
Widget item_menu;
|
||||
Widget button;
|
||||
char *tostr;
|
||||
|
||||
struct Langlist {
|
||||
char *lang; /* lang name ie En_US, Ja_JP */
|
||||
char *desc; /* lang description ie English */
|
||||
};
|
||||
|
||||
struct Langlist list[500];
|
||||
void *state;
|
||||
|
||||
/*
|
||||
* Generate list of langname/description pairs.
|
||||
*/
|
||||
nlang = 0;
|
||||
state = _enumLangStart();
|
||||
if (state)
|
||||
{
|
||||
while (_enumLangNext(state, &list[nlang].lang, &list[nlang].desc))
|
||||
{
|
||||
nlang++;
|
||||
}
|
||||
_enumLangEnd(state);
|
||||
}
|
||||
|
||||
if (nlang > 0) {
|
||||
|
||||
/*
|
||||
* Sort by description
|
||||
*/
|
||||
qsort((char *)list, nlang, sizeof(list[0]), compareLangDesc);
|
||||
|
||||
/*
|
||||
* determine number of language sub-menus ...
|
||||
* (MAX_LANG_ITEMS per menu)
|
||||
*/
|
||||
|
||||
nlangMenus = 0;
|
||||
do {
|
||||
nlangMenus++;
|
||||
maxitems = nlang/nlangMenus;
|
||||
} while ( maxitems > MAX_LANG_ITEMS );
|
||||
if (nlang%nlangMenus != 0) maxitems++; /* allow for stragglers */
|
||||
|
||||
|
||||
/*
|
||||
* build language menu(s)...
|
||||
*/
|
||||
i = 0;
|
||||
lang_menu = XmCreatePulldownMenu(options_menu, "lang_menu", argt, i);
|
||||
item_menu = lang_menu;
|
||||
|
||||
for (k = 0; k < nlang; k++) {
|
||||
|
||||
if ( nlangMenus > 1 && k%maxitems == 0) {
|
||||
i = 0;
|
||||
item_menu = XmCreatePulldownMenu(lang_menu, "item_menu",
|
||||
argt, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* build toggle buttons...
|
||||
*/
|
||||
i = InitArg(ToggleBG);
|
||||
XtSetArg(argt[i], XmNrecomputeSize, True ); i++;
|
||||
if (langenv && (strcmp(langenv, list[k].lang) == 0)) {
|
||||
XtSetArg(argt[i], XmNset, True ); i++;
|
||||
}
|
||||
|
||||
xmstr = XmStringCreateLocalized(list[k].desc);
|
||||
XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
|
||||
|
||||
button = XmCreateToggleButtonGadget(
|
||||
item_menu, list[k].lang, argt, i);
|
||||
XtAddCallback (button, XmNvalueChangedCallback,
|
||||
RespondLangCB, (XtPointer) list[k].lang);
|
||||
XmStringFree(xmstr);
|
||||
|
||||
XtManageChild(button);
|
||||
tostr =
|
||||
(char*) ReadCatalog(MC_LABEL_SET, MC_TO_LABEL, MC_DEF_TO_LABEL);
|
||||
|
||||
if ( nlangMenus > 1 && k%maxitems == 0 ) {
|
||||
int first = k;
|
||||
int last = k+maxitems >= nlang ? nlang-1 : k+maxitems-1;
|
||||
|
||||
i = InitArg(CascadeBG);
|
||||
|
||||
sprintf(cblab, "%s %s %s",
|
||||
list[first].desc, tostr, list[last].desc);
|
||||
|
||||
xmstr = XmStringCreateLocalized(cblab);
|
||||
XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
|
||||
XtSetArg(argt[i], XmNsubMenuId, item_menu ); i++;
|
||||
XtSetArg(argt[i], XmNrecomputeSize, True ); i++;
|
||||
button = XmCreateCascadeButtonGadget(lang_menu, cblab, argt, i);
|
||||
XtManageChild(button);
|
||||
XmStringFree(xmstr);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Free language list
|
||||
*/
|
||||
for (k = 0; k < nlang; k++)
|
||||
{
|
||||
/* free(list[k].lang); -- used as callback data, don't free */
|
||||
free(list[k].desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user