00001 /** 00002 * \file bidi.h <mi32/bidi.h> 00003 * \brief BiDirectional text conversion 00004 * 00005 * \if NODOC 00006 * $Id: bidi.h_v 1.15 2006/02/16 16:11:10 dwilliss Exp $ 00007 * 00008 * $Log: bidi.h_v $ 00009 * Revision 1.15 2006/02/16 16:11:10 dwilliss 00010 * renamed obsolete #define 00011 * 00012 * Revision 1.14 2005/03/31 16:57:09 fileserver!dwilliss 00013 * Rename one of our types to MIUNICODE because it conflicted with a Microsoft #define 00014 * 00015 * Revision 1.13 2003/09/15 13:49:56 fileserver!dwilliss 00016 * Doxygen 00017 * 00018 * Revision 1.12 2003/07/09 14:36:20 mju 00019 * Fix endif. 00020 * Use conventional name for classlibexport. 00021 * 00022 * Revision 1.11 2003/07/09 14:34:26 dwilliss 00023 * Define and undefine MUSYSTEMCLASSEXPORT ourselves. Don't expect ucstring 00024 * to do it for us, cause it shouldn't have been leaving it defined in the 00025 * first place 00026 * 00027 * Revision 1.10 2002/07/05 14:34:20 dwilliss 00028 * Undefine USEEXPORTPRAGMA before end of include file 00029 * 00030 * Revision 1.9 2000/12/07 22:51:00 dwilliss 00031 * Added method to get cursor position relative to visual string 00032 * 00033 * Revision 1.8 2000/12/01 22:21:24 dwilliss 00034 * Added method to set cursor position in visual units. 00035 * 00036 * Revision 1.7 2000/10/13 16:43:52 dwilliss 00037 * Must use "friend class NAME", not "friend NAME" 00038 * 00039 * Revision 1.6 2000/06/07 20:00:22 dwilliss 00040 * Renamed a #define for Mike 00041 * 00042 * Revision 1.5 2000/05/22 16:55:33 dwilliss 00043 * Cleaned up. Split out BIDI cursor into a derived class so we don't 00044 * have to keep track of cursor info in "normal" cases 00045 * 00046 * \endif 00047 */ 00048 00049 #ifndef INC_MI32_BIDI_H 00050 #define INC_MI32_BIDI_H 00051 00052 #ifndef INC_MI32_UCSTRING_H 00053 #include <mi32/ucstring.h> 00054 #endif 00055 00056 #ifdef MISYSTEMDLL 00057 #define CLASSLIBEXPORT MI_DLLCLASSEXPORT 00058 #else 00059 #define CLASSLIBEXPORT MI_DLLCLASSIMPORT 00060 #endif 00061 00062 class BIDICURSOR; 00063 00064 //! 00065 //! This class handles the Bi-Directional ("BiDi") issues of rendering 00066 //! strings which have a mixture of Left-To-Right and Right-To-Left 00067 //! text (such as Hebrew and Arabic) 00068 //! 00069 //! Besides flipping the string as necessary, it can also keep track 00070 //! or a cursor position within the string and resolve the logical 00071 //! position of the cursor withing the string while moving in visual 00072 //! order. 00073 //! 00074 class CLASSLIBEXPORT BIDISTRING { 00075 public: 00076 // Enums 00077 00078 enum DIRECTION { 00079 DIRECTION_LTR, 00080 DIRECTION_RTL 00081 }; 00082 00083 enum ORDER { 00084 ORDER_VISUAL, 00085 ORDER_LOGICAL 00086 }; 00087 00088 // Constructors 00089 00090 BIDISTRING(); 00091 00092 //! Construct with initial values 00093 BIDISTRING ( 00094 const MIUNICODE* source, 00095 DIRECTION DefaultDirection = DIRECTION_LTR, 00096 ORDER StringOrder = ORDER_LOGICAL 00097 ); 00098 00099 // Destructor 00100 00101 virtual ~BIDISTRING(); 00102 00103 // Methods 00104 00105 //! Clear the string. 00106 void Clear ( 00107 ); 00108 00109 //! Get the primary direction of the string. 00110 DIRECTION GetStringDirection ( 00111 ) const; 00112 00113 //! Return a copy of the string in logical order. 00114 //! Caller should free the returned string. 00115 MIUNICODE* GetStringLogical ( 00116 ) const; 00117 00118 //! Return a copy of the string in visual order. 00119 //! Caller should free the returned string. 00120 MIUNICODE* GetStringVisual ( 00121 ) const; 00122 00123 //! Set the string from a logical order string. 00124 //! 00125 //! Note: Normally, the directionality of a string is determined by the first 00126 //! strongly directional character in the string. In this case, the DefaultDirection 00127 //! is only used as a fallback, unless bForceDirection is true. 00128 //! 00129 void SetStringLogical ( 00130 const MIUNICODE* source, 00131 DIRECTION DefaultDirection = DIRECTION_LTR, 00132 bool bForceDirection = false 00133 ); 00134 00135 //! Set the string from a visual order string. 00136 //! Nore: The DefaultDirection is VERY important with a visual order string. 00137 //! This is because it is impossible to tell by looking at a visual order 00138 //! string if it was supposed to be right-to-left or left-to-right. Take 00139 //! the following examples: (assume lowercase letters are left-to-right and 00140 //! capital letters are right to left) 00141 //! 00142 //! <table> 00143 //! <tr><td></td><td>logical</td><td>visual</td></tr> 00144 //! <tr><td>1</td><td>ABC abc DEF</td><td>FED abc CBA</td></tr> 00145 //! <tr><td>2</td><td>ABC abc DEF def</td><td>def FED abc CBA</td></tr> 00146 //! <tr><td>3</td><td>abc ABC def</td><td>abc CBA def</td></tr> 00147 //! <tr><td>4</td><td>abc ABC def DEF def</td><td>abc CBA def FED</td></tr> 00148 //! </table> 00149 //! 00150 //! Strings 1 and 2 are right-to-left, 3 and 4 are left to right (based 00151 //! on the first character in the logical order string). Without prior 00152 //! knowledge of the source strings, you can't tell what direction they 00153 //! were by looking at the visual order strings. 00154 //! 00155 void SetStringVisual ( 00156 const MIUNICODE* source, 00157 DIRECTION DefaultDirection = DIRECTION_LTR 00158 ); 00159 00160 private: 00161 #ifndef GENERATING_DOXYGEN_OUTPUT 00162 class SPAN { 00163 public: 00164 00165 SPAN ( 00166 BIDISTRING* str, 00167 const MIUNICODE* src, 00168 UINT32 start, 00169 UINT32 end, 00170 DIRECTION direction, 00171 ORDER format 00172 ); 00173 00174 ~SPAN(); 00175 00176 // Members 00177 SPAN *m_VisualPrev; //!< Pointer to the previous visual run. 00178 SPAN *m_VisualNext; //!< Pointer to the next visual run. 00179 00180 SPAN *m_LogicalPrev; //!< Pointer to the previous logical run. 00181 SPAN *m_LogicalNext; //!< Pointer to the next logical run. 00182 00183 DIRECTION m_direction; //!< Direction of the run. 00184 00185 INT32 m_cursor; //!< Position of "cursor" in the string. (-1 means just before first char) 00186 00187 00188 MIUNICODE *m_chars; //!< List of characters for the run. 00189 UINT32 *m_positions; //!< List of original positions in source. 00190 00191 UINT32 m_start; //!< Beginning offset in the source string. 00192 UINT32 m_end; //!< Ending offset in the source string. 00193 }; 00194 00195 void AddLTRLogicalSegment ( 00196 const MIUNICODE* source, 00197 UINT32 start, 00198 UINT32 end 00199 ); 00200 00201 void AddRTLLogicalSegment ( 00202 const MIUNICODE* source, 00203 UINT32 start, 00204 UINT32 end 00205 ); 00206 00207 void AddLTRVisualSegment ( 00208 const MIUNICODE* source, 00209 UINT32 start, 00210 UINT32 end 00211 ); 00212 00213 void AddRTLVisualSegment ( 00214 const MIUNICODE* source, 00215 UINT32 start, 00216 UINT32 end 00217 ); 00218 00219 //! Set the string 00220 //! SetStringLogical() first calls Clear() then calls SetStringLogicalNoClear() 00221 //! The constructor doesn't bother to call Clear() 00222 void SetStringLogicalNoClear ( 00223 const MIUNICODE* source, 00224 DIRECTION DefaultDirection = DIRECTION_LTR, 00225 bool bForceDirection = false 00226 ); 00227 00228 //! Set the string 00229 //! SetStringVisual() first calls Clear() then calls SetStringVisualNoClear() 00230 void SetStringVisualNoClear ( 00231 const MIUNICODE* source, 00232 DIRECTION DefaultDirection = DIRECTION_LTR 00233 ); 00234 00235 00236 // Members 00237 DIRECTION m_direction; //!< Overall direction of the string. 00238 00239 00240 SPAN *m_cursor; //!< The run containing the "cursor." 00241 00242 SPAN *m_LogicalFirst; //!< First run in the logical order. 00243 SPAN *m_LogicalLast; //!< Last run in the logical order. 00244 00245 SPAN *m_VisualFirst; //!< First run in the visual order. 00246 SPAN *m_VisualLast; //!< Last run in the visual order. 00247 00248 MIUNICODE *m_source; //!< The logical order string. 00249 UINT32 m_start; //!< The beginning offset in the source. (always 0) 00250 UINT32 m_end; //!< The ending offset in the source. 00251 bool m_bNeedCursorInfo; 00252 00253 friend class BIDISTRING::SPAN; 00254 friend class BIDICURSOR; 00255 #endif // GENERATING_DOXYGEN_OUTPUT 00256 }; 00257 00258 00259 //! 00260 //! An extention of BIDISTRING to handle cursor support. 00261 //! 00262 //! This takes a lot more memory than BIDISTRING itself. 00263 //! 00264 class CLASSLIBEXPORT BIDICURSOR : public BIDISTRING { 00265 public: 00266 // Constructors 00267 BIDICURSOR (); 00268 00269 00270 //! Construct with initial values. 00271 //! Note, this one doesn't let you specify the string order. 00272 //! The string passed to the constructor must be in logical order. 00273 BIDICURSOR ( 00274 const MIUNICODE* source, 00275 DIRECTION DefaultDirection = DIRECTION_LTR 00276 ); 00277 00278 // Destructor 00279 virtual ~BIDICURSOR(); 00280 00281 // Methods 00282 00283 //! Move the cursor to the left. 00284 //! 00285 //! This method moves the cursor to the left in either the logical or 00286 //! visual order depending on the current setting of CursorMotion. 00287 //! It moves the cursor "count" spaces to the left and returns the 00288 //! new offset from the beginning of the logical string. 00289 UINT32 CursorLeft ( 00290 UINT32 count 00291 ); 00292 00293 //! Move the cursor to the right. 00294 //! 00295 //! This method moves the cursor to the right in either the logical or 00296 //! visual order depending on the current setting of CursorMotion. 00297 //! It moves the cursor "count" spaces to the right and returns the 00298 //! new offset from the beginning of the logical string. 00299 UINT32 CursorRight ( 00300 UINT32 count 00301 ); 00302 00303 //! Return the direction of the text under the cursor. 00304 //! Returns the direction that the text under the cursor should 00305 //! be read. 00306 DIRECTION GetCursorDirection ( 00307 ) const; 00308 00309 //! Returns the current CursorMotion setting. 00310 //! Logical cursor motion means that moving to the right will step 00311 //! through the data in the order it is in memory, which may or may 00312 //! not be the same as on the screen. Visual motion is what you 00313 //! expect on the screen. 00314 ORDER GetCursorMotion ( 00315 ) const; 00316 00317 00318 //! Get the current cursor position relative to the start of the string in 00319 //! it's logical order. The cursor should be thought of as a box covering 00320 //! the character position returned. 00321 UINT32 GetCursorPosition ( 00322 ) const; 00323 00324 //! Get the current cursor position relative to the start of the string in 00325 //! it's visual order. The cursor should be thought of as a box covering 00326 //! the character position returned. 00327 UINT32 GetCursorPositionVisual ( 00328 ) const; 00329 00330 //! Set the cursor motion. 00331 //! Returns the previous value 00332 ORDER SetCursorMotion ( 00333 ORDER CursorMotion 00334 ); 00335 00336 //! Set the cursor position (visual order, left-most glyph == 0) 00337 void SetCursorPositionVisual ( 00338 UINT32 pos 00339 ); 00340 00341 private: 00342 #ifndef GENERATING_DOXYGEN_OUTPUT 00343 UINT32 CursorLeftLogical ( 00344 UINT32 count 00345 ); 00346 00347 UINT32 CursorRightLogical ( 00348 UINT32 count 00349 ); 00350 00351 UINT32 CursorLeftVisual ( 00352 UINT32 count 00353 ); 00354 00355 UINT32 CursorRightVisual ( 00356 UINT32 count 00357 ); 00358 00359 ORDER m_CursorMotion; //!< Logical or visual cursor motion flag. 00360 #endif // GENERATING_DOXYGEN_OUTPUT 00361 }; 00362 00363 00364 00365 #undef CLASSLIBEXPORT 00366 00367 00368 #endif //!< INC_MI32_BIDI_H 00369
1.5.2