2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: I18nEnv.c /main/4 1997/08/11 12:31:10 samborn $ */
25 * (c) Copyright 1996 Digital Equipment Corporation.
26 * (c) Copyright 1996 Hewlett-Packard Company.
27 * (c) Copyright 1996 International Business Machines Corp.
28 * (c) Copyright 1996 Sun Microsystems, Inc.
29 * (c) Copyright 1996 Novell, Inc.
30 * (c) Copyright 1996 FUJITSU LIMITED.
31 * (c) Copyright 1996 Hitachi.
33 /************************************<+>*************************************
34 ****************************************************************************
38 ** Description: Controls the Dtstyle I18N component interaction with
42 ****************************************************************************
43 ************************************<+>*************************************/
45 /*+++++++++++++++++++++++++++++++++++++++*/
47 /*+++++++++++++++++++++++++++++++++++++++*/
51 #include <X11/Intrinsic.h>
53 #include <DtHelp/LocaleXlate.h> /* for locale equivalence between platforms */
58 /*+++++++++++++++++++++++++++++++++++++++*/
59 /* include extern functions */
60 /*+++++++++++++++++++++++++++++++++++++++*/
62 /*+++++++++++++++++++++++++++++++++++++++*/
64 /*+++++++++++++++++++++++++++++++++++++++*/
67 /*+++++++++++++++++++++++++++++++++++++++*/
68 /* Internal Functions */
69 /*+++++++++++++++++++++++++++++++++++++++*/
71 static int GetUserEnv(I18nEnv *env);
72 static int FindCDELocaleName(UserEnv *uenv);
73 static int GetUserIMSelectionFile(I18nEnv *env);
74 static int GetUserFileName(I18nEnv *env);
75 static int ReadImSelectionFile(FileSel *fsel, FILE *fp);
76 static int GetImsList(I18nEnv *env, char *hostname);
77 static void TimeOutProc(XtPointer client_data, XtIntervalId* timer);
78 static void ReadPipe(XtPointer client_data, int *fd, XtInputId *id);
79 static int ProcessBuf(char *savebuf, I18nEnv *env);
80 static int CheckHostname(I18nEnv *env, char *hostname);
81 static void PutSelectMode(FILE *fp, int start_mode);
82 static void PutImsName(FILE *fp, char *im_name);
83 static void PutHostname(FILE *fp, char *hostname);
84 static void PutSelectionEntry(FILE *fp, char *tag, char *value);
87 /*+++++++++++++++++++++++++++++++++++++++*/
88 /* Internal Variables */
89 /*+++++++++++++++++++++++++++++++++++++++*/
91 /*+++++++++++++++++++++++++++++++++++++++*/
92 /* Global Variables */
93 /*+++++++++++++++++++++++++++++++++++++++*/
98 /*+++++++++++++++++++++++++++++++++++++++*/
100 /*+++++++++++++++++++++++++++++++++++++++*/
102 #ifdef NEED_STRCASECMP
104 * In case strcasecmp is not provided by the system here is one
105 * which does the trick.
108 strcasecmp(register const char *s1,
109 register const char *s2)
114 c1 = isupper(*s1) ? tolower(*s1) : *s1;
115 c2 = isupper(*s2) ? tolower(*s2) : *s2;
121 return (int) (*s1 - *s2);
126 /*+++++++++++++++++++++++++++++++++++++++*/
127 /* _DtI18nGetEnvValues */
128 /*+++++++++++++++++++++++++++++++++++++++*/
137 /* Get the user environment */
138 env->user_env = (UserEnv *) XtMalloc(sizeof(UserEnv));
139 ret = GetUserEnv(env);
141 /* Get the user selection stored in the IM Selection File */
142 if (ret == NoError) {
143 env->file_sel = (FileSel *) XtMalloc(sizeof(FileSel));
144 ret = GetUserIMSelectionFile(env);
147 /* Alloc the user selection */
148 env->ims_sel = (ImsSel *) XtMalloc(sizeof(ImsSel));
149 env->ims_sel->ims_list = NULL;
150 env->ims_sel->ims_list_size = 0 ;
151 env->ims_sel->host_name = NULL ;
153 /* Get the Input Method available on the selected host.
154 * The selected host is the one stored in the IMS Selection File.
157 ret = _DtI18nGetImList(env, env->file_sel->hostname);
162 /*+++++++++++++++++++++++++++++++++++++++*/
164 /*+++++++++++++++++++++++++++++++++++++++*/
170 UserEnv *uenv = env->user_env ;
172 char buf[BUFSIZ], *p;
174 /* get the host name */
175 gethostname(buf, BUFSIZ);
176 uenv->localhostname = XtNewString(buf);
178 /* get the user name */
179 if ((p = getlogin()) == NULL) {
182 pw = getpwuid(getuid());
186 uenv->username = XtNewString(p);
188 /* get the display name */
189 uenv->displayname = XtNewString(XDisplayString(XtDisplay(env->shell)));
192 if ((p = getenv("LANG")) && *p)
193 uenv->locale = XtNewString(p);
197 /* find the CDE generic locale name */
198 if (FindCDELocaleName(uenv) != NoError)
199 return ErrNoCDELocale;
201 /* get the home directory */
202 if ((p = getenv("HOME")) && *p)
203 uenv->homedir = XtNewString(p);
215 _DtXlateDb db = NULL;
217 char plat[_DtPLATFORM_MAX_LEN];
221 ret = _DtLcxOpenAllDbs(&db);
224 ret = _DtXlateGetXlateEnv(db, plat, &execver, &compver);
227 ret = _DtLcxXlateOpToStd(db, plat, compver, DtLCX_OPER_SETLOCALE,
228 uenv->locale, &uenv->CDE_locale,
231 ret = _DtLcxCloseDb(&db);
237 GetUserIMSelectionFile(
244 ret = GetUserFileName(env);
246 if (ret == NoError) {
247 /* Look if this file is readable */
248 if ((fp = fopen(env->file_sel->fname, "r")) == NULL) {
249 env->file_sel->start_mode = -1;
250 return ErrNoSelectionFile;
254 start_tag_line(env->file_sel->fname);
255 ret = ReadImSelectionFile(env->file_sel, fp);
265 int status, ret = NoError;
266 char *path, *tmp_path;
270 /* The user IMS Selection File should be of the following form:
271 * $HOME/.dt/ims/[display-name]/CDE-locale
274 path = (char *) XtMalloc((MAXPATHLEN + 1) * sizeof(char));
276 strcpy(path, env->user_env->homedir);
277 strcat(path, DtUSER_IMSFS_DIR);
279 /* Look if there is a display specific directory */
281 tmp_path = (char *) XtMalloc((MAXPATHLEN + 1) * sizeof(char));
283 strcpy(tmp_path, path);
284 strcat(tmp_path, "/");
285 strcat(tmp_path, env->user_env->displayname);
287 if ((status = stat (tmp_path, &buf)) == 0) {
289 strcat(path, env->user_env->displayname);
294 /* Now add the CDE-specific locale name */
297 strcat(path, env->user_env->CDE_locale);
299 env->file_sel->fname = path;
311 char *lp, *valp, *vp, *p;
313 char *imsname, *hostname;
316 imsname = hostname = NULL;
318 while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
322 if (lp[0] != STR_PREFIX_CHAR) {
325 if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
326 if (str_to_int(valp, &i) && i >= 0) {
329 } else if (strncmp(lp + 1, STR_IMSNAME, 4) == 0) {
330 vp = valp; cut_field(valp);
333 imsname = XtNewString(vp);
335 } else if (strncmp(lp + 1, STR_HOSTNAME, 4) == 0) {
336 vp = valp; cut_field(valp);
339 if (strcmp(vp, NAME_LOCAL)) {
340 hostname = XtNewString(vp);
346 fsel->im_name = imsname;
347 fsel->hostname = hostname;
348 fsel->start_mode = select_mode;
360 int host_type = HOST_LOCAL;
363 host_type = CheckHostname(env, hostname);
367 ret = ErrUnknownHost;
371 /* Put the host name in the ImsSel structure */
372 env->ims_sel->host_name = hostname;
373 ret = GetImsList(env, hostname);
377 if (hostname && strcasecmp(hostname, "local") != 0)
378 env->ims_sel->host_name = hostname;
379 ret = GetImsList(env, env->user_env->localhostname);
393 char pipe_command[255];
396 unsigned long timeout;
398 /* First check if dtimsstart is installed correctly */
400 if ((ret = stat ("/usr/dt/bin/dtimsstart", &buf)) != NoError) {
401 return ErrNoDtimsstart;
404 sprintf(pipe_command, "/usr/dt/bin/dtimsstart -listname -hostname %s",
407 if (fp = popen(pipe_command, "r")) {
409 /* Set the sensitivity of the InputMethod Title Box to False until we
410 * are done reading the new information. */
411 _DtI18nSetSensitiveImTB(env, False);
413 /* Initialize the pipe record. */
414 if (!(env->pipe_info))
415 env->pipe_info = (PipeRec *) XtMalloc(sizeof(PipeRec));
417 env->pipe_info->pipe = fp; /* to close it */
418 env->pipe_info->input_id = /* to remove it */
419 XtAppAddInput (XtWidgetToApplicationContext(env->shell),
420 fileno(fp), (XtPointer) XtInputReadMask,
421 ReadPipe, (XtPointer) env);
423 /* Also add a timeout in case the pipe ain't talk */
424 timeout = (unsigned long) (style.xrdb.pipeTimeOut) * 1000;
425 env->pipe_info->timer_id =
426 XtAppAddTimeOut(XtWidgetToApplicationContext(env->shell),
427 timeout, TimeOutProc, (XtPointer)env);
435 static void TimeOutProc (XtPointer client_data,
438 I18nEnv *env = (I18nEnv *) client_data;
440 /* the command is not fast enough, but calling pclose blocks
441 and then print "Broken Pipe". I need to kill the child somehow
442 pclose(env->pipe_info->pipe);*/
444 XtRemoveInput(env->pipe_info->input_id);
446 /* Set the sensitivity of the InputMethod Title Box back to True. */
447 _DtI18nSetSensitiveImTB(env, True);
449 _DtI18nErrorDialog(ErrTimeOut) ;
454 XtPointer client_data,
461 int status = NoError;
462 static char * savebuf = NULL;
463 static int savebuf_bytes = 0 ;
464 I18nEnv *env = (I18nEnv *) client_data;
466 nbytes = read (*fd, buf, 512);
469 savebuf = XtRealloc(savebuf, savebuf_bytes + nbytes);
470 memcpy(savebuf+savebuf_bytes, buf, nbytes);
471 savebuf_bytes += nbytes ;
474 *(savebuf + savebuf_bytes) = '\0';
475 status = ProcessBuf(savebuf, client_data);
482 pclose(env->pipe_info->pipe);
485 /* Set the sensitivity of the InputMethod Title Box back to True. */
486 _DtI18nSetSensitiveImTB(env, True);
488 /* Remove timer too */
489 XtRemoveTimeOut(env->pipe_info->timer_id);
491 if (status != NoError)
492 _DtI18nErrorDialog(status) ;
505 char * filename, * label ;
507 /* The dtimsstart execution gave back an empty buffer */
509 return(ErrRemoteFailed);
511 /* parse savebuf: The lines have the following syntax:
512 * [#](im_filename) im_label or
513 * [#]im_filename im_label
514 * where "#" if present means the default IM,
515 * im_filename is the file name where all the IM info is stored,
516 * im_label is the label to present to the user.
519 /* We're at the beginning of a new line */
522 env->ims_sel->ims_list =
523 (ImsEnt *) XtRealloc((char *) env->ims_sel->ims_list,
524 sizeof(ImsEnt)*(n+1));
526 ims_ent = &(env->ims_sel->ims_list[n]);
528 /* Look to see if this is the default one. */
529 if (*savebuf == '#') {
530 ims_ent->im_default = 1;
533 ims_ent->im_default = 0;
535 /* Look to see if it is not reachable. */
536 if (*savebuf == '(') {
537 ims_ent->inactive = 1;
540 ims_ent->inactive = 0 ;
542 /* Mark begin of im filename */
544 /* Go to the end of it */
545 while (!isspace(*savebuf++)) ;
546 /* We're on the first space, mark the end of the im filename,
547 * don't forget to count the ')' if inactive. */
548 *(savebuf - ims_ent->inactive - 1) = '\0';
550 /* Mark the beginning of the im name */
552 while (*savebuf != '\n') savebuf++ ;
557 /* copy the string data here. it's gonna be freed after that */
558 ims_ent->im_name = XtNewString(filename) ;
559 ims_ent->im_label = XtNewString(label) ;
563 env->ims_sel->ims_list_size = n;
575 int host_type = HOST_UNKNOWN;
576 char *local = env->user_env->localhostname;
578 unsigned long addr = 0L;
579 static unsigned long local_addr = 0L;
581 if (!hostname || !*hostname || strcasecmp(hostname, "local") == 0
582 || strcasecmp(hostname, local) == 0) {
583 host_type = HOST_LOCAL;
584 } else { /* compare inet address */
586 if ((hp = gethostbyname(local)) && hp->h_addrtype == AF_INET) {
587 local_addr = *((unsigned long *) hp->h_addr_list[0]);
589 host_type = HOST_REMOTE;
592 if (host_type == HOST_UNKNOWN) {
593 if ((hp = gethostbyname(hostname)) && hp->h_addrtype == AF_INET) {
594 addr = *((unsigned long *) hp->h_addr_list[0]);
595 if (addr == local_addr)
596 host_type = HOST_LOCAL;
598 host_type = HOST_REMOTE;
600 host_type = HOST_UNKNOWN;
609 /*+++++++++++++++++++++++++++++++++++++++*/
610 /* _DtI18nWriteImSelectionFile - writes */
611 /* the values saved in the FileSel */
612 /* structure to the IMS Selection File. */
613 /*+++++++++++++++++++++++++++++++++++++++*/
615 _DtI18nWriteImSelectionFile(
622 /* Look if this file is writable */
623 if ((fp = fopen(env->file_sel->fname, "w")) == NULL)
624 return ErrFileCreate;
626 /* Write the select mode */
627 PutSelectMode(fp, env->file_sel->start_mode);
629 /* Write the IM selected if not null */
630 PutImsName(fp, env->file_sel->im_name);
632 /* Write the hostname if not null */
633 PutHostname(fp, env->file_sel->hostname);
649 sprintf(val, "%ld", (long)start_mode);
650 PutSelectionEntry(fp, STR_SELECTMODE, val);
661 if ((valp = im_name) && *valp)
662 PutSelectionEntry(fp, STR_IMSNAME, valp);
673 if ((valp = hostname) && *valp)
674 PutSelectionEntry(fp, STR_HOSTNAME, valp);
685 fprintf(fp, "%c%s%c\t%s\n", STR_PREFIX_CHAR, tag, TAG_END_CHAR, value);