Create Xref-Html Frames                    Remove All Frames
file:d:/code/LRC/Splicer/splicer_code_ver2.2/splicer-bxutil-c.c        (Tue Mar 14 16:29:00 2000 )


   1: /*
   2:  * WARNING: This file is overwritten at code generation time.
   3:  * Any changes to this file will be lost.
   4:  */
   5: /*
   6:  * MODULE: BxConvert.c
   7:  * AUTHOR: Automatically generated by Builder Xcessory
   8:  * 
   9:  * Description: This module contains various utilities, converters 
  10:  *  for XmStrings (to work properly with app-defaults), and if needed
  11:  *  the XPM pixmap utilities.
  12:  *  
  13:  * Edit the file ${BX}/gen/bxutils.c (BX$SYSTEM:[gen]bxutils.c on VMS) to
  14:  * make system wide changes to this file which will be visible next time
  15:  * this file is generated. 
  16:  * ${BX} is the directory where Builder Xcessory is installed.
  17:  */
  18: 
  19: /*
  20:  * BX supplies a string format for compound strings:
  21:  *
  22:  *    ::[#tag][:t][:r]["str"]
  23:  *
  24:  * where:
  25:  *  :: = indicates compound string.
  26:  *  tag =  the font tag
  27:  *  :t = separator (if not seen no separator added to segment)
  28:  *  :r = right to left (if not seen left to right assumed)
  29:  *  "str" = the text of the string.
  30:  *
  31:  * The components for the compound string can be repeated any number of
  32:  * times.
  33:  */
  34: 
  35: /*****************************************************************************
  36:  *       INCLUDE FILES
  37:  *****************************************************************************/
  38: 
  39: #include <Xm/Xm.h>
  40: #include <Xm/RowColumn.h>
  41: #include <stdio.h>
  42: #include <ctype.h>
  43: #include <string.h>
  44: 
  45: /*
  46:  * Include stdlib.h and malloc.h if code is C++, ANSI, or Extended ANSI.
  47:  */
  48: #if defined(__cplusplus) || defined(__STDC__) || defined(__EXTENSIONS__)
  49: #include <stdlib.h>
  50: #ifndef VMS
  51: #include <malloc.h>
  52: #endif
  53: #endif
  54: 
  55: /*****************************************************************************
  56:  *       TYPDEFS AND DEFINES
  57:  *****************************************************************************/
  58: 
  59: /*
  60:  * Undefine this if you want to use native strcasecmp.
  61:  */
  62: #define LOCAL_STRCASECMP
  63: 
  64: #ifdef _NO_PROTO
  65: #ifdef NeedFunctionPrototypes
  66: #undef NeedFunctionPrototypes
  67: #endif
  68: #endif
  69: 
  70: /*
  71:  * Define SUPPORTS_WCHARS if the system supports wide character sets
  72:  * Note: the following line flags the VAXC compiler and not the
  73:  * DECC compiler running VAXC emulation. 
  74:  */
  75: #if !((defined(VAXC) && !defined(__DECC)) || defined(__CENTERLINE__))
  76: #define SUPPORTS_WCHARS
  77: #endif
  78: 
  79: /*
  80:  * Handy definition used in SET_BACKGROUND_COLOR
  81: */
  82: #define UNSET   (-1)
  83: 
  84: /*
  85:  * Set state of inclusion of prototypes properly
  86:  */
  87: #ifdef NeedFunctionPrototypes
  88: #define ARGLIST(p)  (
  89: #define ARG(a, b) a b,
  90: #define GRA(a, b) a b)
  91: #else
  92: #define ARGLIST(p)  p
  93: #define ARG(a, b) a b;
  94: #define GRA(a, b) a b;
  95: #endif
  96: 
  97: #ifdef NeedFunctionPrototypes
  98: #ifdef __cplusplus
  99: #define UARG(a, b)  a,
 100: #define GRAU(a, b)  a)
 101: #else
 102: #define UARG(a, b)  a b,
 103: #define GRAU(a, b)  a b)
 104: #endif
 105: #else
 106: #define UARG(a, b)  a b;
 107: #define GRAU(a, b)  a b;
 108: #endif
 109: 
 110: /*
 111:  * Set up strcasecmp function
 112:  */
 113: #if defined(LOCAL_STRCASECMP)
 114: #define STRCASECMP  StrCasecmp
 115: #ifndef NeedFunctionPrototypes
 116: static int StrCasecmp();
 117: #else
 118: static int StrCasecmp(char*, char*);
 119: #endif
 120: #else
 121: #define STRCASECMP  strcasecmp
 122: #endif
 123: 
 124: /*
 125:  * Define XTPOINTER so it works with all releases of
 126:  * Xt and c++.
 127:  */
 128: #ifdef __cplusplus
 129: #if XtSpecificationRelease < 5
 130: #define XTPOINTER char *
 131: #else
 132: #define XTPOINTER XPointer
 133: #endif
 134: #else
 135: #define XTPOINTER XtPointer
 136: #endif
 137: 
 138: /*
 139:  * The following enum is used to support wide character sets.
 140:  * Use this enum for references into the Common Wide Characters array.
 141:  * If you add to the array, ALWAYS keep NUM_COMMON_WCHARS as the last
 142:  * entry in the enum.  This will maintain correct memory usage, etc.
 143:  */
 144: enum { WNull, WTab, WNewLine, WCarriageReturn, WFormFeed, WVerticalTab,
 145:        WBackSlash, WQuote, WHash, WColon, WideF, WideL, WideN, WideR,
 146:        WideT, WideV, WideUF, WideUL, WideUR, WideUT, WideZero, WideOne,
 147:        NUM_COMMON_WCHARS };
 148: 
 149: /*****************************************************************************
 150:  *       GLOBAL DECLARATIONS
 151:  *****************************************************************************/
 152: 
 153: /*****************************************************************************
 154:  *       EXTERNAL DECLARATIONS
 155:  *****************************************************************************/
 156: 
 157: /*****************************************************************************
 158:  *  STATIC DECLARATION
 159:  *****************************************************************************/
 160: 
 161: #ifndef NeedFunctionPrototypes
 162: 
 163: #ifndef SUPPORTS_WCHARS
 164: static int   mblen      ();
 165: #endif
 166: static int  strlenWc    ();
 167: static size_t doMbstowcs    ();
 168: static size_t doWcstombs    ();
 169: static void copyWcsToMbs    ();
 170: static int  dombtowc    ();
 171: static Boolean  extractSegment    ();
 172: static XmString StringToXmString  ();
 173: static char*  getNextCStrDelim  ();
 174: static int  getCStrCount    ();
 175: static wchar_t *CStrCommonWideCharsGet  ();
 176: 
 177: #else
 178: 
 179: #ifndef SUPPORTS_WCHARS
 180: static int  mblen     (char*, size_t);
 181: #endif
 182: static int  strlenWc    (wchar_t*);
 183: static size_t doMbstowcs    (wchar_t*, char*, size_t);
 184: static size_t doWcstombs    (char*, wchar_t*, size_t);
 185: static void copyWcsToMbs    (char*, wchar_t*, int, Boolean);
 186: static int  dombtowc    (wchar_t*, char*, size_t);
 187: static Boolean  extractSegment    (wchar_t**, wchar_t**, int *,
 188:            wchar_t**, int*, int*, Boolean*);
 189: static XmString StringToXmString  (char*);
 190: static char*  getNextCStrDelim  (char*);
 191: static int  getCStrCount    (char*);
 192: static wchar_t *CStrCommonWideCharsGet  ();
 193: 
 194: #endif
 195: 
 196: /*****************************************************************************
 197:  *  STATIC CODE
 198:  *****************************************************************************/
 199: 
 200: #if defined(LOCAL_STRCASECMP) 
 201: 
 202: /*
 203:  * Function:
 204:  *      cmp = StrCasecmp(s1, s2);
 205:  * Description:
 206:  *      Compare two strings ignoring case
 207:  * Input:
 208:  *      s1 - char * : string 1 to compare
 209:  *      s2 - char * : string 2 to compare
 210:  * Output:
 211:  *      int :  0; s1 == s2
 212:  *             1; s1 != s2
 213:  */
 214: static int StrCasecmp
 215:     ARGLIST((s1, s2))
 216:         ARG(register char *, s1)
 217:         GRA(register char *, s2)
 218: {
 219:     register int        c1, c2;
 220:     
 221:     while (*s1 && *s2)
 222:     {
 223:         c1 = isupper(*s1) ? tolower(*s1) : *s1;
 224:         c2 = isupper(*s2) ? tolower(*s2) : *s2;
 225:         if (c1 != c2)
 226:         {
 227:             return(1);
 228:         }
 229:         s1++;
 230:         s2++;
 231:     }
 232:     if (*s1 || *s2)
 233:     {
 234:         return(1);
 235:     }
 236:     return(0);
 237: }
 238: #endif
 239: 
 240: #ifndef SUPPORTS_WCHARS
 241: /*
 242:  * Function:
 243:  *      len = mblen(s, n);
 244:  * Description:
 245:  *      The mblen function for platforms that don't have one. This
 246:  *  function simply returns a length of 1 since no wide character
 247:  *  support exists for this platform.
 248:  * Input:
 249:  *      s - char * : the character string to get the length from
 250:  *  n - size_t : the size of the string
 251:  * Output:
 252:  *      int : always 1
 253:  */
 254: static int mblen
 255:     ARGLIST((s, n))
 256:         ARG(char *, s)
 257:         GRA(size_t, n)
 258: {
 259:     return(1);
 260: }
 261: #endif
 262: 
 263: /*
 264:  * Function:
 265:  *      len = strlenWc(ptr);
 266:  * Description:
 267:  *      Return the number of characters in a wide character string (not
 268:  *  the characters in the resultant mbs).
 269:  * Input:
 270:  *      ptr - wchar_t* : pointer to the wcs to count
 271:  * Output:
 272:  *      int : the number of characters found
 273:  */
 274: static int strlenWc
 275:     ARGLIST((ptr))
 276:         GRA(wchar_t *,ptr)
 277: {
 278:     register wchar_t  *p = ptr;
 279:     register int  x = 0;
 280:     
 281:     if (!ptr) return(0);
 282:     
 283:     while (*p++) x++;
 284:     return (x);
 285: }
 286: 
 287: /*
 288:  * Function:
 289:  *      bytesConv = doMbstowcs(wcs, mbs, n);
 290:  * Description:
 291:  *      Create a wcs string from an input mbs. 
 292:  * Input:
 293:  *  wcs - wchar_t* : pointer to result buffer of wcs
 294:  *      mbs - char* : pointer to the source mbs
 295:  *  n - size_t : the number of characters to convert
 296:  * Output:
 297:  *      bytesConv - size_t : number of bytes converted
 298:  */
 299: static size_t doMbstowcs
 300:     ARGLIST((wcs, mbs, n))
 301:         ARG(wchar_t *,wcs)
 302:         ARG(char *, mbs)
 303:         GRA(size_t, n)
 304: {
 305: #ifndef SUPPORTS_WCHARS
 306:     int i;
 307:     
 308:     for (i = 0; i < n && mbs[i] != 0; ++i)
 309:     {
 310:   wcs[i] = mbs[i];
 311:     }
 312:     wcs[i++] = 0;
 313:     return(i);
 314: #else
 315:     return(mbstowcs(wcs, mbs, n));
 316: #endif
 317: }
 318: 
 319: /*
 320:  * Function:
 321:  *      bytesConv = doWcstombs(wcs, mbs, n);
 322:  * Description:
 323:  *      Create a mbs string from an input wcs.
 324:  * Input:
 325:  *  wcs - wchar_t* : pointer to the source wcs
 326:  *      mbs - char* : pointer to result mbs buffer 
 327:  *  n - size_t : the number of characters to convert
 328:  * Output:
 329:  *      bytesConv - size_t : number of bytes converted
 330:  */
 331: static size_t doWcstombs
 332:     ARGLIST((mbs, wcs, n))
 333:         ARG(char *, mbs)
 334:         ARG(wchar_t *, wcs)
 335:         GRA(size_t, n)
 336: {
 337: #ifndef SUPPORTS_WCHARS
 338:     int i;
 339:     
 340:     for (i = 0; i < n && wcs[i] != 0; ++i)
 341:     {
 342:   mbs[i] = wcs[i];
 343:     }
 344:     mbs[i] = 0;
 345:     return(i);
 346: #else
 347:     size_t  retval;
 348: 
 349:     retval = wcstombs(mbs, wcs, (n * sizeof(wchar_t)));
 350:     if ( retval == (size_t)-1 ) return(0);
 351:     else return(retval);
 352: #endif
 353: }
 354: 
 355: /*
 356:  * Function:
 357:  *      copyWcsToMbs(mbs, wcs, len);
 358:  * Description:
 359:  *      Create a mbs string from an input wcs. This function allocates
 360:  *  a buffer if necessary.
 361:  * Input:
 362:  *  mbs - char* : destination for the converted/copied output
 363:  *  wcs - wchar_t* : pointer to wcs to copy/convert
 364:  *  len - int : the number of wchar_t' to convert
 365:  *  process_it - Boolean : True if processing of quoted charcters,
 366:  *      False if blind.
 367:  * Output:
 368:  *      None
 369:  */
 370: static void copyWcsToMbs
 371:     ARGLIST((mbs, wcs, len, process_it))
 372:         ARG(char *, mbs)
 373:         ARG(wchar_t *, wcs)
 374:         ARG(int, len)
 375:         GRA(Boolean, process_it)
 376: {
 377:     static  wchar_t *tbuf = NULL;
 378:     static  int tbufSize = 0;
 379:     
 380:     int   numCvt;
 381:     int   lenToConvert;
 382:     wchar_t *fromP = wcs;
 383:     wchar_t *x = &fromP[len];
 384:     wchar_t *toP;
 385:     wchar_t *commonWChars = CStrCommonWideCharsGet();
 386:     wchar_t tmp;
 387:     
 388:     /*
 389:      * Make sure there's room in the buffer
 390:      */
 391:     if (tbufSize < len)
 392:     {
 393:   tbuf = (wchar_t*)XtRealloc((char*)tbuf, (len + 1) * sizeof(wchar_t));
 394:   tbufSize = len;
 395:     }
 396:     
 397:     /*
 398:      * Now copy and process
 399:      */
 400:     toP = tbuf;
 401:     lenToConvert = 0;
 402:     while (fromP < x)
 403:     {
 404:   /*
 405:    * Check for quoted characters
 406:    */
 407:   if ((*fromP == commonWChars[WBackSlash]) && process_it)
 408:   {
 409:       fromP++;    /* Skip quote */
 410:       if (fromP == x) /* Hanging quote? */
 411:       {
 412:     *toP++ = commonWChars[WBackSlash];
 413:     lenToConvert++;
 414:     break;
 415:       }
 416:       tmp = *fromP++;
 417:       if (tmp == commonWChars[WideN])
 418:       {
 419:     *toP++ = commonWChars[WNewLine];
 420:       }
 421:       else if (tmp == commonWChars[WideT])
 422:       {
 423:     *toP++ = commonWChars[WTab];
 424:       }
 425:       else if (tmp == commonWChars[WideR])
 426:       {
 427:     *toP++ = commonWChars[WCarriageReturn];
 428:       }
 429:       else if (tmp == commonWChars[WideF])
 430:       {
 431:     *toP++ = commonWChars[WFormFeed];
 432:       }
 433:       else if (tmp == commonWChars[WideV])
 434:       {
 435:     *toP++ = commonWChars[WVerticalTab];
 436:       }
 437:       else if (tmp == commonWChars[WBackSlash])
 438:       {
 439:     *toP++ = commonWChars[WBackSlash];
 440:       }
 441:       else
 442:       {
 443:                 /*
 444:      * No special translation needed
 445:      */
 446:     *toP++ = tmp;
 447:       }
 448:   }
 449:   else
 450:   {
 451:       *toP++ = *fromP++;
 452:   }
 453:   lenToConvert++;
 454:     }
 455: 
 456:     tmp = tbuf[lenToConvert];
 457:     tbuf[lenToConvert] = (wchar_t) NULL;
 458:     numCvt = doWcstombs(mbs, tbuf, lenToConvert);
 459:     tbuf[lenToConvert] = tmp;
 460:     
 461:     mbs[numCvt] = '\0';
 462: }
 463: 
 464: /*
 465:  * Function:
 466:  *      status = dombtowc(wide, multi, size);
 467:  * Description:
 468:  *      Convert a multibyte character to a wide character.
 469:  * Input:
 470:  *      wide  - wchar_t * : where to put the wide character
 471:  *  multi - char *  : the multibyte character to convert
 472:  *  size  - size_t  : the number of characters to convert
 473:  * Output:
 474:  *      0 - if multi is a NULL pointer or points to a NULL character
 475:  *  #bytes  - number of bytes in the multibyte character
 476:  *  -1  - multi is an invalid multibyte character.
 477:  *
 478:  *  NOTE:  if wide is NULL, then this returns the number of bytes in
 479:  *         the multibyte character.
 480:  */
 481: static int dombtowc
 482:     ARGLIST((wide, multi, size))
 483:         ARG(wchar_t *, wide)
 484:         ARG(char *, multi)
 485:         GRA(size_t, size)
 486: {
 487:     int   retVal = 0;
 488:     
 489: #ifndef SUPPORTS_WCHARS
 490:     if ((multi == NULL) || (*multi == '\000'))
 491:     {
 492:   if (wide) wide[0] = '\0';
 493:   return (0);
 494:     }
 495:     
 496:     for (retVal = 0; retVal < size && multi[retVal] != '\000'; retVal++)
 497:     {
 498:   if (wide != NULL)
 499:   {
 500:       wide[retVal] = multi[retVal];
 501:   }
 502:     }
 503: #else
 504:     retVal = mbtowc(wide, multi, size);
 505: #endif
 506:     return(retVal);
 507: }
 508: 
 509: /*
 510:  * Function:
 511:  *  ptr = getNextSepartor(str);
 512:  * Description:
 513:  *  Parse through a string looking for the next compound string
 514:  *  field separator
 515:  * Inputs:
 516:  *  str - wchar_t* : the address of address of the string to parse
 517:  * Outputs:
 518:  *  ptr - wchar_t* : pointer to character, if found, points to end
 519:  *      of string otherwise ('\0').
 520:  */
 521: static wchar_t* getNextSeparator
 522:     ARGLIST((str))
 523:         GRA(wchar_t *, str) 
 524: {
 525:     wchar_t *ptr = str;
 526:     wchar_t *commonWChars = CStrCommonWideCharsGet();
 527:     
 528:     while (*ptr)
 529:     {
 530:   /*
 531:    * Check for separator
 532:    */
 533:   if ((*ptr == commonWChars[WHash]) ||
 534:       (*ptr == commonWChars[WQuote]) ||
 535:       (*ptr == commonWChars[WColon]))
 536:   {
 537:       return(ptr);
 538:   }
 539:   else if (*ptr == commonWChars[WBackSlash])
 540:   {
 541:       ptr++;
 542:       if (*ptr) ptr++;  /* Skip quoted character */
 543:   }
 544:   else
 545:   {
 546:       ptr++;
 547:   }
 548:     }
 549:     return(ptr);
 550: }
 551: 
 552: /*
 553:  * Function:
 554:  *  more =
 555:  *        extractSegment(str, tagStart, tagLen, txtStart, txtLen, 
 556:  *      pDir, pSep);
 557:  * Description:
 558:  *  Parse through a string version of a compound string and extract
 559:  *  the first compound string segment from the string.
 560:  * Inputs:
 561:  *  str - char** : the address of address of the string to parse
 562:  *  tagStart - char** : address to return pointer to tag start into 
 563:  *  tagLen - int* : address where to return the tag length into
 564:  *  txtStart - char** : address to return the text start into
 565:  *  txtLen - int* : address where to return the text length
 566:  *  pDir - int* : address to return the string direction into
 567:  *  pSep - Boolean * : address to return the separtor into
 568:  * Outputs:
 569:  *  more - Boolean : True if more of the string to parse.
 570:  *      False means done.
 571:  */
 572: static Boolean extractSegment
 573:     ARGLIST((str, tagStart, tagLen, txtStart, txtLen, pDir, pSep))
 574:         ARG(wchar_t **, str)
 575:         ARG(wchar_t **, tagStart)
 576:         ARG(int *, tagLen)
 577:         ARG(wchar_t **, txtStart)
 578:         ARG(int *, txtLen)
 579:         ARG(int *, pDir)
 580:         GRA(Boolean *, pSep)
 581: {
 582:     wchar_t   *start;
 583:     wchar_t   *text;
 584:     int     textL;
 585:     Boolean   tagSeen;
 586:     wchar_t   *tag;
 587:     int     tagL;
 588:     Boolean   modsSeen;
 589:     Boolean   sep;
 590:     int     dir;
 591:     Boolean   done;
 592:     int     *lenUp;
 593:     Boolean   checkDir;
 594:     wchar_t   *commonWChars;
 595:     wchar_t   emptyStrWcs[1];
 596: 
 597:     /*
 598:      * Initialize variables
 599:      */
 600:     text = NULL;
 601:     textL = 0;
 602:     tagSeen = False;
 603:     tag = NULL;
 604:     tagL = 0;
 605:     modsSeen = False;
 606:     dir = XmSTRING_DIRECTION_L_TO_R;
 607:     sep = False;
 608:     done = False;
 609:     lenUp = NULL;
 610:     commonWChars = CStrCommonWideCharsGet();
 611: 
 612:     /*
 613:      * Guard against nulls
 614:      */
 615:     if (!(start = *str))
 616:     {
 617:   start = emptyStrWcs;
 618:   emptyStrWcs[0] = commonWChars[WNull];
 619:     }
 620: 
 621:     /*
 622:      * If the first character of the string isn't a # or a ", then we
 623:      * just have a regular old simple string. Do the same the thing for
 624:      * the empty string.
 625:      */
 626:     if ((*start == '\0') || (start != getNextSeparator(start)))
 627:     {
 628:   text = start;
 629:   if (!(textL = strlenWc(start)))
 630:   {
 631:       text = NULL;
 632:   }
 633:   start += textL;
 634:     }
 635:     else
 636:     {
 637:   done = False;
 638:   while (!done)
 639:   {
 640:       if (*start == commonWChars[WHash])
 641:       {
 642:     if (tagSeen)
 643:     {
 644:         done = True;
 645:         break;
 646:     }
 647:     else
 648:     {
 649:         tagSeen = True;
 650:         tag = ++start;
 651:         start = getNextSeparator(tag);
 652:         if ((tagL = start - tag) == 0)
 653:         {
 654:       tag = NULL;   /* Null tag specified */
 655:         }
 656:     }
 657:       }
 658:       else if (*start == commonWChars[WQuote])
 659:       {
 660:     text = ++start;
 661:     start = getNextSeparator(start);
 662:     while (!((*start == commonWChars[WQuote]) ||
 663:        (*start == commonWChars[WNull])))
 664:     {
 665:         start = getNextSeparator(++start);
 666:     }
 667:     
 668:     if ((textL = start - text) == 0)
 669:     {
 670:         text = NULL;  /* Null text specified  */
 671:     }
 672:                 /*
 673:      * if a quote, skip over it
 674:      */
 675:     if (*start == commonWChars[WQuote])
 676:     {
 677:         start++;
 678:     }
 679:     done = True;
 680:       }
 681:       else if (*start == commonWChars[WColon])
 682:       {
 683:     if (modsSeen)
 684:     {
 685:         done = True;
 686:         break;
 687:     }
 688:     
 689:     /*
 690:      * If the next character is a t or f, the we've got 
 691:      * a separator.
 692:      */
 693:     modsSeen = True;
 694:     checkDir = False;
 695:     start++;
 696:     if ((*start == commonWChars[WideT]) ||
 697:         (*start == commonWChars[WideUT]) ||
 698:         (*start == commonWChars[WideOne]))
 699:     {
 700:         sep = True;
 701:         start++;
 702:         checkDir = True;
 703:     }
 704:     else if ((*start == commonWChars[WideF]) ||
 705:        (*start == commonWChars[WideUF]) ||
 706:        (*start == commonWChars[WideZero]))
 707:     {
 708:         sep = False;
 709:         start++;
 710:         checkDir = True;
 711:     }
 712:     else if ((*start == commonWChars[WideR]) ||
 713:        (*start == commonWChars[WideUR]))
 714:     {
 715:         start++;
 716:         dir = XmSTRING_DIRECTION_R_TO_L;
 717:     }
 718:     else if ((*start == commonWChars[WideL]) ||
 719:        (*start == commonWChars[WideUL]))
 720:     {
 721:         start++;
 722:         dir = XmSTRING_DIRECTION_L_TO_R;
 723:     }
 724:     /*
 725:      * Look for direction if necessary. This requires a bit of
 726:      * look ahead.
 727:      */
 728:     if (checkDir && (*start == commonWChars[WColon]))
 729:     {
 730:         if ((*(start + 1) == commonWChars[WideL]) ||
 731:       (*(start + 1) == commonWChars[WideUL]))
 732:         {
 733:       dir = XmSTRING_DIRECTION_L_TO_R;
 734:       start += 2;
 735:         }
 736:         else if ((*(start + 1) == commonWChars[WideR]) ||
 737:            (*(start + 1) == commonWChars[WideUR]))
 738:         {
 739:       dir = XmSTRING_DIRECTION_R_TO_L;
 740:       start+=2;
 741:         }
 742:     }
 743:       }
 744:             else
 745:       {
 746:     /*
 747:      * A bad string format! We'll just skip the character.
 748:      */
 749:     start++;
 750:       }
 751:   }
 752:     }
 753: 
 754:     /*
 755:      * Now fill in return values
 756:      */
 757:     if (*str)   *str = start;
 758:     if (tagStart) *tagStart = tag;
 759:     if (tagLen)   *tagLen = tagL;
 760:     if (txtStart) *txtStart = text;
 761:     if (txtLen)   *txtLen = textL;
 762:     if (pDir)   *pDir = dir;
 763:     if (pSep)   *pSep = sep;
 764: 
 765:     return ((*start == commonWChars[WNull]) ? False : True);
 766: }
 767: 
 768: /*
 769:  * Function:
 770:  *  xstr = StringToXmString(str);
 771:  * Description:
 772:  *  Parse a string into an XmString.
 773:  * Inputs:
 774:  *  str - char * : the string to parse
 775:  * Outputs:
 776:  *  xstr - XmString : the allocated return structure
 777:  */
 778: static XmString StringToXmString
 779:     ARGLIST((str))
 780:         GRA(char *,str)
 781: {
 782:     static char*  tagBuf = NULL;
 783:     static int    tagBufLen = 0;
 784:     static char*  textBuf = NULL;
 785:     static int    textBufLen = 0;
 786: 
 787:     wchar_t   *ctx;
 788:     wchar_t   *tag;
 789:     int     tagLen;
 790:     wchar_t   *text;
 791:     int     textLen;
 792:     Boolean   sep;
 793:     int     dir;
 794:     
 795:     Boolean   more;
 796:     wchar_t   *wcStr;
 797:     int     curDir;
 798:     XmString    xmStr;
 799:     XmString    s1;
 800:     XmString    s2;
 801: 
 802:     if (!str) return(NULL);
 803: 
 804:     /*
 805:      * For expediencies sake, we'll overallocate this buffer so that
 806:      * the wcs is guaranteed to fit (1 wc per byte in original string).
 807:      */
 808:     wcStr = (wchar_t*)XtMalloc((strlen(str) + 1) * sizeof(wchar_t));
 809:     doMbstowcs(wcStr, str, strlen(str) + 1);
 810: 
 811:     /*
 812:      * Create the beginning segment
 813:      */
 814:     curDir = XmSTRING_DIRECTION_L_TO_R;
 815:     xmStr = XmStringDirectionCreate(curDir);
 816: 
 817:     /*
 818:      * Convert the string.
 819:      */
 820:     more = True;
 821:     ctx = wcStr;
 822:     while (more)
 823:     {
 824:   more = extractSegment(&ctx, &tag, &tagLen,
 825:             &text, &textLen, &dir, &sep);
 826:   /*
 827:    * Pick up a direction change
 828:    */
 829:   if (dir != curDir)
 830:   {
 831: #if defined(VMS) || (defined(__osf__) && defined(__alpha))
 832: #if XmVERSION > 1 || (XmVERSION == 1 && XmREVISION >= 2)
 833:       /*
 834:        * This is required on DEC Windows systems because they've
 835:        * added the REVERT direction.
 836:        */
 837:       s1 = XmStringDirectionCreate(XmSTRING_DIRECTION_REVERT);
 838:       s2 = xmStr;
 839:       xmStr = XmStringConcat(s2, s1);
 840:       XmStringFree(s1);
 841:       XmStringFree(s2);
 842: #endif
 843: #endif
 844:       curDir = dir;
 845:       s1 = XmStringDirectionCreate(curDir);
 846:       s2 = xmStr;
 847:       xmStr = XmStringConcat(s2, s1);
 848:       XmStringFree(s1);
 849:       XmStringFree(s2);
 850: 
 851:   }
 852: 
 853:   /*
 854:    * Create the segment. Text and tag first.
 855:    */
 856:   if (textLen)
 857:   {
 858:       if (textBufLen <= (textLen * sizeof(wchar_t)))
 859:       {
 860:     textBufLen = (textLen + 1) * sizeof(wchar_t);
 861:     textBuf = (char*)XtRealloc(textBuf, textBufLen);
 862:       }
 863:       copyWcsToMbs(textBuf, text, textLen, True);
 864: 
 865:       if (tagLen)
 866:       {
 867:     if (tagBufLen <= (tagLen * sizeof(wchar_t)))
 868:     {
 869:         tagBufLen = (tagLen + 1) * sizeof(wchar_t);
 870:         tagBuf = (char*)XtRealloc(tagBuf, tagBufLen);
 871:     }
 872:     copyWcsToMbs(tagBuf, tag, tagLen, False);
 873:       }
 874:       else
 875:       {
 876:     if (!tagBuf)
 877:     {
 878:         tagBufLen = strlen(XmSTRING_DEFAULT_CHARSET) + 1;
 879:         tagBuf = (char*)XtMalloc(tagBufLen);
 880:     }
 881:     strcpy(tagBuf, XmSTRING_DEFAULT_CHARSET);
 882:       }
 883: 
 884:       s1 = XmStringCreate(textBuf, tagBuf); 
 885:       s2 = xmStr;
 886:       xmStr = XmStringConcat(s2, s1);
 887:       XmStringFree(s1);
 888:       XmStringFree(s2);
 889:   }
 890: 
 891:   /*
 892:    * Add in the separators.
 893:    */
 894:   if (sep)
 895:   {
 896:       s1 = XmStringSeparatorCreate();
 897:       s2 = xmStr;
 898:       xmStr = XmStringConcat(s2, s1);
 899:       XmStringFree(s1);
 900:       XmStringFree(s2);
 901:   }
 902:     }
 903:     
 904:     /*
 905:      * Free up memory and return
 906:      */
 907:     XtFree((char*)wcStr);
 908:     return(xmStr);
 909: }
 910: 
 911: /*
 912:  * Function:
 913:  *      nextCStr = getNextCStrDelim(str);
 914:  * Description:
 915:  *      Find the next unquoted , or \n in the string
 916:  * Input:
 917:  *  str - char * : the input string
 918:  * Output:
 919:  *      nextCStr - char* : pointer to the next delimiter. Returns NULL if no
 920:  *      delimiter found.
 921:  */
 922: static char* getNextCStrDelim
 923:     ARGLIST((str))
 924:         GRA(char *,str)
 925: {
 926:     char  *comma = str;
 927:     Boolean inQuotes = False;
 928:     int   len;
 929: 
 930:     if (!str) return(NULL);
 931:     if (!*str) return(NULL);  /* At end */
 932: 
 933: #ifdef __CENTERLINE__
 934:     mblen((char *)NULL, sizeof(wchar_t));
 935: #else
 936:     mblen(NULL, sizeof(wchar_t));
 937: #endif
 938:     while (*comma)
 939:     {
 940:   if ((len = mblen(comma, sizeof(wchar_t))) > 1)
 941:   {
 942:       comma += len;
 943:       continue;
 944:   }
 945:   
 946:   if (*comma == '\\')
 947:   {
 948:       comma++;  /* Over quote */
 949:       comma += mblen(comma, sizeof(wchar_t));
 950:       continue;
 951:   }
 952: 
 953:   /*
 954:    * See if we have a delimiter
 955:    */
 956:   if (!inQuotes)
 957:   {
 958:       if ((*comma == ',') || (*comma == '\012'))
 959:       {
 960:     return(comma);
 961:       }
 962:   }
 963: 
 964:   /*
 965:    * Deal with quotes
 966:    */
 967:   if (*comma == '\"')
 968:   {
 969:       inQuotes = ~inQuotes;
 970:   }
 971: 
 972:   comma++;
 973:     }
 974: 
 975:     return(NULL);   /* None found */
 976: }
 977: 
 978: /*
 979:  * Function:
 980:  *  cnt = getCStrCount(str);
 981:  * Description:
 982:  *      Get the count of cstrings in a compound string table ascii
 983:  *  format.
 984:  * Input:
 985:  *      str - char * : string to parse
 986:  * Output:
 987:  *      cnt - int : the number of XmStrings found
 988:  */
 989: static int getCStrCount
 990:     ARGLIST((str))
 991:         GRA(char *, str)
 992: {
 993:     int   x = 1;
 994:     char  *newStr;
 995: 
 996:     if (!str) return(0);
 997:     if (!*str) return(0);
 998: 
 999:     while (newStr = getNextCStrDelim(str))
1000:     {
1001:   x++;
1002:   str = ++newStr;
1003:     }
1004:     return(x);
1005: }
1006: 
1007: /*
1008:  * Function:
1009:  *      cwc = CStrCommonWideCharsGet();
1010:  * Description:
1011:  *      Return the array of common wide characters.
1012:  * Input:
1013:  *      None.
1014:  * Output:
1015:  *      cwc - wchar_t * : this array should never be written to or FREEd.
1016:  */
1017: static wchar_t *CStrCommonWideCharsGet()
1018: {
1019:     static wchar_t  *CommonWideChars = NULL;
1020:     /*
1021:      * If you add to this array, don't forget to change the enum in
1022:      * the TYPEDEFS and DEFINES section above to correspond to this
1023:      * array.
1024:      */
1025:     static char *characters[] = { "\000", "\t", "\n", "\r", "\f", "\v",
1026:           "\\", "\"", "#", ":", "f", "l", "n", "r",
1027:           "t", "v", "F", "L", "R", "T", "0", "1" };
1028:   
1029: 
1030:     if (CommonWideChars == NULL)
1031:     {
1032:   int i;
1033: 
1034:   /*
1035:    * Allocate and create the array.
1036:    */
1037:   CommonWideChars = (wchar_t*)XtMalloc(NUM_COMMON_WCHARS * sizeof(wchar_t));
1038:   
1039:   for (i = 0; i < NUM_COMMON_WCHARS; i++)
1040:   {
1041:       (void)dombtowc(&(CommonWideChars[i]), characters[i], 1);
1042:   }
1043:     }
1044:     return(CommonWideChars);
1045: }
1046: 
1047: /*
1048:  * Function:
1049:  *  CONVERTER CvtStringToXmString
1050:  *           and
1051:  *  XmStringCvtDestroy
1052:  * Description:
1053:  *  Convert a string to an XmString. This allows a string contained in
1054:  *  resource file to contain multiple fonts. The syntax for the string
1055:  *  is:
1056:  *    ::[#[font-tag]]"string"[#[font-tag]"string"] ...
1057:  *
1058:  *  note that the # can be escaped (\#).
1059:  *
1060:  * Input:
1061:  * Output:
1062:  *  Standard.
1063:  */
1064: static Boolean CvtStringToXmString
1065:     ARGLIST((d, args, num_args, fromVal, toVal, data))
1066:         ARG(Display *, d)
1067:         UARG(XrmValue *, args)
1068:         ARG(Cardinal *, num_args)
1069:         ARG(XrmValue *, fromVal)
1070:         ARG(XrmValue *, toVal)
1071:         GRAU(XtPointer, data)
1072: {
1073:     static XmString resStr;
1074:     char    *str;
1075: 
1076:     /*
1077:      * This converter takes no parameters
1078:      */
1079:     if (*num_args != 0)
1080:     {
1081:   XtAppWarningMsg(XtDisplayToApplicationContext(d), 
1082:       "cvtStringToXmString",
1083:       "wrongParameters",
1084:       "XtToolkitError",
1085:       "String to XmString converter needs no extra arguments",
1086:       (String *)NULL,
1087:       (Cardinal *)NULL);
1088:     }
1089: 
1090:     /*
1091:      * See if this is a simple string
1092:      */
1093:     str = (char*)fromVal->addr;
1094:     if (strncmp(str, "::", 2))
1095:     {
1096:   resStr = XmStringCreateLtoR(fromVal->addr, XmSTRING_DEFAULT_CHARSET);
1097:     }
1098:     else
1099:     {
1100:   /*
1101:    * Convert into internal format
1102:    */
1103:   resStr = StringToXmString(fromVal->addr + 2); /* skip :: */
1104:     }
1105: 
1106:     /*
1107:      * Done, return result
1108:      */
1109:     if (toVal->addr == NULL)
1110:     {
1111:   toVal->addr = (XTPOINTER)&resStr;
1112:   toVal->size = sizeof(XmString);
1113:     }
1114:     else if (toVal->size < sizeof(XmString))
1115:     {
1116:   toVal->size = sizeof(XmString);
1117:   XtDisplayStringConversionWarning(d, fromVal->addr, "XmString");
1118:   XmStringFree(resStr);
1119:   return(False);
1120:     }
1121:     else 
1122:     {
1123:   *(XmString *)toVal->addr = resStr;
1124:   toVal->size = sizeof(XmString);
1125:     }
1126:     return(True);
1127: }
1128: static void XmStringCvtDestroy
1129:     ARGLIST((app, to, data, args, num_args))
1130:         UARG(XtAppContext, app)
1131:         ARG(XrmValue *, to)
1132:         UARG(XtPointer, data)
1133:         UARG(XrmValue *, args)
1134:         GRAU(Cardinal *, num_args)
1135: {
1136:     XmStringFree(*(XmString*)(to->addr));
1137: }
1138: 
1139: /*
1140:  * Function:
1141:  *      CONVERTER CvtStringToXmStringTable
1142:  *          and
1143:  *      XmStringTableCvtDestroy
1144:  *
1145:  * Description:
1146:  *  Convert a string to an XmString table. This allows a string contained in
1147:  *  resource file to contain multiple fonts. The syntax for the string
1148:  *  is:
1149:  *     compound_string = [#[font-tag]]"string"[#[font-tag]"string"] ...
1150:  *     compound_string_table = [compound_string][,compound_string] ...
1151:  *
1152:  *  note that the # can be escaped (\#).
1153:  *
1154:  * Input:
1155:  * Output:
1156:  *  Standard.
1157:  */
1158: static Boolean CvtStringToXmStringTable
1159:     ARGLIST((d, args, num_args, fromVal, toVal, data))
1160:         ARG(Display *, d)
1161:         ARG(XrmValue *, args)
1162:         ARG(Cardinal *, num_args)
1163:         ARG(XrmValue *, fromVal)
1164:         ARG(XrmValue *, toVal)
1165:         GRAU(XtPointer, data)
1166: {
1167:     static XmString *CStrTable;
1168:     XmString    *tblPtr;
1169:     char    *str;
1170:     char    *tmpBuf;
1171:     char    *nextDelim;
1172:     XrmValue    fVal;
1173:     XrmValue    tVal;
1174: 
1175:     /*
1176:      * This converter takes no parameters
1177:      */
1178:     if (*num_args != 0)
1179:     {
1180:   XtAppWarningMsg
1181:       (XtDisplayToApplicationContext(d), 
1182:        "cvtStringToXmStringTable",
1183:        "wrongParameters",
1184:        "XtToolkitError",
1185:        "String to XmStringTable converter needs no extra arguments",
1186:        (String *)NULL,
1187:        (Cardinal *)NULL);
1188:     }
1189: 
1190:     /*
1191:      * Set str and make sure there's somethin' there
1192:      */
1193:     if (!(str = (char*)fromVal->addr))
1194:     {
1195:   str = "";
1196:     }
1197: 
1198:     /*
1199:      * Allocate the XmStrings + 1 for NULL termination
1200:      */
1201:     CStrTable = (XmString*)XtMalloc((getCStrCount(str) + 1) * sizeof(XmString*));
1202: 
1203:     /*
1204:      * Use the string converter for the strings
1205:      */
1206:     tmpBuf = (char*)XtMalloc(strlen(str) + 1);
1207:     strcpy(tmpBuf, str);
1208:     str = tmpBuf;
1209: 
1210:     /*
1211:      * Create strings
1212:      */
1213:     tblPtr = CStrTable;
1214:     if (*str)
1215:     {
1216:   while (str)
1217:   {
1218:       nextDelim = getNextCStrDelim(str);
1219:       
1220:       /*
1221:        * Overwrite nextDelim
1222:        */
1223:       if (nextDelim)
1224:       {
1225:     *nextDelim = '\0';
1226:     nextDelim++;
1227:       }
1228:       
1229:       /*
1230:        * Convert it
1231:        */
1232:       fVal.size = strlen(str) + 1;
1233:       fVal.addr = str;
1234:       tVal.size = sizeof(XTPOINTER);
1235:       tVal.addr = (XTPOINTER)tblPtr;
1236:       
1237:       /*
1238:        * Call converter ourselves since this is used to create
1239:        * the strings in the table we create. We need to do this
1240:        * since we don't have a widget to send to the XtConvertAndStore
1241:        * function. Side effects are that we can never get these
1242:        * compound strings cached and that no destructor function is
1243:        * called when the strings leave existance, but we nuke 'em
1244:        * in the XmStringTable destuctor.
1245:        */
1246:       CvtStringToXmString(d, args, num_args, &fVal, &tVal, NULL);
1247:       tblPtr++;
1248:       str = nextDelim;
1249:   }
1250:     }
1251:     XtFree(tmpBuf);
1252: 
1253:     /*
1254:      * Null terminate
1255:      */
1256:     *tblPtr = NULL;
1257: 
1258:     /*
1259:      * Done, return result
1260:      */
1261:     if (toVal->addr == NULL)
1262:     {
1263:   toVal->addr = (XTPOINTER)&CStrTable;
1264:   toVal->size = sizeof(XmString);
1265:     }
1266:     else if (toVal->size < sizeof(XmString*))
1267:     {
1268:   toVal->size = sizeof(XmString*);
1269:   XtDisplayStringConversionWarning(d, fromVal->addr, "XmStringTable");
1270: 
1271:   tblPtr = CStrTable;
1272:   while (*tblPtr)
1273:   {
1274:       XmStringFree(*tblPtr);
1275:   }
1276:   XtFree((char*)CStrTable);
1277:   return(False);
1278:     }
1279:     else 
1280:     {
1281:   *(XmString **)toVal->addr = CStrTable;
1282:   toVal->size = sizeof(XmString*);
1283:     }
1284:     return(True);
1285: }
1286: static void XmStringTableCvtDestroy
1287:     ARGLIST((app, to, data, args, num_args))
1288:         UARG(XtAppContext, app)
1289:         ARG(XrmValue *, to)
1290:         UARG(XtPointer, data)
1291:         UARG(XrmValue *, args)
1292:         GRAU(Cardinal *, num_args)
1293: {
1294:     XmString  *tblPtr = *(XmString**)(to->addr);
1295: 
1296:     while (*tblPtr)
1297:     {
1298:   XmStringFree(*tblPtr);
1299:     }
1300:     XtFree((char*)(*(XmString**)(to->addr)));
1301: }    
1302: 
1303: /*****************************************************************************
1304:  *  GLOBAL CODE
1305:  *****************************************************************************/
1306: 
1307: /*
1308:  * Function:
1309:  *      RegisterBxConverters(appContext);
1310:  * Description:
1311:  *      This globally available function installs all the converters necessary
1312:  *  to run BuilderXcessory generated interfaces that use compound
1313:  *  strings. This is necessary since Motif has not supplied very smart
1314:  *  converters.
1315:  * Input:
1316:  *      appContext - XtAppContext : the application context
1317:  * Output:
1318:  *      None
1319:  */
1320: void RegisterBxConverters
1321:     ARGLIST((appContext))
1322:         GRA(XtAppContext, appContext)
1323: {
1324:     XtAppSetTypeConverter(appContext, XmRString, XmRXmString,
1325:         (XtTypeConverter)CvtStringToXmString,
1326:         NULL, 0, XtCacheNone, XmStringCvtDestroy);
1327: 
1328:     XtAppSetTypeConverter(appContext, XmRString, XmRXmStringTable,
1329:         (XtTypeConverter)CvtStringToXmStringTable,
1330:         NULL, 0, XtCacheNone, XmStringTableCvtDestroy);
1331: }
1332: 
1333: /*
1334:  * Function:
1335:  *      CONVERT(w, from_string, to_type, to_size, success);
1336:  * Description:
1337:  *      A converter wrapper for convenience from BuilderXcessory.
1338:  * Input:
1339:  *      w - Widget : the widget to use for conversion
1340:  *  from_string - char * : the string to convert from
1341:  *  to_type - char * : the type to convert to
1342:  *  to_size - int : the size of the conversion result
1343:  *  success - Boolean* : Set to the result value of the conversion
1344:  * Output:
1345:  *      None
1346:  */
1347: #ifndef IGNORE_CONVERT
1348: XtPointer CONVERT
1349:     ARGLIST((w, from_string, to_type, to_size, success))
1350:         ARG(Widget, w)
1351:         ARG(char *, from_string)
1352:         ARG(char *, to_type)
1353:         ARG(int, to_size)
1354:         GRA(Boolean *, success)
1355: {
1356:     XrmValue    fromVal, toVal; /* resource holders   */
1357:     Boolean   convResult; /* return value     */
1358:     XtPointer   val;    /* Pointer size return value    */
1359: 
1360:     to_size = 0;
1361: 
1362:     /*
1363:      * We will assume that the conversion is going to fail and change this
1364:      * value later if the conversion is a success.
1365:      */
1366:     *success = False;
1367: 
1368:     /*
1369:      * Since we are converting from a string to some type we need to
1370:      * set the fromVal structure up with the string information that
1371:      * the caller passed in.
1372:      */
1373:     fromVal.size = strlen(from_string) + 1;
1374:     fromVal.addr = from_string;
1375: 
1376:     /*
1377:      * Since we are not sure what type and size of data we are going to
1378:      * get back we will set this up so that the converter will point us
1379:      * at a block of valid data.
1380:      */
1381:     toVal.size = 0;
1382:     toVal.addr = NULL;
1383: 
1384:     /*
1385:      * Now lets try to convert this data by calling this handy-dandy Xt
1386:      * routine.
1387:      */
1388:     convResult = XtConvertAndStore(w, XmRString, &fromVal, to_type, &toVal);
1389:     
1390: 
1391:     /*
1392:      * Now we have two conditions here.  One the conversion was a success
1393:      * and two the conversion failed.
1394:      */
1395:     if(!convResult)
1396:     {
1397:   /*
1398:    * If this conversion failed that we can pretty much return right
1399:    * here because there is nothing else we can do.
1400:    */
1401:   return((XtPointer) NULL);
1402:     }
1403: 
1404:     /*
1405:      * If we get this far that means we did the conversion and all is
1406:      * well.  Now we have to handle the special cases for type and
1407:      * size constraints.
1408:      */
1409:     if(!strcmp(to_type, "String"))
1410:     {
1411:   /*
1412:    * Since strings are handled different in Xt we have to deal with
1413:    * the conversion from a string to a string.  When this happens the
1414:    * toVal.size will hold the strlen of the string so generic
1415:    * conversion code can't handle it.  It is possible for a string to
1416:    * string conversion to happen so we do have to watch for it.
1417:    */
1418:   val = (XTPOINTER)toVal.addr;
1419:     }
1420:     else if(!strcmp(to_type, "Double"))
1421:     {
1422:   val = (XTPOINTER)((double*)toVal.addr);
1423:     }
1424:     else if(!strcmp(to_type, "Float"))
1425:     {
1426:   val = (XTPOINTER)((float*)toVal.addr);
1427:     }
1428:     else
1429:     {
1430:   /*
1431:    * Here is the generic conversion return value handler.  This 
1432:    * just does some size specific casting so that value that we
1433:    * return is in the correct bytes of the XtPointer that we
1434:    * return.  Here we check all sizes from 1 to 8 bytes.
1435:    */
1436:   switch(toVal.size)
1437:   {
1438:   case 1:
1439:       val = (XTPOINTER)(*(char*)toVal.addr);
1440:       break;
1441:   case 2:
1442:       val = (XTPOINTER)(*(short*)toVal.addr);
1443:       break;
1444:   case 4:
1445:       val = (XTPOINTER)(*(int*)toVal.addr);
1446:       break;
1447:   case 8:
1448:   default:
1449:       val = (XTPOINTER)(*(long*)toVal.addr);
1450:       break;
1451:   }
1452:     }
1453: 
1454:     /*
1455:      * Well everything is done and the conversion was a success so lets
1456:      * set the success flag to True.
1457:      */
1458:     *success = convResult;
1459: 
1460:     /*
1461:      * Finally lets return the converted value.
1462:      */
1463:     /*SUPPRESS 80*/
1464:     return(val);
1465: }
1466: #endif
1467: 
1468: /*
1469:  * Function:
1470:  *      MENU_POST(p, mw, ev, dispatch);
1471:  * Description:
1472:  *      A converter wrapper for convenience from BuilderXcessory.
1473:  * Input:
1474:  *      p - Widget : the widget to post
1475:  *  mw - XtPointer : the menu widget
1476:  *  ev - XEvent* : the event that caused the menu post
1477:  *  dispatch - Boolean* : not used
1478:  * Output:
1479:  *      None
1480:  */
1481: 
1482: #ifndef IGNORE_MENU_POST
1483: 
1484: void MENU_POST
1485:     ARGLIST((p, mw, ev, dispatch))
1486:         UARG(Widget, p)
1487:         ARG(XtPointer, mw)
1488:         ARG(XEvent *, ev)
1489:         GRAU(Boolean *, dispatch)
1490: {
1491:     Arg args[2];
1492:     int argcnt;
1493:     int button;
1494:     Widget m = (Widget)mw;
1495:     XButtonEvent *e = (XButtonEvent *)ev;
1496: 
1497:     argcnt = 0;
1498:     XtSetArg(args[argcnt], XmNwhichButton, &button);
1499:     argcnt++;
1500:     XtGetValues(m, args, argcnt);
1501:     if(e->button != button) return;
1502:     XmMenuPosition(m, e);
1503:     XtManageChild(m);
1504: }
1505: #endif
1506: 
1507: /*
1508:  * Function:
1509:  *      SET_BACKGROUND_COLOR(w, args, argcnt, bg_color);
1510:  * Description:
1511:  *      Sets the background color and shadows of a widget.
1512:  * Input:
1513:  *      w - The widget to set the background color on.
1514:  *      args, argcnt - The argument list so far.
1515:  *      bg_color - The new background color as a pixel.
1516:  * Output:
1517:  *      none
1518:  *
1519:  *  NOTES:  This assumes that args later in the argument list
1520:  *          override those already in the list.  Therfore i f
1521:  *          there are shadow colors later in the list they will win.
1522:  *        
1523:  *          There is no need to use this function when creating a widget
1524:  *          only when doing a set values, shadow colors are automatically
1525:  *          calculated at creation time.
1526:  */
1527: 
1528: void SET_BACKGROUND_COLOR
1529:     ARGLIST((w, args, argcnt, bg_color))
1530:         ARG(Widget, w)
1531:         ARG(ArgList, args)
1532:         ARG(Cardinal *, argcnt)
1533:         GRA(Pixel, bg_color)
1534: {
1535:     int   i;
1536:     int   topShadowLoc;
1537:     int   bottomShadowLoc;
1538:     int   selectLoc;
1539:     int   fgLoc;
1540: 
1541: #if ((XmVERSION == 1) && (XmREVISION > 0))
1542: 
1543:     /*
1544:      * Walk through the arglist to see if the user set the top or
1545:      * bottom shadow colors.
1546:      */
1547:     selectLoc = topShadowLoc =  bottomShadowLoc = UNSET;
1548:     for (i = 0; i < *argcnt; i++)
1549:     {
1550:   if ((strcmp(args[i].name, XmNtopShadowColor) == 0) ||
1551:       (strcmp(args[i].name, XmNtopShadowPixmap) == 0))
1552:   {
1553:       topShadowLoc = i;
1554:   }
1555:   else if ((strcmp(args[i].name, XmNbottomShadowColor) == 0) ||
1556:      (strcmp(args[i].name, XmNbottomShadowPixmap) == 0))
1557:   {
1558:       bottomShadowLoc = i;
1559:   }
1560:   else if (strcmp(args[i].name, XmNarmColor) == 0)
1561:   {
1562:       selectLoc = i;
1563:   }
1564:   else if (strcmp(args[i].name, XmNforeground) == 0)
1565:   {
1566:       fgLoc = i;
1567:   }
1568:     }
1569: 
1570:     /*
1571:      * If either the top or bottom shadow are not set then we
1572:      * need to use XmGetColors to get the shadow colors from the backgound
1573:      * color and add those that are not already in the arglist to the
1574:      * arglist.
1575:      * 
1576:      */
1577:     if ((bottomShadowLoc == UNSET) ||
1578:   (topShadowLoc == UNSET) ||
1579:   (selectLoc == UNSET) ||
1580:   (fgLoc == UNSET))
1581:     {
1582:   Arg   larg[1];
1583:   Colormap  cmap;
1584:   Pixel   topShadow;
1585:   Pixel   bottomShadow;
1586:   Pixel   select;
1587:   Pixel   fgColor;
1588: 
1589:   XtSetArg(larg[0], XmNcolormap, &cmap);
1590:   XtGetValues(w, larg, 1);
1591:   XmGetColors(XtScreen(w), cmap, bg_color, 
1592:         &fgColor, &topShadow, &bottomShadow, &select);
1593: 
1594:   if (topShadowLoc == UNSET)
1595:   {
1596:       XtSetArg(args[*argcnt], XmNtopShadowColor, topShadow); 
1597:       (*argcnt)++;
1598:   }
1599:   
1600:   if (bottomShadowLoc == UNSET)
1601:   {
1602:       XtSetArg(args[*argcnt], XmNbottomShadowColor, bottomShadow); 
1603:       (*argcnt)++;
1604:   }
1605: 
1606:   if (selectLoc == UNSET)
1607:   {
1608:       XtSetArg(args[*argcnt], XmNarmColor, select); 
1609:       (*argcnt)++;
1610:   }
1611: 
1612:   if (fgLoc == UNSET)
1613:   {
1614:       XtSetArg(args[*argcnt], XmNforeground, fgColor); 
1615:       (*argcnt)++;
1616:   }
1617:     }
1618: #endif
1619: 
1620:     XtSetArg(args[*argcnt], XmNbackground, bg_color); (*argcnt)++;
1621: }
1622: 
1623: /*
1624:  * Function:
1625:  *  w = BxFindTopShell(start);
1626:  * Description:
1627:  *  Go up the hierarhcy until we find a shell widget.
1628:  * Input:
1629:  *      start - Widget : the widget to start with.
1630:  * Output:
1631:  *  w - Widget : the shell widget.
1632:  */
1633: #ifndef _BX_FIND_TOP_SHELL
1634: #define _BX_FIND_TOP_SHELL
1635: 
1636: Widget BxFindTopShell
1637:     ARGLIST((start))
1638:         GRA(Widget, start)
1639: {
1640:     Widget  p;
1641:     
1642:     while(p = XtParent(start))
1643:     {
1644:   start = p;
1645:     }
1646:     return(start);
1647: }
1648: #endif /* _BX_FIND_TOP_SHELL */
1649: 
1650: /*
1651:  * Function:
1652:  *  BxWidgetIdsFromNames(ref, cbName, stringList)
1653:  * Description:
1654:  *  Return an array of widget ids from a list of widget names.
1655:  * Input:
1656:  *  ref - Widget : reference widget.
1657:  *  cbName - char* : callback name.
1658:  *  stringList - char*: list of widget names.
1659:  * Output:
1660:  *  WidgetList : array of widget IDs.
1661:  */
1662: 
1663: #ifndef _BX_WIDGETIDS_FROM_NAMES
1664: #define _BX_WIDGETIDS_FROM_NAMES
1665: 
1666: WidgetList BxWidgetIdsFromNames
1667:     ARGLIST((ref, cbName, stringList))
1668:         ARG(Widget, ref)
1669:         ARG(char, *cbName)
1670:         GRA(char, *stringList)
1671: {
1672:     WidgetList  wgtIds = NULL;
1673:     int   wgtCount = 0;
1674:     Widget  inst;
1675:     Widget  current;
1676:     String  tmp;
1677:     String  start;
1678:     String  widget;
1679:     char       *ptr;
1680:     
1681:     /*
1682:      * For backward compatibility, remove [ and ] from the list.
1683:      */
1684:     tmp = start = XtNewString(stringList);
1685:     if((start = strchr(start, '[')) != NULL) start++;
1686:     else start = tmp;
1687:     
1688:     while((start && *start) && isspace(*start))
1689:     {
1690:   start++;
1691:     }
1692:     ptr = strrchr(start, ']');
1693:     if (ptr)
1694:     {
1695:   *ptr = '\0';
1696:     }
1697:     
1698:     ptr = start + strlen(start) - 1;
1699:     while(ptr && *ptr)
1700:     {
1701:   if (isspace(*ptr))
1702:   {
1703:       ptr--;
1704:   }
1705:   else
1706:   {
1707:       ptr++;
1708:       break;
1709:   }
1710:     }
1711:     if (ptr && *ptr)
1712:     {
1713:   *ptr = '\0';
1714:     }
1715:     
1716:     /*
1717:      * start now points to the first character after the [.
1718:      * the list is now either empty, one, or more widget
1719:      * instance names.
1720:      */
1721:     start = strtok(start, ",");
1722:     while(start)
1723:     {
1724:         while((start && *start) && isspace(*start))
1725:         {
1726:             start++;
1727:         }
1728:         ptr = start + strlen(start) - 1;
1729:         while(ptr && *ptr)
1730:         {
1731:             if (isspace(*ptr))
1732:             {
1733:                 ptr--;
1734:             }
1735:             else
1736:             {
1737:                 ptr++;
1738:                 break;
1739:             }
1740:         }
1741:         if (ptr && *ptr)
1742:         {
1743:             *ptr = '\0';
1744:         }
1745: 
1746:   /*
1747:    * Form a string to use with XtNameToWidget().
1748:    */
1749:         widget = (char *)XtMalloc((strlen(start) + 2) * sizeof(char));
1750:         sprintf(widget, "*%s", start);
1751:   
1752:   /*
1753:    * Start at this level and continue up until the widget is found 
1754:    * or until the top of the hierarchy is reached.
1755:    */
1756:   current = ref;
1757:   while (current != NULL)
1758:   {
1759:       inst = XtNameToWidget(current, widget);
1760:       if (inst != NULL )
1761:       {
1762:     wgtCount++;
1763:     wgtIds = (WidgetList)XtRealloc((char *)wgtIds, 
1764:                  wgtCount * sizeof(Widget));
1765:     wgtIds[wgtCount - 1] = inst;
1766:     break;
1767:       }
1768:       current = XtParent(current);
1769:   }
1770: 
1771:   if (current == NULL)
1772:         {
1773:             printf("Callback Error (%s):\n\t\
1774: Cannot find widget %s\n", cbName, widget);
1775:         }
1776:         XtFree(widget);
1777:         start = strtok(NULL, ",");
1778:     }
1779: 
1780:     /*
1781:      * NULL terminate the list.
1782:      */
1783:     wgtIds = (WidgetList)XtRealloc((char *)wgtIds, 
1784:            (wgtCount + 1) * sizeof(Widget));
1785:     wgtIds[wgtCount] = NULL;
1786: 
1787:     XtFree((char *)tmp);
1788:     return(wgtIds);
1789: }
1790: #endif /* _BX_WIDGETIDS_FROM_NAMES */
1791: 
1792: XtPointer SINGLE
1793:     ARGLIST((val))
1794:     GRA(float, val)
1795: {
1796:     XtPointer pointer;
1797:     
1798:     pointer = (XtPointer)XtMalloc(sizeof(float));
1799:     if ( pointer != NULL ) *((float *)pointer) = val;
1800:     return(pointer);
1801: }
1802: 
1803: XtPointer DOUBLE
1804:     ARGLIST((val))
1805:     GRA(double, val)
1806: {
1807:     XtPointer pointer;
1808:     
1809:     pointer = (XtPointer)XtMalloc(sizeof(double));
1810:     if ( pointer != NULL ) *((double *)pointer) = val;
1811:     return(pointer);
1812: }
1813: 
1814: 
1815: /****************************************************************************
1816:  *
1817:  * Big chunk of code inserted from Bull (based on modified 3.3)
1818:  *
1819:  ****************************************************************************/
1820: 
1821: #ifndef IGNORE_XPM_PIXMAP
1822: 
1823: #ifndef USE_XPM_LIBRARY
1824: 
1825: #ifdef SYSV
1826: #include <memory.h>
1827: #endif
1828: 
1829: /*
1830:  * Copyright 1990, 1991 GROUPE BULL
1831:  *
1832:  * Permission to use, copy, modify, and distribute this software and its
1833:  * documentation for any purpose and without fee is hereby granted, provided
1834:  * that the above copyright notice appear in all copies and that both that
1835:  * copyright notice and this permission notice appear in supporting
1836:  * documentation, and that the name of GROUPE BULL not be used in advertising
1837:  * or publicity pertaining to distribution of the software without specific,
1838:  * written prior permission.  GROUPE BULL makes no representations about the
1839:  * suitability of this software for any purpose.  It is provided "as is"
1840:  * without express or implied warranty.
1841:  *
1842:  * GROUPE BULL disclaims all warranties with regard to this software,
1843:  * including all implied warranties of merchantability and fitness,
1844:  * in no event shall GROUPE BULL be liable for any special,
1845:  * indirect or consequential damages or any damages
1846:  * whatsoever resulting from loss of use, data or profits,
1847:  * whether in an action of contract, negligence or other tortious
1848:  * action, arising out of or in connection with the use 
1849:  * or performance of this software.
1850:  *
1851:  */
1852: 
1853: /* Return ErrorStatus codes:
1854:  * null     if full success
1855:  * positive if partial success
1856:  * negative if failure
1857:  */
1858: 
1859: #define BxXpmColorError    1
1860: #define BxXpmSuccess       0
1861: #define BxXpmOpenFailed   -1
1862: #define BxXpmFileInvalid  -2
1863: #define BxXpmNoMemory     -3
1864: #define BxXpmColorFailed  -4
1865: 
1866: typedef struct {
1867:     char *name;                         /* Symbolic color name */
1868:     char *value;                        /* Color value */
1869:     Pixel pixel;                        /* Color pixel */
1870: }   BxXpmColorSymbol;
1871: 
1872: typedef struct {
1873:     unsigned long valuemask;            /* Specifies which attributes are
1874:                                          * defined */
1875: 
1876:     Visual *visual;                     /* Specifies the visual to use */
1877:     Colormap colormap;                  /* Specifies the colormap to use */
1878:     unsigned int depth;                 /* Specifies the depth */
1879:     unsigned int width;                 /* Returns the width of the created
1880:                                          * pixmap */
1881:     unsigned int height;                /* Returns the height of the created
1882:                                          * pixmap */
1883:     unsigned int x_hotspot;             /* Returns the x hotspot's
1884:                                          * coordinate */
1885:     unsigned int y_hotspot;             /* Returns the y hotspot's
1886:                                          * coordinate */
1887:     unsigned int cpp;                   /* Specifies the number of char per
1888:                                          * pixel */
1889:     Pixel *pixels;                      /* List of used color pixels */
1890:     unsigned int npixels;               /* Number of pixels */
1891:     BxXpmColorSymbol *colorsymbols;       /* Array of color symbols to
1892:                                          * override */
1893:     unsigned int numsymbols;            /* Number of symbols */
1894:     char *rgb_fname;                    /* RGB text file name */
1895: 
1896:     /* Infos */
1897:     unsigned int ncolors;               /* Number of colors */
1898:     char ***colorTable;                 /* Color table pointer */
1899:     char *hints_cmt;                    /* Comment of the hints section */
1900:     char *colors_cmt;                   /* Comment of the colors section */
1901:     char *pixels_cmt;                   /* Comment of the pixels section */
1902:     unsigned int mask_pixel;            /* Transparent pixel's color table
1903:                                          * index */
1904: }      BxXpmAttributes;
1905: 
1906: /* Xpm attribute value masks bits */
1907: #define BxXpmVisual          (1L<<0)
1908: #define BxXpmColormap        (1L<<1)
1909: #define BxXpmDepth           (1L<<2)
1910: #define BxXpmSize            (1L<<3)      /* width & height */
1911: #define BxXpmHotspot         (1L<<4)      /* x_hotspot & y_hotspot */
1912: #define BxXpmCharsPerPixel   (1L<<5)
1913: #define BxXpmColorSymbols    (1L<<6)
1914: #define BxXpmRgbFilename     (1L<<7)
1915: #define BxXpmInfos           (1L<<8)      /* all infos members */
1916: 
1917: #define BxXpmReturnPixels    (1L<<9)
1918: #define BxXpmReturnInfos     BxXpmInfos
1919: 
1920: /*
1921:  * minimal portability layer between ansi and KR C
1922:  */
1923: 
1924: /* forward declaration of functions with prototypes */
1925: 
1926: #ifdef NeedFunctionPrototypes
1927: #define LFUNC(f, t, p) static t f p
1928: #else
1929: #define LFUNC(f, t, p) static t f()
1930: #endif
1931: 
1932: /*
1933:  * functions declarations
1934:  */
1935: 
1936: #ifdef __cplusplus
1937: extern "C" {
1938: #endif
1939: 
1940: LFUNC(XpmCreatePixmapFromData, int, (Display * display,
1941:              Drawable d,
1942:              char **data,
1943:              Pixmap * pixmap_return,
1944:              Pixmap * shapemask_return,
1945:              BxXpmAttributes * attributes));
1946: 
1947: LFUNC(XpmCreateImageFromData, int, (Display * display,
1948:             char **data,
1949:             XImage ** image_return,
1950:             XImage ** shapemask_return,
1951:             BxXpmAttributes * attributes));
1952: 
1953: LFUNC(XpmFreeAttributes, void, (BxXpmAttributes * attributes));
1954: 
1955: #ifdef __cplusplus
1956: }                                       /* for C++ V2.0 */
1957: #endif
1958: 
1959: 
1960: typedef struct {
1961:     unsigned int type;
1962:     union {
1963:         FILE *file;
1964:         char **data;
1965:     }     stream;
1966:     char *cptr;
1967:     unsigned int line;
1968:     int CommentLength;
1969:     char Comment[BUFSIZ];
1970:     char *Bcmt, *Ecmt, Bos, Eos;
1971:     unsigned int InsideString;          /* used during parsing: 0 or 1
1972:                                          * whether we are inside or not */
1973: }      bxxpmData;
1974: 
1975: #define BXXPMARRAY 0
1976: #define BXXPMFILE  1
1977: #define BXXPMPIPE  2
1978: 
1979: typedef unsigned char byte;
1980: 
1981: #define BX_TRANSPARENT_COLOR "None"        /* this must be a string! */
1982: 
1983: /* number of BxXpmColorKeys */
1984: #define BXNKEYS 5
1985: 
1986: /*
1987:  * key numbers for visual type, they must fit along with the number key of
1988:  * each corresponding element in BxXpmColorKeys[] defined in xpm.h
1989:  */
1990: #define BXMONO    2
1991: #define BXGRAY4   3
1992: #define BXGRAY    4
1993: #define BXCOLOR   5
1994: 
1995: /* structure containing data related to an Xpm pixmap */
1996: typedef struct {
1997:     char *name;
1998:     unsigned int width;
1999:     unsigned int height;
2000:     unsigned int cpp;
2001:     unsigned int ncolors;
2002:     char ***colorTable;
2003:     unsigned int *pixelindex;
2004:     XColor *xcolors;
2005:     char **colorStrings;
2006:     unsigned int mask_pixel;            /* mask pixel's colorTable index */
2007: }      bxxpmInternAttrib;
2008: 
2009: #define BX_UNDEF_PIXEL 0x80000000
2010: 
2011: char *BxXpmColorKeys[] =
2012: {
2013:  "s",         /* key #1: symbol */
2014:  "m",         /* key #2: mono visual */
2015:  "g4",          /* key #3: 4 grays visual */
2016:  "g",         /* key #4: gray visual */
2017:  "c",         /* key #5: color visual */
2018: };
2019: 
2020: /* XPM private routines */
2021: 
2022: LFUNC(xpmCreateImage, int, (Display * display,
2023:                            bxxpmInternAttrib * attrib,
2024:                            XImage ** image_return,
2025:                            XImage ** shapeimage_return,
2026:                            BxXpmAttributes * attributes));
2027: 
2028: LFUNC(xpmParseData, int, (bxxpmData * data,
2029:                          bxxpmInternAttrib * attrib_return,
2030:                          BxXpmAttributes * attributes));
2031: 
2032: LFUNC(BxXpmVisualType, int, (Visual * visual));
2033: LFUNC(xpmFreeColorTable, void, (char ***colorTable, int ncolors));
2034: 
2035: LFUNC(xpmInitInternAttrib, void, (bxxpmInternAttrib * xmpdata));
2036: 
2037: LFUNC(xpmFreeInternAttrib, void, (bxxpmInternAttrib * xmpdata));
2038: 
2039: LFUNC(xpmSetAttributes, void, (bxxpmInternAttrib * attrib,
2040:                              BxXpmAttributes * attributes));
2041: 
2042: /* I/O utility */
2043: 
2044: LFUNC(xpmNextString, void, (bxxpmData * mdata));
2045: LFUNC(xpmNextUI, int, (bxxpmData * mdata, unsigned int *ui_return));
2046: LFUNC(xpmGetC, int, (bxxpmData * mdata));
2047: LFUNC(xpmUngetC, int, (int c, bxxpmData * mdata));
2048: LFUNC(xpmNextWord, unsigned int, (bxxpmData * mdata, char *buf));
2049: LFUNC(xpmGetCmt, void, (bxxpmData * mdata, char **cmt));
2050: LFUNC(xpmOpenArray, int, (char **data, bxxpmData * mdata));
2051: LFUNC(XpmDataClose, void, (bxxpmData * mdata));
2052: 
2053: /* RGB utility */
2054: 
2055: LFUNC(xpm_xynormalizeimagebits, void, (register unsigned char *bp,
2056:                                      register XImage * img));
2057: LFUNC(xpm_znormalizeimagebits, void, (register unsigned char *bp,
2058:                                     register XImage * img));
2059: 
2060: /* Image utility */
2061: 
2062: LFUNC(SetColor, int, (Display * display, Colormap colormap, char *colorname,
2063:           unsigned int color_index, Pixel * image_pixel,
2064:           Pixel * mask_pixel, unsigned int *mask_pixel_index));
2065: 
2066: LFUNC(CreateXImage, int, (Display * display, Visual * visual,
2067:         unsigned int depth, unsigned int width,
2068:         unsigned int height, XImage ** image_return));
2069: 
2070: LFUNC(SetImagePixels, void, (XImage * image, unsigned int width,
2071:           unsigned int height, unsigned int *pixelindex,
2072:           Pixel * pixels));
2073: 
2074: LFUNC(SetImagePixels32, void, (XImage * image, unsigned int width,
2075:             unsigned int height, unsigned int *pixelindex,
2076:             Pixel * pixels));
2077: 
2078: LFUNC(SetImagePixels16, void, (XImage * image, unsigned int width,
2079:             unsigned int height, unsigned int *pixelindex,
2080:             Pixel * pixels));
2081: 
2082: LFUNC(SetImagePixels8, void, (XImage * image, unsigned int width,
2083:            unsigned int height, unsigned int *pixelindex,
2084:            Pixel * pixels));
2085: 
2086: LFUNC(SetImagePixels1, void, (XImage * image, unsigned int width,
2087:            unsigned int height, unsigned int *pixelindex,
2088:            Pixel * pixels));
2089: 
2090: LFUNC(atoui, unsigned int, (char *p, unsigned int l, unsigned int *ui_return));
2091: 
2092: /*
2093:  * Macros
2094:  *
2095:  * The BXXYNORMALIZE macro determines whether XY format data requires
2096:  * normalization and calls a routine to do so if needed. The logic in
2097:  * this module is designed for LSBFirst byte and bit order, so
2098:  * normalization is done as required to present the data in this order.
2099:  *
2100:  * The BXZNORMALIZE macro performs byte and nibble order normalization if
2101:  * required for Z format data.
2102:  *
2103:  * The BXXYINDEX macro computes the index to the starting byte (char) boundary
2104:  * for a bitmap_unit containing a pixel with coordinates x and y for image
2105:  * data in XY format.
2106:  *
2107:  * The BXZINDEX* macros compute the index to the starting byte (char) boundary
2108:  * for a pixel with coordinates x and y for image data in ZPixmap format.
2109:  *
2110:  */
2111: 
2112: #define BXXYNORMALIZE(bp, img) \
2113:     if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \
2114:         xpm_xynormalizeimagebits((unsigned char *)(bp), img)
2115: 
2116: #define BXZNORMALIZE(bp, img) \
2117:     if (img->byte_order == MSBFirst) \
2118:         xpm_znormalizeimagebits((unsigned char *)(bp), img)
2119: 
2120: #define BXXYINDEX(x, y, img) \
2121:     ((y) * img->bytes_per_line) + \
2122:     (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3)
2123: 
2124: #define BXZINDEX(x, y, img) ((y) * img->bytes_per_line) + \
2125:     (((x) * img->bits_per_pixel) >> 3)
2126: 
2127: #define BXZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2)
2128: 
2129: #define BXZINDEX16(x, y, img) ((y) * img->bytes_per_line) + ((x) << 1)
2130: 
2131: #define BXZINDEX8(x, y, img) ((y) * img->bytes_per_line) + (x)
2132: 
2133: #define BXZINDEX1(x, y, img) ((y) * img->bytes_per_line) + ((x) >> 3)
2134: 
2135: #if __STDC__
2136: #define Const const
2137: #else
2138: #define Const
2139: #endif
2140: 
2141: 
2142: 
2143: static unsigned int atoui
2144: ARGLIST((p, l, ui_return))
2145: ARG(register char *, p)
2146: ARG(unsigned int, l)
2147: GRA(unsigned int *, ui_return)
2148: {
2149:     register int n, i;
2150: 
2151:     n = 0;
2152:     for (i = 0; i < l; i++)
2153:         if (*p >= '0' && *p <= '9')
2154:             n = n * 10 + *p++ - '0';
2155:         else
2156:             break;
2157: 
2158:     if (i != 0 && i == l) {
2159:         *ui_return = n;
2160:         return 1;
2161:     } else
2162:         return 0;
2163: }
2164: 
2165: static int XpmCreatePixmapFromData
2166: ARGLIST((display, d, data, pixmap_return, shapemask_return, attributes))
2167: ARG(Display *, display)
2168: ARG(Drawable, d)
2169: ARG(char **, data)
2170: ARG(Pixmap *, pixmap_return)
2171: ARG(Pixmap *, shapemask_return)
2172: GRA(BxXpmAttributes *,attributes)
2173: {
2174:     XImage *image, **imageptr = NULL;
2175:     XImage *shapeimage, **shapeimageptr = NULL;
2176:     int ErrorStatus;
2177:     XGCValues gcv;
2178:     GC gc;
2179: 
2180:     /*
2181:      * initialize return values
2182:      */
2183:     if (pixmap_return) {
2184:         *pixmap_return = (Pixmap) NULL;
2185:         imageptr = &image;
2186:     }
2187:     if (shapemask_return) {
2188:         *shapemask_return = (Pixmap) NULL;
2189:         shapeimageptr = &shapeimage;
2190:     }
2191: 
2192:     /*
2193:      * create the images
2194:      */
2195:     ErrorStatus = XpmCreateImageFromData(display, data, imageptr,
2196:                                          shapeimageptr, attributes);
2197:     if (ErrorStatus < 0)
2198:         return (ErrorStatus);
2199: 
2200:     /*
2201:      * create the pixmaps
2202:      */
2203:     if (imageptr && image) {
2204:         *pixmap_return = XCreatePixmap(display, d, image->width,
2205:                                        image->height, image->depth);
2206:         gcv.function = GXcopy;
2207:         gc = XCreateGC(display, *pixmap_return, GCFunction, &gcv);
2208: 
2209:         XPutImage(display, *pixmap_return, gc, image, 0, 0, 0, 0,
2210:                   image->width, image->height);
2211: 
2212:         XDestroyImage(image);
2213:         XFreeGC(display, gc);
2214:     }
2215:     if (shapeimageptr && shapeimage) {
2216:         *shapemask_return = XCreatePixmap(display, d, shapeimage->width,
2217:                                           shapeimage->height,
2218:                                           shapeimage->depth);
2219:         gcv.function = GXcopy;
2220:         gc = XCreateGC(display, *shapemask_return, GCFunction, &gcv);
2221: 
2222:         XPutImage(display, *shapemask_return, gc, shapeimage, 0, 0, 0, 0,
2223:                   shapeimage->width, shapeimage->height);
2224: 
2225:         XDestroyImage(shapeimage);
2226:         XFreeGC(display, gc);
2227:     }
2228:     return (ErrorStatus);
2229: }
2230: 
2231: 
2232: static int XpmCreateImageFromData
2233: ARGLIST((display, data, image_return, shapeimage_return, attributes))
2234: ARG(Display *,display)
2235: ARG(char **, data)
2236: ARG(XImage **, image_return)
2237: ARG(XImage **, shapeimage_return)
2238: GRA(BxXpmAttributes *, attributes)
2239: {
2240:     bxxpmData mdata;
2241:     int ErrorStatus;
2242:     bxxpmInternAttrib attrib;
2243: 
2244:     /*
2245:      * initialize return values
2246:      */
2247:     if (image_return)
2248:         *image_return = NULL;
2249:     if (shapeimage_return)
2250:         *shapeimage_return = NULL;
2251: 
2252:     if ((ErrorStatus = xpmOpenArray(data, &mdata)) != BxXpmSuccess)
2253:         return (ErrorStatus);
2254: 
2255:     xpmInitInternAttrib(&attrib);
2256: 
2257:     ErrorStatus = xpmParseData(&mdata, &attrib, attributes);
2258: 
2259:     if (ErrorStatus == BxXpmSuccess)
2260:         ErrorStatus = xpmCreateImage(display, &attrib, image_return,
2261:                                      shapeimage_return, attributes);
2262: 
2263:     if (ErrorStatus >= 0)
2264:         xpmSetAttributes(&attrib, attributes);
2265:     else if (attributes)
2266:         XpmFreeAttributes(attributes);
2267: 
2268:     xpmFreeInternAttrib(&attrib);
2269:     XpmDataClose(&mdata);
2270: 
2271:     return (ErrorStatus);
2272: }
2273: 
2274: /*
2275:  * open the given array to be read or written as an bxxpmData which is returned
2276:  */
2277: static int xpmOpenArray
2278: ARGLIST((data, mdata))
2279: ARG(char **,data)
2280: GRA(bxxpmData *,mdata)
2281: {
2282:     mdata->type = BXXPMARRAY;
2283:     mdata->stream.data = data;
2284:     mdata->cptr = *data;
2285:     mdata->line = 0;
2286:     mdata->CommentLength = 0;
2287:     mdata->Bcmt = mdata->Ecmt = NULL;
2288:     mdata->Bos = mdata->Eos = '\0';
2289:     mdata->InsideString = 0;
2290:     return (BxXpmSuccess);
2291: }
2292: 
2293: /*
2294:  * Intialize the bxxpmInternAttrib pointers to Null to know
2295:  * which ones must be freed later on.
2296:  */
2297: static void xpmInitInternAttrib
2298: ARGLIST((attrib))
2299: GRA(bxxpmInternAttrib *,attrib)
2300: {
2301:     attrib->ncolors = 0;
2302:     attrib->colorTable = NULL;
2303:     attrib->pixelindex = NULL;
2304:     attrib->xcolors = NULL;
2305:     attrib->colorStrings = NULL;
2306:     attrib->mask_pixel = BX_UNDEF_PIXEL;
2307: }
2308: 
2309: /* function call in case of error, frees only localy allocated variables */
2310: #undef RETURN
2311: #define RETURN(status) \
2312:   { if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
2313:     if (chars) free(chars); \
2314:     if (pixelindex) free((char *)pixelindex); \
2315:     if (hints_cmt)  free((char *)hints_cmt); \
2316:     if (colors_cmt) free((char *)colors_cmt); \
2317:     if (pixels_cmt) free((char *)pixels_cmt); \
2318:     return(status); }
2319: 
2320: /*
2321:  * This function parses an Xpm file or data and store the found informations
2322:  * in an an bxxpmInternAttrib structure which is returned.
2323:  */
2324: static int xpmParseData
2325: ARGLIST((data, attrib_return, attributes))
2326: ARG(bxxpmData *,data)
2327: ARG(bxxpmInternAttrib *, attrib_return)
2328: GRA(BxXpmAttributes *, attributes)
2329: {
2330:     /* variables to return */
2331:     unsigned int width, height;
2332:     unsigned int ncolors = 0;
2333:     unsigned int cpp;
2334:     unsigned int x_hotspot, y_hotspot, hotspot = 0;
2335:     char ***colorTable = NULL;
2336:     unsigned int *pixelindex = NULL;
2337:     char *hints_cmt = NULL;
2338:     char *colors_cmt = NULL;
2339:     char *pixels_cmt = NULL;
2340: 
2341:     /* calculation variables */
2342:     unsigned int rncolors = 0;    /* read number of colors, it is
2343:            * different to ncolors to avoid
2344:            * problem when freeing the
2345:            * colorTable in case an error
2346:            * occurs while reading the hints
2347:            * line */
2348:     unsigned int key;     /* color key */
2349:     char *chars = NULL, buf[BUFSIZ];
2350:     unsigned int *iptr;
2351:     unsigned int a, b, x, y, l;
2352: 
2353:     unsigned int curkey;    /* current color key */
2354:     unsigned int lastwaskey;    /* key read */
2355:     char curbuf[BUFSIZ];    /* current buffer */
2356: 
2357:     /*
2358:      * read hints: width, height, ncolors, chars_per_pixel 
2359:      */
2360:     if (!(xpmNextUI(data, &width) && xpmNextUI(data, &height)
2361:     && xpmNextUI(data, &rncolors) && xpmNextUI(data, &cpp)))
2362:   RETURN(BxXpmFileInvalid);
2363: 
2364:     ncolors = rncolors;
2365: 
2366:     /*
2367:      * read hotspot coordinates if any 
2368:      */
2369:     hotspot = xpmNextUI(data, &x_hotspot) && xpmNextUI(data, &y_hotspot);
2370: 
2371:     /*
2372:      * store the hints comment line 
2373:      */
2374:     if (attributes && (attributes->valuemask & BxXpmReturnInfos))
2375:   xpmGetCmt(data, &hints_cmt);
2376: 
2377:     /*
2378:      * read colors 
2379:      */
2380:     colorTable = (char ***) calloc(ncolors, sizeof(char **));
2381:     if (!colorTable)
2382:   RETURN(BxXpmNoMemory);
2383: 
2384:     for (a = 0; a < ncolors; a++) {
2385:   xpmNextString(data);    /* skip the line */
2386:   colorTable[a] = (char **) calloc((BXNKEYS + 1), sizeof(char *));
2387:   if (!colorTable[a])
2388:       RETURN(BxXpmNoMemory);
2389: 
2390:   /*
2391:    * read pixel value 
2392:    */
2393:   colorTable[a][0] = (char *) malloc(cpp);
2394:   if (!colorTable[a][0])
2395:       RETURN(BxXpmNoMemory);
2396:   for (b = 0; b < cpp; b++)
2397:       colorTable[a][0][b] = xpmGetC(data);
2398: 
2399:   /*
2400:    * read color keys and values 
2401:    */
2402:   curkey = 0;
2403:   lastwaskey = 0;
2404:   while (l = xpmNextWord(data, buf)) {
2405:       if (!lastwaskey) {
2406:     for (key = 1; key < BXNKEYS + 1; key++)
2407:         if ((strlen(BxXpmColorKeys[key - 1]) == l)
2408:       && (!strncmp(BxXpmColorKeys[key - 1], buf, l)))
2409:       break;
2410:       }
2411:       if (!lastwaskey && key <= BXNKEYS) {  /* open new key */
2412:     if (curkey) {   /* flush string */
2413:         colorTable[a][curkey] =
2414:       (char *) malloc(strlen(curbuf) + 1);
2415:         if (!colorTable[a][curkey])
2416:       RETURN(BxXpmNoMemory);
2417:         strcpy(colorTable[a][curkey], curbuf);
2418:     }
2419:     curkey = key;   /* set new key  */
2420:     curbuf[0] = '\0'; /* reset curbuf */
2421:     lastwaskey = 1;
2422:       } else {
2423:     if (!curkey)
2424:         RETURN(BxXpmFileInvalid); /* key without value */
2425:     if (!lastwaskey)
2426:         strcat(curbuf, " ");/* append space */
2427:     buf[l] = '\0';
2428:     strcat(curbuf, buf);  /* append buf */
2429:     lastwaskey = 0;
2430:       }
2431:   }
2432:   if (!curkey)
2433:       RETURN(BxXpmFileInvalid); /* key without value */
2434:   colorTable[a][curkey] = (char *) malloc(strlen(curbuf) + 1);
2435:   if (!colorTable[a][curkey])
2436:       RETURN(BxXpmNoMemory);
2437:   strcpy(colorTable[a][curkey], curbuf);
2438:     }
2439: 
2440:     /*
2441:      * store the colors comment line 
2442:      */
2443:     if (attributes && (attributes->valuemask & BxXpmReturnInfos))
2444:   xpmGetCmt(data, &colors_cmt);
2445: 
2446:     /*
2447:      * read pixels and index them on color number 
2448:      */
2449:     pixelindex =
2450:   (unsigned int *) malloc(sizeof(unsigned int) * width * height);
2451:     if (!pixelindex)
2452:   RETURN(BxXpmNoMemory);
2453: 
2454:     iptr = pixelindex;
2455: 
2456:     chars = (char *) malloc(cpp);
2457:     if (!chars)
2458:   RETURN(BxXpmNoMemory);
2459: 
2460:     for (y = 0; y < height; y++) {
2461:   xpmNextString(data);
2462:   for (x = 0; x < width; x++, iptr++) {
2463:       for (a = 0; a < cpp; a++)
2464:     chars[a] = xpmGetC(data);
2465:       for (a = 0; a < ncolors; a++)
2466:     if (!strncmp(colorTable[a][0], chars, cpp))
2467:         break;
2468:       if (a == ncolors)
2469:     RETURN(BxXpmFileInvalid); /* no color matches */
2470:       *iptr = a;
2471:   }
2472:     }
2473: 
2474:     /*
2475:      * store the pixels comment line 
2476:      */
2477:     if (attributes && (attributes->valuemask & BxXpmReturnInfos))
2478:   xpmGetCmt(data, &pixels_cmt);
2479: 
2480:     free(chars);
2481: 
2482:     /*
2483:      * store found informations in the bxxpmInternAttrib structure 
2484:      */
2485:     attrib_return->width = width;
2486:     attrib_return->height = height;
2487:     attrib_return->cpp = cpp;
2488:     attrib_return->ncolors = ncolors;
2489:     attrib_return->colorTable = colorTable;
2490:     attrib_return->pixelindex = pixelindex;
2491: 
2492:     if (attributes) {
2493:   if (attributes->valuemask & BxXpmReturnInfos) {
2494:       attributes->hints_cmt = hints_cmt;
2495:       attributes->colors_cmt = colors_cmt;
2496:       attributes->pixels_cmt = pixels_cmt;
2497:   }
2498:   if (hotspot) {
2499:       attributes->x_hotspot = x_hotspot;
2500:       attributes->y_hotspot = y_hotspot;
2501:       attributes->valuemask |= BxXpmHotspot;
2502:   }
2503:     }
2504:     return (BxXpmSuccess);
2505: }
2506: 
2507: /*
2508:  * set the color pixel related to the given colorname,
2509:  * return 0 if success, 1 otherwise.
2510:  */
2511: 
2512: static int SetColor
2513: ARGLIST((display, colormap,colorname, color_index, image_pixel, mask_pixel, mask_pixel_index))
2514: ARG(Display *, display)
2515: ARG(Colormap, colormap)
2516: ARG(char *, colorname)
2517: ARG(unsigned int, color_index)
2518: ARG(Pixel *, image_pixel)
2519: ARG(Pixel *, mask_pixel)
2520: GRA(unsigned int *, mask_pixel_index)
2521: {
2522:     XColor xcolor;
2523: 
2524:     if (STRCASECMP(colorname, BX_TRANSPARENT_COLOR)) {
2525:   if (!XParseColor(display, colormap, colorname, &xcolor)
2526:       || (!XAllocColor(display, colormap, &xcolor)))
2527:       return (1);
2528:   *image_pixel = xcolor.pixel;
2529:   *mask_pixel = 1;
2530:     } else {
2531:   *image_pixel = 0;
2532:   *mask_pixel = 0;
2533:   *mask_pixel_index = color_index;/* store the color table index */
2534:     }
2535:     return (0);
2536: }
2537: 
2538: /* function call in case of error, frees only localy allocated variables */
2539: #undef RETURN
2540: #define RETURN(status) \
2541:   { if (image) XDestroyImage(image); \
2542:     if (shapeimage) XDestroyImage(shapeimage); \
2543:     if (image_pixels) free((char *)image_pixels); \
2544:     if (mask_pixels) free((char *)mask_pixels); \
2545:     return(status); }
2546: 
2547: static int xpmCreateImage
2548: ARGLIST((display, attrib, image_return, shapeimage_return, attributes))
2549: ARG(Display *, display)
2550: ARG(bxxpmInternAttrib *, attrib)
2551: ARG(XImage **, image_return)
2552: ARG(XImage **, shapeimage_return)
2553: GRA(BxXpmAttributes *, attributes)
2554: {
2555:     /* variables stored in the BxXpmAttributes structure */
2556:     Visual *visual;
2557:     Colormap colormap;
2558:     unsigned int depth;
2559:     BxXpmColorSymbol *colorsymbols;
2560:     unsigned int numsymbols;
2561: 
2562:     /* variables to return */
2563:     XImage *image = NULL;
2564:     XImage *shapeimage = NULL;
2565:     unsigned int mask_pixel;
2566:     unsigned int ErrorStatus, ErrorStatus2;
2567: 
2568:     /* calculation variables */
2569:     Pixel *image_pixels = NULL;
2570:     Pixel *mask_pixels = NULL;
2571:     char *colorname;
2572:     unsigned int a, b, l;
2573:     Boolean pixel_defined;
2574:     unsigned int key;
2575: 
2576: 
2577:     /*
2578:      * retrieve information from the BxXpmAttributes 
2579:      */
2580:     if (attributes && attributes->valuemask & BxXpmColorSymbols) {
2581:   colorsymbols = attributes->colorsymbols;
2582:   numsymbols = attributes->numsymbols;
2583:     } else
2584:   numsymbols = 0;
2585: 
2586:     if (attributes && attributes->valuemask & BxXpmVisual)
2587:   visual = attributes->visual;
2588:     else
2589:   visual = DefaultVisual(display, DefaultScreen(display));
2590: 
2591:     if (attributes && attributes->valuemask & BxXpmColormap)
2592:   colormap = attributes->colormap;
2593:     else
2594:   colormap = DefaultColormap(display, DefaultScreen(display));
2595: 
2596:     if (attributes && attributes->valuemask & BxXpmDepth)
2597:   depth = attributes->depth;
2598:     else
2599:   depth = DefaultDepth(display, DefaultScreen(display));
2600: 
2601: 
2602:     ErrorStatus = BxXpmSuccess;
2603: 
2604:     /*
2605:      * alloc pixels index tables 
2606:      */
2607: 
2608:     key = BxXpmVisualType(visual);
2609:     image_pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
2610:     if (!image_pixels)
2611:   RETURN(BxXpmNoMemory);
2612: 
2613:     mask_pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
2614:     if (!mask_pixels)
2615:   RETURN(BxXpmNoMemory);
2616: 
2617:     mask_pixel = BX_UNDEF_PIXEL;
2618: 
2619:     /*
2620:      * get pixel colors, store them in index tables 
2621:      */
2622:     for (a = 0; a < attrib->ncolors; a++) {
2623:   colorname = NULL;
2624:   pixel_defined = False;
2625: 
2626:   /*
2627:    * look for a defined symbol 
2628:    */
2629:   if (numsymbols && attrib->colorTable[a][1]) {
2630:       for (l = 0; l < numsymbols; l++)
2631:     if (!strcmp(colorsymbols[l].name, attrib->colorTable[a][1]))
2632:         break;
2633:       if (l != numsymbols) {
2634:     if (colorsymbols[l].value)
2635:         colorname = colorsymbols[l].value;
2636:     else
2637:         pixel_defined = True;
2638:       }
2639:   }
2640:   if (!pixel_defined) {   /* pixel not given as symbol value */
2641: 
2642:       if (colorname) {    /* colorname given as symbol value */
2643:     if (!SetColor(display, colormap, colorname, a,
2644:          &image_pixels[a], &mask_pixels[a], &mask_pixel))
2645:         pixel_defined = True;
2646:     else
2647:         ErrorStatus = BxXpmColorError;
2648:       }
2649:       b = key;
2650:       while (!pixel_defined && b > 1) {
2651:     if (attrib->colorTable[a][b]) {
2652:         if (!SetColor(display, colormap, attrib->colorTable[a][b],
2653:           a, &image_pixels[a], &mask_pixels[a],
2654:           &mask_pixel)) {
2655:       pixel_defined = True;
2656:       break;
2657:         } else
2658:       ErrorStatus = BxXpmColorError;
2659:     }
2660:     b--;
2661:       }
2662: 
2663:       b = key + 1;
2664:       while (!pixel_defined && b < BXNKEYS + 1) {
2665:     if (attrib->colorTable[a][b]) {
2666:         if (!SetColor(display, colormap, attrib->colorTable[a][b],
2667:           a, &image_pixels[a], &mask_pixels[a],
2668:           &mask_pixel)) {
2669:       pixel_defined = True;
2670:       break;
2671:         } else
2672:       ErrorStatus = BxXpmColorError;
2673:     }
2674:     b++;
2675:       }
2676: 
2677:       if (!pixel_defined)
2678:     RETURN(BxXpmColorFailed);
2679: 
2680:   } else {
2681:       image_pixels[a] = colorsymbols[l].pixel;
2682:       mask_pixels[a] = 1;
2683:   }
2684:     }
2685: 
2686:     /*
2687:      * create the image 
2688:      */
2689:     if (image_return) {
2690:   ErrorStatus2 = CreateXImage(display, visual, depth,
2691:             attrib->width, attrib->height, &image);
2692:   if (ErrorStatus2 != BxXpmSuccess)
2693:       RETURN(ErrorStatus2);
2694: 
2695:   /*
2696:    * set the image data 
2697:    *
2698:    * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
2699:    * optimized functions, otherwise use slower but sure general one. 
2700:    *
2701:    */
2702: 
2703:   if (image->depth == 1)
2704:       SetImagePixels1(image, attrib->width, attrib->height,
2705:           attrib->pixelindex, image_pixels);
2706:   else if (image->bits_per_pixel == 8)
2707:       SetImagePixels8(image, attrib->width, attrib->height,
2708:           attrib->pixelindex, image_pixels);
2709:   else if (image->bits_per_pixel == 16)
2710:       SetImagePixels16(image, attrib->width, attrib->height,
2711:            attrib->pixelindex, image_pixels);
2712:   else if (image->bits_per_pixel == 32)
2713:       SetImagePixels32(image, attrib->width, attrib->height,
2714:            attrib->pixelindex, image_pixels);
2715:   else
2716:       SetImagePixels(image, attrib->width, attrib->height,
2717:          attrib->pixelindex, image_pixels);
2718:     }
2719: 
2720:     /*
2721:      * create the shape mask image 
2722:      */
2723:     if (mask_pixel != BX_UNDEF_PIXEL && shapeimage_return) {
2724:   ErrorStatus2 = CreateXImage(display, visual, 1, attrib->width,
2725:             attrib->height, &shapeimage);
2726:   if (ErrorStatus2 != BxXpmSuccess)
2727:       RETURN(ErrorStatus2);
2728: 
2729:   SetImagePixels1(shapeimage, attrib->width, attrib->height,
2730:       attrib->pixelindex, mask_pixels);
2731:     }
2732:     free((char *)mask_pixels);
2733: 
2734:     /*
2735:      * if requested store allocated pixels in the BxXpmAttributes structure 
2736:      */
2737:     if (attributes &&
2738:   (attributes->valuemask & BxXpmReturnInfos
2739:    || attributes->valuemask & BxXpmReturnPixels)) {
2740:   if (mask_pixel != BX_UNDEF_PIXEL) {
2741:       Pixel *pixels, *p1, *p2;
2742: 
2743:       attributes->npixels = attrib->ncolors - 1;
2744:       pixels = (Pixel *) malloc(sizeof(Pixel) * attributes->npixels);
2745:       if (pixels) {
2746:     p1 = image_pixels;
2747:     p2 = pixels;
2748:     for (a = 0; a < attrib->ncolors; a++, p1++)
2749:         if (a != mask_pixel)
2750:       *p2++ = *p1;
2751:     attributes->pixels = pixels;
2752:       } else {
2753:     /* if error just say we can't return requested data */
2754:     attributes->valuemask &= ~BxXpmReturnPixels;
2755:     attributes->valuemask &= ~BxXpmReturnInfos;
2756:     attributes->pixels = NULL;
2757:     attributes->npixels = 0;
2758:       }
2759:       free((char *)image_pixels);
2760:   } else {
2761:       attributes->pixels = image_pixels;
2762:       attributes->npixels = attrib->ncolors;
2763:   }
2764:   attributes->mask_pixel = mask_pixel;
2765:     } else
2766:   free((char *)image_pixels);
2767: 
2768: 
2769:     /*
2770:      * return created images 
2771:      */
2772:     if (image_return)
2773:   *image_return = image;
2774: 
2775:     if (shapeimage_return)
2776:   *shapeimage_return = shapeimage;
2777: 
2778:     return (ErrorStatus);
2779: }
2780: 
2781: 
2782: /*
2783:  * Create an XImage
2784:  */
2785: static int CreateXImage
2786: ARGLIST((display, visual, depth, width, height, image_return))
2787: ARG(Display *, display)
2788: ARG(Visual *, visual)
2789: ARG(unsigned int, depth)
2790: ARG(unsigned int, width)
2791: ARG(unsigned int, height)
2792: GRA(XImage **, image_return)
2793: {
2794:     int bitmap_pad;
2795: 
2796:     /* first get bitmap_pad */
2797:     if (depth > 16)
2798:   bitmap_pad = 32;
2799:     else if (depth > 8)
2800:   bitmap_pad = 16;
2801:     else
2802:   bitmap_pad = 8;
2803: 
2804:     /* then create the XImage with data = NULL and bytes_per_line = 0 */
2805: 
2806:     *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0,
2807:          width, height, bitmap_pad, 0);
2808:     if (!*image_return)
2809:   return (BxXpmNoMemory);
2810: 
2811:     /* now that bytes_per_line must have been set properly alloc data */
2812: 
2813:     (*image_return)->data =
2814:   (char *) malloc((*image_return)->bytes_per_line * height);
2815: 
2816:     if (!(*image_return)->data) {
2817:   XDestroyImage(*image_return);
2818:   *image_return = NULL;
2819:   return (BxXpmNoMemory);
2820:     }
2821:     return (BxXpmSuccess);
2822: }
2823: 
2824: 
2825: /*
2826:  * The functions below are written from X11R5 MIT's code (XImUtil.c)
2827:  *
2828:  * The idea is to have faster functions than the standard XPutPixel function
2829:  * to build the image data. Indeed we can speed up things by supressing tests
2830:  * performed for each pixel. We do exactly the same tests but at the image
2831:  * level. Assuming that we use only ZPixmap images. 
2832:  */
2833: 
2834: LFUNC(_putbits, void, (register char *src, int dstoffset,
2835:           register int numbits, register char *dst));
2836: 
2837: LFUNC(_XReverse_Bytes, void, (register unsigned char *bpt, register int nb));
2838: 
2839: static unsigned char Const _reverse_byte[0x100] = {
2840:           0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
2841:           0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
2842:           0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
2843:           0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
2844:           0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
2845:           0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
2846:           0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
2847:           0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
2848:           0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
2849:           0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
2850:           0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
2851:           0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
2852:           0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
2853:           0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
2854:           0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
2855:           0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
2856:           0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
2857:           0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
2858:           0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
2859:           0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
2860:           0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
2861:           0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
2862:           0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
2863:           0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
2864:           0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
2865:           0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
2866:           0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
2867:           0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
2868:           0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
2869:           0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
2870:           0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
2871:            0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
2872: };
2873: 
2874: static void _XReverse_Bytes
2875: ARGLIST((bpt, nb))
2876: ARG(register unsigned char *, bpt)
2877: GRA(register int, nb)
2878: {
2879:     do {
2880:   *bpt = _reverse_byte[*bpt];
2881:   bpt++;
2882:     } while (--nb > 0);
2883: }
2884: 
2885: static void xpm_xynormalizeimagebits
2886: ARGLIST((bp,img))
2887: ARG(register unsigned char *, bp)
2888: GRA(register XImage *, img)
2889: {
2890:     register unsigned char c;
2891: 
2892:     if (img->byte_order != img->bitmap_bit_order) {
2893:   switch (img->bitmap_unit) {
2894: 
2895:   case 16:
2896:       c = *bp;
2897:       *bp = *(bp + 1);
2898:       *(bp + 1) = c;
2899:       break;
2900: 
2901:   case 32:
2902:       c = *(bp + 3);
2903:       *(bp + 3) = *bp;
2904:       *bp = c;
2905:       c = *(bp + 2);
2906:       *(bp + 2) = *(bp + 1);
2907:       *(bp + 1) = c;
2908:       break;
2909:   }
2910:     }
2911:     if (img->bitmap_bit_order == MSBFirst)
2912:   _XReverse_Bytes(bp, img->bitmap_unit >> 3);
2913: }
2914: 
2915: static void xpm_znormalizeimagebits
2916: ARGLIST((bp,img))
2917: ARG(register unsigned char *, bp)
2918: GRA(register XImage *, img)
2919: {
2920:     register unsigned char c;
2921: 
2922:     switch (img->bits_per_pixel) {
2923: 
2924:     case 4:
2925:   *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
2926:   break;
2927: 
2928:     case 16:
2929:   c = *bp;
2930:   *bp = *(bp + 1);
2931:   *(bp + 1) = c;
2932:   break;
2933: 
2934:     case 24:
2935:   c = *(bp + 2);
2936:   *(bp + 2) = *bp;
2937:   *bp = c;
2938:   break;
2939: 
2940:     case 32:
2941:   c = *(bp + 3);
2942:   *(bp + 3) = *bp;
2943:   *bp = c;
2944:   c = *(bp + 2);
2945:   *(bp + 2) = *(bp + 1);
2946:   *(bp + 1) = c;
2947:   break;
2948:     }
2949: }
2950: 
2951: static unsigned char Const _lomask[0x09] = {
2952:          0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
2953: static unsigned char Const _himask[0x09] = {
2954:          0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
2955: 
2956: static void _putbits
2957: ARGLIST((src, dstoffset, numbits, dst))
2958: ARG(register char *, src)   /* address of source bit string */
2959: ARG(int, dstoffset)     /* bit offset into destination;
2960:            * range is 0-31 */
2961: ARG(register int, numbits)    /* number of bits to copy to
2962:            * destination */
2963: GRA(register char *, dst)   /* address of destination bit string */
2964: {
2965:     register unsigned char chlo, chhi;
2966:     int hibits;
2967: 
2968:     dst = dst + (dstoffset >> 3);
2969:     dstoffset = dstoffset & 7;
2970:     hibits = 8 - dstoffset;
2971:     chlo = *dst & _lomask[dstoffset];
2972:     for (;;) {
2973:   chhi = (*src << dstoffset) & _himask[dstoffset];
2974:   if (numbits <= hibits) {
2975:       chhi = chhi & _lomask[dstoffset + numbits];
2976:       *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
2977:       break;
2978:   }
2979:   *dst = chhi | chlo;
2980:   dst++;
2981:   numbits = numbits - hibits;
2982:   chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
2983:   src++;
2984:   if (numbits <= dstoffset) {
2985:       chlo = chlo & _lomask[numbits];
2986:       *dst = (*dst & _himask[numbits]) | chlo;
2987:       break;
2988:   }
2989:   numbits = numbits - dstoffset;
2990:     }
2991: }
2992: 
2993: /*
2994:  * Default method to write pixels into a Z image data structure.
2995:  * The algorithm used is:
2996:  *
2997:  *  copy the destination bitmap_unit or Zpixel to temp
2998:  *  normalize temp if needed
2999:  *  copy the pixel bits into the temp
3000:  *  renormalize temp if needed
3001:  *  copy the temp back into the destination image data
3002:  */
3003: 
3004: static void SetImagePixels
3005: ARGLIST((image, width, height, pixelindex, pixels))
3006: ARG(XImage *, image)
3007: ARG(unsigned int, width)
3008: ARG(unsigned int, height)
3009: ARG(unsigned int *, pixelindex)
3010: GRA(Pixel *, pixels)
3011: {
3012:     Pixel pixel;
3013:     unsigned long px;
3014:     register char *src;
3015:     register char *dst;
3016:     int nbytes;
3017:     register unsigned int *iptr;
3018:     register int x, y, i;
3019: 
3020:     iptr = pixelindex;
3021:     if (image->depth == 1) {
3022:   for (y = 0; y < height; y++)
3023:       for (x = 0; x < width; x++, iptr++) {
3024:     pixel = pixels[*iptr];
3025:     for (i = 0, px = pixel;
3026:          i < sizeof(unsigned long); i++, px >>= 8)
3027:         ((unsigned char *) &pixel)[i] = (unsigned char)px;
3028:     src = &image->data[BXXYINDEX(x, y, image)];
3029:     dst = (char *) &px;
3030:     px = 0;
3031:     nbytes = image->bitmap_unit >> 3;
3032:     for (i = nbytes; --i >= 0;)
3033:         *dst++ = *src++;
3034:     BXXYNORMALIZE(&px, image);
3035:     i = ((x + image->xoffset) % image->bitmap_unit);
3036:     _putbits((char *) &pixel, i, 1, (char *) &px);
3037:     BXXYNORMALIZE(&px, image);
3038:     src = (char *) &px;
3039:     dst = &image->data[BXXYINDEX(x, y, image)];
3040:     for (i = nbytes; --i >= 0;)
3041:         *dst++ = *src++;
3042:       }
3043:     } else {
3044:   for (y = 0; y < height; y++)
3045:       for (x = 0; x < width; x++, iptr++) {
3046:     pixel = pixels[*iptr];
3047:     if (image->depth == 4)
3048:         pixel &= 0xf;
3049:     for (i = 0, px = pixel;
3050:          i < sizeof(unsigned long); i++, px >>= 8)
3051:         ((unsigned char *) &pixel)[i] = (unsigned char)px;
3052:     src = &image->data[BXZINDEX(x, y, image)];
3053:     dst = (char *) &px;
3054:     px = 0;
3055:     nbytes = (image->bits_per_pixel + 7) >> 3;
3056:     for (i = nbytes; --i >= 0;)
3057:         *dst++ = *src++;
3058:     BXZNORMALIZE(&px, image);
3059:     _putbits((char *) &pixel,
3060:        (x * image->bits_per_pixel) & 7,
3061:        image->bits_per_pixel, (char *) &px);
3062:     BXZNORMALIZE(&px, image);
3063:     src = (char *) &px;
3064:     dst = &image->data[BXZINDEX(x, y, image)];
3065:     for (i = nbytes; --i >= 0;)
3066:         *dst++ = *src++;
3067:       }
3068:     }
3069: }
3070: 
3071: /*
3072:  * write pixels into a 32-bits Z image data structure
3073:  */
3074: 
3075: #ifndef WORD64
3076: static unsigned long byteorderpixel = MSBFirst << 24;
3077: 
3078: #endif
3079: 
3080: static void SetImagePixels32
3081: ARGLIST((image, width, height, pixelindex, pixels))
3082: ARG(XImage *, image)
3083: ARG(unsigned int, width)
3084: ARG(unsigned int, height)
3085: ARG(unsigned int *, pixelindex)
3086: GRA(Pixel *, pixels)
3087: {
3088:     register unsigned char *addr;
3089:     register unsigned int *paddr;
3090:     register unsigned int *iptr;
3091:     register int x, y;
3092: 
3093:     iptr = pixelindex;
3094: #ifndef WORD64
3095:     if (*((char *) &byteorderpixel) == image->byte_order) {
3096:   for (y = 0; y < height; y++)
3097:       for (x = 0; x < width; x++, iptr++) {
3098:     paddr =
3099:         (unsigned int *)(&(image->data[BXZINDEX32(x, y, image)]));
3100:     *paddr = (unsigned int)pixels[*iptr];
3101:       }
3102:     } else
3103: #endif
3104:     if (image->byte_order == MSBFirst)
3105:   for (y = 0; y < height; y++)
3106:       for (x = 0; x < width; x++, iptr++) {
3107:     addr = &((unsigned char *) image->data)[BXZINDEX32(x, y, image)];
3108:     addr[0] = (unsigned char)(pixels[*iptr] >> 24);
3109:     addr[1] = (unsigned char)(pixels[*iptr] >> 16);
3110:     addr[2] = (unsigned char)(pixels[*iptr] >> 8);
3111:     addr[3] = (unsigned char)(pixels[*iptr]);
3112:       }
3113:     else
3114:   for (y = 0; y < height; y++)
3115:       for (x = 0; x < width; x++, iptr++) {
3116:     addr = &((unsigned char *) image->data)[BXZINDEX32(x, y, image)];
3117:     addr[3] = (unsigned char)(pixels[*iptr] >> 24);
3118:     addr[2] = (unsigned char)(pixels[*iptr] >> 16);
3119:     addr[1] = (unsigned char)(pixels[*iptr] >> 8);
3120:     addr[0] = (unsigned char)(pixels[*iptr]);
3121:       }
3122: }
3123: 
3124: /*
3125:  * write pixels into a 16-bits Z image data structure
3126:  */
3127: 
3128: static void SetImagePixels16
3129: ARGLIST((image, width, height, pixelindex, pixels))
3130: ARG(XImage *, image)
3131: ARG(unsigned int, width)
3132: ARG(unsigned int, height)
3133: ARG(unsigned int *, pixelindex)
3134: GRA(Pixel *, pixels)
3135: {
3136:     register unsigned char *addr;
3137:     register unsigned int *iptr;
3138:     register int x, y;
3139: 
3140:     iptr = pixelindex;
3141:     if (image->byte_order == MSBFirst)
3142:   for (y = 0; y < height; y++)
3143:       for (x = 0; x < width; x++, iptr++) {
3144:     addr = &((unsigned char *) image->data)[BXZINDEX16(x, y, image)];
3145:     addr[0] = (unsigned char)(pixels[*iptr] >> 8);
3146:     addr[1] = (unsigned char)(pixels[*iptr]);
3147:       }
3148:     else
3149:   for (y = 0; y < height; y++)
3150:       for (x = 0; x < width; x++, iptr++) {
3151:     addr = &((unsigned char *) image->data)[BXZINDEX16(x, y, image)];
3152:     addr[1] = (unsigned char)(pixels[*iptr] >> 8);
3153:     addr[0] = (unsigned char)(pixels[*iptr]);
3154:       }
3155: }
3156: 
3157: /*
3158:  * write pixels into a 8-bits Z image data structure
3159:  */
3160: 
3161: static void SetImagePixels8
3162: ARGLIST((image, width, height, pixelindex, pixels))
3163: ARG(XImage *, image)
3164: ARG(unsigned int, width)
3165: ARG(unsigned int, height)
3166: ARG(unsigned int *, pixelindex)
3167: GRA(Pixel *, pixels)
3168: 
3169: {
3170:     register unsigned int *iptr;
3171:     register int x, y;
3172: 
3173:     iptr = pixelindex;
3174:     for (y = 0; y < height; y++)
3175:   for (x = 0; x < width; x++, iptr++)
3176:       image->data[BXZINDEX8(x, y, image)] = (char)pixels[*iptr];
3177: }
3178: 
3179: /*
3180:  * write pixels into a 1-bit depth image data structure and **offset null**
3181:  */
3182: 
3183: static void SetImagePixels1
3184: ARGLIST((image, width, height, pixelindex, pixels))
3185: ARG(XImage *, image)
3186: ARG(unsigned int, width)
3187: ARG(unsigned int, height)
3188: ARG(unsigned int *, pixelindex)
3189: GRA(Pixel *, pixels)
3190: {
3191:     unsigned char bit;
3192:     int xoff, yoff;
3193:     register unsigned int *iptr;
3194:     register int x, y;
3195: 
3196:     if (image->byte_order != image->bitmap_bit_order)
3197:   SetImagePixels(image, width, height, pixelindex, pixels);
3198:     else {
3199:   iptr = pixelindex;
3200:   if (image->bitmap_bit_order == MSBFirst)
3201:       for (y = 0; y < height; y++)
3202:     for (x = 0; x < width; x++, iptr++) {
3203:         yoff = BXZINDEX1(x, y, image);
3204:         xoff = x & 7;
3205:         bit = 0x80 >> xoff;
3206:         if (pixels[*iptr] & 1)
3207:       image->data[yoff] |= bit;
3208:         else
3209:       image->data[yoff] &= ~bit;
3210:     }
3211:   else
3212:       for (y = 0; y < height; y++)
3213:     for (x = 0; x < width; x++, iptr++) {
3214:         yoff = BXZINDEX1(x, y, image);
3215:         xoff = x & 7;
3216:         bit = 1 << xoff;
3217:         if (pixels[*iptr] & 1)
3218:       image->data[yoff] |= bit;
3219:         else
3220:       image->data[yoff] &= ~bit;
3221:     }
3222:     }
3223: }
3224: 
3225: /*
3226:  * Store into the BxXpmAttributes structure the required informations stored in
3227:  * the bxxpmInternAttrib structure.
3228:  */
3229: 
3230: static void xpmSetAttributes
3231: ARGLIST((attrib, attributes))
3232: ARG(bxxpmInternAttrib *, attrib)
3233: GRA(BxXpmAttributes *, attributes)
3234: {
3235:     if (attributes) {
3236:         if (attributes->valuemask & BxXpmReturnInfos) {
3237:             attributes->cpp = attrib->cpp;
3238:             attributes->ncolors = attrib->ncolors;
3239:             attributes->colorTable = attrib->colorTable;
3240: 
3241:             attrib->ncolors = 0;
3242:             attrib->colorTable = NULL;
3243:         }
3244:         attributes->width = attrib->width;
3245:         attributes->height = attrib->height;
3246:         attributes->valuemask |= BxXpmSize;
3247:     }
3248: }
3249: 
3250: /*
3251:  * Free the BxXpmAttributes structure members
3252:  * but the structure itself
3253:  */
3254: 
3255: static void XpmFreeAttributes
3256: ARGLIST((attributes))
3257: GRA(BxXpmAttributes *, attributes)
3258: {
3259:     if (attributes) {
3260:         if (attributes->valuemask & BxXpmReturnPixels && attributes->pixels) {
3261:             free((char *)attributes->pixels);
3262:             attributes->pixels = NULL;
3263:             attributes->npixels = 0;
3264:         }
3265:         if (attributes->valuemask & BxXpmInfos) {
3266:             if (attributes->colorTable) {
3267:                 xpmFreeColorTable(attributes->colorTable, attributes->ncolors);
3268:                 attributes->colorTable = NULL;
3269:                 attributes->ncolors = 0;
3270:             }
3271:             if (attributes->hints_cmt) {
3272:                 free(attributes->hints_cmt);
3273:                 attributes->hints_cmt = NULL;
3274:             }
3275:             if (attributes->colors_cmt) {
3276:                 free(attributes->colors_cmt);
3277:                 attributes->colors_cmt = NULL;
3278:             }
3279:             if (attributes->pixels_cmt) {
3280:                 free(attributes->pixels_cmt);
3281:                 attributes->pixels_cmt = NULL;
3282:             }
3283:             if (attributes->pixels) {
3284:                 free((char *)attributes->pixels);
3285:                 attributes->pixels = NULL;
3286:             }
3287:         }
3288:         attributes->valuemask = 0;
3289:     }
3290: }
3291: 
3292: /*
3293:  * Free the bxxpmInternAttrib pointers which have been allocated
3294:  */
3295: 
3296: static void xpmFreeInternAttrib
3297: ARGLIST((attrib))
3298: GRA(bxxpmInternAttrib *, attrib)
3299: {
3300:     unsigned int a;
3301: 
3302:     if (attrib->colorTable)
3303:         xpmFreeColorTable(attrib->colorTable, attrib->ncolors);
3304:     if (attrib->pixelindex)
3305:         free((char *)attrib->pixelindex);
3306:     if (attrib->xcolors)
3307:         free((char *)attrib->xcolors);
3308:     if (attrib->colorStrings) {
3309:         for (a = 0; a < attrib->ncolors; a++)
3310:             if (attrib->colorStrings[a])
3311:                 free((char *)attrib->colorStrings[a]);
3312:         free((char *)attrib->colorStrings);
3313:     }
3314: }
3315: 
3316: /*
3317:  * close the file related to the bxxpmData if any
3318:  */
3319: static void XpmDataClose
3320: ARGLIST((mdata))
3321: GRA(bxxpmData *, mdata)
3322: {
3323:     switch (mdata->type) {
3324:     case BXXPMARRAY:
3325:         break;
3326:     case BXXPMFILE:
3327:         if (mdata->stream.file != (stdout) && mdata->stream.file != (stdin))
3328:             fclose(mdata->stream.file);
3329:         break;
3330: #ifdef ZPIPE
3331:     case BXXPMPIPE:
3332:         pclose(mdata->stream.file);
3333: #endif
3334:     }
3335: }
3336: 
3337: /*
3338:  * skip whitespace and compute the following unsigned int,
3339:  * returns 1 if one is found and 0 if not
3340:  */
3341: static int xpmNextUI
3342: ARGLIST((mdata, ui_return))
3343: ARG(bxxpmData *, mdata)
3344: GRA(unsigned int *, ui_return)
3345: {
3346:     char buf[BUFSIZ];
3347:     int l;
3348: 
3349:     l = xpmNextWord(mdata, buf);
3350:     return atoui(buf, l, ui_return);
3351: }
3352: 
3353: /*
3354:  * get the current comment line
3355:  */
3356: static void xpmGetCmt
3357: ARGLIST((mdata, cmt))
3358: ARG(bxxpmData *, mdata)
3359: GRA(char **, cmt)
3360: {
3361:     switch (mdata->type) {
3362:     case BXXPMARRAY:
3363:         *cmt = NULL;
3364:         break;
3365:     case BXXPMFILE:
3366:     case BXXPMPIPE:
3367:         if (mdata->CommentLength) {
3368:             *cmt = (char *) malloc(mdata->CommentLength + 1);
3369:             strncpy(*cmt, mdata->Comment, mdata->CommentLength);
3370:             (*cmt)[mdata->CommentLength] = '\0';
3371:             mdata->CommentLength = 0;
3372:         } else
3373:             *cmt = NULL;
3374:         break;
3375:     }
3376: }
3377: 
3378: /*
3379:  * skip to the end of the current string and the beginning of the next one
3380:  */
3381: static void xpmNextString
3382: ARGLIST((mdata))
3383: GRA(bxxpmData *, mdata)
3384: {
3385:     int c;
3386: 
3387:     switch (mdata->type) {
3388:     case BXXPMARRAY:
3389:         mdata->cptr = (mdata->stream.data)[++mdata->line];
3390:         break;
3391:     case BXXPMFILE:
3392:     case BXXPMPIPE:
3393:         if (mdata->Eos)
3394:             while ((c = xpmGetC(mdata)) != mdata->Eos && c != EOF);
3395:         if (mdata->Bos)                 /* if not natural XPM2 */
3396:             while ((c = xpmGetC(mdata)) != mdata->Bos && c != EOF);
3397:         break;
3398:     }
3399: }
3400: 
3401: /*
3402:  * return the current character, skipping comments
3403:  */
3404: static int xpmGetC
3405: ARGLIST((mdata))
3406: GRA(bxxpmData *, mdata)
3407: {
3408:     int c;
3409:     register unsigned int n = 0, a;
3410:     unsigned int notend;
3411: 
3412:     switch (mdata->type) {
3413:     case BXXPMARRAY:
3414:         return (*mdata->cptr++);
3415:     case BXXPMFILE:
3416:     case BXXPMPIPE:
3417:         c = getc(mdata->stream.file);
3418: 
3419:         if (mdata->Bos && mdata->Eos
3420:             && (c == mdata->Bos || c == mdata->Eos)) {
3421:             /* if not natural XPM2 */
3422:             mdata->InsideString = !mdata->InsideString;
3423:             return (c);
3424:         }
3425:         if (!mdata->InsideString && mdata->Bcmt && c == mdata->Bcmt[0]) {
3426:             mdata->Comment[0] = c;
3427: 
3428:             /*
3429:              * skip the string begining comment
3430:              */
3431:             do {
3432:                 c = getc(mdata->stream.file);
3433:                 mdata->Comment[++n] = c;
3434:             } while (c == mdata->Bcmt[n] && mdata->Bcmt[n] != '\0'
3435:                      && c != EOF);
3436: 
3437:             if (mdata->Bcmt[n] != '\0') {
3438:                 /* this wasn't the begining of a comment */
3439:                 /* put characters back in the order that we got them */
3440:                 for (a = n; a > 0; a--)
3441:                     xpmUngetC(mdata->Comment[a], mdata);
3442:                 return (mdata->Comment[0]);
3443:             }
3444: 
3445:             /*
3446:              * store comment
3447:              */
3448:             mdata->Comment[0] = mdata->Comment[n];
3449:             notend = 1;
3450:             n = 0;
3451:             while (notend) {
3452:                 while (mdata->Comment[n] != mdata->Ecmt[0] && c != EOF) {
3453:                     c = getc(mdata->stream.file);
3454:                     mdata->Comment[++n] = c;
3455:                 }
3456:                 mdata->CommentLength = n;
3457:                 a = 0;
3458:                 do {
3459:                     c = getc(mdata->stream.file);
3460:                     n++;
3461:                     a++;
3462:                     mdata->Comment[n] = c;
3463:                 } while (c == mdata->Ecmt[a] && mdata->Ecmt[a] != '\0'
3464:                          && c != EOF);
3465:                 if (mdata->Ecmt[a] == '\0') {
3466:                     /* this is the end of the comment */
3467:                     notend = 0;
3468:                     xpmUngetC(mdata->Comment[n], mdata);
3469:                 }
3470:             }
3471:             c = xpmGetC(mdata);
3472:         }
3473:         return (c);
3474:     }
3475:     return('\0');
3476: }
3477: 
3478: 
3479: /*
3480:  * push the given character back
3481:  */
3482: static int xpmUngetC
3483: ARGLIST((c, mdata))
3484: ARG(int, c)
3485: GRA(bxxpmData *, mdata)
3486: {
3487:     switch (mdata->type) {
3488:     case BXXPMARRAY:
3489:         return (*--mdata->cptr = c);
3490:     case BXXPMFILE:
3491:     case BXXPMPIPE:
3492:         if (mdata->Bos && (c == mdata->Bos || c == mdata->Eos))
3493:             /* if not natural XPM2 */
3494:             mdata->InsideString = !mdata->InsideString;
3495:         return (ungetc(c, mdata->stream.file));
3496:     }
3497:     return('\0');
3498: }
3499: 
3500: /*
3501:  * skip whitespace and return the following word
3502:  */
3503: static unsigned int xpmNextWord
3504: ARGLIST((mdata, buf))
3505: ARG(bxxpmData *, mdata)
3506: GRA(char *, buf)
3507: {
3508:     register unsigned int n = 0;
3509:     int c;
3510: 
3511:     switch (mdata->type) {
3512:     case BXXPMARRAY:
3513:         while (isspace(c = *mdata->cptr) && c != mdata->Eos)
3514:             mdata->cptr++;
3515:         do {
3516:             c = *mdata->cptr++;
3517:             buf[n++] = c;
3518:         } while (!isspace(c) && c != mdata->Eos && c != '\0');
3519:         n--;
3520:         mdata->cptr--;
3521:         break;
3522:     case BXXPMFILE:
3523:     case BXXPMPIPE:
3524:         while (isspace(c = xpmGetC(mdata)) && c != mdata->Eos);
3525:         while (!isspace(c) && c != mdata->Eos && c != EOF) {
3526:             buf[n++] = c;
3527:             c = xpmGetC(mdata);
3528:         }
3529:         xpmUngetC(c, mdata);
3530:         break;
3531:     }
3532:     return (n);
3533: }
3534: 
3535: static int BxXpmVisualType
3536: ARGLIST((visual))
3537: GRA(Visual *, visual)
3538: {
3539: #if defined(__cplusplus) || defined(c_plusplus)
3540:     switch ( visual->c_class )
3541: #else
3542:     switch ( visual->class )
3543: #endif
3544:     {
3545:     case StaticGray:
3546:     case GrayScale:
3547:   switch (visual->map_entries)
3548:   {
3549:   case 2:
3550:       return (BXMONO);
3551:   case 4:
3552:       return (BXGRAY4);
3553:   default:
3554:       return (BXGRAY);
3555:   }
3556:     default:
3557:   return (BXCOLOR);
3558:     }
3559: }
3560: 
3561: /*
3562:  * Free the computed color table
3563:  */
3564: 
3565: static void xpmFreeColorTable
3566: ARGLIST((colorTable, ncolors))
3567: ARG(char ***, colorTable)
3568: GRA(int, ncolors)
3569: {
3570:     int a, b;
3571: 
3572:     if (colorTable) {
3573:         for (a = 0; a < ncolors; a++)
3574:             if (colorTable[a]) {
3575:                 for (b = 0; b < (BXNKEYS + 1); b++)
3576:                     if (colorTable[a][b])
3577:                         free(colorTable[a][b]);
3578:                 free((char *)colorTable[a]);
3579:             }
3580:         free((char *)colorTable);
3581:     }
3582: }
3583: 
3584: #else /* USE_XPM_LIBRARY */
3585: 
3586: #include <xpm.h>
3587: 
3588: #define BxXpmColorError    XpmColorError
3589: #define BxXpmSuccess       XpmSuccess
3590: #define BxXpmOpenFailed    XpmOpenFailed
3591: #define BxXpmFileInvalid   XpmFileInvalid
3592: #define BxXpmNoMemory      XpmNoMemory
3593: #define BxXpmColorFailed   XpmColorFailed
3594: 
3595: #define BxXpmVisual        XpmVisual
3596: #define BxXpmColormap      XpmColormap
3597: #define BxXpmDepth         XpmDepth
3598: #define BxXpmSize          XpmSize
3599: #define BxXpmHotspot       XpmHotspot
3600: #define BxXpmCharsPerPixel XpmCharsPerPixel
3601: #define BxXpmColorSymbols  XpmColorSymbols
3602: #define BxXpmRgbFilename   XpmRgbFilename
3603: #define BxXpmInfos         XpmInfos
3604: 
3605: #define BxXpmReturnPixels  XpmReturnPixels
3606: #define BxXpmReturnInfos   XpmReturnInfos
3607: 
3608: typedef XpmAttributes      BxXpmAttributes;
3609: 
3610: #endif /* USE_XPM_LIBRARY */
3611:     
3612: Pixmap XPM_PIXMAP
3613: ARGLIST((w, pixmapName))
3614: ARG(Widget, w)
3615: GRA(char **, pixmapName)
3616: {
3617:     BxXpmAttributes attributes;
3618:     int     argcnt;
3619:     Arg     args[10];
3620:     Pixmap    pixmap;
3621:     Pixmap    shape;
3622:     int     returnValue;
3623:     
3624:     argcnt = 0;
3625:     XtSetArg(args[argcnt], XmNdepth, &(attributes.depth)); argcnt++;
3626:     XtSetArg(args[argcnt], XmNcolormap, &(attributes.colormap)); argcnt++;
3627:     XtGetValues(w, args, argcnt);
3628: 
3629:     attributes.visual = DefaultVisual(XtDisplay(w),
3630:               DefaultScreen(XtDisplay(w)));
3631:     attributes.valuemask = (BxXpmDepth | BxXpmColormap | BxXpmVisual);
3632:     
3633:     returnValue = XpmCreatePixmapFromData(XtDisplay(w),
3634:             DefaultRootWindow(XtDisplay(w)),
3635:             pixmapName, &pixmap, &shape,
3636:             &attributes);
3637:     if ( shape )
3638:     {
3639:   XFreePixmap(XtDisplay(w), shape);
3640:     } 
3641: 
3642:     switch(returnValue)
3643:     {
3644:     case BxXpmOpenFailed:
3645:     case BxXpmFileInvalid:
3646:     case BxXpmNoMemory:
3647:     case BxXpmColorFailed:
3648:   XtWarning("Could not create pixmap.");
3649:   return(XmUNSPECIFIED_PIXMAP);
3650:     default:
3651:   return(pixmap);
3652:     }
3653: }
3654: 
3655: #endif
3656: 
3657: /* This structure is for capturing app-defaults values for a Class */
3658: 
3659: typedef struct _UIAppDefault
3660: {
3661:     char*   cName;    /* Class name */
3662:     char*   wName;    /* Widget name */
3663:     char*   cInstName;  /* Name of class instance(nested) */
3664:     char*   wRsc;   /* Widget resource */
3665:     char*   value;    /* value read from app-defaults */
3666: } UIAppDefault;
3667: 
3668: 
3669: void setDefaultResources ARGLIST((_name, w, resourceSpec))
3670: ARG(char*, _name)
3671: ARG(Widget, w)
3672: GRA(String *,resourceSpec)
3673: {
3674:    int         i; 
3675:    Display    *dpy = XtDisplay ( w );   /* Retrieve the display pointer */
3676:    XrmDatabase rdb = NULL;             /* A resource data base */
3677: 
3678:    /* Create an empty resource database */
3679: 
3680:    rdb = XrmGetStringDatabase ( "" );
3681: 
3682:    /* Add the Component resources, prepending the name of the component */
3683: 
3684:    i = 0;
3685:    while ( resourceSpec[i] != NULL )
3686:    {
3687:        char buf[1000];
3688: 
3689:        sprintf(buf, "*%s%s", _name, resourceSpec[i++]);
3690:        XrmPutLineResource( &rdb, buf );
3691:    }
3692: 
3693:    /* Merge them into the Xt database, with lowest precendence */
3694: 
3695:    if ( rdb )
3696:    {
3697: #if (XlibSpecificationRelease>=5)
3698:         XrmDatabase db = XtDatabase(dpy);
3699:   XrmCombineDatabase(rdb, &db, FALSE);
3700: #else
3701:         XrmMergeDatabases ( dpy->db, &rdb );
3702:         dpy->db = rdb;
3703: #endif
3704:     }
3705: }
3706: 
3707: /*
3708:  * This method gets all the resources from the app-defaults file 
3709:  * (resource databse) and fills in the table (defs) if the app default 
3710:  * value exists.
3711:  */
3712: void
3713: InitAppDefaults ARGLIST((parent, defs))
3714: ARG(Widget, parent)
3715: GRA(UIAppDefault *, defs)
3716: {
3717:     XrmQuark    cQuark;
3718:     XrmQuark    rsc[6];
3719:     XrmRepresentation rep;
3720:     XrmValue    val;
3721:     XrmDatabase   rdb;
3722:     int     rscIdx;
3723: 
3724:     /* Get the database */
3725: 
3726: #if (XlibSpecificationRelease >= 5)
3727:     if ((rdb = XrmGetDatabase(XtDisplay(parent))) == NULL)
3728:     {
3729:   return;     /*  Can't get the database */
3730:     }
3731: #else
3732:     Display *dpy = XtDisplay(parent);
3733:     if ((rdb = dpy->db) == NULL)
3734:     {
3735:   return;
3736:     }
3737: #endif
3738: 
3739:     /* Look for each resource in the table */
3740: 
3741:     while (defs->wName)
3742:     {
3743:   rscIdx = 0;
3744:   
3745:   cQuark = XrmStringToQuark(defs->cName); /* class quark */
3746:   rsc[rscIdx++] = cQuark;
3747:   if (defs->wName[0] == '\0')
3748:   {
3749:       rsc[rscIdx++] = cQuark;
3750:   }
3751:   else
3752:   {
3753:       if( strchr(defs->wName, '.') == NULL )
3754:       {
3755:     rsc[rscIdx++] = XrmStringToQuark(defs->wName);
3756:       }
3757:       else
3758:       {
3759:     /*
3760:      * If we found a '.' that means that this is not
3761:      * a simple widget name, but a sub specification so
3762:      * we need to split this into several quarks.
3763:      */
3764:     char *copy = strdup(defs->wName), *ptr;
3765: 
3766:     for( ptr = strtok(copy, "."); ptr != NULL;
3767:          ptr = strtok(NULL, ".") )
3768:     {
3769:         rsc[rscIdx++] = XrmStringToQuark(ptr);
3770:     }
3771:     free(copy);
3772:       }
3773:   }
3774: 
3775:   if (defs->cInstName && defs->cInstName[0] != '\0')
3776:   {
3777:       rsc[rscIdx++] = XrmStringToQuark(defs->cInstName);
3778:   }
3779: 
3780:   rsc[rscIdx++] = XrmStringToQuark(defs->wRsc);
3781:   rsc[rscIdx++] = NULLQUARK;
3782: 
3783:   if (XrmQGetResource(rdb, rsc, rsc, &rep, &val))
3784:   {
3785:       defs->value = strdup((char*)val.addr);
3786:   }
3787:   defs++;
3788:     }
3789: }
3790: 
3791: /*
3792:  * This method applies the app defaults for the class to a specific
3793:  * instance. All the widgets in the path are loosly coupled (use *).
3794:  * To override a specific instance, use a tightly coupled app defaults
3795:  * resource line (use .).
3796:  */
3797: void
3798: SetAppDefaults ARGLIST((w, defs, inst_name))
3799: ARG(Widget,w)
3800: ARG(UIAppDefault*, defs)
3801: GRA(char*, inst_name)
3802: {
3803:    Display*   dpy = XtDisplay ( w );  /*  Retrieve the display */
3804:    XrmDatabase    rdb = NULL;   /* A resource data base */
3805:    char     lineage[1000];
3806:    char     buf[1000];
3807:    Widget         parent;
3808:    char*    wName;
3809:    
3810:    /* Protect ourselves */
3811:    
3812:    if (inst_name == NULL) return;
3813: 
3814:    /*  Create an empty resource database */
3815: 
3816:    rdb = XrmGetStringDatabase ( "" );
3817: 
3818:    /* Start the lineage with our name and then get our parents */
3819: 
3820:    lineage[0] = '\0';
3821:    parent = w;
3822: 
3823:    while (parent)
3824:    {
3825:        WidgetClass wclass = XtClass(parent);
3826: 
3827:        if (wclass == applicationShellWidgetClass) break;
3828: 
3829:        strcpy(buf, lineage);
3830:        sprintf(lineage, "*%s%s", XtName(parent), buf);
3831: 
3832:        parent = XtParent(parent);
3833:    }
3834: 
3835:    /*  Add the Component resources, prepending the name of the component */
3836: 
3837:    while (defs->wName != NULL)
3838:    {
3839:        if ( !strcmp(defs->wName, "" ) ) wName = inst_name;
3840:        else wName = (char *)(defs->wName);
3841: 
3842:        /*
3843:   * See if we need to deal with this record.
3844:   *  (1) If we've been passed an instance name (meaning we're
3845:   *      creating a nested instance of a class), then make sure
3846:   *      we're dealing with the proper nested instance.
3847:   *  (2) If we're not creating a nested instance, then
3848:   *      ignore resources for nested instances.
3849:   *  (3) We didn't find a default value in the app-defaults
3850:   */
3851: 
3852:        if ((inst_name && strcmp(inst_name, wName)) ||   /* (1) */
3853:      (!inst_name && defs->cInstName) ||     /* (2) */
3854:      (defs->value == NULL))       /* (3) */
3855:        {
3856:      defs++;
3857:      continue;
3858:        }
3859: 
3860:        /* Build up string after lineage */
3861:        if (defs->cInstName != NULL)
3862:        {
3863:      /* Don't include class instance name if it is also the instance */
3864:      /* being affected.  */
3865: 
3866:      if (*defs->cInstName != '\0')
3867:      {
3868:          sprintf(buf, "%s.%s*%s.%s: %s",
3869:            lineage, wName, defs->cInstName, defs->wRsc,
3870:            defs->value);
3871:      }
3872:      else
3873:      {
3874:          sprintf(buf, "%s.%s.%s: %s",
3875:            lineage, wName, defs->wRsc, defs->value);
3876:      }
3877:        }
3878:        else if (*defs->wName != '\0')
3879:        {
3880:      sprintf(buf, "%s*%s*%s.%s: %s",
3881:        lineage, inst_name, defs->wName, defs->wRsc, defs->value);
3882:        }
3883:        else
3884:        {
3885:      sprintf(buf, "%s*%s.%s: %s", 
3886:        lineage, inst_name, defs->wRsc, defs->value);
3887:        }
3888: 
3889:        XrmPutLineResource( &rdb, buf );
3890:        defs++;
3891:    }
3892: 
3893:    /* Merge them into the Xt database, with lowest precendence */
3894:    if ( rdb )
3895:    {
3896: #if (XlibSpecificationRelease >= 5)
3897:         XrmDatabase db = XtDatabase(dpy);
3898:   XrmCombineDatabase(rdb, &db, FALSE);
3899: #else
3900:         XrmMergeDatabases ( dpy->db, &rdb );
3901:         dpy->db = rdb;
3902: #endif
3903:     }
3904: }
3905: 
3906: 
3907: 








































Html form generated by Xrefactory version 1.6.7 on Fri Sep 03 17:18:59 2004