~ubuntu-branches/ubuntu/quantal/openmotif/quantal

« back to all changes in this revision

Viewing changes to lib/Xm/Xmos.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bauer
  • Date: 2010-06-23 12:12:31 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100623121231-u89gxdp51sg9wjj2
Tags: 2.3.0-1
* New Maintainer (Closes: #379258) 
* Acknowledge NMU changes
* New upstream release (Closes: #494375)
* Get rid of security patches as they are already part of new upstream
  release (00-xpmvuln.openmotif.patch, 342092-CVE-2005-3964.patch)
* Bump Standards to 3.8.4
* Added {misc:Depends} to make the package lintian cleaner
* Fix weak-library-dev-dependency by adding ${binary:Version}) for the
  -dev Package of openmotif
* Let package depend on autotools-dev to use newer autotools-helper-files
* Work around an autoconf-bug (Gentoo-Bug #1475)
* Added Client-side anti-aliased fonts support via XFT
* Added UTF-8 and UTF8_STRING atom support
* Ability to show text and pixmaps in Label, LabelGadget and all
  derived widgets
* Support of PNG/JPEG image formats in the same way as XPM is supported
* Increase FILE_OFFSET_BITS to 64 to show files >2GB in file-selector
  Idea taken from Magne Oestlyngen (Closes: #288537)

Show diffs side-by-side

added added

removed removed

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