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 librararies 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;
253 start_tag_line(env->file_sel->fname);
254 ret = ReadImSelectionFile(env->file_sel, fp);
264 int status, ret = NoError;
265 char *path, *tmp_path;
269 /* The user IMS Selection File should be of the following form:
270 * $HOME/.dt/ims/[display-name]/CDE-locale
273 path = (char *) XtMalloc((MAXPATHLEN + 1) * sizeof(char));
275 strcpy(path, env->user_env->homedir);
276 strcat(path, DtUSER_IMSFS_DIR);
278 /* Look if there is a display specific directory */
280 tmp_path = (char *) XtMalloc((MAXPATHLEN + 1) * sizeof(char));
282 strcpy(tmp_path, path);
283 strcat(tmp_path, "/");
284 strcat(tmp_path, env->user_env->displayname);
286 if ((status = stat (tmp_path, &buf)) == 0) {
288 strcat(path, env->user_env->displayname);
293 /* Now add the CDE-specific locale name */
296 strcat(path, env->user_env->CDE_locale);
298 env->file_sel->fname = path;
310 char *lp, *valp, *vp, *p;
312 char *imsname, *hostname;
315 imsname = hostname = NULL;
317 while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
321 if (lp[0] != STR_PREFIX_CHAR) {
324 if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
325 if (str_to_int(valp, &i) && i >= 0)
327 } else if (strncmp(lp + 1, STR_IMSNAME, 4) == 0) {
328 vp = valp; cut_field(valp);
331 imsname = XtNewString(vp);
333 } else if (strncmp(lp + 1, STR_HOSTNAME, 4) == 0) {
334 vp = valp; cut_field(valp);
337 if (strcmp(vp, NAME_LOCAL))
338 hostname = XtNewString(vp);
343 fsel->im_name = imsname;
344 fsel->hostname = hostname;
345 fsel->start_mode = select_mode;
357 int host_type = HOST_LOCAL;
360 host_type = CheckHostname(env, hostname);
364 ret = ErrUnknownHost;
368 /* Put the host name in the ImsSel structure */
369 env->ims_sel->host_name = hostname;
370 ret = GetImsList(env, hostname);
374 if (hostname && strcasecmp(hostname, "local") != 0)
375 env->ims_sel->host_name = hostname;
376 ret = GetImsList(env, env->user_env->localhostname);
390 char pipe_command[255];
393 unsigned long timeout;
395 /* First check if dtimsstart is installed correctly */
397 if ((ret = stat ("/usr/dt/bin/dtimsstart", &buf)) != NoError) {
398 return ErrNoDtimsstart;
401 sprintf(pipe_command, "/usr/dt/bin/dtimsstart -listname -hostname %s",
404 if (fp = popen(pipe_command, "r")) {
406 /* Set the sensitivity of the InputMethod Title Box to False until we
407 * are done reading the new information. */
408 _DtI18nSetSensitiveImTB(env, False);
410 /* Initialize the pipe record. */
411 if (!(env->pipe_info))
412 env->pipe_info = (PipeRec *) XtMalloc(sizeof(PipeRec));
414 env->pipe_info->pipe = fp; /* to close it */
415 env->pipe_info->input_id = /* to remove it */
416 XtAppAddInput (XtWidgetToApplicationContext(env->shell),
417 fileno(fp), (XtPointer) XtInputReadMask,
418 ReadPipe, (XtPointer) env);
420 /* Also add a timeout in case the pipe ain't talk */
421 timeout = (unsigned long) (style.xrdb.pipeTimeOut) * 1000;
422 env->pipe_info->timer_id =
423 XtAppAddTimeOut(XtWidgetToApplicationContext(env->shell),
424 timeout, TimeOutProc, (XtPointer)env);
432 static void TimeOutProc (XtPointer client_data,
435 I18nEnv *env = (I18nEnv *) client_data;
437 /* the command is not fast enough, but calling pclose blocks
438 and then print "Broken Pipe". I need to kill the child somehow
439 pclose(env->pipe_info->pipe);*/
441 XtRemoveInput(env->pipe_info->input_id);
443 /* Set the sensitivity of the InputMethod Title Box back to True. */
444 _DtI18nSetSensitiveImTB(env, True);
446 _DtI18nErrorDialog(ErrTimeOut) ;
451 XtPointer client_data,
458 int status = NoError;
459 static char * savebuf = NULL;
460 static int savebuf_bytes = 0 ;
461 I18nEnv *env = (I18nEnv *) client_data;
463 nbytes = read (*fd, buf, 512);
466 savebuf = XtRealloc(savebuf, savebuf_bytes + nbytes);
467 memcpy(savebuf+savebuf_bytes, buf, nbytes);
468 savebuf_bytes += nbytes ;
471 *(savebuf + savebuf_bytes) = '\0';
472 status = ProcessBuf(savebuf, client_data);
479 pclose(env->pipe_info->pipe);
482 /* Set the sensitivity of the InputMethod Title Box back to True. */
483 _DtI18nSetSensitiveImTB(env, True);
485 /* Remove timer too */
486 XtRemoveTimeOut(env->pipe_info->timer_id);
488 if (status != NoError)
489 _DtI18nErrorDialog(status) ;
502 char * filename, * label ;
504 /* The dtimsstart execution gave back an empty buffer */
506 return(ErrRemoteFailed);
508 /* parse savebuf: The lines have the following syntax:
509 * [#](im_filename) im_label or
510 * [#]im_filename im_label
511 * where "#" if present means the default IM,
512 * im_filename is the file name where all the IM info is stored,
513 * im_label is the label to present to the user.
516 /* We're at the beginning of a new line */
519 env->ims_sel->ims_list =
520 (ImsEnt *) XtRealloc((char *) env->ims_sel->ims_list,
521 sizeof(ImsEnt)*(n+1));
523 ims_ent = &(env->ims_sel->ims_list[n]);
525 /* Look to see if this is the default one. */
526 if (*savebuf == '#') {
527 ims_ent->im_default = 1;
530 ims_ent->im_default = 0;
532 /* Look to see if it is not reachable. */
533 if (*savebuf == '(') {
534 ims_ent->inactive = 1;
537 ims_ent->inactive = 0 ;
539 /* Mark begin of im filename */
541 /* Go to the end of it */
542 while (!isspace(*savebuf++)) ;
543 /* We're on the first space, mark the end of the im filename,
544 * don't forget to count the ')' if inactive. */
545 *(savebuf - ims_ent->inactive - 1) = '\0';
547 /* Mark the beginning of the im name */
549 while (*savebuf != '\n') savebuf++ ;
554 /* copy the string data here. it's gonna be freed after that */
555 ims_ent->im_name = XtNewString(filename) ;
556 ims_ent->im_label = XtNewString(label) ;
560 env->ims_sel->ims_list_size = n;
572 int host_type = HOST_UNKNOWN;
573 char *local = env->user_env->localhostname;
575 unsigned long addr = 0L;
576 static unsigned long local_addr = 0L;
578 if (!hostname || !*hostname || strcasecmp(hostname, "local") == 0
579 || strcasecmp(hostname, local) == 0) {
580 host_type = HOST_LOCAL;
581 } else { /* compare inet address */
583 if ((hp = gethostbyname(local)) && hp->h_addrtype == AF_INET) {
584 local_addr = *((unsigned long *) hp->h_addr_list[0]);
586 host_type = HOST_REMOTE;
589 if (host_type == HOST_UNKNOWN) {
590 if ((hp = gethostbyname(hostname)) && hp->h_addrtype == AF_INET) {
591 addr = *((unsigned long *) hp->h_addr_list[0]);
592 if (addr == local_addr)
593 host_type = HOST_LOCAL;
595 host_type = HOST_REMOTE;
597 host_type = HOST_UNKNOWN;
606 /*+++++++++++++++++++++++++++++++++++++++*/
607 /* _DtI18nWriteImSelectionFile - writes */
608 /* the values saved in the FileSel */
609 /* structure to the IMS Selection File. */
610 /*+++++++++++++++++++++++++++++++++++++++*/
612 _DtI18nWriteImSelectionFile(
619 /* Look if this file is writable */
620 if ((fp = fopen(env->file_sel->fname, "w")) == NULL)
621 return ErrFileCreate;
623 /* Write the select mode */
624 PutSelectMode(fp, env->file_sel->start_mode);
626 /* Write the IM selected if not null */
627 PutImsName(fp, env->file_sel->im_name);
629 /* Write the hostname if not null */
630 PutHostname(fp, env->file_sel->hostname);
644 sprintf(val, "%ld", (long)start_mode);
645 PutSelectionEntry(fp, STR_SELECTMODE, val);
656 if ((valp = im_name) && *valp)
657 PutSelectionEntry(fp, STR_IMSNAME, valp);
668 if ((valp = hostname) && *valp)
669 PutSelectionEntry(fp, STR_HOSTNAME, valp);
680 fprintf(fp, "%c%s%c\t%s\n", STR_PREFIX_CHAR, tag, TAG_END_CHAR, value);