home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Utilities / StdTypIO.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  40.1 KB  |  1,370 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        StdTypIO.cpp
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>    .03.1996    NP        1313878: Fixed problem of out-of-sync
  13.                                     values for IText property.
  14.  
  15.     To Do:
  16. */
  17.  
  18. /*
  19.     File:        StdTypIO.cpp
  20.  
  21.     Contains:    functions for read/writing standard typed values from/to storage units
  22.  
  23.     Owned by:    Tantek Çelik
  24.  
  25.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  26.  
  27.     Theory of operation:
  28.     
  29.  The philosophy of StdTypIO is to give the client of the standard type IO functions
  30.  flexibility with respect to where the data is stored while providing a standard for
  31.  the data format used to store the types of data used in the various pieces of 
  32.  OpenDoc metadata in order to facilitate document exchange.  
  33.  
  34.  The standard type IO functions are designed to be used independent of property & 
  35.  value type, and in some/most cases can even be used to manipulate data midstream 
  36.  (in the middle of values) by passing in a prefocused storageunit along with the 
  37.  offset set correctly, and passing in kODNULL for the prop and the val params.  
  38.   
  39.         
  40. */
  41.  
  42.  
  43. #ifndef _ALTPOINT_
  44. #include "AltPoint.h"
  45. #endif
  46.  
  47. #ifndef _ALTPOLY_
  48. #include "AltPoly.h"
  49. #endif
  50.  
  51. #ifndef _EXCEPT_
  52. #include <Except.h>
  53. #endif
  54.  
  55. #ifndef _ODDEBUG_
  56. #include "ODDebug.h"
  57. #endif
  58.  
  59. #ifndef __SCRIPT__
  60. #include <Script.h>
  61. #endif
  62.  
  63. #ifndef _TEMPITER_
  64. #include <TempIter.h>
  65. #endif
  66.  
  67. #ifndef _ITEXT_
  68. #include <IText.h>
  69. #endif
  70.  
  71. #ifndef __TIME_H__
  72. #include <Time.h>
  73. #endif
  74.  
  75. #ifndef _ODMEMORY_
  76. #include <ODMemory.h>
  77. #endif
  78.  
  79. #ifndef SOM_ODStorageUnit_xh
  80. #include <StorageU.xh>
  81. #endif
  82.  
  83. #ifndef SOM_ODStorageUnitView_xh
  84. #include <SUView.xh>
  85. #endif
  86.  
  87. #ifndef _STDTYPIO_
  88. #include "StdTypIO.h"
  89. #endif
  90.  
  91. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  92. #include "StdDefs.xh"
  93. #endif
  94.  
  95. #ifndef _STORUTIL_
  96. #include <StorUtil.h>
  97. #endif
  98.  
  99. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  100. #include "StdTypes.xh"
  101. #endif
  102.  
  103. #ifndef SOM_ODTypeList_xh
  104. #include <TypeList.xh>
  105. #endif
  106.  
  107. #ifndef SOM_ODTypeListIterator_xh
  108. #include <TypLsItr.xh>
  109. #endif
  110.  
  111. #ifndef __OSUTILS__
  112. #include <OSUtils.h>
  113. #endif
  114.  
  115. #ifndef _FLIPEND_
  116. #include <FlipEnd.h>
  117. #endif
  118.  
  119. #ifndef _ODUTILS_
  120. #include <ODUtils.h>
  121. #endif
  122.  
  123. #ifndef _UTILERRS_
  124. #include <UtilErrs.h>
  125. #endif
  126.  
  127. #ifndef _TEMPOBJ_
  128. #include <TempObj.h>
  129. #endif
  130.  
  131. //==============================================================================
  132. // Constants
  133. //==============================================================================
  134.  
  135. #define        kODBooleanLen         1
  136. #define        kODUShortLen        2
  137. #define        kODSShortLen        2
  138. #define        kODULongLen            4
  139. #define        kODSLongLen            4
  140. #define        kODCoordinateLen    4
  141. #define        kODPointLen            (4*2)
  142. #define        kODRectLen            (4*4)
  143. #define        kODStorageUnitRefLen 4
  144.  
  145. #define useGMT 1
  146.  
  147. //==============================================================================
  148. // Boolean
  149. //==============================================================================
  150.  
  151. ODBoolean    ODGetBooleanProp(Environment* ev, 
  152.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  153. {
  154.     if (ODSUExistsThenFocus(ev, su, prop, val))
  155.     {
  156.         ODBoolean value;
  157.         StorageUnitGetValue(su, ev, sizeof(ODBoolean), (ODValue)&value);
  158.         return (value ? kODTrue : kODFalse);
  159.     }
  160.     else {
  161.         WARN("No Boolean Property.");
  162.         return kODFalse;
  163.     }
  164. }
  165.  
  166. void        ODSetBooleanProp(Environment* ev, 
  167.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  168.                 ODBoolean value)
  169. {
  170.     ODSUForceFocus(ev, su, prop, val);
  171.     StorageUnitSetValue(su, ev, sizeof(ODBoolean), (ODValue)&value);
  172. }
  173.  
  174. //==============================================================================
  175. // Short
  176. //==============================================================================
  177.  
  178. ODUShort    ODGetUShortProp(Environment* ev, 
  179.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  180. {
  181.     if (ODSUExistsThenFocus(ev, su, prop, val))
  182.     {
  183.         ODUShort value;
  184.         StorageUnitGetValue(su, ev, kODUShortLen, (ODValue)&value);
  185.         return ConvertODUShortFromStd(value);
  186.     }
  187.     else {
  188.         WARN("No UShort Property.");
  189.         return 0;
  190.     }
  191. }
  192.  
  193. void        ODSetUShortProp(Environment* ev, 
  194.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  195.                 ODUShort value)
  196. {
  197.     ODSUForceFocus(ev, su, prop, val);
  198.     value = ConvertODUShortToStd(value);
  199.     StorageUnitSetValue(su, ev, kODUShortLen, (ODValue)&value);
  200. }
  201.  
  202.  
  203. ODSShort    ODGetSShortProp(Environment* ev, 
  204.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  205. {
  206.     if (ODSUExistsThenFocus(ev, su, prop, val))
  207.     {
  208.         ODSShort value;
  209.         StorageUnitGetValue(su, ev, kODSShortLen, (ODValue)&value);
  210.         return ConvertODSShortFromStd(value);
  211.     }
  212.     else {
  213.         WARN("No SShort Property.");
  214.         return 0;
  215.     }
  216. }
  217.  
  218. void        ODSetSShortProp(Environment* ev, 
  219.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  220.                 ODSShort value)
  221. {
  222.     ODSUForceFocus(ev, su, prop, val);
  223.     value = ConvertODSShortToStd(value);
  224.     StorageUnitSetValue(su, ev, kODSShortLen, (ODValue)&value);
  225. }
  226.  
  227.  
  228. //==============================================================================
  229. // Long
  230. //==============================================================================
  231.  
  232. ODULong        ODGetULongProp(Environment* ev, 
  233.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  234. {
  235.     if (ODSUExistsThenFocus(ev, su, prop, val))
  236.     {
  237.         ODULong value;
  238.         StorageUnitGetValue(su, ev, kODULongLen, (ODValue)&value);
  239.         return ConvertODULongFromStd(value);
  240.     }
  241.     else {
  242.         //WARN("No ULong Property.");  // This is EXPECTED in many uses of ODGetULongProp, so this makes sense.
  243.         return 0;
  244.     }
  245. }
  246.  
  247. void        ODSetULongProp(Environment* ev, 
  248.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  249.                 ODULong value)
  250. {
  251.     ODSUForceFocus(ev, su, prop, val);
  252.     value = ConvertODULongToStd(value);
  253.     StorageUnitSetValue(su, ev, kODULongLen, (ODValue)&value);
  254. }
  255.  
  256.  
  257. ODSLong        ODGetSLongProp(Environment* ev, 
  258.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  259. {
  260.     if (ODSUExistsThenFocus(ev, su, prop, val))
  261.     {
  262.         ODSLong value;
  263.         StorageUnitGetValue(su, ev, kODSLongLen, (ODValue)&value);
  264.         return ConvertODSLongFromStd(value);
  265.     }
  266.     else {
  267.         WARN("No SLong Property.");
  268.         return 0;
  269.     }
  270. }
  271.  
  272. void        ODSetSLongProp(Environment* ev, 
  273.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  274.                 ODSLong value)
  275. {
  276.     ODSUForceFocus(ev, su, prop, val);
  277.     value = ConvertODSLongToStd(value);
  278.     StorageUnitSetValue(su, ev, kODSLongLen, (ODValue)&value);
  279. }
  280.  
  281.  
  282. //==============================================================================
  283. // ISOStr
  284. //==============================================================================
  285.  
  286. // In: The size parameter is the length of the longest ISOStr which can be written
  287. // to the 'value' buffer.  This does not include the '\0' which is written to the buffer
  288. // at the end.
  289. // In other words, at most (*size)+1 bytes can be written to 'value' by ODGetISOStrProp.
  290. // If the value parameter is NULL, then an ISOStr is allocated and for you and returned.
  291. // Out: The size parameter is the length of the ISOStr which was read in.
  292. // If there is no value at the passed in prop & val then kODNULL is returned.
  293. // This is consistent with the other routines in StdTypIO which return pointers.
  294. // The reason is that there are clients of ODGetISOStrProp which more easily handle the
  295. // flow of control if it just returns kODNULL instead of THROWing. -Tantek
  296. // One such client: ODGetKindFromPartSU in InfoUtil.
  297.  
  298. ODISOStr    ODGetISOStrProp(Environment* ev, 
  299.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  300.                 ODISOStr value, ODULong* size)
  301. {
  302.     if (ODSUExistsThenFocus(ev, su, prop, val))
  303.     {
  304.         ODULong    valueSize = su->GetSize(ev);
  305.         if (valueSize == 0) 
  306.             valueSize++;    /* just to be absolutely safe */
  307.         if (!value)
  308.         {
  309.             value = (ODISOStr)ODNewPtr(valueSize);
  310.         }
  311.         else 
  312.         {
  313.             if (size!=kODNULL && valueSize > *size) 
  314.                 valueSize = *size;
  315.         }
  316.         ODULong length = valueSize - 1;
  317.         StorageUnitGetValue(su, ev, length, (ODValue)value);
  318.         value[length] = '\0';
  319.         if (size!=kODNULL)
  320.             *size = length;
  321.         return value;
  322.     }
  323.     else
  324.     {
  325.         if (size!=kODNULL)
  326.             *size = 0;
  327.         return kODNULL;
  328.     }
  329. }
  330.  
  331. void        ODSetISOStrProp(Environment* ev, 
  332.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  333.                 ODISOStr value)
  334. {
  335.     ODSUForceFocus(ev, su, prop, val);
  336.     ODULong oldsize = su->GetSize(ev);
  337.     ODULong newsize = strlen(value)+1;
  338.     StorageUnitSetValue(su, ev, newsize, (ODValue)value);
  339.     if (oldsize > newsize)
  340.         su->DeleteValue(ev, oldsize - newsize);
  341. }
  342.  
  343.  
  344. //==============================================================================
  345. // TypeList
  346. //==============================================================================
  347. //
  348. // Aan ODTypeList property value containing n elements begins with (n+1) offsets,
  349. // followed by n ISO strings with their null termination.  The first n offsets
  350. // identify the starting positions of the corresponding ISO string.  The last
  351. // offset is always equal to the size of the value, and is immediately before
  352. // the first character of the first ISO string (its actually redundant)
  353. // For example, a property value representing an empty ODTypeList will be 
  354. // four bytes long and contain offset four, signifying that there are no ISO 
  355. // strings present.
  356.  
  357. void ODGetTypeListProp(Environment* ev,
  358.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  359.                 ODTypeList* typeList)
  360. {
  361.     // If an error is thrown, typeList may be partially updated.
  362.  
  363.     if ( ODSUExistsThenFocus(ev, su, prop, val) )
  364.     {
  365.         ODULong    valueSize = su->GetSize(ev);
  366.         if ( valueSize >= kODULongLen )
  367.         {
  368.             ODULong index = 0;
  369.             ODULong offset;
  370.             ODULong nextOffset;
  371.  
  372.             su->SetOffset(ev, 0);
  373.             StorageUnitGetValue(su, ev, kODULongLen, (ODValue) &offset);
  374.             
  375.             while ( offset < valueSize )
  376.             {
  377.                 su->SetOffset(ev, (index+1)*kODULongLen);
  378.                 StorageUnitGetValue(su, ev, kODULongLen, (ODValue) &nextOffset);
  379.  
  380.                 su->SetOffset(ev, offset);
  381.  
  382.                 TempODType kind = (ODType) ODNewPtr(nextOffset-offset);;
  383.                 
  384.                 StorageUnitGetValue(su, ev, nextOffset-offset, (ODValue) kind);
  385.                 typeList->AddLast(ev, kind);
  386.                 
  387.                 offset = nextOffset;
  388.                 ++index;
  389.             }
  390.         }
  391.     }
  392.     else
  393.     {
  394.         WARN("No TypeList Property.");
  395.     }
  396. }
  397.  
  398. void ODSetTypeListProp(Environment* ev,
  399.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  400.                 ODTypeList* typeList)
  401. {
  402.     // If an error is thrown, the property value will be truncated to zero length.
  403.  
  404.     ODSUForceFocus(ev, su, prop, val);
  405.     ODULong oldsize = su->GetSize(ev);
  406.  
  407.     ODType kind = kODNULL;
  408.     ODULong index = 0;
  409.     ODULong offset = (typeList->Count(ev)+1)*kODULongLen;
  410.     
  411.     TRY
  412.     
  413.         // Write the offset to the first Type value and placeholders for 
  414.         // the remaining offsets to be written later
  415.         su->SetOffset(ev, 0);
  416.         while ( su->GetSize(ev) < offset )
  417.             StorageUnitSetValue(su, ev, kODULongLen, (ODValue) &offset);
  418.  
  419.         for( TempODTypeListIterator iter(ev,typeList); iter; iter.Next() )
  420.         {
  421.             kind = iter.Current();
  422.             su->SetOffset(ev, offset);
  423.             ODULong size = strlen(kind)+1;
  424.  
  425.             StorageUnitSetValue(su, ev, size, (ODValue) kind);
  426.             offset += size;
  427.             ++index;
  428.             su->SetOffset(ev, index*kODULongLen);
  429.             StorageUnitSetValue(su, ev, kODULongLen, (ODValue) &offset);
  430.             
  431.             ODDisposePtr(kind);
  432.         }
  433.  
  434.     CATCH_ALL
  435.     
  436.         ODDisposePtr(kind);
  437.         su->SetOffset(ev, 0);
  438.         su->DeleteValue(ev, oldsize);
  439.         RERAISE;
  440.  
  441.     ENDTRY
  442.     
  443.     if (oldsize > offset)
  444.     {
  445.         su->SetOffset(ev, offset);
  446.         su->DeleteValue(ev, oldsize - offset);
  447.     }
  448. }
  449.  
  450. //==============================================================================
  451. // IText
  452. //==============================================================================
  453.  
  454.  
  455. // TABLE ONLY HANDLES MACINTOSH EXTENDED CHARACTER SET FOR THE MacRoman SCRIPT,
  456. //    THE langEngligh LANGUAGE, AND A "NORMAL" FONT (I.E. NOT THE "SYMBOL" FONT
  457. //    OR A DINGBAT FONT). PROBABLY VALID FOR OTHER LANGUAGES AS WELL. - NP
  458.  
  459. // NOTE THAT MAC CHARACTERS 0x0000 - 0x007F ARE MAPPED THE SAME UNICODE
  460. //    CHARACTERS. DIFFERENCES APPEAR FROM 0x0080 - 0x00FF
  461.  
  462. ODUShort MacToUniTable[256] =
  463. {
  464. /* 0x0000 */  0x0000,
  465. /* 0x0001 */  0x0001,
  466. /* 0x0002 */  0x0002,
  467. /* 0x0003 */  0x0003,
  468. /* 0x0004 */  0x0004,
  469. /* 0x0005 */  0x0005,
  470. /* 0x0006 */  0x0006,
  471. /* 0x0007 */  0x0007,
  472. /* 0x0008 */  0x0008,
  473. /* 0x0009 */  0x0009,
  474. /* 0x000A */  0x000A,
  475. /* 0x000B */  0x000B,
  476. /* 0x000C */  0x000C,
  477. /* 0x000D */  0x000D,
  478. /* 0x000E */  0x000E,
  479. /* 0x000F */  0x000F,
  480. /* 0x0010 */  0x0010,
  481. /* 0x0011 */  0x0011,
  482. /* 0x0012 */  0x0012,
  483. /* 0x0013 */  0x0013,
  484. /* 0x0014 */  0x0014,
  485. /* 0x0015 */  0x0015,
  486. /* 0x0016 */  0x0016,
  487. /* 0x0017 */  0x0017,
  488. /* 0x0018 */  0x0018,
  489. /* 0x0019 */  0x0019,
  490. /* 0x001A */  0x001A,
  491. /* 0x001B */  0x001B,
  492. /* 0x001C */  0x001C,
  493. /* 0x001D */  0x001D,
  494. /* 0x001E */  0x001E,
  495. /* 0x001F */  0x001F,
  496. /* 0x0020 ' ' */  ' ',
  497. /* 0x0021 '!' */  '!',
  498. /* 0x0022 '"' */  '"',
  499. /* 0x0023 '#' */  '#',
  500. /* 0x0024 '$' */  '$',
  501. /* 0x0025 '%' */  '%',
  502. /* 0x0026 '&' */  '&',
  503. /* 0x0027 '\'' */  '\'',
  504. /* 0x0028 '(' */  '(',
  505. /* 0x0029 ')' */  ')',
  506. /* 0x002A '*' */  '*',
  507. /* 0x002B '+' */  '+',
  508. /* 0x002C ',' */  ',',
  509. /* 0x002D '-' */  '-',
  510. /* 0x002E '.' */  '.',
  511. /* 0x002F '/' */  '/',
  512. /* 0x0030 '0' */  '0',
  513. /* 0x0031 '1' */  '1',
  514. /* 0x0032 '2' */  '2',
  515. /* 0x0033 '3' */  '3',
  516. /* 0x0034 '4' */  '4',
  517. /* 0x0035 '5' */  '5',
  518. /* 0x0036 '6' */  '6',
  519. /* 0x0037 '7' */  '7',
  520. /* 0x0038 '8' */  '8',
  521. /* 0x0039 '9' */  '9',
  522. /* 0x003A ':' */  ':',
  523. /* 0x003B ';' */  ';',
  524. /* 0x003C '<' */  '<',
  525. /* 0x003D '=' */  '=',
  526. /* 0x003E '>' */  '>',
  527. /* 0x003F '?' */  '?',
  528. /* 0x0040 '@' */  '@',
  529. /* 0x0041 'A' */  'A',
  530. /* 0x0042 'B' */  'B',
  531. /* 0x0043 'C' */  'C',
  532. /* 0x0044 'D' */  'D',
  533. /* 0x0045 'E' */  'E',
  534. /* 0x0046 'F' */  'F',
  535. /* 0x0047 'G' */  'G',
  536. /* 0x0048 'H' */  'H',
  537. /* 0x0049 'I' */  'I',
  538. /* 0x004A 'J' */  'J',
  539. /* 0x004B 'K' */  'K',
  540. /* 0x004C 'L' */  'L',
  541. /* 0x004D 'M' */  'M',
  542. /* 0x004E 'N' */  'N',
  543. /* 0x004F 'O' */  'O',
  544. /* 0x0050 'P' */  'P',
  545. /* 0x0051 'Q' */  'Q',
  546. /* 0x0052 'R' */  'R',
  547. /* 0x0053 'S' */  'S',
  548. /* 0x0054 'T' */  'T',
  549. /* 0x0055 'U' */  'U',
  550. /* 0x0056 'V' */  'V',
  551. /* 0x0057 'W' */  'W',
  552. /* 0x0058 'X' */  'X',
  553. /* 0x0059 'Y' */  'Y',
  554. /* 0x005A 'Z' */  'Z',
  555. /* 0x005B '[' */  '[',
  556. /* 0x005C '\\' */  '\\',
  557. /* 0x005D ']' */  ']',
  558. /* 0x005E '^' */  '^',
  559. /* 0x005F '_' */  '_',
  560. /* 0x0060 '`' */  '`',
  561. /* 0x0061 'a' */  'a',
  562. /* 0x0062 'b' */  'b',
  563. /* 0x0063 'c' */  'c',
  564. /* 0x0064 'd' */  'd',
  565. /* 0x0065 'e' */  'e',
  566. /* 0x0066 'f' */  'f',
  567. /* 0x0067 'g' */  'g',
  568. /* 0x0068 'h' */  'h',
  569. /* 0x0069 'i' */  'i',
  570. /* 0x006A 'j' */  'j',
  571. /* 0x006B 'k' */  'k',
  572. /* 0x006C 'l' */  'l',
  573. /* 0x006D 'm' */  'm',
  574. /* 0x006E 'n' */  'n',
  575. /* 0x006F 'o' */  'o',
  576. /* 0x0070 'p' */  'p',
  577. /* 0x0071 'q' */  'q',
  578. /* 0x0072 'r' */  'r',
  579. /* 0x0073 's' */  's',
  580. /* 0x0074 't' */  't',
  581. /* 0x0075 'u' */  'u',
  582. /* 0x0076 'v' */  'v',
  583. /* 0x0077 'w' */  'w',
  584. /* 0x0078 'x' */  'x',
  585. /* 0x0079 'y' */  'y',
  586. /* 0x007A 'z' */  'z',
  587. /* 0x007B '{' */  '{',
  588. /* 0x007C '|' */  '|',
  589. /* 0x007D '}' */  '}',
  590. /* 0x007E '~' */  '~',
  591. /* 0x007F */  0x007F,
  592.  
  593. /* 0x0080 */  0x00C4,    // LATIN CAPITAL LETTER A DIAERESIS 
  594. /* 0x0081 */  0x00C5,    // LATIN CAPITAL LETTER A RING 
  595. /* 0x0082 */  0x00C7,    // LATIN CAPITAL LETTER C CEDILLA 
  596. /* 0x0083 */  0x00C9,    // LATIN CAPITAL LETTER E ACUTE 
  597. /* 0x0084 */  0x00D1,    // LATIN CAPITAL LETTER N TILDE 
  598. /* 0x0085 */  0x00D6,    // LATIN CAPITAL LETTER O DIAERESIS 
  599. /* 0x0086 */  0x00DC,    // LATIN CAPITAL LETTER U DIAERESIS 
  600. /* 0x0087 */  0x00E1,    // LATIN SMALL LETTER A ACUTE 
  601. /* 0x0088 */  0x00E0,    // LATIN SMALL LETTER A GRAVE 
  602. /* 0x0089 */  0x00E2,    // LATIN SMALL LETTER A CIRCUMFLEX 
  603. /* 0x008A */  0x00E4,    // LATIN SMALL LETTER A DIAERESIS 
  604. /* 0x008B */  0x00E3,    // LATIN SMALL LETTER A TILDE 
  605. /* 0x008C */  0x00E5,    // LATIN SMALL LETTER A RING ABOVE 
  606. /* 0x008D */  0x00E7,    // LATIN SMALL LETTER C CEDILLA 
  607. /* 0x008E */  0x00E9,    // LATIN SMALL LETTER E ACUTE 
  608. /* 0x008F */  0x00E8,    // LATIN SMALL LETTER E GRAVE 
  609. /* 0x0090 */  0x00EA,    // LATIN SMALL LETTER E CIRCUMFLEX 
  610. /* 0x0091 */  0x00EB,    // LATIN SMALL LETTER E DIAERESIS 
  611. /* 0x0092 */  0x00ED,    // LATIN SMALL LETTER I ACUTE 
  612. /* 0x0093 */  0x00EC,    // LATIN SMALL LETTER I GRAVE 
  613. /* 0x0094 */  0x00EE,    // LATIN SMALL LETTER I CIRCUMFLEX 
  614. /* 0x0095 */  0x00EF,    // LATIN SMALL LETTER I DIAERESIS 
  615. /* 0x0096 */  0x00F1,    // LATIN SMALL LETTER N TILDE 
  616. /* 0x0097 */  0x00F3,    // LATIN SMALL LETTER O ACUTE 
  617. /* 0x0098 */  0x00F2,    // LATIN SMALL LETTER O GRAVE 
  618. /* 0x0099 */  0x00F4,    // LATIN SMALL LETTER O CIRCUMFLEX 
  619. /* 0x009A */  0x00F6,    // LATIN SMALL LETTER O DIAERESIS 
  620. /* 0x009B */  0x00F5,    // LATIN SMALL LETTER O TILDE 
  621. /* 0x009C */  0x00FA,    // LATIN SMALL LETTER U ACUTE 
  622. /* 0x009D */  0x00F9,    // LATIN SMALL LETTER U GRAVE 
  623. /* 0x009E */  0x00FB,    // LATIN SMALL LETTER U CIRCUMFLEX 
  624. /* 0x009F */  0x00FC,    // LATIN SMALL LETTER U DIAERESIS 
  625. /* 0x00A0 */  0x2020,    // DAGGER             
  626. /* 0x00A1 */  0x00B0,    // DEGREE SIGN        
  627. /* 0x00A2 */  0x00A2,    // CENT SIGN          
  628. /* 0x00A3 */  0x00A3,    // POUND SIGN         
  629. /* 0x00A4 */  0x00A7,    // SECTION SIGN       
  630. /* 0x00A5 */  0x2022,    // BULLET             
  631. /* 0x00A6 */  0x00B6,    // PILCROW SIGN       
  632. /* 0x00A7 */  0x00DF,    // LATIN SMALL LETTER SHARP S 
  633. /* 0x00A8 */  0x00AE,    // REGISTERED SIGN    
  634. /* 0x00A9 */  0x00A9,    // COPYRIGHT SIGN     
  635. /* 0x00AA */  0x2122,    // TRADE MARK SIGN    
  636. /* 0x00AB */  0x00B4,    // ACUTE ACCENT       
  637. /* 0x00AC */  0x00A8,    // DIAERESIS          
  638. /* 0x00AD */  0x2260,    // NOT EQUAL TO       
  639. /* 0x00AE */  0x00C6,    // LATIN CAPITAL LETTER LIGATURE A E 
  640. /* 0x00AF */  0x00D8,    // LATIN CAPITAL LETTER O STROKE 
  641. /* 0x00B0 */  0x221E,    // INFINITY           
  642. /* 0x00B1 */  0x00B1,    // PLUS-MINUS SIGN    
  643. /* 0x00B2 */  0x2264,    // LESS-THAN OR EQUAL TO 
  644. /* 0x00B3 */  0x2265,    // GREATER-THAN OR EQUAL TO 
  645. /* 0x00B4 */  0x00A5,    // YEN SIGN           
  646. /* 0x00B5 */  0x00B5,    // MICRO SIGN         
  647. /* 0x00B6 */  0x2202,    // PARTIAL DIFFERENTIAL 
  648. /* 0x00B7 */  0x2211,    // N-ARY SUMMATION    
  649. /* 0x00B8 */  0x220F,    // N-ARY PRODUCT      
  650. /* 0x00B9 */  0x03C0,    // GREEK SMALL LETTER PI 
  651. /* 0x00BA */  0x222B,    // INTEGRAL           
  652. /* 0x00BB */  0x00AA,    // FEMININE ORDINAL INDICATOR 
  653. /* 0x00BC */  0x00BA,    // MASCULINE ORDINAL INDICATOR 
  654. /* 0x00BD */  0x2126,    // OHM SIGN           
  655. /* 0x00BE */  0x00E6,    // LATIN SMALL LETTER LIGATURE A E 
  656. /* 0x00BF */  0x00F8,    // LATIN SMALL LETTER O SLASH 
  657. /* 0x00C0 */  0x00BF,    // INVERTED QUESTION MARK 
  658. /* 0x00C1 */  0x00A1,    // INVERTED EXCLAMATION MARK 
  659. /* 0x00C2 */  0x00AC,    // NOT SIGN           
  660. /* 0x00C3 */  0x221A,    // SQUARE ROOT        
  661. /* 0x00C4 */  0x0192,    // LATIN SMALL LETTER F HOOK  
  662. /* 0x00C5 */  0x2248,    // ALMOST EQUAL TO    
  663. /* 0x00C6 */  0x2206,    // INCREMENT          
  664. /* 0x00C7 */  0x00AB,    // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 
  665. /* 0x00C8 */  0x00BB,    // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 
  666. /* 0x00C9 */  0x2026,    // HORIZONTAL ELLIPSIS 
  667. /* 0x00CA */  0x00A0,    // NO-BREAK SPACE 
  668. /* 0x00CB */  0x00C0,    // LATIN CAPITAL LETTER A GRAVE 
  669. /* 0x00CC */  0x00C3,    // LATIN CAPITAL LETTER A TILDE 
  670. /* 0x00CD */  0x00D5,    // LATIN CAPITAL LETTER O TILDE 
  671. /* 0x00CE */  0x0152,    // LATIN CAPITAL LETTER LIGATURE O E 
  672. /* 0x00CF */  0x0153,    // LATIN SMALL LETTER LIGATURE O E 
  673. /* 0x00D0 */  0x2013,    // EN DASH            
  674. /* 0x00D1 */  0x2014,    // EM DASH            
  675. /* 0x00D2 */  0x201C,    // LEFT DOUBLE QUOTATION MARK 
  676. /* 0x00D3 */  0x201D,    // RIGHT DOUBLE QUOTATION MARK 
  677. /* 0x00D4 */  0x2018,    // LEFT SINGLE QUOTATION MARK 
  678. /* 0x00D5 */  0x2019,    // RIGHT SINGLE QUOTATION MARK 
  679. /* 0x00D6 */  0x00F7,    // DIVISION SIGN      
  680. /* 0x00D7 */  0x25CA,    // LOZENGE            
  681. /* 0x00D8 */  0x00FF,    // LATIN SMALL LETTER Y DIAERESIS 
  682. /* 0x00D9 */  0x0178,    // LATIN CAPITAL LETTER Y DIAERESIS 
  683. /* 0x00DA */  0x2044,    // FRACTION SLASH     
  684. /* 0x00DB */  0x00A4,    // CURRENCY SIGN      
  685. /* 0x00DC */  0x2039,    // SINGLE LEFT-POINTING ANGLE QUOTE MARK 
  686. /* 0x00DD */  0x203A,    // SINGLE RIGHT-POINTING ANGLE QUOTE MARK 
  687. /* 0x00DE */  0xFB01,    // LATIN SMALL LETTER LIGATURE FI 
  688. /* 0x00DF */  0xFB02,    // LATIN SMALL LETTER LIGATURE FL 
  689. /* 0x00E0 */  0x2021,    // DOUBLE DAGGER      
  690. /* 0x00E1 */  0x00B7,    // MIDDLE DOT         
  691. /* 0x00E2 */  0x201A,    // SINGLE LOW-9 QUOTATION MARK 
  692. /* 0x00E3 */  0x201E,    // DOUBLE LOW-9 QUOTATION MARK 
  693. /* 0x00E4 */  0x2030,    // PER MILLE SIGN     
  694. /* 0x00E5 */  0x00C2,    // LATIN CAPITAL LETTER A CIRCUMFLEX 
  695. /* 0x00E6 */  0x00CA,    // LATIN CAPITAL LETTER E CIRCUMFLEX 
  696. /* 0x00E7 */  0x00C1,    // LATIN CAPITAL LETTER A ACUTE 
  697. /* 0x00E8 */  0x00CB,    // LATIN CAPITAL LETTER E DIAERESIS 
  698. /* 0x00E9 */  0x00C8,    // LATIN CAPITAL LETTER E GRAVE 
  699. /* 0x00EA */  0x00CD,    // LATIN CAPITAL LETTER I ACUTE 
  700. /* 0x00EB */  0x00CE,    // LATIN CAPITAL LETTER I CIRCUMFLEX 
  701. /* 0x00EC */  0x00CF,    // LATIN CAPITAL LETTER I DIAERESIS 
  702. /* 0x00ED */  0x00CC,    // LATIN CAPITAL LETTER I GRAVE 
  703. /* 0x00EE */  0x00D3,    // LATIN CAPITAL LETTER O ACUTE 
  704. /* 0x00EF */  0x00D4,    // LATIN CAPITAL LETTER O CIRCUMFLEX 
  705. /* 0x00F0 */  0xF8FF,    // APPLE LOGO         
  706. /* 0x00F1 */  0x00D2,    // LATIN CAPITAL LETTER O GRAVE 
  707. /* 0x00F2 */  0x00DA,    // LATIN CAPITAL LETTER U ACUTE 
  708. /* 0x00F3 */  0x00DB,    // LATIN CAPITAL LETTER U CIRCUMFLEX 
  709. /* 0x00F4 */  0x00D9,    // LATIN CAPITAL LETTER U GRAVE 
  710. /* 0x00F5 */  0x0131,    // LATIN SMALL LETTER DOTLESS I 
  711. /* 0x00F6 */  0x02C6,    // MODIFIER LETTER CIRCUMFLEX ACCENT 
  712. /* 0x00F7 */  0x02DC,    // SMALL TILDE        
  713. /* 0x00F8 */  0x00AF,    // MACRON             
  714. /* 0x00F9 */  0x02D8,    // BREVE              
  715. /* 0x00FA */  0x02D9,    // DOT ABOVE          
  716. /* 0x00FB */  0x02DA,    // RING ABOVE         
  717. /* 0x00FC */  0x00B8,    // CEDILLA            
  718. /* 0x00FD */  0x02DD,    // DOUBLE ACUTE ACCENT 
  719. /* 0x00FE */  0x02DB,    // OGONEK             
  720. /* 0x00FF */  0x02C7,    // CARON              
  721. };
  722.  
  723. //------------------------------------------------------------------------------
  724. // TradMacTextToUnicode
  725. //
  726. //    Using mapping table, convert characters. Note, we make no attempt to handle
  727. //    double-byte characters!
  728. //
  729. //    uniCodeBufferLength is expressed in BYTES!
  730. //
  731. //    Storage will be allocated for *unicodeText with ODNewPtr.
  732. //------------------------------------------------------------------------------
  733.  
  734. void TradMacTextToUnicode(ODUByte* macText, ODULong macTextLength,
  735.                         ODUShort** unicodeText, ODULong* uniCodeBufferLength);
  736. void TradMacTextToUnicode(ODUByte* macText, ODULong macTextLength,
  737.                         ODUShort** unicodeText, ODULong* uniCodeBufferLength)
  738. {
  739.     ODUShort*    uniCodeTextPtr;
  740.  
  741.     *uniCodeBufferLength = macTextLength * 2;
  742.     *unicodeText = uniCodeTextPtr = (ODUShort*)ODNewPtr(*uniCodeBufferLength);
  743.     
  744.     for (ODULong i = 0; i < macTextLength; i++)
  745.         uniCodeTextPtr[i] = MacToUniTable[macText[i]];
  746. }
  747.  
  748. //------------------------------------------------------------------------------
  749. // UnicodeToTradMacText
  750. //
  751. //    Using mapping table, convert characters. Note, we make no attempt to handle
  752. //    most unicode characters above 0x00FF. Most will be mapped to '*'!
  753. //
  754. //    uniCodeTextLength is expressed in BYTES!
  755. //
  756. //    uniCodeTextLength must be even!
  757. //
  758. //    Storage will be allocated for *macText with ODNewPtr.
  759. //------------------------------------------------------------------------------
  760.  
  761. void UnicodeToTradMacText(ODUShort* unicodeText, ODULong uniCodeTextLength,
  762.                         ODUByte** macText, ODULong* macTextLength);
  763. void UnicodeToTradMacText(ODUShort* unicodeText, ODULong uniCodeTextLength,
  764.                         ODUByte** macText, ODULong* macTextLength)
  765. {
  766.     ODUByte*    macTextPtr;
  767.     ODULong        numUnicodeChars = *macTextLength = uniCodeTextLength / 2;
  768.  
  769.     *macText = macTextPtr = (ODUByte*)ODNewPtr(numUnicodeChars);
  770.     
  771.     for (ODULong i = 0; i < numUnicodeChars; i++)
  772.     {
  773.         // CAN MAP 0x0000 - 0x007F ONE TO ONE.
  774.         if (unicodeText[i] <= 0x007F)
  775.             macTextPtr[i] = unicodeText[i];
  776.         else // LINEAR SEARCH FOR NOW! THIS CODE SHOULD BE REPLACED - NP 1234657
  777.         {
  778.             ODBoolean    foundChar = kODFalse;
  779.  
  780.             for (int tableIndex = 0;
  781.                     tableIndex < sizeof(MacToUniTable);
  782.                     tableIndex++)
  783.             {
  784.                 if (MacToUniTable[tableIndex] == unicodeText[i])
  785.                 {
  786.                     macTextPtr[i] = tableIndex;
  787.                     foundChar = kODTrue;
  788.                     break;
  789.                 }
  790.             }
  791.             if (!foundChar)
  792.                 macTextPtr[i] = '*'; // SUBSITUTE ASTERISK FOR UNKNOWN UNICODE
  793.                                         //    CHARACTER.
  794.         }
  795.     }
  796. }
  797.  
  798. //------------------------------------------------------------------------------
  799. // UnicodeToIText
  800. //
  801. //    IText will be filled in. If iText is kODNULL, it will be created.
  802. //------------------------------------------------------------------------------
  803.  
  804. ODIText* UnicodeToIText(ODIText* iText, ODUShort* unicodeText,
  805.                         ODULong unicodeTextLength);
  806. ODIText* UnicodeToIText(ODIText* iText, ODUShort* unicodeText,
  807.                         ODULong unicodeTextLength)
  808. {
  809.     ODUByte*    text;
  810.     ODULong        textSize;
  811.     
  812.     UnicodeToTradMacText(unicodeText, unicodeTextLength, &text, &textSize);
  813.  
  814.     TRY
  815.         if (iText)
  816.         {
  817.             SetITextScriptCode(iText, smRoman);
  818.             SetITextLangCode(iText, langEnglish);
  819.             SetITextText(iText, text, textSize);
  820.         }
  821.         else
  822.             iText = CreateIText(smRoman, langEnglish, text, textSize);
  823.     CATCH_ALL
  824.         ODDisposePtr(text);
  825.     ENDTRY
  826.  
  827.     ODDisposePtr(text);
  828.  
  829.     return iText;
  830. }
  831.  
  832.  
  833. const ODULong    kODUnicodeEncodingSize = 2;
  834. const ODULong    kODUnicodeTextLengthSize = 4;
  835.  
  836. //------------------------------------------------------------------------------
  837. // ODGetITextProp
  838. //
  839. //    If iText is kODNULL, it is allocated and passed back.
  840. //    If not, the _buffer of the text of the iText is disposed and a new _buffer
  841. //        is allocated and filled.
  842. //    If there is no value at the passed in prop & val then kODNULL is returned.
  843. //    This is consistent with the other routines in StdTypIO which return pointers.
  844. //    The reason is that there may be clients of ODGetITextProp which more easily 
  845. //    handle the flow of control if it just returns kODNULL instead of THROWing. -Tantek
  846. //------------------------------------------------------------------------------
  847.  
  848. ODIText* ODGetITextProp(Environment* ev, 
  849.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  850.                 ODIText* iText)
  851. {
  852.     // CHECK FOR EXISTENCE OF TRADITIONAL MAC TEXT FIRST.
  853.     ODULong        macTextBufferSize = 0;
  854.     ODBoolean    tradMacTextExists = ODSUExistsThenFocus(ev, su, prop, val);
  855.  
  856.     if (tradMacTextExists)
  857.     {
  858.         macTextBufferSize = su->GetSize(ev);
  859.         if (macTextBufferSize == 0)    // if nothing there, treat as if doesn't exist
  860.             tradMacTextExists = false;
  861.         else
  862.             macTextBufferSize -= sizeof(ODITextFormat);
  863.             // otherwise, we need to account for the format info
  864.     }
  865.  
  866. //    if (0) { // FOR TESTING, UNCOMMENT THIS LINE AND UNICODE WILL ALWAYS BE USED.
  867.     if (tradMacTextExists) {
  868.         ODITextFormat format;
  869.         su->SetOffset(ev,0);
  870.         StorageUnitGetValue(su, ev, sizeof(ODITextFormat),(ODValue)&format);
  871.         if( format != kODTraditionalMacText ) {
  872.             WARN("Reading IText prop in unknown format %ld",format);
  873.             THROW(kODErrReadErr);        // Is this the best error code?
  874.         }
  875.  
  876.         octet *macTextBuffer = (octet *)ODNewPtr(macTextBufferSize, kDefaultHeapID);
  877.         TRY{ // HEY! GROPING OF THE ODITEXT GOING ON HERE! - NP
  878.             StorageUnitGetValue(su, ev, macTextBufferSize,macTextBuffer);
  879.             if( !iText ) {
  880.                 iText = new ODIText;
  881.                 iText->format = format;
  882.             } else
  883.                 ODDisposePtr(iText->text._buffer);
  884.         }CATCH_ALL{
  885.             ODDisposePtr(macTextBuffer);
  886.             RERAISE;
  887.         }ENDTRY
  888.         iText->text._buffer = macTextBuffer;
  889.         iText->text._length = macTextBufferSize;
  890.         iText->text._maximum = macTextBufferSize;
  891.         
  892.     }
  893.     // USE UNICODE IF TRADITIONAL MAC TEXT DOESN'T EXIST.
  894.     else
  895.     {
  896.         ODBoolean    unicodeExists = ODSUExistsThenFocus(ev, su, prop,
  897.                                                         kODIntlText);
  898.  
  899.         ODULong    sizeOfValue = 0;
  900.         ODULong    sizeOfValueMinusHeader = 0;
  901.         ODULong    unicodeHeaderSize = kODUnicodeEncodingSize
  902.                                                 + kODUnicodeTextLengthSize;
  903.         if (unicodeExists)
  904.         {
  905.             sizeOfValue = su->GetSize(ev);
  906.             if (sizeOfValue == 0)    // if nothing there, treat as if doesn't exist
  907.                 unicodeExists = kODFalse;
  908.             else
  909.                 // unused for now.
  910.                 sizeOfValueMinusHeader = sizeOfValue - unicodeHeaderSize;
  911.         }
  912.         
  913.         if (unicodeExists)
  914.         {
  915.     WARN("Reading Unicode. Hot doggy! Is this document from another platform?");
  916.  
  917.             ODUShort    unicodeEncoding;
  918.             ODULong        unicodeTextSize;
  919.     
  920.             su->SetOffset(ev,0);
  921.             StorageUnitGetValue(su, ev, kODUnicodeEncodingSize,
  922.                                 (ODValue)&unicodeEncoding);
  923.     
  924.             ASSERTM(kODUnicodeEncodingSize == 2, kODErrAssertionFailed, "Code is broken. Assuming incorrect size passed to \"FlipEnd\" functions");
  925.             ASSERTM(kODUnicodeTextLengthSize == 4, kODErrAssertionFailed, "Code is broken. Assuming incorrect size passed to \"FlipEnd\" functions");
  926.     
  927.             ConvertODUShortFromStd(unicodeEncoding);
  928.  
  929.             if( unicodeEncoding != kODISO10646_1993BaseEncoding )
  930.             {
  931.                 WARN("Reading Unicode value in unknown encoding %d",
  932.                         unicodeEncoding);
  933.                 THROW(kODErrReadErr);        // Is this the best error code?
  934.             }
  935.     
  936.             StorageUnitGetValue(su, ev, kODUnicodeTextLengthSize,
  937.                                 (ODValue)&unicodeTextSize);
  938.     
  939.             ConvertODULongFromStd(unicodeTextSize);
  940.  
  941.             octet*    uniCodeTextBuffer;
  942.             
  943.             TRY
  944.                 uniCodeTextBuffer = (octet *)ODNewPtr(unicodeTextSize);
  945.                 StorageUnitGetValue(su, ev, unicodeTextSize, uniCodeTextBuffer);
  946.         
  947.                 ConvertODUShortArrayFromStd((ODUShort*)uniCodeTextBuffer,
  948.                                             unicodeTextSize / 2);
  949.  
  950.                 iText = UnicodeToIText(iText, (ODUShort*)uniCodeTextBuffer,
  951.                                         unicodeTextSize);
  952.             CATCH_ALL
  953.                 ODDisposePtr(uniCodeTextBuffer);
  954.                 RERAISE;
  955.             ENDTRY
  956.  
  957.             ODDisposePtr(uniCodeTextBuffer);
  958.         }
  959.         else
  960.         {
  961.             // clear the iText passed in if any.
  962.             if( iText )
  963.                 SetITextString(iText,(char*)kODNULL);
  964.  
  965.             // but make sure we return kODNULL to indicate the lack of a property
  966.             iText = kODNULL;
  967.         }
  968.     }
  969.  
  970.     return iText;
  971. }
  972.  
  973. //------------------------------------------------------------------------------
  974. // ITextToUnicode
  975. //
  976. //    Storage passed back must be deallocated with ODDisposePtr.
  977. //
  978. //    The only Unicode converter we use now does not understand anything but
  979. //    MacRoman. So we return an empty string if the script code is not smRoman.
  980. //------------------------------------------------------------------------------
  981.  
  982. void ITextToUnicode(ODIText* iText, ODUShort** unicodeText,
  983.                         ODULong* unicodeTextLength);
  984. void ITextToUnicode(ODIText* iText, ODUShort** unicodeText,
  985.                         ODULong* unicodeTextLength)
  986. {
  987.     if (GetITextScriptCode(iText) == smRoman)
  988.     {
  989.         TradMacTextToUnicode((ODUByte*)GetITextPtr(iText),
  990.                                 GetITextStringLength(iText), unicodeText,
  991.                                 unicodeTextLength);
  992.     }
  993.     else
  994.     {
  995.         *unicodeText = (ODUShort*)ODNewPtr(0);
  996.         *unicodeTextLength = 0;
  997.     }
  998. }
  999.  
  1000. //------------------------------------------------------------------------------
  1001. // ODSetITextProp
  1002. //------------------------------------------------------------------------------
  1003.  
  1004. void     ODSetITextProp(Environment* ev, 
  1005.             ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1006.             ODIText* iText)
  1007. {
  1008.     ODSUForceFocus(ev, su, prop, val);
  1009.         
  1010.     ODULong oldsize = su->GetSize(ev);
  1011.     ODULong newsize = sizeof(ODITextFormat) + iText->text._length;
  1012.     StorageUnitSetValue(su, ev,  sizeof(ODITextFormat),  (ODValue)&iText->format);    
  1013.     su->SetValue(ev, &iText->text);            // text is an ODByteArray after all
  1014.     if (oldsize > newsize)
  1015.         su->DeleteValue(ev, oldsize - newsize);
  1016.     
  1017.     // WRITE OUT kODIntlText NOW TOO.
  1018.     
  1019.     //    NOTE!!! CURRENTLY, OUR UNICODE CONVERTER IS A HOME-GROWN ONE THAT
  1020.     //    DOESN'T HANDLE SCRIPTS OTHER THAN MACROMAN CORRECTLY. WHEN WE GET A REAL
  1021.     //    ONE, WE CAN REMOVE THE FOLLOWING IF...ELSE
  1022.  
  1023.     ODSUForceFocus(ev, su, prop, kODIntlText);
  1024.  
  1025.     if (GetITextScriptCode(iText) == smRoman)
  1026.     {
  1027.         ODUShort*    unicodeText;
  1028.         ODULong        unicodeTextLength;
  1029.         const ODUShort    encoding = kODISO10646_1993BaseEncoding;
  1030.         ITextToUnicode(iText, &unicodeText, &unicodeTextLength);
  1031.         oldsize = su->GetSize(ev);
  1032.         newsize = kODUnicodeEncodingSize + kODUnicodeTextLengthSize
  1033.                     + unicodeTextLength;
  1034.     
  1035.         ASSERTM(kODUnicodeEncodingSize == 2, kODErrAssertionFailed, "Code is broken. Assuming incorrect size passed to \"FlipEnd\" functions");
  1036.         ASSERTM(kODUnicodeTextLengthSize == 4, kODErrAssertionFailed, "Code is broken. Assuming incorrect size passed to \"FlipEnd\" functions");
  1037.     
  1038.         ConvertODUShortToStd(encoding);
  1039.         StorageUnitSetValue(su, ev, kODUnicodeEncodingSize,
  1040.                                     (ODValue)&encoding);
  1041.     
  1042.         ConvertODULongToStd(unicodeTextLength);
  1043.         StorageUnitSetValue(su, ev, kODUnicodeTextLengthSize,
  1044.                                 &unicodeTextLength);
  1045.     
  1046.         ConvertODUShortArrayToStd(unicodeText, unicodeTextLength / 2);
  1047.         StorageUnitSetValue(su, ev, unicodeTextLength,
  1048.                                 unicodeText);
  1049.     
  1050.         ODDisposePtr(unicodeText);
  1051.     }
  1052.     else
  1053.         su->Remove(ev);
  1054. }
  1055.  
  1056. //==============================================================================
  1057. // Time_T
  1058. //==============================================================================
  1059.  
  1060. #if useGMT
  1061.  
  1062. // actually most of these can be replaced by a constant that is platform specific
  1063.  
  1064. static ODTime    diffBtwStdAndLocalTime()
  1065. {
  1066.     MachineLocation theLocation;
  1067.     struct tm date;
  1068.     ODTime baseDate;
  1069.     ODSLong internalGMTDelta;
  1070.  
  1071.     // 1970 Jan 1 in local time
  1072.     date.tm_sec = 0;
  1073.     date.tm_min = 0;
  1074.     date.tm_hour = 0;
  1075.     date.tm_mday = 1;
  1076.     date.tm_mon = 0;
  1077.     date.tm_year = 70;
  1078.     date.tm_isdst = 0;
  1079.     baseDate = (ODTime)mktime(&date);
  1080.     
  1081.     ReadLocation(&theLocation);
  1082.  
  1083.     internalGMTDelta = theLocation.u.gmtDelta & 0x00FFFFFF;
  1084.  
  1085.     if ((internalGMTDelta >> 23) &1)
  1086.         internalGMTDelta |= 0xFF000000;
  1087.         
  1088.     return (baseDate + internalGMTDelta);
  1089. }
  1090. #endif
  1091.  
  1092. ODTime        ODGetTime_TProp(Environment* ev, 
  1093.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  1094. {
  1095.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1096.     {
  1097.         ODTime value;
  1098.         StorageUnitGetValue(su, ev, kODULongLen, (ODValue)&value);
  1099.  
  1100. #if useGMT
  1101.         return (ConvertODULongFromStd(value) + diffBtwStdAndLocalTime());
  1102. #else
  1103.         return ConvertODULongFromStd(value);
  1104. #endif
  1105.     }
  1106.     else {
  1107.         WARN("No Time_T Property.");
  1108.         return 0;
  1109.     }
  1110. }
  1111.  
  1112. void        ODSetTime_TProp(Environment* ev, 
  1113.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1114.                 ODTime value)
  1115. {
  1116.     ODSUForceFocus(ev, su, prop, val);
  1117.     
  1118. #if useGMT
  1119.     value = ConvertODULongToStd(value - diffBtwStdAndLocalTime());
  1120. #else
  1121.     value = ConvertODULongToStd(value);
  1122. #endif
  1123.  
  1124.     StorageUnitSetValue(su, ev, kODULongLen, (ODValue)&value);
  1125. }
  1126.  
  1127.  
  1128. //==============================================================================
  1129. // Point
  1130. //==============================================================================
  1131.  
  1132. //    If there is no value at the passed in prop & val then kODNULL is returned.
  1133. //    This is consistent with the other routines in StdTypIO which return pointers.
  1134. //    The reason is that there may be clients of ODGetPointProp which more easily 
  1135. //    handle the flow of control if it just returns kODNULL instead of THROWing. -Tantek
  1136.  
  1137. ODPoint*    ODGetPointProp(Environment* ev, 
  1138.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1139.                 ODPoint* value)
  1140. {
  1141.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1142.     {
  1143.         if (!value)
  1144.             value = (ODPoint*)ODNewPtrClear(kODPointLen);
  1145.         
  1146.         StorageUnitGetValue(su, ev, sizeof(ODPoint), (ODValue) value);
  1147.         
  1148.         ConvertODSLongArrayFromStd((ODSLong*) value, sizeof(ODPoint)/sizeof(ODSLong));
  1149.         
  1150.         return value;
  1151.     }
  1152.     else {
  1153.         return kODNULL;
  1154.     }
  1155. }
  1156.  
  1157. void        ODSetPointProp(Environment* ev, 
  1158.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1159.                 ODPoint* value)
  1160. {
  1161.     ODSUForceFocus(ev, su, prop, val);
  1162.     
  1163.     ODPoint tmpValue = *value;
  1164.     ConvertODSLongArrayToStd((ODULong*) &tmpValue, sizeof(ODPoint)/sizeof(ODSLong));
  1165.     
  1166.     StorageUnitSetValue(su, ev, sizeof(ODPoint), (ODValue) &tmpValue);
  1167. }
  1168.  
  1169. //==============================================================================
  1170. // Rect
  1171. //==============================================================================
  1172.  
  1173. //    If there is no value at the passed in prop & val then kODNULL is returned.
  1174. //    This is consistent with the other routines in StdTypIO which return pointers.
  1175. //    The reason is that there may be clients of ODGetRectProp which more easily 
  1176. //    handle the flow of control if it just returns kODNULL instead of THROWing. -Tantek
  1177.  
  1178. ODRect*        ODGetRectProp(Environment* ev, 
  1179.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1180.                 ODRect* value)
  1181. {
  1182.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1183.     {
  1184.         if (!value)
  1185.             value = (ODRect*)ODNewPtrClear(kODRectLen);
  1186.         
  1187.         StorageUnitGetValue(su, ev, sizeof(ODRect), (ODValue) value);
  1188.         ConvertODSLongArrayFromStd((ODSLong*) value, sizeof(ODRect)/sizeof(ODCoordinate));
  1189.         
  1190.         return value;
  1191.     }
  1192.     else {
  1193.         return kODNULL;
  1194.     }
  1195. }
  1196.  
  1197. void        ODSetRectProp(Environment* ev, 
  1198.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1199.                 ODRect* value)
  1200. {
  1201.     ODSUForceFocus(ev, su, prop, val);
  1202.     
  1203.     ODRect tmpValue = *value;
  1204.     ConvertODSLongArrayToStd((ODULong*) &tmpValue, sizeof(ODRect)/sizeof(ODCoordinate));
  1205.     
  1206.     StorageUnitSetValue(su, ev, sizeof(ODRect), (ODValue) &tmpValue);
  1207. }
  1208.  
  1209. //==============================================================================
  1210. // StorageUnit Reference
  1211. //==============================================================================
  1212.  
  1213. ODID        ODGetStrongSURefProp(Environment* ev, 
  1214.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  1215. {
  1216.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1217.     {
  1218.         ODStorageUnitRef value;
  1219.         StorageUnitGetValue(su, ev, kODStorageUnitRefLen, (ODValue)&value);
  1220.         if ( su->IsValidStorageUnitRef(ev, value) )
  1221.             return su->GetIDFromStorageUnitRef(ev,value);
  1222.         else
  1223.             return kODNULLID;
  1224.     }
  1225.     else {
  1226.         //WARN("No StrongSURef Property.");// This is EXPECTED in many uses of ODGetStrongSURefProp, so this makes sense.
  1227.         return kODNULLID;
  1228.     }
  1229. }
  1230.  
  1231. void        ODSetStrongSURefProp(Environment* ev, 
  1232.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1233.                 ODID id)
  1234. {
  1235.     ODSUForceFocus(ev, su, prop, val);
  1236.     ODStorageUnitRef value;
  1237.     su->GetStrongStorageUnitRef(ev, id, value);
  1238.     StorageUnitSetValue(su, ev, kODStorageUnitRefLen, value);
  1239. }
  1240.  
  1241.  
  1242. ODID        ODGetWeakSURefProp(Environment* ev, 
  1243.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val)
  1244. {
  1245.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1246.     {
  1247.         ODStorageUnitRef value;
  1248.         StorageUnitGetValue(su, ev, kODStorageUnitRefLen, (ODValue)&value);
  1249.         ODID id = kODNULLID;
  1250.         if (su->IsValidStorageUnitRef(ev, value))
  1251.             id = su->GetIDFromStorageUnitRef(ev,value);
  1252.             
  1253.         return id;
  1254.     }
  1255.     else {
  1256.         //WARN("No WeakSURef Property."); // This is EXPECTED in many uses of ODGetWeakSURefProp, so this makes sense.
  1257.         return kODNULLID;
  1258.     }
  1259. }
  1260.  
  1261. void        ODSetWeakSURefProp(Environment* ev, 
  1262.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1263.                 ODID id)
  1264. {
  1265.     ODSUForceFocus(ev, su, prop, val);
  1266.     ODStorageUnitRef value;
  1267.     su->GetWeakStorageUnitRef(ev, id, value);
  1268.     StorageUnitSetValue(su, ev, kODStorageUnitRefLen, value);
  1269. }
  1270.  
  1271. //==============================================================================
  1272. // Polygon
  1273. //==============================================================================
  1274.  
  1275. //    If there is no value at the passed in prop & val then kODNULL is returned.
  1276. //    This is consistent with the other routines in StdTypIO which return pointers.
  1277. //    The reason is that there may be clients of ODGetPolygonProp which more easily 
  1278. //    handle the flow of control if it just returns kODNULL instead of THROWing. -Tantek
  1279.  
  1280. ODPolygon*    ODGetPolygonProp(Environment* ev, 
  1281.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1282.                 ODPolygon* value)
  1283. {
  1284.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1285.     {
  1286.         ODULong    valueSize = su->GetSize(ev);
  1287.         if (value == kODNULL)
  1288.         {
  1289.             value = new ODPolygon;
  1290.         }
  1291.         // value->Realloc(valueSize); // can't because Realloc is private. Doh!
  1292.         // instead we do the following
  1293.         if (valueSize > 0)
  1294.         {
  1295.             ODPolygonData* data = (ODPolygonData*)ODNewPtr(valueSize);
  1296.             StorageUnitGetValue(su, ev, valueSize, (ODValue)data);
  1297.             ConvertODSLongArrayFromStd(data, valueSize/sizeof(ODSLong));
  1298.             value->SetData(data);
  1299.         }
  1300.         return value;
  1301.     }
  1302.     else
  1303.     {
  1304.         return kODNULL;
  1305.     }
  1306. }
  1307.  
  1308.  
  1309. void        ODSetPolygonProp(Environment* ev, 
  1310.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1311.                 const ODPolygon* value)
  1312. {
  1313.     ODSUForceFocus(ev, su, prop, val);
  1314.     ODULong oldsize = su->GetSize(ev);
  1315.     ODULong newsize = value->GetDataSize();
  1316.     ODPtr buf = ODNewPtr(newsize);
  1317.     ODBlockMove(value->GetData(), buf, newsize);
  1318.     ConvertODSLongArrayToStd(buf, newsize/sizeof(ODSLong));
  1319.     StorageUnitSetValue(su, ev, newsize, (ODValue) buf);
  1320.     if (oldsize > newsize)
  1321.         su->DeleteValue(ev, oldsize - newsize);
  1322.     ODDisposePtr(buf);
  1323. }
  1324.  
  1325. //==============================================================================
  1326. // Matrix
  1327. //==============================================================================
  1328.  
  1329. //    If there is no value at the passed in prop & val then kODNULL is returned.
  1330. //    This is consistent with the other routines in StdTypIO which return pointers.
  1331. //    The reason is that there may be clients of ODGetMatrixProp which more easily 
  1332. //    handle the flow of control if it just returns kODNULL instead of THROWing. -Tantek
  1333.  
  1334. ODMatrix*    ODGetMatrixProp(Environment* ev, 
  1335.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1336.                 ODMatrix* value)
  1337. {
  1338.     if (ODSUExistsThenFocus(ev, su, prop, val))
  1339.     {
  1340.         if (!value)
  1341.             value = (ODMatrix*)ODNewPtrClear(sizeof(ODMatrix));
  1342.  
  1343.         StorageUnitGetValue(su, ev, sizeof(ODMatrix), (ODValue)value);
  1344.         ConvertODSLongArrayFromStd((ODSLong*) value, sizeof(ODMatrix)/sizeof(ODFixed));
  1345.         
  1346.         return value;
  1347.     }
  1348.     else
  1349.     {
  1350.         return kODNULL;
  1351.     }
  1352. }
  1353.  
  1354. void    ODSetMatrixProp(Environment* ev, 
  1355.                 ODStorageUnit* su, ODPropertyName prop, ODValueType val,
  1356.                 ODMatrix* value)
  1357. {
  1358.     ODSUForceFocus(ev, su, prop, val);
  1359.     
  1360.     ODMatrix tmpValue = *value;
  1361.     ConvertODSLongArrayToStd((ODULong*) &tmpValue, sizeof(ODMatrix)/sizeof(ODFixed));
  1362.     
  1363.     StorageUnitSetValue(su, ev, sizeof(ODMatrix), (ODValue) &tmpValue);
  1364. }
  1365.  
  1366. //==============================================================================
  1367. // IconFamily -- see StdIFmIO.cpp
  1368. //==============================================================================
  1369.  
  1370.