1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
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)
10 * any later version.
11 *
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
16 * details.
17 *
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
22 */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27
28 #ifdef REV_INFO
29 #ifndef lint
30 static char rcsid[] = "$TOG: Xmos.c /main/33 1998/01/21 11:07:25 csn $"
31 #endif
32 #endif
33
34 #include <stdio.h>
35
36 #ifdef __cplusplus
37 extern "C" { /* some 'locale.h' do not have prototypes (sun) */
38 #endif
39 #include <X11/Xlocale.h>
40 #ifdef __cplusplus
41 } /* Close scope of 'extern "C"' declaration */
42 #endif /* __cplusplus */
43
44 #include <X11/Xos.h>
45 #ifndef NEED_XPOLL_H
46 #include <X11/Xpoll.h>
47 #else
48 #include <Xm/Xmpoll.h>
49 #endif
50
51 #ifndef X_NOT_STDC_ENV
52 #include <stdlib.h>
53 #include <unistd.h>
54 #endif
55
56 #include <ctype.h> /* for isspace() */
57
58 #include <sys/time.h> /* For declaration of select(). */
59
60 #if defined(NO_REGCOMP) && !defined(NO_REGEX)
61 # ifdef __sgi
62 extern char *regcmp();
63 extern int regex();
64 # elif defined(SVR4)
65 # include <libgen.h>
66 # elif defined(SYSV)
67 extern char *regcmp();
68 extern int regex();
69 # endif
70 #endif /* NO_REGEX */
71
72 #ifndef NO_REGCOMP
73 # include <regex.h>
74 #endif /* NO_REGCOMP */
75
76 #include <sys/stat.h>
77
78 #define X_INCLUDE_PWD_H
79 #define X_INCLUDE_DIRENT_H
80 #define XOS_USE_XT_LOCKING
81
82 #ifndef NEED_XOS_R_H
83 #include <X11/Xos_r.h>
84 #else
85 #include <Xm/Xmos_r.h>
86 #endif
87
88 #include "XmosI.h"
89 #include "XmI.h"
90
91 #ifdef USE_GETWD
92 # include <sys/param.h>
93 # define MAX_DIR_PATH_LEN MAXPATHLEN
94 # define getcwd(buf, len) ((char *) getwd(buf))
95 #else
96 # define MAX_DIR_PATH_LEN 1024
97 #endif
98 #define MAX_USER_NAME_LEN 256
99
100 #ifndef S_ISDIR
101 # define S_ISDIR(m) ((m & S_IFMT)==S_IFDIR)
102 #endif
103
104 #ifndef S_ISREG
105 # define S_ISREG(m) ((m & S_IFMT)==S_IFREG)
106 #endif
107
108 #define FILE_LIST_BLOCK 64
109
110 typedef struct {
111 unsigned char type ;
112 char file_name[1] ; /* Must be last entry in structure. */
113 } XmDirCacheRec, **XmDirCache ;
114
115
116 /********
117 * Set defaults for resources that are implementation dependant
118 * and may be modified.
119 ********/
120
121 externaldef(xmos) char _XmSDEFAULT_FONT[] = "fixed";
122 externaldef(xmos) char _XmSDEFAULT_BACKGROUND[] = "#c4c4c4";
123
124 /**************** end of vendor dependant defaults ********/
125
126 /******** Static Function Declarations ********/
127
128 static String GetCurrentDir(String buf);
129 static String GetQualifiedDir(String dirSpec);
130 static String GetFixedMatchPattern(String pattern);
131 static void FreeDirCache(void);
132 static void ResetCache(char *qDirName);
133 static unsigned char AddEntryToCache(char *entryName, unsigned entryNameLen);
134 static int Wcslen(wchar_t *wcs);
135
136 /******** End Static Function Declarations ********/
137
138 static char *dirCacheName;
139 static unsigned dirCacheNameLen;
140 static XmDirCache dirCache;
141 static unsigned numCacheAlloc;
142 static unsigned numCacheEntries;
143
144 static void
FreeDirCache(void)145 FreeDirCache(void)
146 {
147 if (dirCacheName != NULL)
148 {
149 XtFree(dirCacheName);
150 dirCacheName = NULL;
151 dirCacheNameLen = 0;
152
153 while (numCacheEntries)
154 XtFree((char *) dirCache[--numCacheEntries]);
155 }
156 }
157
158 static void
ResetCache(char * qDirName)159 ResetCache(char *qDirName)
160 {
161 FreeDirCache();
162
163 dirCacheNameLen = strlen(qDirName);
164 dirCacheName = XtMalloc(dirCacheNameLen + MAX_USER_NAME_LEN + 1);
165 strcpy(dirCacheName, qDirName);
166 }
167
168 static unsigned char
AddEntryToCache(char * entryName,unsigned entryNameLen)169 AddEntryToCache(char *entryName,
170 unsigned entryNameLen)
171 {
172 struct stat statBuf;
173 unsigned char result = 0;
174
175 if (numCacheEntries == numCacheAlloc)
176 {
177 numCacheAlloc += FILE_LIST_BLOCK;
178 dirCache = (XmDirCache)
179 XtRealloc((char *) dirCache, numCacheAlloc * sizeof(XmDirCacheRec *));
180 }
181
182 dirCache[numCacheEntries] = (XmDirCacheRec *)
183 XtMalloc(sizeof(XmDirCacheRec) + entryNameLen);
184 strcpy(dirCache[numCacheEntries]->file_name, entryName);
185
186 /* Use dirCacheName character array as temporary buffer for full file name.*/
187 strcpy(&dirCacheName[dirCacheNameLen], entryName);
188
189 if (!stat(dirCacheName, &statBuf))
190 {
191 if (S_ISREG(statBuf.st_mode))
192 result = XmFILE_REGULAR;
193 else if (S_ISDIR(statBuf.st_mode))
194 result = XmFILE_DIRECTORY;
195 }
196
197 /* Restore to dir path only. */
198 dirCacheName[dirCacheNameLen] = '\0';
199
200 dirCache[numCacheEntries++]->type = result;
201 return result;
202 }
203
204 /****************************************************************/
205 static String
GetQualifiedDir(String dirSpec)206 GetQualifiedDir(String dirSpec)
207 /*************GENERAL:
208 * dirSpec is a directory name, that can contain relative
209 * as well as logical reference. This routine resolves all these
210 * references, so that dirSpec is now suitable for open().
211 * The routine allocates memory for the result, which is guaranteed to be
212 * of length >= 1. This memory should eventually be freed using XtFree().
213 ****************/
214
215 /*************UNIX:
216 * Builds directory name showing descriptive path components. The result
217 * is a directory path beginning at the root directory and terminated
218 * with a '/'. The path will not contain ".", "..", or "~" components.
219 ****************/
220 {
221 int dirSpecLen;
222 _Xgetpwparams pwd_buf;
223 struct passwd * pwd_value;
224
225 char * userDir;
226 int userDirLen;
227 int userNameLen;
228 char * outputBuf;
229 char * destPtr;
230 char * srcPtr;
231 char * scanPtr;
232 char nameBuf[MAX_USER_NAME_LEN];
233 char dirbuf[MAX_DIR_PATH_LEN];
234
235 dirSpecLen = strlen(dirSpec);
236 outputBuf = NULL;
237
238 switch (*dirSpec)
239 {
240 case '~':
241 if (!(dirSpec[1]) || (dirSpec[1] == '/'))
242 {
243 userDir = XmeGetHomeDirName();
244 if (*userDir)
245 {
246 userDirLen = strlen(userDir);
247 outputBuf = XtMalloc(userDirLen + dirSpecLen + 2);
248 strcpy(outputBuf, userDir);
249 strcpy(&outputBuf[userDirLen], (dirSpec + 1));
250 }
251 }
252 else
253 {
254 destPtr = nameBuf;
255 userNameLen = 0;
256 srcPtr = dirSpec + 1;
257 while (*srcPtr && (*srcPtr != '/') &&
258 (++userNameLen < MAX_USER_NAME_LEN))
259 {
260 *destPtr++ = *srcPtr++;
261 }
262 *destPtr = '\0';
263
264 pwd_value = _XGetpwnam(nameBuf, pwd_buf);
265 if (pwd_value != NULL)
266 {
267 userDirLen = strlen(pwd_value->pw_dir);
268 dirSpecLen = strlen(srcPtr);
269 outputBuf = XtMalloc(userDirLen + dirSpecLen + 2);
270 strcpy(outputBuf, pwd_value->pw_dir);
271 strcpy(&outputBuf[userDirLen], srcPtr);
272 }
273 }
274 break;
275
276 case '/':
277 outputBuf = XtMalloc(dirSpecLen + 2);
278 strcpy(outputBuf, dirSpec);
279 break;
280
281 default:
282 if ((destPtr = GetCurrentDir(dirbuf)) != NULL)
283 {
284 userDirLen = strlen(destPtr);
285 outputBuf = XtMalloc(userDirLen + dirSpecLen + 3);
286 strcpy(outputBuf, destPtr);
287 outputBuf[userDirLen++] = '/';
288 strcpy(&outputBuf[userDirLen], dirSpec);
289 }
290 break;
291 }
292
293 if (!outputBuf)
294 {
295 outputBuf = XtMalloc(2);
296 outputBuf[0] = '/';
297 outputBuf[1] = '\0';
298 }
299 else
300 {
301 userDirLen = strlen(outputBuf);
302 if (outputBuf[userDirLen - 1] != '/')
303 {
304 outputBuf[userDirLen] = '/';
305 outputBuf[++userDirLen] = '\0';
306 }
307 /* The string in outputBuf is assumed to begin and end with a '/'. */
308 scanPtr = outputBuf;
309 while (*++scanPtr) /* Skip past '/'. */
310 {
311 /* scanPtr now points to non-NULL character following '/'. */
312 if (scanPtr[0] == '.')
313 {
314 if (scanPtr[1] == '/')
315 {
316 /* Have "./", so just erase (overwrite with shift).
317 */
318 destPtr = scanPtr;
319 srcPtr = &scanPtr[2];
320 while ((*destPtr++ = *srcPtr++) != '\0')
321 /*EMPTY*/;
322 --scanPtr; /* Leave scanPtr at preceding '/'. */
323 continue;
324 }
325 else
326 {
327 if ((scanPtr[1] == '.') && (scanPtr[2] == '/'))
328 {
329 /* Have "../", so back up one directory. */
330 srcPtr = &scanPtr[2];
331 --scanPtr; /* Move scanPtr to preceding '/'.*/
332 if (scanPtr != outputBuf)
333 {
334 while ((*--scanPtr != '/'))
335 /*EMPTY*/; /* Now move to previous '/'.*/
336 }
337 destPtr = scanPtr;
338 while ((*++destPtr = *++srcPtr) != '\0')
339 /*EMPTY*/; /* Overwrite "../" with shift.*/
340 continue;
341 }
342 }
343 }
344 else
345 {
346 /* Check for embedded "//". Posix allows a leading double
347 * slash (and Apollos require it).
348 */
349 if (*scanPtr == '/')
350 {
351 if ((scanPtr > (outputBuf + 1)) ||
352 (scanPtr[1] == '/'))
353 {
354 /* Have embedded "//" (other than root specification),
355 * so erase with shift and reset scanPtr.
356 */
357 srcPtr = scanPtr;
358 --scanPtr;
359 destPtr = scanPtr;
360 while ((*++destPtr = *++srcPtr) != '\0')
361 /*EMPTY*/;
362 }
363 continue;
364 }
365 }
366 while (*++scanPtr != '/')
367 /*EMPTY*/;
368 }
369 }
370
371 return outputBuf;
372 }
373
374 /****************************************************************/
375 String
_XmOSFindPatternPart(String fileSpec)376 _XmOSFindPatternPart(String fileSpec)
377 /****************GENERAL:
378 * fileSpec is made of a directory part and a pattern part.
379 * Returns the pointer to the first character of the pattern part
380 ****************/
381
382 /****************UNIX:
383 * Returns the pointer to the character following the '/' of the name segment
384 * which contains a wildcard or which is not followed by a '/'.
385 ****************/
386 {
387 char * lookAheadPtr = fileSpec;
388 char * maskPtr;
389 Boolean hasWildcards;
390 char prevChar;
391 char prev2Char ;
392
393 /* Stop at final name segment or if wildcards were found. */
394 do {
395 maskPtr = lookAheadPtr;
396 hasWildcards = FALSE;
397 prevChar = '\0';
398 prev2Char = '\0';
399 while ((*lookAheadPtr != '/') && !hasWildcards && *lookAheadPtr)
400 {
401 switch (*lookAheadPtr)
402 {
403 case '*':
404 case '?':
405 case '[':
406 if ((prevChar != '\\') || (prev2Char == '\\'))
407 {
408 hasWildcards = TRUE;
409 break;
410 }
411 }
412 prev2Char = prevChar;
413 prevChar = *lookAheadPtr;
414 #ifndef NO_MULTIBYTE
415 lookAheadPtr += ((MB_CUR_MAX > 1) ?
416 abs(mblen(lookAheadPtr, MB_CUR_MAX)) : 1);
417 #else
418 lookAheadPtr++;
419 #endif
420 }
421 } while (!hasWildcards && *lookAheadPtr++);
422
423 if (*maskPtr == '/')
424 ++maskPtr;
425
426 return(maskPtr);
427 }
428
429 /****************************************************************/
430 void
_XmOSQualifyFileSpec(String dirSpec,String filterSpec,String * pQualifiedDir,String * pQualifiedPattern)431 _XmOSQualifyFileSpec(String dirSpec,
432 String filterSpec,
433 String *pQualifiedDir, /* Cannot be NULL.*/
434 String *pQualifiedPattern) /* Cannot be NULL.*/
435 /************GENERAL:
436 * dirSpec, filterSpec can contain relative or logical reference.
437 * dirSpec cannot contain pattern characters.
438 * if filterSpec does not specify all for its last segment, a pattern
439 * for 'all' is added.
440 * Use GetQualifiedDir() for dirSpec.
441 ****************/
442
443 /************UNIX:
444 * 'all' is '*' and '/' is the delimiter.
445 ****************/
446 {
447 int filterLen;
448 int dirLen;
449 char *fSpec;
450 char *remFSpec;
451 char *maskPtr;
452 char *dSpec;
453 char *dPtr;
454
455 if (!dirSpec)
456 dirSpec = "";
457 if (!filterSpec)
458 filterSpec = "";
459
460 filterLen = strlen(filterSpec);
461
462 /* Allocate extra for NULL character and for the appended '*' (as needed). */
463 fSpec = XtMalloc(filterLen + 2);
464 strcpy(fSpec, filterSpec);
465
466 /* If fSpec ends with a '/' or is a null string, add '*' since this is
467 * the interpretation.
468 */
469 if (!filterLen || (fSpec[filterLen - 1] == '/'))
470 {
471 fSpec[filterLen] = '*';
472 fSpec[filterLen + 1] = '\0';
473 }
474
475 /* Some parts of fSpec may be copied to dSpec, so allocate "filterLen"
476 * extra, plus some for added literals.
477 */
478 dirLen = strlen(dirSpec);
479 dSpec = XtMalloc(filterLen + dirLen + 4);
480 strcpy(dSpec, dirSpec);
481 dPtr = dSpec + dirLen;
482
483 /* Check for cases when the specified filter overrides anything
484 * in the dirSpec.
485 */
486 remFSpec = fSpec;
487 switch(*fSpec)
488 {
489 case '/':
490 dSpec[0] = '/';
491 dSpec[1] = '\0';
492 dPtr = dSpec + 1;
493 ++remFSpec;
494 break;
495
496 case '~':
497 dPtr = dSpec;
498 while ((*dPtr = *remFSpec) && (*remFSpec++ != '/'))
499 ++dPtr;
500 *dPtr = '\0';
501 break;
502 }
503
504 /* If directory spec. is not null, then make sure that it has a
505 * trailing '/', to be prepared for appending from filter spec.
506 */
507 if (*dSpec && (*(dPtr - 1) != '/'))
508 {
509 *dPtr++ = '/';
510 *dPtr = '\0';
511 }
512
513 maskPtr = _XmOSFindPatternPart(remFSpec);
514
515 if (maskPtr != remFSpec)
516 {
517 do {
518 *dPtr++ = *remFSpec++;
519 } while (remFSpec != maskPtr);
520 *dPtr = '\0';
521 }
522
523 if (remFSpec != fSpec)
524 {
525 /* Shift remaining filter spec. to the beginning of the buffer. */
526 remFSpec = fSpec;
527 while ((*remFSpec++ = *maskPtr++) != '\0')
528 /*EMPTY*/;
529 }
530
531 *pQualifiedDir = GetQualifiedDir(dSpec);
532 *pQualifiedPattern = fSpec;
533 XtFree(dSpec);
534 }
535
536 /****************************************************************/
537 static String
GetFixedMatchPattern(String pattern)538 GetFixedMatchPattern(String pattern)
539 /**********GENERAL:
540 * The pattern parameter is converted to the format required of the
541 * the regular expression library routines.
542 * Memory is allocated and returned with the result. This memory
543 * should eventually be freed by a call to XtFree().
544 ****************/
545
546 /**********UNIX:
547 * '/' is used as a delimiter for the pattern.
548 ****************/
549 {
550 register char *bufPtr;
551 char *outputBuf;
552 char lastchar = '\0';
553 int len;
554
555 outputBuf = XtCalloc(2, strlen(pattern) + 4);
556
557 bufPtr = outputBuf;
558 *bufPtr++ = '^';
559
560 #ifndef NO_MULTIBYTE
561 while ((len = mblen(pattern, MB_CUR_MAX)) > 0)
562 #else
563 while ((len = *pattern ? 1 : 0))
564 #endif
565 {
566 if (len <= 1)
567 {
568 if (*pattern == '/')
569 break;
570
571 if (lastchar == '\\')
572 *bufPtr++ = *pattern;
573 else
574 {
575 switch(*pattern)
576 {
577 case '.':
578 *bufPtr++ = '\\';
579 *bufPtr++ = '.';
580 break;
581
582 case '?':
583 *bufPtr++ = '.';
584 break;
585
586 case '*':
587 *bufPtr++ = '.';
588 *bufPtr++ = '*';
589 break;
590
591 default:
592 *bufPtr++ = *pattern;
593 break;
594 }
595 }
596 lastchar = *pattern;
597 ++pattern;
598 }
599 else
600 {
601 strncpy(bufPtr, pattern, len);
602 bufPtr += len;
603 pattern += len;
604 lastchar = '\0';
605 }
606 }
607
608 *bufPtr++ = '$';
609 *bufPtr = '\0';
610
611 return outputBuf;
612 }
613
614 /****************************************************************/
615 void
_XmOSGetDirEntries(String qualifiedDir,String matchPattern,unsigned int fileType,int matchDotsLiterally,int listWithFullPath,String ** pEntries,unsigned int * pNumEntries,unsigned int * pNumAlloc)616 _XmOSGetDirEntries(String qualifiedDir,
617 String matchPattern,
618 #if NeedWidePrototypes
619 unsigned int fileType,
620 int matchDotsLiterally,
621 int listWithFullPath,
622 #else
623 unsigned char fileType,
624 Boolean matchDotsLiterally,
625 Boolean listWithFullPath,
626 #endif /* NeedWidePrototypes */
627 String * * pEntries, /* Cannot be NULL. */
628 unsigned int * pNumEntries, /* Cannot be NULL. */
629 unsigned int * pNumAlloc) /* Cannot be NULL. */
630
631 /***********GENERAL:
632 * This routine opens the specified directory and builds a buffer containing
633 * a series of strings containing the full path of each file in the directory
634 * The memory allocated should eventually be freed using XtFree.
635 * The 'qualifiedDir' parameter must be a fully qualified directory path
636 * The matchPattern parameter must be in the proper form for a regular
637 * expression parsing.
638 * If the location pointed to by pEntries is NULL, this routine allocates
639 * and returns a list to *pEntries, though the list may have no entries.
640 * pEntries, pEndIndex, pNumAlloc are updated as required for memory
641 * management.
642 ****************/
643
644 /***********UNIX:
645 * Fully qualified directory means begins with '/', does not have
646 * embedded "." or "..", but does not need trailing '/'.
647 * Regular expression parsing is regcmp or re_comp.
648 * Directory entries are also Unix dependent.
649 ****************/
650
651 {
652 char * fixedMatchPattern;
653 String entryPtr;
654 DIR * dirStream = NULL;
655 struct stat statBuf;
656 Boolean entryTypeOK;
657 unsigned int dirLen = strlen(qualifiedDir);
658 Boolean useCache = FALSE;
659 Boolean loadCache = FALSE;
660 unsigned readCacheIndex = 0;
661 unsigned char dirFileType = 0;
662 #ifndef NO_REGCOMP
663 regex_t preg;
664 int comp_status = 0;
665 #elif !defined(NO_REGEX)
666 char * compiledRE = NULL;
667 #endif /* NO_REGCOMP */
668 /****************/
669
670 _XmProcessLock();
671
672 if (!*pEntries)
673 {
674 *pNumEntries = 0;
675 *pNumAlloc = FILE_LIST_BLOCK;
676 *pEntries = (String *) XtMalloc(FILE_LIST_BLOCK * sizeof(char *));
677 }
678 fixedMatchPattern = GetFixedMatchPattern(matchPattern);
679
680 if (fixedMatchPattern)
681 {
682 if (!*fixedMatchPattern)
683 {
684 XtFree(fixedMatchPattern);
685 fixedMatchPattern = NULL;
686 }
687 else
688 {
689 #ifndef NO_REGCOMP
690 comp_status = regcomp(&preg, fixedMatchPattern, REG_NOSUB);
691 if (comp_status)
692 #elif !defined(NO_REGEX)
693 compiledRE = (char *)regcmp(fixedMatchPattern, (char *) NULL);
694 if (!compiledRE)
695 #else
696 if (re_comp(fixedMatchPattern))
697 #endif
698 {
699 XtFree(fixedMatchPattern);
700 fixedMatchPattern = NULL;
701 }
702 }
703 }
704
705 if ((dirCacheName != NULL) &&
706 !strcmp(qualifiedDir, dirCacheName))
707 {
708 useCache = TRUE;
709 readCacheIndex = 0;
710 }
711 else
712 {
713 if (!strcmp(matchPattern, "*") &&
714 (fileType == XmFILE_DIRECTORY) &&
715 !matchDotsLiterally)
716 {
717 /* This test is a incestual way of knowing that we are searching
718 * a directory to fill the directory list. We can thereby conclude
719 * that a subsequent call will be made to search the same directory
720 * to fill the file list. Since a "stat" of every file is very
721 * performance-expensive, we will cache the directory used for
722 * a directory list search and subsequently use the results for
723 * the file list search.
724 */
725 loadCache = TRUE;
726 }
727 dirStream = opendir(qualifiedDir);
728 }
729
730 if (dirStream || useCache)
731 {
732 unsigned loopCount = 0;
733 _Xreaddirparams dirEntryBuf;
734
735 if (loadCache)
736 ResetCache(qualifiedDir);
737
738 /* The POSIX specification for the "readdir" routine makes
739 * it OPTIONAL to return the "." and ".." entries in a
740 * directory. The algorithm used here depends on these
741 * entries being included in the directory list. So, we
742 * will first handle "." and ".." explicitly, then ignore
743 * them later if they happen to be returned by "readdir".
744 */
745 while (TRUE)
746 {
747 char *dirName;
748 unsigned dirNameLen = 0;
749
750 if (loopCount < 2)
751 {
752 if (loopCount == 0)
753 {
754 /* Do current directory the first time through. */
755 dirName = ".";
756 dirNameLen = 1;
757 }
758 else
759 {
760 /* Do parent directory the second time through. */
761 dirName = "..";
762 dirNameLen = 2;
763 }
764 ++loopCount;
765
766 if (useCache || loadCache)
767 dirFileType = XmFILE_DIRECTORY;
768 }
769 else
770 {
771 struct dirent * dirEntry;
772
773 do {
774 if (useCache)
775 {
776 if (readCacheIndex == numCacheEntries)
777 {
778 dirName = NULL;
779 break;
780 }
781 else
782 {
783 dirFileType = dirCache[readCacheIndex]->type;
784 dirName = dirCache[readCacheIndex++]->file_name;
785 dirNameLen = strlen(dirName);
786 }
787 }
788 else
789 {
790 if ((dirEntry = _XReaddir(dirStream, dirEntryBuf)) == NULL)
791 {
792 dirName = NULL;
793 break;
794 }
795 dirName = dirEntry->d_name;
796 dirNameLen = strlen(dirName);
797 if (loadCache)
798 dirFileType = AddEntryToCache(dirName, dirNameLen);
799 }
800 /* Check to see if directory entry is "." or "..",
801 * since these have already been processed.
802 * So if/when readdir returns these directories,
803 * we just ignore them.
804 */
805 } while (((dirNameLen == 1) && (dirName[0] == '.')) ||
806 ((dirNameLen == 2) &&
807 (dirName[0] == '.') && (dirName[1] == '.')));
808
809 if (dirName == NULL)
810 break; /* Exit from outer loop. */
811 }
812 if (fixedMatchPattern)
813 {
814 #ifndef NO_REGCOMP
815 if (regexec(&preg, dirName, 0, NULL, 0))
816 #else /* NO_REGCOMP */
817 # ifndef NO_REGEX
818 if (!regex(compiledRE, dirName))
819 # else
820 if (!re_exec(dirName))
821 # endif
822 #endif /* NO_REGCOMP */
823 continue;
824 }
825 if (matchDotsLiterally &&
826 (dirName[0] == '.') &&
827 (*matchPattern != '.'))
828 continue;
829 if (*pNumEntries == *pNumAlloc)
830 {
831 *pNumAlloc += FILE_LIST_BLOCK;
832 *pEntries = (String *)
833 XtRealloc((char*) *pEntries, (*pNumAlloc* sizeof(char *)));
834 }
835 entryPtr = XtMalloc(dirNameLen + dirLen + 1);
836 strcpy(entryPtr, qualifiedDir);
837 strcpy(&entryPtr[dirLen], dirName);
838
839 /* Now screen entry according to type. */
840 entryTypeOK = FALSE;
841
842 if (fileType == XmFILE_ANY_TYPE)
843 {
844 entryTypeOK = TRUE;
845 }
846 else if (useCache || loadCache)
847 {
848 if (dirFileType == fileType)
849 entryTypeOK = TRUE;
850 }
851 else
852 {
853 if (!stat(entryPtr, &statBuf))
854 {
855 switch (fileType)
856 {
857 case XmFILE_REGULAR:
858 if (S_ISREG(statBuf.st_mode))
859 entryTypeOK = TRUE;
860 break;
861
862 case XmFILE_DIRECTORY:
863 if (S_ISDIR(statBuf.st_mode))
864 entryTypeOK = TRUE;
865 break;
866 }
867 }
868 }
869 if (entryTypeOK)
870 {
871 if (listWithFullPath)
872 {
873 (*pEntries)[(*pNumEntries)++] = entryPtr;
874 }
875 else
876 {
877 /* This is ONLY for BC in a (apparently unused) API, (w/o
878 * full path) so don't worry too much about efficiency.
879 */
880 XtFree(entryPtr);
881 entryPtr = XtMalloc(dirNameLen + 1);
882 strcpy(entryPtr, dirName);
883 (*pEntries)[(*pNumEntries)++] = entryPtr;
884 }
885 }
886 else
887 XtFree(entryPtr);
888 }
889 if (!useCache)
890 closedir(dirStream);
891 }
892 #ifndef NO_REGCOMP
893 if (!comp_status)
894 regfree(&preg);
895 #else /* NO_REGCOMP */
896 # ifndef NO_REGEX
897 if (compiledRE)
898 {
899 /* Use free instead of XtFree since malloc is inside of regex(). */
900 free(compiledRE);
901 }
902 # endif
903 #endif /* NO_REGCOMP */
904 XtFree(fixedMatchPattern);
905
906 if (!loadCache)
907 FreeDirCache();
908 _XmProcessUnlock();
909 }
910
911 /****************************************************************
912 * _XmOSBuildFileList:
913 *
914 * GENERAL:
915 * The 'dirPath' parameter must be a qualified directory path.
916 * The 'pattern' parameter must be valid as a suffix to dirPath.
917 * typeMask is an Xm constant coming from Xm.h.
918 *
919 * UNIX:
920 * Qualified directory path means no match characters, with '/'
921 * at end.
922 ****************************************************************/
923 void
_XmOSBuildFileList(String dirPath,String pattern,unsigned int typeMask,String ** pEntries,unsigned int * pNumEntries,unsigned int * pNumAlloc)924 _XmOSBuildFileList(String dirPath,
925 String pattern,
926 #if NeedWidePrototypes
927 unsigned int typeMask,
928 #else
929 unsigned char typeMask,
930 #endif /* NeedWidePrototypes */
931 String * * pEntries, /* Cannot be NULL. */
932 unsigned int * pNumEntries, /* Cannot be NULL. */
933 unsigned int * pNumAlloc) /* Cannot be NULL. */
934 {
935 String qualifiedDir;
936 String nextPatternPtr;
937 String * localEntries;
938 unsigned int localNumEntries;
939 unsigned int localNumAlloc;
940 unsigned int entryIndex;
941
942 qualifiedDir = GetQualifiedDir(dirPath);
943 nextPatternPtr = pattern;
944 while (*nextPatternPtr && (*nextPatternPtr != '/'))
945 ++nextPatternPtr;
946
947 if (!*nextPatternPtr)
948 {
949 /* At lowest level directory, so simply return matching entries.*/
950 _XmOSGetDirEntries(qualifiedDir, pattern, typeMask, FALSE, TRUE,
951 pEntries, pNumEntries, pNumAlloc);
952 }
953 else
954 {
955 ++nextPatternPtr; /* Move past '/' character.*/
956 localEntries = NULL;
957 _XmOSGetDirEntries(qualifiedDir, pattern, XmFILE_DIRECTORY, TRUE, TRUE,
958 &localEntries, &localNumEntries, &localNumAlloc);
959 entryIndex = 0;
960 while (entryIndex < localNumEntries)
961 {
962 _XmOSBuildFileList(localEntries[entryIndex], nextPatternPtr,
963 typeMask, pEntries, pNumEntries, pNumAlloc);
964 XtFree(localEntries[entryIndex]);
965 ++entryIndex;
966 }
967 XtFree((char*)localEntries);
968 }
969 XtFree(qualifiedDir);
970 }
971
972 /****************************************************************
973 * GENERAL:
974 * The routine must return an integer less than, equal to, or
975 * greater than 0 according as the first argument is to be
976 * considered less than, equal to, or greater than the second.
977 ****************************************************************/
978
979 int
_XmOSFileCompare(XmConst void * sp1,XmConst void * sp2)980 _XmOSFileCompare(XmConst void *sp1,
981 XmConst void *sp2)
982 {
983 return strcmp(*((XmConst String *) sp1), *((XmConst String *) sp2));
984 }
985
986 /*************************************************************************
987 *
988 * Path code, used in Mwm and Xm.
989 * Returned pointer should not be freed!
990 *
991 *************************************************************************/
992
993 String
XmeGetHomeDirName(void)994 XmeGetHomeDirName(void)
995 {
996 uid_t uid;
997 _Xgetpwparams pwd_buf;
998 struct passwd * pwd_value;
999
1000 char *ptr = NULL;
1001 static char empty = '\0';
1002 static char *homeDir = NULL;
1003
1004 _XmProcessLock();
1005 if (homeDir == NULL)
1006 {
1007 if ((ptr = (char *)getenv("HOME")) == NULL)
1008 {
1009 if ((ptr = (char *)getenv(USER_VAR)) != NULL)
1010 pwd_value = _XGetpwnam(ptr, pwd_buf);
1011 else
1012 {
1013 uid = getuid();
1014 pwd_value = _XGetpwuid(uid, pwd_buf);
1015 }
1016
1017 if (pwd_value != NULL)
1018 ptr = pwd_value->pw_dir;
1019 else
1020 ptr = NULL;
1021 }
1022
1023 if (ptr != NULL)
1024 {
1025 homeDir = XtMalloc (strlen(ptr) + 1);
1026 strcpy (homeDir, ptr);
1027 }
1028 else
1029 {
1030 homeDir = ∅
1031 }
1032 }
1033
1034 _XmProcessUnlock();
1035 return homeDir;
1036 }
1037
1038 #ifndef LIBDIR
1039 #define LIBDIR "/usr/lib/X11"
1040 #endif
1041 #ifndef INCDIR
1042 #define INCDIR "/usr/include/X11"
1043 #endif
1044
1045 static XmConst char libdir[] = LIBDIR;
1046 static XmConst char incdir[] = INCDIR;
1047
1048 /*************************************************************************
1049 *
1050 * When the locale contains a codeset, the Toolkit's default path fail
1051 * to search for the directory with only language and territory.
1052 *
1053 * For example, when locale is "zh_TW.dechanyu", directories searched
1054 * should be :
1055 *
1056 * 1. zh_TW.dechanyu (%L)
1057 * 2. zh_TW (%l_%t)
1058 * 3. zh (%l)
1059 *
1060 *************************************************************************/
1061
1062 static XmConst char XAPPLRES_DEFAULT[] = "\
1063 %%P\
1064 %%S:\
1065 %s/%%L/%%T/%%N/%%P\
1066 %%S:\
1067 %s/%%l_%%t/%%T/%%N/%%P\
1068 %%S:\
1069 %s/%%l/%%T/%%N/%%P\
1070 %%S:\
1071 %s/%%T/%%N/%%P\
1072 %%S:\
1073 %s/%%L/%%T/%%P\
1074 %%S:\
1075 %s/%%l_%%t/%%T/%%P\
1076 %%S:\
1077 %s/%%l/%%T/%%P\
1078 %%S:\
1079 %s/%%T/%%P\
1080 %%S:\
1081 %s/%%T/%%P\
1082 %%S:\
1083 %s/%%P\
1084 %%S:\
1085 %s/%%L/%%T/%%N/%%P\
1086 %%S:\
1087 %s/%%l_%%t/%%T/%%N/%%P\
1088 %%S:\
1089 %s/%%l/%%T/%%N/%%P\
1090 %%S:\
1091 %s/%%T/%%N/%%P\
1092 %%S:\
1093 %s/%%L/%%T/%%P\
1094 %%S:\
1095 %s/%%l_%%t/%%T/%%P\
1096 %%S:\
1097 %s/%%l/%%T/%%P\
1098 %%S:\
1099 %s/%%T/%%P\
1100 %%S:\
1101 %s/%%T/%%P\
1102 %%S";
1103
1104 static XmConst char PATH_DEFAULT[] = "\
1105 %%P\
1106 %%S:\
1107 %s/%%L/%%T/%%N/%%P\
1108 %%S:\
1109 %s/%%l_%%t/%%T/%%N/%%P\
1110 %%S:\
1111 %s/%%l/%%T/%%N/%%P\
1112 %%S:\
1113 %s/%%T/%%N/%%P\
1114 %%S:\
1115 %s/%%L/%%T/%%P\
1116 %%S:\
1117 %s/%%l_%%t/%%T/%%P\
1118 %%S:\
1119 %s/%%l/%%T/%%P\
1120 %%S:\
1121 %s/%%T/%%P\
1122 %%S:\
1123 %s/%%P\
1124 %%S:\
1125 %s/%%L/%%T/%%N/%%P\
1126 %%S:\
1127 %s/%%l_%%t/%%T/%%N/%%P\
1128 %%S:\
1129 %s/%%l/%%T/%%N/%%P\
1130 %%S:\
1131 %s/%%T/%%N/%%P\
1132 %%S:\
1133 %s/%%L/%%T/%%P\
1134 %%S:\
1135 %s/%%l_%%t/%%T/%%P\
1136 %%S:\
1137 %s/%%l/%%T/%%P\
1138 %%S:\
1139 %s/%%T/%%P\
1140 %%S:\
1141 %s/%%T/%%P\
1142 %%S";
1143
1144 static XmConst char ABSOLUTE_PATH[] = "\
1145 %P\
1146 %S";
1147
1148 /*
1149 * buf must be of length MAX_DIR_PATH_LEN
1150 */
1151 static String
GetCurrentDir(String buf)1152 GetCurrentDir(String buf)
1153 {
1154 String pwd = getenv ("PWD");
1155 struct stat stat1, stat2;
1156
1157 if (pwd
1158 && stat (pwd, &stat1) == 0
1159 && stat (".", &stat2) == 0
1160 && stat1.st_dev == stat2.st_dev
1161 && stat1.st_ino == stat2.st_ino) {
1162 /* Use PWD environment variable */
1163 strcpy(buf, pwd);
1164 return pwd ;
1165 }
1166
1167 return getcwd(buf, MAX_DIR_PATH_LEN) ;
1168 }
1169
1170 #ifdef notdef
1171 /* old way */
1172 String pwd = NULL;
1173
1174 if ((pwd = getenv("PWD")) != NULL)
1175 strcpy(buf, pwd);
1176 if (!pwd) pwd = getcwd(buf, MAX_DIR_PATH_LEN)
1177 return pwd ;
1178 #endif
1179
1180
1181 /*
1182 * buf must be of length MAX_DIR_PATH_LEN
1183 */
1184 Boolean
_XmOSAbsolutePathName(String path,String * pathRtn,String buf)1185 _XmOSAbsolutePathName(String path, String *pathRtn, String buf)
1186 {
1187 Boolean doubleDot = False;
1188
1189 *pathRtn = path;
1190
1191 if (path[0] == '/')
1192 return True;
1193
1194 if (path[0] == '.') {
1195 if (path[1] == '/')
1196 doubleDot = False;
1197 else if ((path[1] == '.') &&
1198 (path[2] == '/'))
1199 doubleDot = True;
1200
1201 if (GetCurrentDir(buf) != NULL) {
1202 if (doubleDot) {
1203 String filePart, suffixPart;
1204 _XmOSFindPathParts(buf, &filePart, &suffixPart);
1205 (void) strcpy(filePart, &path[2]);
1206 }
1207 else {
1208 (void) strcat(buf, &path[1]);
1209 }
1210 *pathRtn = buf;
1211 return True;
1212 }
1213 else {
1214 XmeWarning(NULL, "Cannot find current dir");
1215 return True;
1216 }
1217 }
1218 return False;
1219 }
1220
1221 String
_XmOSInitPath(String file_name,String env_pathname,Boolean * user_path)1222 _XmOSInitPath(String file_name,
1223 String env_pathname,
1224 Boolean *user_path)
1225 {
1226 String path;
1227 String old_path;
1228 char stackString[MAX_DIR_PATH_LEN];
1229 String homedir = stackString ;
1230 String local_path;
1231
1232 *user_path = False;
1233
1234 if (file_name && _XmOSAbsolutePathName(file_name, &file_name, homedir)) {
1235 path = XtNewString(ABSOLUTE_PATH);
1236 }
1237 else
1238 {
1239 local_path = (char *)getenv (env_pathname);
1240 if (local_path == NULL)
1241 {
1242 homedir = XmeGetHomeDirName();
1243 old_path = (char *)getenv ("XAPPLRESDIR");
1244 if (old_path == NULL)
1245 {
1246 path = XtCalloc(1, (9*strlen(homedir) + strlen(PATH_DEFAULT) +
1247 8*strlen(libdir) + strlen(incdir) + 1));
1248 sprintf(path, PATH_DEFAULT, homedir, homedir, homedir,
1249 homedir, homedir, homedir, homedir, homedir, homedir,
1250 libdir, libdir, libdir, libdir, libdir, libdir, libdir,
1251 libdir, incdir);
1252 }
1253 else
1254 {
1255 path = XtCalloc(1, (8*strlen(old_path) + 2*strlen(homedir) +
1256 strlen(XAPPLRES_DEFAULT) + 8*strlen(libdir) +
1257 strlen(incdir) + 1));
1258 sprintf(path, XAPPLRES_DEFAULT,
1259 old_path, old_path, old_path, old_path, old_path,
1260 old_path, old_path, old_path, homedir, homedir,
1261 libdir, libdir, libdir, libdir, libdir, libdir, libdir,
1262 libdir, incdir);
1263 }
1264 }
1265 else
1266 {
1267 path = XtMalloc(strlen(local_path) + 1);
1268 strcpy (path, local_path);
1269 *user_path = True;
1270 }
1271 }
1272
1273 return path;
1274 }
1275
1276 int
XmeMicroSleep(long usecs)1277 XmeMicroSleep(long usecs)
1278 {
1279 struct timeval timeoutVal;
1280
1281 /* split the micro seconds in seconds and remainder */
1282 timeoutVal.tv_sec = usecs/1000000;
1283 timeoutVal.tv_usec = usecs - timeoutVal.tv_sec*1000000;
1284
1285 return Select(0, NULL, NULL, NULL, &timeoutVal);
1286 }
1287
1288 /************************************************************************
1289 *
1290 * XmeGetLocalizedString Map an X11 R5 XPCS string in a locale
1291 * sensitive XmString.
1292 *
1293 * reserved Reserved for future use.
1294 * widget The widget id.
1295 * resource The resource name.
1296 * string The input 8859-1 value.
1297 *
1298 ************************************************************************/
1299
1300 /*ARGSUSED*/
1301 XmString
XmeGetLocalizedString(char * reserved,Widget widget,char * resource,String string)1302 XmeGetLocalizedString(char *reserved, /* unused */
1303 Widget widget, /* unused */
1304 char *resource, /* unused */
1305 String string)
1306 {
1307 return XmStringCreateLocalized(string);
1308 }
1309
1310 /************************************************************************
1311 * *
1312 * _XmOSBuildFileName *
1313 * *
1314 * Build an absolute file name from a directory and file. *
1315 * Handle case where 'file' is already absolute. *
1316 * Return value should be freed by XtFree() *
1317 * *
1318 ************************************************************************/
1319
1320 String
_XmOSBuildFileName(String path,String file)1321 _XmOSBuildFileName(String path,
1322 String file)
1323 {
1324 String fileName;
1325
1326 if (file[0] == '/')
1327 {
1328 fileName = XtMalloc (strlen (file) + 1);
1329 strcpy (fileName, file);
1330 }
1331 else
1332 {
1333 fileName = XtMalloc (strlen(path) + strlen (file) + 2);
1334 strcpy (fileName, path);
1335 strcat (fileName, "/");
1336 strcat (fileName, file);
1337 }
1338
1339 return fileName;
1340 }
1341
1342
1343
1344 /************************************************************
1345 *
1346 * return poiinter to the file and the suffix
1347 * /usr/foo/bar.xpm returns &"bar.xpm" and &"xpm"
1348 *
1349 ************************************************************/
1350
1351 void
_XmOSFindPathParts(String path,String * filenameRtn,String * suffixRtn)1352 _XmOSFindPathParts(String path,
1353 String *filenameRtn,
1354 String *suffixRtn)
1355 {
1356 String filename = path, suffix = NULL;
1357 String s;
1358 /*
1359 * maybe a problem for I18N - probably: filenames may be multibyte!!!
1360 */
1361 #define FILESEP '/'
1362 #define SUFFIXSEP '.'
1363
1364 s = path;
1365 while (*s)
1366 {
1367 if (*s == FILESEP)
1368 {
1369 filename = s++;
1370 }
1371 else if (*s == SUFFIXSEP)
1372 {
1373 suffix = s++;
1374 }
1375 else
1376 s++;
1377 }
1378
1379 if (suffix < filename)
1380 suffix = NULL;
1381
1382 if ((*filenameRtn = filename) != NULL)
1383 {
1384 if (filename != path)
1385 (*filenameRtn)++;
1386 }
1387
1388 if ((*suffixRtn = suffix) != NULL)
1389 (*suffixRtn)++;
1390 }
1391
1392
1393
1394 /************************************************************
1395 *
1396 * Add _m to the imageName:
1397 * transform /usr/foo/bar.xpm in /usr/foo/bar_m.xpm
1398 * or joe in joe_m
1399 *
1400 ************************************************************/
1401
1402 void
_XmOSGenerateMaskName(String imageName,String maskNameBuf)1403 _XmOSGenerateMaskName(
1404 String imageName,
1405 String maskNameBuf)
1406 {
1407 String file, suffix;
1408 int len;
1409
1410 _XmOSFindPathParts(imageName, &file, &suffix);
1411
1412 if (suffix) {
1413 len = (int)(suffix - imageName) - 1;
1414 /* point before the '.' */
1415 suffix--;
1416 }
1417 else
1418 len = strlen(imageName);
1419
1420 strncpy(maskNameBuf, imageName, len);
1421 maskNameBuf += len;
1422 strcpy(maskNameBuf, "_m");
1423 if (suffix)
1424 strcpy(maskNameBuf+2, suffix);
1425 else
1426 maskNameBuf[2] = '\0';
1427 }
1428
1429
1430
1431 /*ARGSUSED*/
1432 Status
_XmOSGetInitialCharsDirection(XtPointer characters,XmTextType type,XmStringTag locale,unsigned int * num_bytes,XmDirection * direction)1433 _XmOSGetInitialCharsDirection(XtPointer characters,
1434 XmTextType type,
1435 XmStringTag locale, /* unused */
1436 unsigned int *num_bytes,
1437 XmDirection *direction)
1438 {
1439 /* ??? This is a temporary stub implementation. */
1440 switch (type)
1441 {
1442 case XmWIDECHAR_TEXT:
1443 *num_bytes = Wcslen((wchar_t*) characters) * sizeof(wchar_t);
1444 *direction = XmLEFT_TO_RIGHT;
1445 return Success;
1446
1447 case XmCHARSET_TEXT:
1448 case XmMULTIBYTE_TEXT:
1449 *num_bytes = strlen((char*) characters);
1450 *direction = XmLEFT_TO_RIGHT;
1451 return Success;
1452
1453 default:
1454 *num_bytes = 0;
1455 *direction = XmDEFAULT_DIRECTION;
1456 return ~Success;
1457 }
1458 }
1459
1460 /*ARGSUSED*/
1461 XmDirection
_XmOSGetCharDirection(XtPointer character,XmTextType type,XmStringTag locale)1462 _XmOSGetCharDirection(XtPointer character, /* unused */
1463 XmTextType type,
1464 XmStringTag locale) /* unused */
1465 {
1466 /* ??? This is a temporary stub implementation. */
1467 switch (type)
1468 {
1469 case XmWIDECHAR_TEXT:
1470 case XmCHARSET_TEXT:
1471 case XmMULTIBYTE_TEXT:
1472 return XmLEFT_TO_RIGHT;
1473
1474 default:
1475 return XmDEFAULT_DIRECTION;
1476 }
1477 }
1478
1479 static int
Wcslen(wchar_t * wcs)1480 Wcslen(wchar_t *wcs)
1481 {
1482 /* Count characters, not bytes. */
1483 wchar_t *ptr = wcs;
1484 if (ptr != NULL)
1485 while (*ptr++)
1486 /*EMPTY*/;
1487
1488 return (ptr - wcs);
1489 }
1490
1491 typedef struct XmOSMethodEntryRec {
1492 String method_id;
1493 XtPointer method;
1494 XtPointer os_data;
1495 XtPointer reserved; /* for future use - fonts & such?*/
1496 } XmOSMethodEntry;
1497
1498
1499 static XmOSMethodEntry method_table[] = {
1500 {
1501 XmMCharDirection,
1502 (XtPointer)_XmOSGetCharDirection,
1503 NULL, NULL
1504 },
1505
1506 {
1507 XmMInitialCharsDirection,
1508 (XtPointer)_XmOSGetInitialCharsDirection,
1509 NULL, NULL
1510 },
1511
1512 { NULL, NULL, NULL, NULL}
1513 };
1514
1515 /****************************************************************
1516 * XmOSGetMethod:
1517 * get the function that implements the requested method.
1518 ****************************************************************/
1519
1520 /*ARGSUSED*/
1521 XmOSMethodStatus
XmOSGetMethod(Widget w,String method_id,XtPointer * method,XtPointer * os_data)1522 XmOSGetMethod(Widget w, /* unused */
1523 String method_id,
1524 XtPointer *method,
1525 XtPointer *os_data)
1526 {
1527 int i;
1528
1529 if (method == NULL)
1530 return XmOS_METHOD_NULL;
1531
1532 for (i = 0; method_table[i].method_id; i++)
1533 if (method_id == method_table[i].method_id)
1534 {
1535 if (*method == NULL || (method_table[i].method != NULL &&
1536 *method != method_table[i].method))
1537 {
1538 *method = method_table[i].method;
1539 if (os_data) *os_data = method_table[i].os_data;
1540 return XmOS_METHOD_REPLACED;
1541 }
1542 else
1543 {
1544 if (os_data) *os_data = method_table[i].os_data;
1545 return XmOS_METHOD_DEFAULTED;
1546 }
1547 }
1548
1549 for (i = 0; method_table[i].method_id; i++)
1550 if (strcmp(method_id, method_table[i].method_id) == 0)
1551 {
1552 if (*method == NULL || (method_table[i].method != NULL &&
1553 *method != method_table[i].method))
1554 {
1555 *method = method_table[i].method;
1556 if (os_data) *os_data = method_table[i].os_data;
1557 return XmOS_METHOD_REPLACED;
1558 }
1559 else
1560 {
1561 if (os_data) *os_data = method_table[i].os_data;
1562 return XmOS_METHOD_DEFAULTED;
1563 }
1564 }
1565
1566 return XmOS_METHOD_DEFAULTED;
1567 }
1568
1569 /*
1570 * This routine is used by Label (and LabelG) to determine which
1571 * character in the label string matches the Mnemonic keysym, and
1572 * thus should be underlined.
1573 *
1574 * Parameters:
1575 * keysym - Specifies the keysym to be converted.
1576 * locale - Specifies the locale to convert into. NULL => current locale.
1577 * buffer - A buffer allocated by the caller to hold the (at most one)
1578 * multibyte character that corresponds to the keysym.
1579 *
1580 * Return value:
1581 * The number of bytes written into the buffer.
1582 */
1583
1584 /*ARGSUSED*/
1585 int
_XmOSKeySymToCharacter(KeySym keysym,char * locale,char * buffer)1586 _XmOSKeySymToCharacter(KeySym keysym,
1587 char *locale,
1588 char *buffer)
1589 {
1590 /*
1591 * This implementation is exceptionally stupid, but works in the
1592 * common case of ISO8859-1 locales and keysyms.
1593 *
1594 * Vendors who use more exotic encodings (e.g. roman8) should
1595 * replace this code with something appropriate.
1596 */
1597
1598 /* Maybe we should generate a warning for non-Latin 1 encodings */
1599 /* outside the range 0..127? */
1600 *buffer = (keysym & 0xFF);
1601
1602 return 1;
1603 }
1604
1605 /* ****************************************************** **
1606 ** Threading stuff. Stuck here to allow easier debugging.
1607 ** ****************************************************** */
1608 /*
1609 static unsigned int _lockCounter = 0;
1610 static unsigned int _unlockCounter = 0;
1611 static int _outstandingLockCounter = 0;
1612 int _debugProcessLocking = 0;
1613
1614 void _XmProcessLock()
1615 {
1616 _lockCounter++;
1617 _outstandingLockCounter++;
1618 #if defined(XTHREADS) && defined(XUSE_MTSAFE_API)
1619 XtProcessLock();
1620 #endif
1621 if(_debugProcessLocking)
1622 {
1623 fprintf(stderr, "File: %s, line: %d - _XmProcessLock() - _lockCounter = %d, _outstandingLockCounter = %d\n", __FILE__, __LINE__,
1624 _lockCounter, _outstandingLockCounter);
1625 }
1626 }
1627
1628
1629 void _XmProcessUnlock()
1630 {
1631 _unlockCounter++;
1632 _outstandingLockCounter--;
1633 #if defined(XTHREADS) && defined(XUSE_MTSAFE_API)
1634 XtProcessUnlock();
1635 #endif
1636 if(_debugProcessLocking)
1637 {
1638 fprintf(stderr, "File: %s, line: %d - _XmProcessUnlock() - _unlockCounter = %d, _outstandingLockCounter = %d\n", __FILE__, __LINE__,
1639 _unlockCounter, _outstandingLockCounter);
1640 }
1641 }
1642 */
1643