1{\rtf1\mac\deff1 2{\fonttbl 3{\f6\fnil Bookman;} 4{\f5\fnil Palatino;} 5{\f4\fnil Symbol;} 6{\f3\fnil Courier;} 7{\f2\fnil Helvetica;} 8{\f1\fnil Times;} 9} 10\paperh15840 \paperw12240 11\margl1440 \margr2160 \pard \f1\i0\b0 12\fs20 \fs16 \fs20 \fs24 \f1\i0\b0 13\b \fs28 \pard \qc \sl280 14\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 15A Tool for RTF Processing 16\par 17{\sl-140\sa0\sb0\par} 18Release 1.10 19\par 20\f1\i0\b0 21\i {\sl-280\sa0\sb0\par} 22\fs20 Paul DuBois 23\par 24dubois@primate.wisc.edu 25\par 26\f1\i0\b0 27{\sl-140\sa0\sb0\par} 28Wisconsin Regional Primate Research Center 29\par 30Revision date: 5 April 1994 31\par 32{\sl-280\sa0\sb0\par} 33\fs28 \f1\i0\b0 34\b \pard \qj \sl320 35\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 36Introduction\f1\i0\b0 37 38\par 39{\sl-320\sa0\sb0\par} 40\fs20 {\sl-120\sa0\sb0\par} 41\pard \qj \sl240 42\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 43This document describes a general purpose tool for 44processing RTF files\'d1an RTF reader which may be 45configured in a well-defined manner to allow it to 46be used with a variety of writers generating different 47output formats. This provides a method for generating 48RTF-to-\f1\i0\b0 49 50\i XXX\f1\i0\b0 51 translators. 52\par 53{\sl-120\sa0\sb0\par} 54I assume that you have some familiarity with RTF syntax 55and semantics, and that you\'d5re willing to study 56the source code of the RTF distribution described here. 57If you don\'d5t have the RTF specification, you can 58get it from the FTP site listed under \'d2Distribution 59Availability\'d3 at the end of this document. References 60to \'d2the specification\'d3 refer to the RTF specification 61document. 62\par 63{\sl-120\sa0\sb0\par} 64If you use this tool and find that you have an RTF 65file that won\'d5t pass through the sample translator 66\f1\i0\b0 67\i rtf2null\f1\i0\b0 68, or for which \f1\i0\b0 69 70\i rtf2null\f1\i0\b0 71 announces unknown symbols, please contact 72me so the tool can be improved. It is best if you can 73supply the RTF file for which this behavior is observed. 74\par 75{\sl-240\sa0\sb0\par} 76\fs28 \f1\i0\b0 77\b \pard \qj \sl320 78\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 79Theory of Operation\f1\i0\b0 80 81\par 82{\sl-320\sa0\sb0\par} 83{\sl-320\sa0\sb0\par} 84\fs20 \fs24 \f1\i0\b0 85\b \pard \qj \sl280 86\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 87Translator Architecture\f1\i0\b0 88 89\par 90{\sl-280\sa0\sb0\par} 91\fs20 {\sl-120\sa0\sb0\par} 92\pard \qj \sl240 93\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 94This is a brief description of how translators are 95designed. For more details, see the document \f1\i0\b0 96 97\i RTF Tools Translator Architecture\f1\i0\b0 98. 99\par 100{\sl-120\sa0\sb0\par} 101There are three components to an RTF translator: reader 102code, writer code, and driver code. These break down 103as follows. 104\par 105{\sl-120\sa0\sb0\par} 106\pard \qj \li500 \fi-500 \sl240 107\tx1000 \tx500 \tqr 108reader\tab 109\par 110\pard \qj \li500 \sl240 111\tx1000 \tx500 \tqr 112Responsible for peeling tokens out of the input stream, 113classifying them, and causing the writer to process 114them. 115\par 116{\sl-120\sa0\sb0\par} 117\pard \qj \li500 \fi-500 \sl240 118\tx1000 \tx500 \tqr 119writer\tab 120\par 121\pard \qj \li500 \sl240 122\tx1000 \tx500 \tqr 123Responsible for translating tokens from the input stream 124into the required output format. 125\par 126{\sl-120\sa0\sb0\par} 127\pard \qj \li500 \fi-500 \sl240 128\tx1000 \tx500 \tqr 129driver\tab 130\par 131\pard \qj \li500 \sl240 132\tx1000 \tx500 \tqr 133Responsible for making sure the reader and writer are 134initialized, and for calling the reader, to cause translation 135to occur. 136\par 137{\sl-120\sa0\sb0\par} 138\pard \qj \sl240 139\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 140This architecture allows the reader to remain constant, 141so that different translators can be built by supplying 142different writer and driver code. Also, for a given 143translator, the reader and writer remain constant and 144the translator can be ported to different types of 145systems by supplying system-specific driver code. 146\par 147{\sl-120\sa0\sb0\par} 148In practice, to build a new translator, you supply 149a \f1\i0\b0 150 151\i main()\f1\i0\b0 152 function and the writer code, and link in the 153RTF reader. \f1\i0\b0 154 155\i main()\f1\i0\b0 156 includes the driver code and is responsible 157to see that the following are done: 158\par 159{\sl-120\sa0\sb0\par} 160\pard \qj \li300 \fi-300 \sl240 161\tx600 \tx300 \tqr 162\'a5\tab Determine which files are to be translated 163\par 164{\sl-120\sa0\sb0\par} 165\'a5\tab Configure the reader, which may involve: 166\par 167{\sl-120\sa0\sb0\par} 168\pard \qj \li600 \fi-300 \sl240 169\tx900 \tx300 \tqr 170\'d1\tab Reset the input stream if necessary 171\par 172{\sl-120\sa0\sb0\par} 173\pard \qj \li600 \fi-300 \sl240 174\tx900 \tx300 \tqr 175\'d1\tab Configure other reader behavior, such as whether 176or not to process the font and color tables internally 177\par 178{\sl-120\sa0\sb0\par} 179\'d1\tab Install writer callbacks into the reader so 180it knows what functions to call when various kinds 181of tokens occur 182\par 183{\sl-120\sa0\sb0\par} 184{\sl-120\sa0\sb0\par} 185\pard \qj \li300 \fi-300 \sl240 186\tx600 \tx300 \tqr 187\'a5\tab Initialize the writer 188\par 189{\sl-120\sa0\sb0\par} 190\pard \qj \li300 \fi-300 \sl240 191\tx600 \tx300 \tqr 192\'a5\tab Call the reader to process the input stream 193\par 194{\sl-120\sa0\sb0\par} 195\'a5\tab Terminate the writer 196\par 197{\sl-120\sa0\sb0\par} 198\pard \qj \sl240 199\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 200A minimal translator (for a UNIX system) looks something 201like this: 202\par 203{\sl-120\sa0\sb0\par} 204\fs16 \f3\i0\b0 205\pard \ql \li400 \sl200 206\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 207# include\tab <stdio.h> 208\par 209# include\tab "rtf.h" 210\par 211{\sl-200\sa0\sb0\par} 212int 213\par 214main () 215\par 216\{ 217\par 218\tab RTFSetOpenLibFileProc (UnixOpenLibFile); 219\par 220\tab RTFInit (); 221\par 222\tab RTFRead (); 223\par 224\tab exit (0); 225\par 226\} 227\par 228{\sl-120\sa0\sb0\par} 229\fs20 \f1\i0\b0 230\pard \qj \sl240 231\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 232This installs a function that\'d5s suitable for opening 233RTF library files on a UNIX system, initializes the 234reader, and calls it to read \f1\i0\b0 235 236\i stdin\f1\i0\b0 237 (the default input stream). The writer portion 238is null (i.e., there is no writer), so all that happens 239is that the reader tokenizes the input and discards 240it. That isn\'d5t very interesting; most of the sample 241translators are examples of more elaborate translators. 242\par 243{\sl-240\sa0\sb0\par} 244\fs24 \f1\i0\b0 245\b \pard \qj \sl280 246\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 247Reader Operation\f1\i0\b0 248 249\par 250{\sl-280\sa0\sb0\par} 251\fs20 {\sl-120\sa0\sb0\par} 252\pard \qj \sl240 253\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 254Each time a token is read, several global variables 255are set: 256\par 257{\sl-120\sa0\sb0\par} 258{\sl-120\sa0\sb0\par} 259\f1\i0\b0 260\i \pard \ql \li720 \sl240 261\tx2880 262rtfClass\f1\i0\b0 263\tab token class 264\par 265\f1\i0\b0 266\i rtfMajor\f1\i0\b0 267\tab token major number 268\par 269\f1\i0\b0 270\i rtfMinor\f1\i0\b0 271\tab token minor number 272\par 273\f1\i0\b0 274\i rtfParam\f1\i0\b0 275\tab token parameter value 276\par 277\f1\i0\b0 278\i rtfTextBuf\f1\i0\b0 279\tab token text 280\par 281\f1\i0\b0 282\i rtfTextLen\f1\i0\b0 283\tab length of token (including parameter 284text) 285\par 286{\sl-120\sa0\sb0\par} 287{\sl-120\sa0\sb0\par} 288\pard \qj \sl240 289\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 290Tokens are classified using up to three numbers: token 291class, and major and minor numbers. The major and minor 292numbers may be meaningless depending on the kind of 293token. 294\par 295{\sl-120\sa0\sb0\par} 296The class number can be: 297\par 298{\sl-120\sa0\sb0\par} 299{\sl-120\sa0\sb0\par} 300\f1\i0\b0 301\i \pard \ql \li720 \sl240 302\tx2880 303rtfUnknown\f1\i0\b0 304\tab unrecognized token 305\par 306\f1\i0\b0 307\i rtfGroup\f1\i0\b0 308\tab \'d2\{\'d3 or \'d2\}\'d3 309\par 310\f1\i0\b0 311\i rtfText\f1\i0\b0 312\tab plain text character 313\par 314\f1\i0\b0 315\i rtfControl\f1\i0\b0 316\tab token beginning with \'d2\\\'d3 317\par 318\f1\i0\b0 319\i rtfEOF\f1\i0\b0 320\tab fake class number; indicates end of input 321stream 322\par 323{\sl-120\sa0\sb0\par} 324{\sl-120\sa0\sb0\par} 325\pard \qj \sl240 326\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 327There are some exceptions. A few tokens beginning with 328\f3\i0\b0 329\\\f1\i0\b0 330 actually belong to other classes, a tab character 331is treated like \f3\i0\b0 332\\tab\f1\i0\b0 333, and unrecognized tokens are 334put in class \f1\i0\b0 335 336\i rtfUnknown\f1\i0\b0 337 no matter what they look like. 338\par 339{\sl-120\sa0\sb0\par} 340Within a class, tokens are assigned a major number, 341and perhaps a minor number. For the \f1\i0\b0 342 343\i rtfText\f1\i0\b0 344 class, the major number is the value of the 345input character (0..255), and the minor number is assigned 346a standard character code. Text characters have different 347mappings in different RTF character sets, so to avoid 348the problems associated with this, the reader maps 349the character onto a standard character code using 350a charset-dependent translation table. Translators 351should generally use the standard character code in 352\f1\i0\b0 353\i rtfMinor\f1\i0\b0 354 rather than the raw character code in \f1\i0\b0 355 356\i rtfMajor\f1\i0\b0 357. Character mapping issues are described further 358in the document \f1\i0\b0 359 360\i RTF Tools Character Mapping\f1\i0\b0 361. 362\par 363{\sl-120\sa0\sb0\par} 364A \'d2plain text\'d3 character can be a literal character, 365a character specified in hex notation (\f3\i0\b0 366\\'\f1\i0\b0 367\f1\i0\b0 368 369\i xx\f1\i0\b0 370) or one of the special escaped characters (\f3\i0\b0 371\\\{\f1\i0\b0 372, 373\f3\i0\b0 374\\\}\f1\i0\b0 375, \f3\i0\b0 376\\\\\f1\i0\b0 377). The sequence \f3\i0\b0 378\\:\f1\i0\b0 379 is treated as a plain 380text colon. This is arguably wrong; the rationale is 381given later under the description of the \f1\i0\b0 382 383\i RTFGetToken()\f1\i0\b0 384 function. 385\par 386{\sl-120\sa0\sb0\par} 387For the \f1\i0\b0 388 389\i rtfControl\f1\i0\b0 390 class, most tokens have both a major and 391minor number. For instance, all paragraph attribute 392control symbols have major number \f1\i0\b0 393 394\i rtfParAttr\f1\i0\b0 395 and a minor number indicating a paragraph 396formatting property, such as \f1\i0\b0 397 398\i rtfLeftIndent\f1\i0\b0 399 or \f1\i0\b0 400 401\i rtfSpaceBefore\f1\i0\b0 402. A few oddball control tokens have no 403minor number. 404\par 405{\sl-120\sa0\sb0\par} 406Control symbols may have a parameter value, e.g., \f3\i0\b0 407\\margr720\f1\i0\b0 408 409specifies a right margin (in units of 720 twentieths 410of a point). 411\par 412{\sl-120\sa0\sb0\par} 413If no parameter value is given, \f1\i0\b0 414 415\i rtfParam\f1\i0\b0 416 is \f1\i0\b0 417 418\i rtfNoParam\f1\i0\b0 419. 420\par 421{\sl-120\sa0\sb0\par} 422Ideally, there should never be any tokens in the \f1\i0\b0 423 424\i rtfUnknown\f1\i0\b0 425 class, but as the RTF standard continues 426to develop, unknown tokens are inevitable. 427\par 428{\sl-120\sa0\sb0\par} 429To write a translator, you\'d5ll need to familiarize 430yourself with the token classification scheme by reading 431\f1\i0\b0 432\i rtf.h\f1\i0\b0 433. A skeleton translator \f1\i0\b0 434 435\i rtfskel\f1\i0\b0 436 is included with the distribution and may be 437used as a basis for new translators. 438\par 439{\sl-120\sa0\sb0\par} 440As of release 1.10, the reader allows an 8-bit character 441set since the current RTF specification (version 1.2) 442now allows 8-bit characters. Formerly, if the reader 443saw an 8-bit character, it converted the character 444to the equivalent \f3\i0\b0 445\\'\f1\i0\b0 446\f1\i0\b0 447 448\i xx\f1\i0\b0 449 hex notation sequence and returned that as the token. 450\par 451{\sl-120\sa0\sb0\par} 452Generally, a translator will configure the RTF reader 453to call particular writer functions when certain kinds 454of tokens are encountered in the input stream. These 455functions are known as \f1\i0\b0 456 457\i class callbacks\f1\i0\b0 458. Writer callbacks can be registered 459with the reader using \f1\i0\b0 460 461\i RTFSetClassCallback()\f1\i0\b0 462 for each token class. 463\par 464{\sl-120\sa0\sb0\par} 465The reader reads each token, classifies it, and sends 466it to a token routing function \f1\i0\b0 467 468\i RTFRouteToken()\f1\i0\b0 469, which tries to find a writer callback 470function to process the token. Tokens in a given class 471are ignored if no callback is registered for the class. 472\par 473{\sl-120\sa0\sb0\par} 474Class callbacks make it quite easy to receive notification 475when certain types of tokens occur in the input. For 476instance, a crude RTF text extractor could be written 477by installing a callback function for the \f1\i0\b0 478 479\i rtfText\f1\i0\b0 480 class.[1] 481\fs16 \par 482{\sl-60\sa0\sb0\par} 483\pard \qj \ri720 \fi200 \sl200 [1] Reasons this is a crude translator are that: (i) 484some text characters occur in contexts where the characters 485are not intended to be output, e.g., font tables, stylesheets; 486(ii) some control symbols like \f3\i0\b0 487\\tab\f1\i0\b0 488 represent output 489text characters; (iii) it writes output based on the 490raw input character value in \f1\i0\b0 491 492\i rtfMajor\f1\i0\b0 493 rather than mapping the standard character 494code in \f1\i0\b0 495 496\i rtfMinor\f1\i0\b0 497. The sample translator \f1\i0\b0 498 499\i rtf2text\f1\i0\b0 500 addresses these problems in a (slightly) more 501sophisticated manner. 502\par 503\fs20 \pard \qj \sl240 504\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 505Whenever the function is invoked, \f1\i0\b0 506 507\i rtfMajor\f1\i0\b0 508 will contain a value in the range 0..255 representing 509the character value. 510\par 511{\sl-120\sa0\sb0\par} 512\fs16 \f3\i0\b0 513\pard \ql \li400 \sl200 514\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 515# include\tab <stdio.h> 516\par 517# include\tab "rtf.h" 518\par 519{\sl-200\sa0\sb0\par} 520void 521\par 522TextCallback () 523\par 524\{ 525\par 526\tab putchar (rtfMajor); 527\par 528\} 529\par 530{\sl-120\sa0\sb0\par} 531\fs20 \f1\i0\b0 532{\sl-120\sa0\sb0\par} 533\fs16 \f3\i0\b0 534int 535\par 536main () 537\par 538\{ 539\par 540\tab RTFSetOpenLibFileProc (UnixOpenLibFile); 541\par 542\tab RTFInit (); 543\par 544\tab RTFSetClassCallback (rtfText, TextCallback); 545\par 546\tab RTFRead (); 547\par 548\tab exit (0); 549\par 550\} 551\par 552{\sl-120\sa0\sb0\par} 553\fs20 \f1\i0\b0 554\pard \qj \sl240 555\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 556Callbacks for the \f1\i0\b0 557 558\i rtfControl\f1\i0\b0 559 and \f1\i0\b0 560 561\i rtfGroup\f1\i0\b0 562 classes typically operate by selecting on 563the token major number to determine the action to take. 564A callback for the \f1\i0\b0 565 566\i rtfGroup\f1\i0\b0 567 class usually will do something like this: 568\par 569{\sl-120\sa0\sb0\par} 570\fs16 \f3\i0\b0 571\pard \ql \li400 \sl200 572\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 573void 574\par 575BraceCallback () 576\par 577\{ 578\par 579\tab switch (rtfMajor) 580\par 581\tab \{ 582\par 583\tab case rtfBeginGroup: 584\par 585\tab \tab \f1\i0\b0 586 587\i ...push state...\f1\i0\b0 588 589\par 590\tab \tab break; 591\par 592\tab case rtfEndGroup: 593\par 594\tab \tab \f1\i0\b0 595 596\i ...pop state...\f1\i0\b0 597 598\par 599\tab \tab break; 600\par 601\tab \} 602\par 603\} 604\par 605{\sl-120\sa0\sb0\par} 606\fs20 {\sl-240\sa0\sb0\par} 607\fs24 \f1\i0\b0 608\b \pard \qj \sl280 609\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 610Destination Readers\f1\i0\b0 611 612\par 613{\sl-280\sa0\sb0\par} 614\fs20 {\sl-120\sa0\sb0\par} 615\pard \qj \sl240 616\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 617Grouping in RTF documents occurs within braces \'d2\{\'d3 618and \'d2\}\'d3. One kind of group is the \f1\i0\b0 619 620\i destination\f1\i0\b0 621. The token immediately following the opening 622brace is a destination control symbol. These indicate 623such things as headers, footers, footnotes, etc. 624\par 625{\sl-120\sa0\sb0\par} 626Three destinations which specify information for internal 627use (i.e., information which affects output but isn\'d5t 628itself written) are the font table, color table and 629stylesheet. Since these three destinations occur so 630commonly and have a special syntax, the RTF reader 631by default gobbles them up itself when it recognizes 632them. The functions which do this are called \f1\i0\b0 633 634\i destination readers\f1\i0\b0 635 and are probably the nearest thing 636in the reader to what might be called parsers. They 637are installed by default so that translators can be 638written without the burden of understanding the syntax 639or digesting the contents of these destinations. Each 640of them constructs a list of the entries specified 641in the destination and the reader includes functions 642providing access to these lists. 643\par 644{\sl-120\sa0\sb0\par} 645Translators can turn off or override these defaults 646with \f1\i0\b0 647 648\i RTFSetDestinationCallback()\f1\i0\b0 649 if necessary. To override 650one, pass the address of a different destination reader 651function. To turn one off, pass \f3\i0\b0 652NULL\f1\i0\b0 653. 654\par 655{\sl-120\sa0\sb0\par} 656Destination callbacks may be called for any destination, 657not just \f1\i0\b0 658 659\i rtfFontTbl\f1\i0\b0 660, \f1\i0\b0 661 662\i rtfColorTbl\f1\i0\b0 663 and \f1\i0\b0 664 665\i rtfStyleSheet\f1\i0\b0 666. Destinations for which no callback is 667registered are not treated specially. 668\par 669{\sl-120\sa0\sb0\par} 670Other destinations for which there is a default reader 671are the information (\f3\i0\b0 672\\info\f1\i0\b0 673), picture (\f3\i0\b0 674\\pict\f1\i0\b0 675), and 676object (\f3\i0\b0 677\\object\f1\i0\b0 678) destinations; all they do is skip 679to the end of the group. 680\par 681{\sl-240\sa0\sb0\par} 682\f1\i0\b0 683\b Using the Built-in Destination Readers\f1\i0\b0 684 685\par 686{\sl-240\sa0\sb0\par} 687{\sl-120\sa0\sb0\par} 688The font table, color table and stylesheet information 689is maintained internally, and the reader either acts 690on that information itself, or allows itself to be 691queried by the writer about it, as described below. 692These descriptions do not apply if the translator shuts 693off or overrides the default destination readers, of 694course. 695\par 696{\sl-120\sa0\sb0\par} 697\f1\i0\b0 698\b Stylesheet\'d1\f1\i0\b0 699The reader acts on this itself. When 700the stylesheet destination is encountered, the style 701contents are remembered. Thereafter, whenever the writer 702receives notification that a style number control symbol 703(\f3\i0\b0 704\\s\f1\i0\b0 705\f1\i0\b0 706 707\i nnn\f1\i0\b0 708) has occurred, it can call \f1\i0\b0 709 710\i RTFExpandStyle(rtfParam)\f1\i0\b0 711 to cause the style to be expanded. 712The reader consults contents of the stylesheet and 713each token in the style definition is routed in turn 714back to the writer. This effects a sort of macro expansion. 715\par 716{\sl-120\sa0\sb0\par} 717If the writer doesn\'d5t care about style expansion, 718it simply refrains from calling \f1\i0\b0 719 720\i RTFExpandStyle()\f1\i0\b0 721. 722\par 723{\sl-120\sa0\sb0\par} 724If the writer wants information about a style, it can 725call \f1\i0\b0 726 727\i RTFGetStyle()\f1\i0\b0 728. 729\par 730{\sl-120\sa0\sb0\par} 731\f1\i0\b0 732\b Font table\'d1\f1\i0\b0 733For each entry in the font table, the 734font number, type and name are maintained by the reader. 735The writer finds out that a font number has been specified 736in the input when its control class callback is invoked 737and \f1\i0\b0 738 739\i rtfMajor\f1\i0\b0 740 = \f1\i0\b0 741 742\i rtfCharAttr\f1\i0\b0 743 and \f1\i0\b0 744 745\i rtfMinor\f1\i0\b0 746 = \f1\i0\b0 747 748\i rtfFontNum\f1\i0\b0 749. To obtain a pointer to the appropriate 750\f1\i0\b0 751\i RTFFont\f1\i0\b0 752 structure, the reader function \f1\i0\b0 753 754\i RTFGetFont(rtfParam)\f1\i0\b0 755 may be called. 756\par 757{\sl-120\sa0\sb0\par} 758\f1\i0\b0 759\b Color table\'d1\f1\i0\b0 760For each entry in the color table, the 761color number is maintained along with the red, green 762and blue values. The writer finds out that a color 763number has been specified in the input when its control 764class callback is invoked and \f1\i0\b0 765 766\i rtfMajor\f1\i0\b0 767 = \f1\i0\b0 768 769\i rtfCharAttr\f1\i0\b0 770 and \f1\i0\b0 771 772\i rtfMinor\f1\i0\b0 773 = \f1\i0\b0 774 775\i rtfColorNum\f1\i0\b0 776. To obtain a pointer to the appropriate 777\f1\i0\b0 778\i RTFColor\f1\i0\b0 779 structure, the reader function \f1\i0\b0 780 781\i RTFGetColor(rtfParam)\f1\i0\b0 782 may be called. 783\par 784{\sl-120\sa0\sb0\par} 785One subtle point about the built-in destination readers: 786destinations cannot be recognized until \f1\i0\b0 787 788\i after\f1\i0\b0 789 the occurrence of the \'d2\{\'d3 symbol that 790begins the destination. This means the writer, if it 791maintains a state stack, will already have pushed a 792state. In order to allow the writer to properly pop 793that state in response to the \'d2\}\'d3, these destination 794readers feed the \'d2\}\'d3 back into the token router 795after they pull it from the input stream. What the 796writer actually sees is a \'d2\{\'d3 followed immediately 797by a \'d2\}\'d3. 798\par 799{\sl-120\sa0\sb0\par} 800Applications that maintain a state stack may find it 801necessary to do something similar if they supply their 802own destination readers. 803\par 804{\sl-240\sa0\sb0\par} 805\fs28 \f1\i0\b0 806\b \pard \qj \sl320 807\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 808Programming Interface\f1\i0\b0 809 810\par 811{\sl-320\sa0\sb0\par} 812\fs20 {\sl-120\sa0\sb0\par} 813\pard \qj \sl240 814\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 815Source files using the RTF reader should #include \f1\i0\b0 816 817\i rtf.h\f1\i0\b0 818. The library files common to all translators 819are used to build a library \f1\i0\b0 820 821\i librtf.a\f1\i0\b0 822 in the distribution\'d5s \f1\i0\b0 823 824\i lib\f1\i0\b0 825 directory. This library should be part of the final 826application link. 827\par 828{\sl-120\sa0\sb0\par} 829The best way to learn how these source files work is 830to study the sample translators, which vary in complexity 831from very simple (e.g., \f1\i0\b0 832 833\i rtf2text\f1\i0\b0 834, \f1\i0\b0 835 836\i rtfwc\f1\i0\b0 837), to wretchedly messy (e.g., \f1\i0\b0 838 839\i rtf2troff\f1\i0\b0 840). You should be aware that one implication 841of the way the translators are built (callbacks and 842switch statements) is that it\'d5s quite easy to build 843them incrementally. You can start with a very bare-bones 844model, and start plugging in callbacks as you progress. 845Within the callbacks, your switch statements can progressively 846handle more cases. 847\par 848{\sl-120\sa0\sb0\par} 849An alternative approach is to start with a copy of 850\f1\i0\b0 851\i rtfskel\f1\i0\b0 852, which includes a full set of class callbacks 853and complete switch statements for all tokens. Each 854case is empty; you simply add code for those cases 855you want to handle. You can also rip out the code for 856the cases you don\'d5t care about. 857\par 858{\sl-240\sa0\sb0\par} 859\fs24 \f1\i0\b0 860\b \pard \qj \sl280 861\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 862Types\f1\i0\b0 863 864\par 865{\sl-280\sa0\sb0\par} 866\fs20 {\sl-120\sa0\sb0\par} 867\pard \qj \sl240 868\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 869Most types are pretty standard. The one of note is 870\f1\i0\b0 871\i RTFFuncPtr\f1\i0\b0 872, a generic function pointer which is defined 873like so: 874\par 875{\sl-120\sa0\sb0\par} 876\fs16 \f3\i0\b0 877\pard \ql \li400 \sl200 878\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 879typedef\tab void (*RTFFuncPtr) (); 880\par 881{\sl-120\sa0\sb0\par} 882\fs20 \f1\i0\b0 883\pard \qj \sl240 884\tx720 \tx1040 \tx1360 \tx1680 \tx2000 \tx2320 \tx2640 \tx2960 \tx3280 \tx3600 \tx3920 \tx4240 \tx4560 \tx4880 \tx5200 \tx5520 \tx5840 \tx6160 \tx6480 \tx6800 885That is, it\'d5s a pointer to a function that takes 886no arguments and returns no value. 887\par 888{\sl-240\sa0\sb0\par} 889\fs24 \f1\i0\b0 890\b \pard \qj \sl280 891\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 892Global variables\f1\i0\b0 893 894\par 895{\sl-280\sa0\sb0\par} 896\fs20 {\sl-120\sa0\sb0\par} 897\pard \qj \sl240 898\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 899The global RTF reader variables are: 900\par 901{\sl-120\sa0\sb0\par} 902{\sl-120\sa0\sb0\par} 903\pard \ql \li720 \sl240 904\tx1584 \tx3600 905int\tab rtfClass;\tab token class 906\par 907int\tab rtfMajor;\tab token major number 908\par 909int\tab rtfMinor;\tab token minor number 910\par 911int\tab rtfParam;\tab parameter value for control symbols 912\par 913char\tab *rtfTextBuf;\tab token text 914\par 915int\tab rtfTextLen;\tab length of token text 916\par 917{\sl-120\sa0\sb0\par} 918{\sl-120\sa0\sb0\par} 919\pard \qj \sl240 920\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 921These variables always apply to the token with which 922the writer should be concerned. This may be either 923the last token read or the current token within a style 924which is being reprocessed. 925\par 926{\sl-120\sa0\sb0\par} 927\f1\i0\b0 928\b Warning:\f1\i0\b0 929 \f1\i0\b0 930 931\i rtfTextBuf\f1\i0\b0 932 is \f3\i0\b0 933NULL\f1\i0\b0 934 until \f1\i0\b0 935 936\i RTFInit()\f1\i0\b0 937 has been called. 938\par 939{\sl-120\sa0\sb0\par} 940Two other global variables which may be of interest 941provide the current input line number and position 942within the line: 943\par 944{\sl-120\sa0\sb0\par} 945{\sl-120\sa0\sb0\par} 946\pard \ql \li720 \sl240 947\tx1584 \tx3600 948long\tab rtfLineNum;\tab current input line 949\par 950int\tab rtfLinePos;\tab position within current line 951\par 952{\sl-120\sa0\sb0\par} 953{\sl-120\sa0\sb0\par} 954\pard \qj \sl240 955\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 956These variables can be used to provide feedback to 957the user when a problem is found in an input file as 958to the location of the problem. They indicate the position 959immediately after the last token read. 960\par 961{\sl-240\sa0\sb0\par} 962\fs24 \f1\i0\b0 963\b \pard \qj \sl280 964\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 965Functions\f1\i0\b0 966 967\par 968{\sl-280\sa0\sb0\par} 969\fs20 {\sl-120\sa0\sb0\par} 970\f3\i0\b0 971\pard \ql \sl240 972\tx1152 973void 974\par 975RTFInit () 976\par 977\fs24 \f1\i0\b0 978\fs20 \f3\i0\b0 979\fs24 \f1\i0\b0 980{\sl-120\sa0\sb0\par} 981\pard \qj \li360 \sl280 982\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 983Initialize the RTF reader. This should be called once 984for each input file to be processed. It performs some 985initialization such as computing hash values for the 986token lookup table and installation of some built-in 987destination and token class readers. 988\par 989{\sl-140\sa0\sb0\par} 990\f1\i0\b0 991\i RTFInit()\f1\i0\b0 992 may be called multiple times. Each invocation 993resets the reader\'d5s state completely, except that 994the input stream is not disturbed. 995\par 996\fs20 \f3\i0\b0 997{\sl-120\sa0\sb0\par} 998\f1\i0\b0 999\f3\i0\b0 1000\pard \ql \sl240 1001\tx1152 1002void 1003\par 1004RTFRead () 1005\par 1006\fs24 \f1\i0\b0 1007\fs20 \f3\i0\b0 1008\fs24 \f1\i0\b0 1009{\sl-120\sa0\sb0\par} 1010\f1\i0\b0 1011\i \pard \qj \li360 \sl280 1012\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 1013RTFRead()\f1\i0\b0 1014 calls \f1\i0\b0 1015 1016\i RTFGetToken()\f1\i0\b0 1017 to tokenize the input stream and \f1\i0\b0 1018 1019\i RTFRouteToken()\f1\i0\b0 1020 to process each token, until input 1021is exhausted. When \f1\i0\b0 1022 1023\i RTFRead()\f1\i0\b0 1024 returns, input has been completely read and 1025the writer can perform any cleanup or termination needed. 1026\par 1027{\sl-140\sa0\sb0\par} 1028If you want to read multiple files per invocation of 1029your translator, you should do the following for each 1030file: call \f1\i0\b0 1031 1032\i RTFInit()\f1\i0\b0 1033, install callbacks, etc., then call \f1\i0\b0 1034 1035\i RTFRead()\f1\i0\b0 1036. 1037\par 1038\fs20 \f3\i0\b0 1039{\sl-120\sa0\sb0\par} 1040\f1\i0\b0 1041\f3\i0\b0 1042\pard \ql \sl240 1043\tx1152 1044void 1045\par 1046RTFRouteToken () 1047\par 1048\fs24 \f1\i0\b0 1049\fs20 \f3\i0\b0 1050\fs24 \f1\i0\b0 1051{\sl-120\sa0\sb0\par} 1052\pard \qj \li360 \sl280 1053\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 1054This routine decides what to do with the current token 1055and routes it to the correct place for processing. 1056Usually this is directly to the writer via a class 1057callback. The token is \f1\i0\b0 1058 1059\i not\f1\i0\b0 1060 passed to the writer (i.e., the class callback 1061is bypassed) when it is a destination token for which 1062a reader callback is installed. 1063\par 1064{\sl-140\sa0\sb0\par} 1065By default, built-in readers are installed for font 1066table, color table, stylesheet and information and 1067picture group destinations. The built-in readers can 1068be disabled if the writer wants to see all tokens directly. 1069\par 1070\fs20 \f3\i0\b0 1071{\sl-120\sa0\sb0\par} 1072\f1\i0\b0 1073\f3\i0\b0 1074\pard \ql \sl240 1075\tx1152 1076int 1077\par 1078RTFGetToken () 1079\par 1080\fs24 \f1\i0\b0 1081\fs20 \f3\i0\b0 1082\fs24 \f1\i0\b0 1083{\sl-120\sa0\sb0\par} 1084\pard \qj \li360 \sl280 1085\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 1086Reads one token from the input stream, classifies it, 1087sets the global variables, and returns the class number. 1088If the class is \f1\i0\b0 1089 1090\i rtfEOF\f1\i0\b0 1091 the end of the input stream has been reached. 1092Newlines (\f3\i0\b0 1093\\n\f1\i0\b0 1094), carriage returns (\f3\i0\b0 1095\\r\f1\i0\b0 1096), and nulls are 1097silently discarded by \f1\i0\b0 1098 1099\i RTFGetToken()\f1\i0\b0 1100, as they have no meaning. All are passed 1101to the token hook if one is installed, however. 1102\par 1103{\sl-140\sa0\sb0\par} 1104The sequence \f3\i0\b0 1105\\:\f1\i0\b0 1106 is treated as a plain text character, 1107with \f1\i0\b0 1108 1109\i rtfClass\f1\i0\b0 1110 set to \f1\i0\b0 1111 1112\i rtfText\f1\i0\b0 1113 and \f1\i0\b0 1114 1115\i rtfMajor\f1\i0\b0 1116 set to the colon ASCII code. Strictly speaking, 1117\f3\i0\b0 1118\\:\f1\i0\b0 1119 is the control word for an index subentry, but 1120some versions of Microsoft Word write out plain text 1121colons with a preceding backslash, while others don\'d5t. 1122This unfortunate ambiguity results in an ugly dilemma. 1123It seems the lesser burden to require translators to 1124recognize that plain text colons should \'d2really\'d3 1125be treated as index subentry indicators while inside 1126of an index entry destination, than to recognize that 1127an index subentry control word should \'d2really\'d3 1128be treated as a plain text colon everywhere else. 1129\par 1130{\sl-140\sa0\sb0\par} 1131Writer code usually does not call \f1\i0\b0 1132 1133\i RTFGetToken()\f1\i0\b0 1134 directly except within specialized destination 1135readers. Driver code usually does not call \f1\i0\b0 1136 1137\i RTFGetToken()\f1\i0\b0 1138 if it calls \f1\i0\b0 1139 1140\i RTFRead()\f1\i0\b0 1141. However, the following loop is an alternative 1142to \f1\i0\b0 1143 1144\i RTFRead()\f1\i0\b0 1145: 1146\par 1147{\sl-120\sa0\sb0\par} 1148\fs16 \f3\i0\b0 1149\pard \ql \li760 \sl200 1150\tx1080 \tx1400 \tx1720 \tx2040 \tx2360 \tx2680 \tx3000 \tx3320 \tx3640 \tx3960 \tx4280 \tx4600 \tx4920 \tx5240 \tx5560 \tx5880 \tx6200 \tx6520 \tx6840 \tx7160 1151while (RTFGetToken () != rtfEOF) 1152\par 1153\{ 1154\par 1155\tab RTFRouteToken (); 1156\par 1157\} 1158\par 1159{\sl-120\sa0\sb0\par} 1160\fs24 \f1\i0\b0 1161\pard \qj \li360 \sl280 1162\tx1080 \tx1400 \tx1720 \tx2040 \tx2360 \tx2680 \tx3000 \tx3320 \tx3640 \tx3960 \tx4280 \tx4600 \tx4920 \tx5240 \tx5560 \tx5880 \tx6200 \tx6520 \tx6840 \tx7160 1163If a driver wants to regain control after reading each 1164token, this loop may be preferable to \f1\i0\b0 1165 1166\i RTFRead()\f1\i0\b0 1167. 1168\par 1169\fs20 \f3\i0\b0 1170{\sl-120\sa0\sb0\par} 1171\f1\i0\b0 1172\f3\i0\b0 1173\pard \ql \sl240 1174\tx1152 1175int 1176\par 1177RTFUngetToken () 1178\par 1179\fs24 \f1\i0\b0 1180\fs20 \f3\i0\b0 1181\fs24 \f1\i0\b0 1182{\sl-120\sa0\sb0\par} 1183\pard \qj \li360 \sl280 1184\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1185Pushes the last token back on the input stream so that 1186\f1\i0\b0 1187\i RTFGetToken()\f1\i0\b0 1188 returns it again. You can\'d5t put back 1189the same token twice unless you read it again in the 1190interim. 1191\par 1192\fs20 \f3\i0\b0 1193{\sl-120\sa0\sb0\par} 1194\f1\i0\b0 1195\f3\i0\b0 1196\pard \ql \sl240 1197\tx1152 1198int 1199\par 1200RTFPeekToken () 1201\par 1202\fs24 \f1\i0\b0 1203\fs20 \f3\i0\b0 1204\fs24 \f1\i0\b0 1205{\sl-120\sa0\sb0\par} 1206\pard \qj \li360 \sl280 1207\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1208Reads a token from the input stream and sets the global 1209token variables, but does not remove the token from 1210the input stream. 1211\par 1212\fs20 \f3\i0\b0 1213{\sl-120\sa0\sb0\par} 1214\f1\i0\b0 1215\f3\i0\b0 1216\pard \ql \sl240 1217\tx1152 1218void 1219\par 1220RTFSetToken (class, major, minor, param, text) 1221\par 1222int\tab class, major, minor, param; 1223\par 1224char\tab *text; 1225\par 1226\fs24 \f1\i0\b0 1227\fs20 \f3\i0\b0 1228\fs24 \f1\i0\b0 1229{\sl-120\sa0\sb0\par} 1230\pard \qj \li360 \sl280 1231\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1232It is sometimes useful to construct a fake token and 1233run it through the token router to cause the effects 1234of the token to be applied. \f1\i0\b0 1235 1236\i RTFSetToken()\f1\i0\b0 1237 allows you to do this, by setting the 1238reader\'d5s global variables to the values supplied. 1239If \f1\i0\b0 1240 1241\i param\f1\i0\b0 1242 is \f1\i0\b0 1243 1244\i rtfNoParam\f1\i0\b0 1245, the token text \f1\i0\b0 1246 1247\i rtfTextBuf\f1\i0\b0 1248 is constructed from \f1\i0\b0 1249 1250\i text\f1\i0\b0 1251 and \f1\i0\b0 1252 1253\i param\f1\i0\b0 1254, otherwise \f1\i0\b0 1255 1256\i rtfTextBuf\f1\i0\b0 1257 is just copied from \f1\i0\b0 1258 1259\i text\f1\i0\b0 1260. 1261\par 1262\fs20 \f3\i0\b0 1263{\sl-120\sa0\sb0\par} 1264\f1\i0\b0 1265\f3\i0\b0 1266\pard \ql \sl240 1267\tx1152 1268void 1269\par 1270RTFSetReadHook (f) 1271\par 1272RTFFuncPtr\tab f; 1273\par 1274\fs24 \f1\i0\b0 1275\fs20 \f3\i0\b0 1276\fs24 \f1\i0\b0 1277{\sl-120\sa0\sb0\par} 1278\pard \qj \li360 \sl280 1279\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1280Install a function to be called by \f1\i0\b0 1281 1282\i RTFGetToken()\f1\i0\b0 1283 after each token is read from the input 1284stream. The function takes no arguments and returns 1285no value. Within the function, information about the 1286current token can be obtained from the global variables. 1287This function is for token examination purposes only, 1288and should not modify those variables. 1289\par 1290\fs20 \f3\i0\b0 1291{\sl-120\sa0\sb0\par} 1292\f1\i0\b0 1293\f3\i0\b0 1294\pard \ql \sl240 1295\tx1152 1296RTFFuncPtr 1297\par 1298RTFGetReadHook () 1299\par 1300\fs24 \f1\i0\b0 1301\fs20 \f3\i0\b0 1302\fs24 \f1\i0\b0 1303{\sl-120\sa0\sb0\par} 1304\pard \qj \li360 \sl280 1305\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1306Returns a pointer to the current read hook, or \f3\i0\b0 1307NULL\f1\i0\b0 1308 1309if there isn\'d5t one. 1310\par 1311\fs20 \f3\i0\b0 1312{\sl-120\sa0\sb0\par} 1313\f1\i0\b0 1314\f3\i0\b0 1315\pard \ql \sl240 1316\tx1152 1317void 1318\par 1319RTFSkipGroup () 1320\par 1321\fs24 \f1\i0\b0 1322\fs20 \f3\i0\b0 1323\fs24 \f1\i0\b0 1324{\sl-120\sa0\sb0\par} 1325\pard \qj \li360 \sl280 1326\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1327This function can be called to skip to the end of the 1328current group (including any subgroups). It\'d5s useful 1329for explicitly ignoring \f3\i0\b0 1330\\*\\\f1\i0\b0 1331\f1\i0\b0 1332 1333\i dest\f1\i0\b0 1334 groups, where \f1\i0\b0 1335 1336\i dest\f1\i0\b0 1337 is an unrecognized destination, or for causing 1338groups that you don\'d5t want to deal with to effectively 1339\'d2disappear\'d3 from the input stream. 1340\par 1341{\sl-140\sa0\sb0\par} 1342Calling this function in the middle of expanding a 1343style may cause problems. However, it is typically 1344called when you have just seen a destination symbol, 1345which won\'d5t happen during a style expansion\'d1I 1346think. 1347\par 1348{\sl-140\sa0\sb0\par} 1349Be careful with this function if your writer maintains 1350a state stack, because you will already have pushed 1351a state when the opening group brace was seen. After 1352\f1\i0\b0 1353\i RTFSkipGroup()\f1\i0\b0 1354 returns, the group closing brace has 1355been read, and you\'d5ll need to pop a state. All global 1356token variables will still be set to the closing brace, 1357so you may only need to call \f1\i0\b0 1358 1359\i RTFRouteToken()\f1\i0\b0 1360 to cause the state to be unstacked. 1361\par 1362\fs20 \f3\i0\b0 1363{\sl-120\sa0\sb0\par} 1364\f1\i0\b0 1365\f3\i0\b0 1366\pard \ql \sl240 1367\tx1152 1368void 1369\par 1370RTFExpandStyle (num) 1371\par 1372int\tab num; 1373\par 1374\fs24 \f1\i0\b0 1375\fs20 \f3\i0\b0 1376\fs24 \f1\i0\b0 1377{\sl-120\sa0\sb0\par} 1378\pard \qj \li360 \sl280 1379\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1380Performs style expansion of the given style number, 1381or does nothing if there is no such style. The writer 1382should call this when it notices that the current token 1383is a style number indicator. 1384\par 1385\fs20 \f3\i0\b0 1386{\sl-120\sa0\sb0\par} 1387\f1\i0\b0 1388\f3\i0\b0 1389\pard \ql \sl240 1390\tx1152 1391void 1392\par 1393RTFSetStream (stream) 1394\par 1395FILE\tab *stream; 1396\par 1397\fs24 \f1\i0\b0 1398\fs20 \f3\i0\b0 1399\fs24 \f1\i0\b0 1400{\sl-120\sa0\sb0\par} 1401\pard \qj \li360 \sl280 1402\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1403Redirects the RTF reader to the given stream. This 1404should be called before any reading is done. The default 1405input stream is \f1\i0\b0 1406 1407\i stdin\f1\i0\b0 1408. An alternative to \f1\i0\b0 1409 1410\i RTFSetStream()\f1\i0\b0 1411 is to simply \f1\i0\b0 1412 1413\i freopen()\f1\i0\b0 1414 the input file on \f1\i0\b0 1415 1416\i stdin\f1\i0\b0 1417 (that\'d5s what all the sample translators do). 1418\par 1419{\sl-140\sa0\sb0\par} 1420The input stream is \f1\i0\b0 1421 1422\i not\f1\i0\b0 1423 modified by \f1\i0\b0 1424 1425\i RTFInit()\f1\i0\b0 1426. 1427\par 1428\fs20 \f3\i0\b0 1429{\sl-120\sa0\sb0\par} 1430\f1\i0\b0 1431\f3\i0\b0 1432\pard \ql \sl240 1433\tx1152 1434void 1435\par 1436RTFSetClassCallback (class, callback) 1437\par 1438int\tab \tab class; 1439\par 1440RTFFuncPtr\tab callback; 1441\par 1442\fs24 \f1\i0\b0 1443\fs20 \f3\i0\b0 1444\fs24 \f1\i0\b0 1445{\sl-120\sa0\sb0\par} 1446\pard \qj \li360 \sl280 1447\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1448Installs a writer callback function for the given token 1449class. The first argument is a class number, the second 1450is the function to call when tokens from that class 1451are encountered in the input stream. This will cause 1452\f1\i0\b0 1453\i RTFRouteToken()\f1\i0\b0 1454 to invoke the callback when it encounters 1455a token in the class. If \f1\i0\b0 1456 1457\i callback\f1\i0\b0 1458 is \f3\i0\b0 1459NULL\f1\i0\b0 1460 (which is the default for all classes), 1461tokens in the class are ignored, i.e., discarded. 1462\par 1463{\sl-140\sa0\sb0\par} 1464The callback should take no arguments and return no 1465value. Within the callback, information about the current 1466token can be obtained from the global variables. 1467\par 1468{\sl-140\sa0\sb0\par} 1469Installing a callback for the \f1\i0\b0 1470 1471\i rtfEOF\f1\i0\b0 1472 \'d2class\'d3 is silly and has no effect. 1473\par 1474\fs20 \f3\i0\b0 1475{\sl-120\sa0\sb0\par} 1476\f1\i0\b0 1477\f3\i0\b0 1478\pard \ql \sl240 1479\tx1152 1480RTFFuncPtr 1481\par 1482RTFGetClassCallback (class) 1483\par 1484int\tab class; 1485\par 1486\fs24 \f1\i0\b0 1487\fs20 \f3\i0\b0 1488\fs24 \f1\i0\b0 1489{\sl-120\sa0\sb0\par} 1490\pard \qj \li360 \sl280 1491\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1492Returns a pointer to the callback function for the 1493given token class, or \f3\i0\b0 1494NULL\f1\i0\b0 1495 if there isn\'d5t one. 1496\par 1497\fs20 \f3\i0\b0 1498{\sl-120\sa0\sb0\par} 1499\f1\i0\b0 1500\f3\i0\b0 1501\pard \ql \sl240 1502\tx1152 1503void 1504\par 1505RTFSetDestinationCallback (dest, callback) 1506\par 1507int\tab \tab dest; 1508\par 1509RTFFuncPtr\tab callback; 1510\par 1511\fs24 \f1\i0\b0 1512\fs20 \f3\i0\b0 1513\fs24 \f1\i0\b0 1514{\sl-120\sa0\sb0\par} 1515\pard \qj \li360 \sl280 1516\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1517Installs a callback function for the given destination 1518(\f1\i0\b0 1519 1520\i dest\f1\i0\b0 1521 is a token minor number). When \f1\i0\b0 1522 1523\i RTFRouteToken()\f1\i0\b0 1524 sees a token with class \f1\i0\b0 1525 1526\i rtfControl\f1\i0\b0 1527 and major number \f1\i0\b0 1528 1529\i rtfDestination\f1\i0\b0 1530, it checks whether there is a callback 1531for the destination indicated by the minor number. 1532If so, it invokes it. If \f1\i0\b0 1533 1534\i callback\f1\i0\b0 1535 is \f3\i0\b0 1536NULL\f1\i0\b0 1537, the given destination is not treated 1538specially (the control class callback is invoked as 1539usual). By default, destination callbacks are installed 1540for the font table, color table, stylesheet, and information 1541and picture group. 1542\par 1543{\sl-140\sa0\sb0\par} 1544The callback should take no arguments and return no 1545value. When the functon is invoked, the current token 1546will be the destination token following the destination\'d5s 1547initial opening brace \f3\i0\b0 1548\{\f1\i0\b0 1549. (For optional destinations, 1550the destination token follows the \f3\i0\b0 1551\\*\f1\i0\b0 1552 symbol.) 1553\par 1554\fs20 \f3\i0\b0 1555{\sl-120\sa0\sb0\par} 1556\f1\i0\b0 1557\f3\i0\b0 1558\pard \ql \sl240 1559\tx1152 1560RTFFuncPtr 1561\par 1562RTFGetDestinationCallback (dest) 1563\par 1564int\tab dest; 1565\par 1566\fs24 \f1\i0\b0 1567\fs20 \f3\i0\b0 1568\fs24 \f1\i0\b0 1569{\sl-120\sa0\sb0\par} 1570\pard \qj \li360 \sl280 1571\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1572Returns a pointer to the callback function for the 1573given token class, or \f3\i0\b0 1574NULL\f1\i0\b0 1575 if there isn\'d5t one. 1576\par 1577\fs20 \f3\i0\b0 1578{\sl-120\sa0\sb0\par} 1579\f1\i0\b0 1580\f3\i0\b0 1581\pard \ql \sl240 1582\tx1152 1583RTFStyle * 1584\par 1585RTFGetStyle (num) 1586\par 1587int\tab num; 1588\par 1589\fs24 \f1\i0\b0 1590\fs20 \f3\i0\b0 1591\fs24 \f1\i0\b0 1592{\sl-120\sa0\sb0\par} 1593\pard \qj \li360 \sl280 1594\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1595Returns a pointer to the \f1\i0\b0 1596 1597\i RTFStyle\f1\i0\b0 1598 structure for the given style number. The 1599\'d2Normal\'d3 style number is 0. Pass \'d01 to get 1600a pointer to the first style in the list. Styles are 1601not stored in any particular order. 1602\par 1603{\sl-140\sa0\sb0\par} 1604Be sure to check the result; it might be \f3\i0\b0 1605NULL\f1\i0\b0 1606. 1607\par 1608{\sl-140\sa0\sb0\par} 1609This function is meaningless if the default stylesheet 1610destination reader is overridden. 1611\par 1612\fs20 \f3\i0\b0 1613{\sl-120\sa0\sb0\par} 1614\f1\i0\b0 1615\f3\i0\b0 1616\pard \ql \sl240 1617\tx1152 1618RTFFont * 1619\par 1620RTFGetFont (num) 1621\par 1622int\tab num; 1623\par 1624\fs24 \f1\i0\b0 1625\fs20 \f3\i0\b0 1626\fs24 \f1\i0\b0 1627{\sl-120\sa0\sb0\par} 1628\pard \qj \li360 \sl280 1629\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1630Returns a pointer to the \f1\i0\b0 1631 1632\i RTFFont\f1\i0\b0 1633 structure for the given font number. Pass \'d01 1634to get a pointer to the first font in the list. Fonts 1635are not stored in any particular order. 1636\par 1637{\sl-140\sa0\sb0\par} 1638Be sure to check the result; it might be \f3\i0\b0 1639NULL\f1\i0\b0 1640. In particular, 1641you might think that passing the number specified with 1642the \f3\i0\b0 1643\\deff\f1\i0\b0 1644 (default font) control symbol would always 1645yield a valid font structure, but that\'d5s not true. 1646The default font might not be listed in the font table. 1647\par 1648{\sl-140\sa0\sb0\par} 1649This function is meaningless if the default font table 1650destination reader is overridden. 1651\par 1652\fs20 \f3\i0\b0 1653{\sl-120\sa0\sb0\par} 1654\f1\i0\b0 1655\f3\i0\b0 1656\pard \ql \sl240 1657\tx1152 1658RTFColor * 1659\par 1660RTFGetColor (num) 1661\par 1662int\tab num; 1663\par 1664\fs24 \f1\i0\b0 1665\fs20 \f3\i0\b0 1666\fs24 \f1\i0\b0 1667{\sl-120\sa0\sb0\par} 1668\pard \qj \li360 \sl280 1669\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1670Returns a pointer to the \f1\i0\b0 1671 1672\i RTFColor\f1\i0\b0 1673 structure for the given color number. Pass 1674\'d01 to get a pointer to the first color in the list. 1675Colors are not stored in any particular order. If the 1676color values in the entry are \'d01, the default color 1677should be used. The default color is translator-dependent. 1678\par 1679{\sl-140\sa0\sb0\par} 1680Be sure to check the result; it might be \f3\i0\b0 1681NULL\f1\i0\b0 1682. I think 1683this means you should use the default color. 1684\par 1685{\sl-140\sa0\sb0\par} 1686This function is meaningless if the default color table 1687destination reader is overridden. 1688\par 1689\fs20 \f3\i0\b0 1690{\sl-120\sa0\sb0\par} 1691\f1\i0\b0 1692\f3\i0\b0 1693\pard \ql \sl240 1694\tx1152 1695int 1696\par 1697RTFCheckCM (class, major) 1698\par 1699int\tab class, major; 1700\par 1701\fs24 \f1\i0\b0 1702\fs20 \f3\i0\b0 1703\fs24 \f1\i0\b0 1704{\sl-120\sa0\sb0\par} 1705\pard \qj \li360 \sl280 1706\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1707Returns non-zero if \f1\i0\b0 1708 1709\i rtfClass\f1\i0\b0 1710 and \f1\i0\b0 1711 1712\i rtfMajor\f1\i0\b0 1713 are equal to \f1\i0\b0 1714 1715\i class\f1\i0\b0 1716 and \f1\i0\b0 1717 1718\i major\f1\i0\b0 1719, respectively, zero otherwise. 1720\par 1721\fs20 \f3\i0\b0 1722{\sl-120\sa0\sb0\par} 1723\f1\i0\b0 1724\f3\i0\b0 1725\pard \ql \sl240 1726\tx1152 1727int 1728\par 1729RTFCheckCMM (class, major, minor) 1730\par 1731int\tab class, major, minor; 1732\par 1733\fs24 \f1\i0\b0 1734\fs20 \f3\i0\b0 1735\fs24 \f1\i0\b0 1736{\sl-120\sa0\sb0\par} 1737\pard \qj \li360 \sl280 1738\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1739Returns non-zero if \f1\i0\b0 1740 1741\i rtfClass\f1\i0\b0 1742, \f1\i0\b0 1743 1744\i rtfMajor\f1\i0\b0 1745 and \f1\i0\b0 1746 1747\i rtfMinor\f1\i0\b0 1748 are equal to \f1\i0\b0 1749 1750\i class\f1\i0\b0 1751, \f1\i0\b0 1752 1753\i major\f1\i0\b0 1754 and \f1\i0\b0 1755 1756\i minor\f1\i0\b0 1757, respectively, zero otherwise. 1758\par 1759\fs20 \f3\i0\b0 1760{\sl-120\sa0\sb0\par} 1761\f1\i0\b0 1762\f3\i0\b0 1763\pard \ql \sl240 1764\tx1152 1765int 1766\par 1767RTFCheckMM (major, minor) 1768\par 1769int\tab major, minor; 1770\par 1771\fs24 \f1\i0\b0 1772\fs20 \f3\i0\b0 1773\fs24 \f1\i0\b0 1774{\sl-120\sa0\sb0\par} 1775\pard \qj \li360 \sl280 1776\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1777Returns non-zero if \f1\i0\b0 1778 1779\i rtfMajor\f1\i0\b0 1780 and \f1\i0\b0 1781 1782\i rtfMinor\f1\i0\b0 1783 are equal to \f1\i0\b0 1784 1785\i major\f1\i0\b0 1786 and \f1\i0\b0 1787 1788\i minor\f1\i0\b0 1789, respectively, zero otherwise. 1790\par 1791\fs20 \f3\i0\b0 1792{\sl-120\sa0\sb0\par} 1793\f1\i0\b0 1794\f3\i0\b0 1795\pard \ql \sl240 1796\tx1152 1797char * 1798\par 1799RTFAlloc (size) 1800\par 1801int\tab size; 1802\par 1803\fs24 \f1\i0\b0 1804\fs20 \f3\i0\b0 1805\fs24 \f1\i0\b0 1806{\sl-120\sa0\sb0\par} 1807\pard \qj \li360 \sl280 1808\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1809Returns a pointer to a block of memory \f1\i0\b0 1810 1811\i size\f1\i0\b0 1812 bytes long, or \f3\i0\b0 1813NULL\f1\i0\b0 1814 if insufficient memory was 1815available. 1816\par 1817\fs20 \f3\i0\b0 1818{\sl-120\sa0\sb0\par} 1819\f1\i0\b0 1820\f3\i0\b0 1821\pard \ql \sl240 1822\tx1152 1823char * 1824\par 1825RTFStrSave (s) 1826\par 1827char\tab *s; 1828\par 1829\fs24 \f1\i0\b0 1830\fs20 \f3\i0\b0 1831\fs24 \f1\i0\b0 1832{\sl-120\sa0\sb0\par} 1833\pard \qj \li360 \sl280 1834\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1835Allocates a block of memory big enough for a copy of 1836the given string (including terminating null byte), 1837copies the string into it, and returns a pointer to 1838the copy. Returns \f3\i0\b0 1839NULL\f1\i0\b0 1840 if insufficient memory was available. 1841\par 1842\fs20 \f3\i0\b0 1843{\sl-120\sa0\sb0\par} 1844\f1\i0\b0 1845\f3\i0\b0 1846\pard \ql \sl240 1847\tx1152 1848void 1849\par 1850RTFFree (p) 1851\par 1852char\tab *p; 1853\par 1854\fs24 \f1\i0\b0 1855\fs20 \f3\i0\b0 1856\fs24 \f1\i0\b0 1857{\sl-120\sa0\sb0\par} 1858\pard \qj \li360 \sl280 1859\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1860Frees the block of memory pointed to by \f1\i0\b0 1861 1862\i p\f1\i0\b0 1863, which should have been allocated by \f1\i0\b0 1864 1865\i RTFAlloc()\f1\i0\b0 1866 or \f1\i0\b0 1867 1868\i RTFStrSave()\f1\i0\b0 1869. It is safe to pass \f3\i0\b0 1870NULL\f1\i0\b0 1871 to this routine. 1872\par 1873\fs20 \f3\i0\b0 1874{\sl-120\sa0\sb0\par} 1875\f1\i0\b0 1876\f3\i0\b0 1877\pard \ql \sl240 1878\tx1152 1879void 1880\par 1881RTFCharToHex (c) 1882\par 1883char\tab c; 1884\par 1885\fs24 \f1\i0\b0 1886\fs20 \f3\i0\b0 1887\fs24 \f1\i0\b0 1888{\sl-120\sa0\sb0\par} 1889\pard \qj \li360 \sl280 1890\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1891Returns 0..15 for the characters \'d40\'d4..\'d49\'d4,\'d4a\'d4..\'d4f\'d4. 1892\par 1893\fs20 \f3\i0\b0 1894{\sl-120\sa0\sb0\par} 1895\f1\i0\b0 1896\f3\i0\b0 1897\pard \ql \sl240 1898\tx1152 1899void 1900\par 1901RTFHexToChar (i) 1902\par 1903int\tab i; 1904\par 1905\fs24 \f1\i0\b0 1906\fs20 \f3\i0\b0 1907\fs24 \f1\i0\b0 1908{\sl-120\sa0\sb0\par} 1909\pard \qj \li360 \sl280 1910\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1911Returns the characters \'d40\'d4..\'d49\'d4,\'d4a\'d4..\'d4f\'d4 1912for 0..15. 1913\par 1914\fs20 \f3\i0\b0 1915{\sl-120\sa0\sb0\par} 1916\f1\i0\b0 1917\f3\i0\b0 1918\pard \ql \sl240 1919\tx1152 1920int 1921\par 1922RTFReadCharSetMap (file, csId) 1923\par 1924char\tab *file; 1925\par 1926int\tab csId; 1927\par 1928\fs24 \f1\i0\b0 1929\fs20 \f3\i0\b0 1930\fs24 \f1\i0\b0 1931{\sl-120\sa0\sb0\par} 1932\pard \qj \li360 \sl280 1933\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1934Reads a charset map file into the charset map indicated 1935by \f1\i0\b0 1936 1937\i csId\f1\i0\b0 1938, which should be either \f1\i0\b0 1939 1940\i rtfCSGeneral\f1\i0\b0 1941 or \f1\i0\b0 1942 1943\i rtfCSSymbol\f1\i0\b0 1944. Returns non-zero for success, zero otherwise. 1945\par 1946\fs20 \f3\i0\b0 1947{\sl-120\sa0\sb0\par} 1948\f1\i0\b0 1949\f3\i0\b0 1950\pard \ql \sl240 1951\tx1152 1952void 1953\par 1954RTFSetCharSetMap (file, csId) 1955\par 1956char\tab *file; 1957\par 1958int\tab csId; 1959\par 1960\fs24 \f1\i0\b0 1961\fs20 \f3\i0\b0 1962\fs24 \f1\i0\b0 1963{\sl-120\sa0\sb0\par} 1964\pard \qj \li360 \sl280 1965\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 1966Specify the name of the file to be read for the charset 1967map indicated by \f1\i0\b0 1968 1969\i csId\f1\i0\b0 1970 (which should be either \f1\i0\b0 1971 1972\i rtfCSGeneral\f1\i0\b0 1973 or \f1\i0\b0 1974 1975\i rtfCSSymbol\f1\i0\b0 1976) when auto-charset-file reading is done. 1977This can be used to override the default charset map 1978names. \f1\i0\b0 1979 1980\i RTFSetCharSetMap()\f1\i0\b0 1981 should be called after \f1\i0\b0 1982 1983\i RTFInit()\f1\i0\b0 1984 but before you begin reading any input. 1985\par 1986\fs20 \f3\i0\b0 1987{\sl-120\sa0\sb0\par} 1988\f1\i0\b0 1989\f3\i0\b0 1990\pard \ql \sl240 1991\tx1152 1992void 1993\par 1994RTFSetCharSet (csId) 1995\par 1996int\tab csId; 1997\par 1998\fs24 \f1\i0\b0 1999\fs20 \f3\i0\b0 2000\fs24 \f1\i0\b0 2001{\sl-120\sa0\sb0\par} 2002\pard \qj \li360 \sl280 2003\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2004Switches to the charset map given by \f1\i0\b0 2005 2006\i csId\f1\i0\b0 2007, which should be either \f1\i0\b0 2008 2009\i rtfCSGeneral\f1\i0\b0 2010 or \f1\i0\b0 2011 2012\i rtfCSSymbol\f1\i0\b0 2013. 2014\par 2015\fs20 \f3\i0\b0 2016{\sl-120\sa0\sb0\par} 2017\f1\i0\b0 2018\f3\i0\b0 2019\pard \ql \sl240 2020\tx1152 2021int 2022\par 2023RTFGetCharSet () 2024\par 2025\fs24 \f1\i0\b0 2026\fs20 \f3\i0\b0 2027\fs24 \f1\i0\b0 2028{\sl-120\sa0\sb0\par} 2029\pard \qj \li360 \sl280 2030\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2031Returns the id of the current charset map, either \f1\i0\b0 2032 2033\i rtfCSGeneral\f1\i0\b0 2034 or \f1\i0\b0 2035 2036\i rtfCSSymbol\f1\i0\b0 2037. 2038\par 2039\fs20 \f3\i0\b0 2040{\sl-120\sa0\sb0\par} 2041\f1\i0\b0 2042\f3\i0\b0 2043\pard \ql \sl240 2044\tx1152 2045int 2046\par 2047RTFMapChar (c) 2048\par 2049int\tab c; 2050\par 2051\fs24 \f1\i0\b0 2052\fs20 \f3\i0\b0 2053\fs24 \f1\i0\b0 2054{\sl-120\sa0\sb0\par} 2055\pard \qj \li360 \sl280 2056\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2057Maps in input character onto a standard character code. 2058\par 2059\fs20 \f3\i0\b0 2060{\sl-120\sa0\sb0\par} 2061\f1\i0\b0 2062\f3\i0\b0 2063\pard \ql \sl240 2064\tx1152 2065int 2066\par 2067RTFStdCharCode (name) 2068\par 2069char\tab *name; 2070\par 2071\fs24 \f1\i0\b0 2072\fs20 \f3\i0\b0 2073\fs24 \f1\i0\b0 2074{\sl-120\sa0\sb0\par} 2075\pard \qj \li360 \sl280 2076\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2077Given a standard character name, returns the standard 2078code corresponding to the name, or \'d01 if the name 2079is unknown. 2080\par 2081\fs20 \f3\i0\b0 2082{\sl-120\sa0\sb0\par} 2083\f1\i0\b0 2084\f3\i0\b0 2085\pard \ql \sl240 2086\tx1152 2087char * 2088\par 2089RTFStdCharName (code) 2090\par 2091int\tab code; 2092\par 2093\fs24 \f1\i0\b0 2094\fs20 \f3\i0\b0 2095\fs24 \f1\i0\b0 2096{\sl-120\sa0\sb0\par} 2097\pard \qj \li360 \sl280 2098\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2099Given a standard character code, returns a string pointing 2100to the standard character name, or \f3\i0\b0 2101NULL\f1\i0\b0 2102 if the code 2103is unknown. 2104\par 2105\fs20 \f3\i0\b0 2106{\sl-120\sa0\sb0\par} 2107\f1\i0\b0 2108\f3\i0\b0 2109\pard \ql \sl240 2110\tx1152 2111int 2112\par 2113RTFReadOutputMap (file, outMap, reinit) 2114\par 2115char\tab *file; 2116\par 2117char\tab *outMap[]; 2118\par 2119int\tab reinit; 2120\par 2121\fs24 \f1\i0\b0 2122\fs20 \f3\i0\b0 2123\fs24 \f1\i0\b0 2124{\sl-120\sa0\sb0\par} 2125\pard \qj \li360 \sl280 2126\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2127Reads an output map from the named file into \f1\i0\b0 2128 2129\i outMap\f1\i0\b0 2130. If \f1\i0\b0 2131 2132\i reinit\f1\i0\b0 2133 is non-zero, the map is cleared first. See the 2134document \f1\i0\b0 2135 2136\i RTF Tools Character Mapping\f1\i0\b0 2137 for further details. 2138\par 2139{\sl-140\sa0\sb0\par} 2140Generally, the output map needs to be read only once. 2141\par 2142\fs20 \f3\i0\b0 2143{\sl-120\sa0\sb0\par} 2144\f1\i0\b0 2145\f3\i0\b0 2146\pard \ql \sl240 2147\tx1152 2148void 2149\par 2150RTFSetInputName (name) 2151\par 2152char\tab *name; 2153\par 2154\fs24 \f1\i0\b0 2155\fs20 \f3\i0\b0 2156\fs24 \f1\i0\b0 2157{\sl-120\sa0\sb0\par} 2158\fs20 \f3\i0\b0 2159{\sl-120\sa0\sb0\par} 2160\f1\i0\b0 2161\f3\i0\b0 2162void 2163\par 2164RTFSetOutputName (name) 2165\par 2166char\tab *name; 2167\par 2168\fs24 \f1\i0\b0 2169\fs20 \f3\i0\b0 2170\fs24 \f1\i0\b0 2171{\sl-120\sa0\sb0\par} 2172\pard \qj \li360 \sl280 2173\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2174These functions tell the RTF library the input or output 2175file names. They\'d5re called by driver code so that 2176writer code can determine the names by calling \f1\i0\b0 2177 2178\i RTFGetInputName()\f1\i0\b0 2179 and \f1\i0\b0 2180 2181\i RTFGetOutputName()\f1\i0\b0 2182. Since \f1\i0\b0 2183 2184\i RTFInit()\f1\i0\b0 2185 sets the names to \f3\i0\b0 2186NULL\f1\i0\b0 2187, the driver should 2188set the names after calling \f1\i0\b0 2189 2190\i RTFInit()\f1\i0\b0 2191 but before calling the writer to tell it 2192to set up for a new file. 2193\par 2194\fs20 \f3\i0\b0 2195{\sl-120\sa0\sb0\par} 2196\f1\i0\b0 2197\f3\i0\b0 2198\pard \ql \sl240 2199\tx1152 2200char * 2201\par 2202RTFGetInputName () 2203\par 2204\fs24 \f1\i0\b0 2205\fs20 \f3\i0\b0 2206\fs24 \f1\i0\b0 2207{\sl-120\sa0\sb0\par} 2208\fs20 \f3\i0\b0 2209{\sl-120\sa0\sb0\par} 2210\f1\i0\b0 2211\f3\i0\b0 2212char * 2213\par 2214RTFGetOutputName () 2215\par 2216\fs24 \f1\i0\b0 2217\fs20 \f3\i0\b0 2218\fs24 \f1\i0\b0 2219{\sl-120\sa0\sb0\par} 2220\pard \qj \li360 \sl280 2221\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2222These functions return pointers to the current input 2223and output file names, assuming the driver has set 2224them up. The caller should make a copy of the strings 2225returned if it wants to modify them. 2226\par 2227\fs20 \f3\i0\b0 2228{\sl-120\sa0\sb0\par} 2229\f1\i0\b0 2230\f3\i0\b0 2231\pard \ql \sl240 2232\tx1152 2233void 2234\par 2235RTFMsg (args ...) 2236\par 2237\fs24 \f1\i0\b0 2238\fs20 \f3\i0\b0 2239\fs24 \f1\i0\b0 2240{\sl-120\sa0\sb0\par} 2241\pard \qj \li360 \sl280 2242\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2243This function generates a diagnostic message. It takes 2244\f1\i0\b0 2245\i printf()\f1\i0\b0 2246-like arguments. 2247\par 2248{\sl-140\sa0\sb0\par} 2249See the description of \f1\i0\b0 2250 2251\i RTFSetMsgProc()\f1\i0\b0 2252. 2253\par 2254\fs20 \f3\i0\b0 2255{\sl-120\sa0\sb0\par} 2256\f1\i0\b0 2257\f3\i0\b0 2258\pard \ql \sl240 2259\tx1152 2260void 2261\par 2262RTFPanic (args ...) 2263\par 2264\fs24 \f1\i0\b0 2265\fs20 \f3\i0\b0 2266\fs24 \f1\i0\b0 2267{\sl-120\sa0\sb0\par} 2268\pard \qj \li360 \sl280 2269\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2270This function generates an error message and terminates 2271the process. It takes \f1\i0\b0 2272 2273\i printf()\f1\i0\b0 2274-like arguments. 2275\par 2276{\sl-140\sa0\sb0\par} 2277See the description of \f1\i0\b0 2278 2279\i RTFSetPanicProc()\f1\i0\b0 2280. 2281\par 2282\fs20 \f3\i0\b0 2283{\sl-120\sa0\sb0\par} 2284\f1\i0\b0 2285\f3\i0\b0 2286\pard \ql \sl240 2287\tx1152 2288FILE * 2289\par 2290RTFOpenLibFile (name, mode) 2291\par 2292char\tab *name; 2293\par 2294char\tab *mode; 2295\par 2296\fs24 \f1\i0\b0 2297\fs20 \f3\i0\b0 2298\fs24 \f1\i0\b0 2299{\sl-120\sa0\sb0\par} 2300\pard \qj \li360 \sl280 2301\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2302This function opens a library file and returns a \f3\i0\b0 2303FILE\f1\i0\b0 2304 2305pointer to it, or \f3\i0\b0 2306NULL\f1\i0\b0 2307 if the file could not be opened. 2308\par 2309{\sl-140\sa0\sb0\par} 2310See the description of \f1\i0\b0 2311 2312\i RTFSetOpenLibFileProc()\f1\i0\b0 2313. 2314\par 2315\fs20 \f3\i0\b0 2316{\sl-120\sa0\sb0\par} 2317\f1\i0\b0 2318\f3\i0\b0 2319\pard \ql \sl240 2320\tx1152 2321void 2322\par 2323RTFSetMsgProc (proc) 2324\par 2325void\tab (*proc) (); 2326\par 2327\fs24 \f1\i0\b0 2328\fs20 \f3\i0\b0 2329\fs24 \f1\i0\b0 2330{\sl-120\sa0\sb0\par} 2331\pard \qj \li360 \sl280 2332\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2333This function installs a function for use by \f1\i0\b0 2334 2335\i RTFMsg()\f1\i0\b0 2336; see \f1\i0\b0 2337 2338\i RTF Tools Translator Architecture\f1\i0\b0 2339 for details. 2340\par 2341\fs20 \f3\i0\b0 2342{\sl-120\sa0\sb0\par} 2343\f1\i0\b0 2344\f3\i0\b0 2345\pard \ql \sl240 2346\tx1152 2347void 2348\par 2349RTFSetPanicProc (proc) 2350\par 2351void\tab (*proc) (); 2352\par 2353\fs24 \f1\i0\b0 2354\fs20 \f3\i0\b0 2355\fs24 \f1\i0\b0 2356{\sl-120\sa0\sb0\par} 2357\pard \qj \li360 \sl280 2358\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2359This function installs a function for use by \f1\i0\b0 2360 2361\i RTFPanic()\f1\i0\b0 2362; see \f1\i0\b0 2363 2364\i RTF Tools Translator Architecture\f1\i0\b0 2365 for details. 2366\par 2367\fs20 \f3\i0\b0 2368{\sl-120\sa0\sb0\par} 2369\f1\i0\b0 2370\f3\i0\b0 2371\pard \ql \sl240 2372\tx1152 2373void 2374\par 2375RTFSetOpenLibFileProc (proc) 2376\par 2377FILE\tab *(*proc) (); 2378\par 2379\fs24 \f1\i0\b0 2380\fs20 \f3\i0\b0 2381\fs24 \f1\i0\b0 2382{\sl-120\sa0\sb0\par} 2383\pard \qj \li360 \sl280 2384\tx320 \tx640 \tx960 \tx1280 \tx1600 \tx1920 \tx2240 \tx2560 \tx2880 \tx3200 \tx3520 \tx3840 \tx4160 \tx4480 \tx4800 \tx5120 \tx5440 \tx5760 \tx6080 \tx6400 2385This function installs a function that the library 2386will use to open library files. The driver must call 2387this when it starts up or \f1\i0\b0 2388 2389\i RTFOpenLibFile()\f1\i0\b0 2390 will always return \f3\i0\b0 2391NULL\f1\i0\b0 2392. The function 2393should take a library file basename and open mode, 2394open the file, and return the \f3\i0\b0 2395FILE\f1\i0\b0 2396 pointer, or \f3\i0\b0 2397NULL\f1\i0\b0 2398 2399if the file could not be found and opened. 2400\par 2401{\sl-280\sa0\sb0\par} 2402\fs20 \fs28 \f1\i0\b0 2403\b \pard \qj \sl320 2404\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 2405Distribution Availability\f1\i0\b0 2406 2407\par 2408{\sl-320\sa0\sb0\par} 2409\fs20 {\sl-120\sa0\sb0\par} 2410\pard \qj \sl240 2411\tx500 \tx1000 \tx1500 \tx2000 \tx2500 \tx3000 \tx3500 \tx4000 \tx4500 \tx5000 \tx5500 \tx6000 \tx6500 \tx7000 \tx7500 2412This software may be redistributed without restriction 2413and used for any purpose whatsoever. 2414\par 2415{\sl-120\sa0\sb0\par} 2416The RTF Tools distribution is available for anonymous 2417\f1\i0\b0 2418\i ftp\f1\i0\b0 2419 access on \f1\i0\b0 2420 2421\i ftp.primate.wisc.edu\f1\i0\b0 2422. Look in the \f1\i0\b0 2423 2424\i /pub/RTF\f1\i0\b0 2425 directory. Updates appear there as they become 2426available. 2427\par 2428{\sl-120\sa0\sb0\par} 2429A version of the RTF specification is available in 2430this directory, as a binhex\'d5ed Word for Macintosh 2431document and in RTF and PostScript formats. 2432\par 2433{\sl-120\sa0\sb0\par} 2434The software and documentation may also be accessed 2435using gopher by connecting to \f1\i0\b0 2436 2437\i gopher.primate.wisc.edu\f1\i0\b0 2438 or using World Wide Web by 2439connecting to \f1\i0\b0 2440 2441\i www.primate.wisc.edu\f1\i0\b0 2442 using the URL \f1\i0\b0 2443 2444\i http://www.primate.wisc.edu/\f1\i0\b0 2445. In both cases, look under 2446\'d2Primate Center Software Archives\'d3. 2447\par 2448{\sl-120\sa0\sb0\par} 2449If you do not have Internet access, send requests to 2450\f1\i0\b0 2451\i software@primate.wisc.edu\f1\i0\b0 2452. Bug reports and questions 2453should be sent to this address as well. 2454\par 2455{\sl-120\sa0\sb0\par} 2456If you use this software as the basis for a translater 2457not included in the current collection, please send 2458me a description that indicates how it may be obtained 2459and I\'d5ll add the description to the archive site. 2460\par 2461} 2462