Xct.c revision e120bd27
1/* 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25*/ 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30#include <X11/Xfuncs.h> 31#include "Xct.h" 32#include <stdio.h> 33 34#define UsedGraphic 0x0001 35#define UsedDirection 0x0002 36 37typedef struct _XctPriv { 38 XctString ptr; 39 XctString ptrend; 40 unsigned flags; 41 XctHDirection *dirstack; 42 unsigned dirsize; 43 char **encodings; 44 unsigned enc_count; 45 XctString itembuf; 46 unsigned buf_count; 47} *XctPriv; 48 49#define IsMore(priv) ((priv)->ptr != (priv)->ptrend) 50#define AmountLeft(priv) ((priv)->ptrend - (priv)->ptr) 51 52#include <stdlib.h> 53 54#define HT 0x09 55#define NL 0x0a 56#define ESC 0x1b 57#define CSI 0x9b 58 59#define IsLegalC0(data, c) (((c) == HT) || ((c) == NL) || \ 60 (((data)->version > XctVersion) && \ 61 ((data)->flags & XctAcceptC0Extensions))) 62 63#define IsLegalC1(priv, c) (((data)->version > XctVersion) && \ 64 ((data)->flags & XctAcceptC1Extensions)) 65 66#define IsI2(c) (((c) >= 0x20) && ((c) <= 0x2f)) 67#define IsI3(c) (((c) >= 0x30) && ((c) <= 0x3f)) 68#define IsESCF(c) (((c) >= 0x30) && ((c) <= 0x7e)) 69#define IsCSIF(c) (((c) >= 0x40) && ((c) <= 0x7e)) 70#define IsC0(c) ((c) <= 0x1f) 71#define IsGL(c) (((c) >= 0x20) && ((c) <= 0x7f)) 72#define IsC1(c) (((c) >= 0x80) && ((c) <= 0x9f)) 73#define IsGR(c) ((c) >= 0xa0) 74 75#define HasC 1 76#define HasGL 2 77#define HasGR 4 78#define ToGL 8 79 80/* 81 * Prototypes 82 */ 83static void ComputeGLGR(XctData); 84static int Handle94GR(XctData, int); 85static int Handle96GR(XctData, int); 86static int HandleExtended(XctData data, int); 87static int HandleGL(XctData, int); 88static int HandleMultiGL(XctData, int); 89static int HandleMultiGR(XctData data, int); 90static void ShiftGRToGL(XctData, int); 91 92/* 93 * Implementation 94 */ 95static void 96ComputeGLGR(register XctData data) 97{ 98 /* XXX this will need more work if more sets are registered */ 99 if ((data->GL_set_size == 94) && (data->GL_char_size == 1) && 100 (data->GL[0] == '\102') && 101 (data->GR_set_size == 96) && (data->GR_char_size == 1)) 102 data->GLGR_encoding = data->GR_encoding; 103 else if ((data->GL_set_size == 94) && (data->GL_char_size == 1) && 104 (data->GL[0] == '\112') && 105 (data->GR_set_size == 94) && (data->GR_char_size == 1)) 106 data->GLGR_encoding = data->GR_encoding; 107 else 108 data->GLGR_encoding = (char *)NULL; 109} 110 111static int 112HandleGL(register XctData data, int c) 113{ 114 switch (c) { 115 case 0x42: 116 data->GL = "\102"; 117 data->GL_encoding = "ISO8859-1"; 118 break; 119 case 0x4a: 120 data->GL = "\112"; 121 data->GL_encoding = "JISX0201.1976-0"; 122 break; 123 default: 124 return 0; 125 } 126 data->GL_set_size = 94; 127 data->GL_char_size = 1; 128 ComputeGLGR(data); 129 return 1; 130} 131 132static int 133HandleMultiGL(register XctData data, int c) 134{ 135 switch (c) { 136 case 0x41: 137 data->GL = "\101"; 138 data->GL_encoding = "GB2312.1980-0"; 139 break; 140 case 0x42: 141 data->GL = "\102"; 142 data->GL_encoding = "JISX0208.1983-0"; 143 break; 144 case 0x43: 145 data->GL = "\103"; 146 data->GL_encoding = "KSC5601.1987-0"; 147 break; 148 default: 149 return 0; 150 } 151 data->GL_set_size = 94; 152 data->GL_char_size = 2; 153#ifdef notdef 154 if (c < 0x60) 155 data->GL_char_size = 2; 156 else if (c < 0x70) 157 data->GL_char_size = 3; 158 else 159 data->GL_char_size = 4; 160#endif 161 data->GLGR_encoding = (char *)NULL; 162 return 1; 163} 164 165static int 166Handle94GR(register XctData data, int c) 167{ 168 switch (c) { 169 case 0x49: 170 data->GR = "\111"; 171 data->GR_encoding = "JISX0201.1976-0"; 172 break; 173 default: 174 return 0; 175 } 176 data->priv->flags &= ~ToGL; 177 data->GR_set_size = 94; 178 data->GR_char_size = 1; 179 data->GLGR_encoding = (char *)NULL; 180 return 1; 181} 182 183static int 184Handle96GR(register XctData data, int c) 185{ 186 switch (c) { 187 case 0x41: 188 data->GR = "\101"; 189 data->GR_encoding = "ISO8859-1"; 190 break; 191 case 0x42: 192 data->GR = "\102"; 193 data->GR_encoding = "ISO8859-2"; 194 break; 195 case 0x43: 196 data->GR = "\103"; 197 data->GR_encoding = "ISO8859-3"; 198 break; 199 case 0x44: 200 data->GR = "\104"; 201 data->GR_encoding = "ISO8859-4"; 202 break; 203 case 0x46: 204 data->GR = "\106"; 205 data->GR_encoding = "ISO8859-7"; 206 break; 207 case 0x47: 208 data->GR = "\107"; 209 data->GR_encoding = "ISO8859-6"; 210 break; 211 case 0x48: 212 data->GR = "\110"; 213 data->GR_encoding = "ISO8859-8"; 214 break; 215 case 0x4c: 216 data->GR = "\114"; 217 data->GR_encoding = "ISO8859-5"; 218 break; 219 case 0x4d: 220 data->GR = "\115"; 221 data->GR_encoding = "ISO8859-9"; 222 break; 223 default: 224 return 0; 225 } 226 data->priv->flags &= ~ToGL; 227 data->GR_set_size = 96; 228 data->GR_char_size = 1; 229 ComputeGLGR(data); 230 return 1; 231} 232 233static int 234HandleMultiGR(register XctData data, int c) 235{ 236 switch (c) { 237 case 0x41: 238 data->GR = "\101"; 239 if (data->flags & XctShiftMultiGRToGL) 240 data->GR_encoding = "GB2312.1980-0"; 241 else 242 data->GR_encoding = "GB2312.1980-1"; 243 break; 244 case 0x42: 245 data->GR = "\102"; 246 if (data->flags & XctShiftMultiGRToGL) 247 data->GR_encoding = "JISX0208.1983-0"; 248 else 249 data->GR_encoding = "JISX0208.1983-1"; 250 break; 251 case 0x43: 252 data->GR = "\103"; 253 if (data->flags & XctShiftMultiGRToGL) 254 data->GR_encoding = "KSC5601.1987-0"; 255 else 256 data->GR_encoding = "KSC5601.1987-1"; 257 break; 258 default: 259 return 0; 260 } 261 if (data->flags & XctShiftMultiGRToGL) 262 data->priv->flags |= ToGL; 263 else 264 data->priv->flags &= ~ToGL; 265 data->GR_set_size = 94; 266 data->GR_char_size = 2; 267#ifdef notdef 268 if (c < 0x60) 269 data->GR_char_size = 2; 270 else if (c < 0x70) 271 data->GR_char_size = 3; 272 else 273 data->GR_char_size = 4; 274#endif 275 data->GLGR_encoding = (char *)NULL; 276 return 1; 277} 278 279static int 280HandleExtended(register XctData data, int c) 281{ 282 register XctPriv priv = data->priv; 283 XctString enc = data->item + 6; 284 register XctString ptr = enc; 285 unsigned i, len; 286 287 while (*ptr != 0x02) { 288 if (!*ptr || (++ptr == priv->ptr)) 289 return 0; 290 } 291 data->item = ptr + 1; 292 data->item_length = priv->ptr - data->item; 293 len = ptr - enc; 294 for (i = 0; 295 (i < priv->enc_count) && 296 strncmp(priv->encodings[i], (char *)enc, len); 297 i++) 298 ; 299 if (i == priv->enc_count) { 300 XctString cp; 301 302 for (cp = enc; cp != ptr; cp++) { 303 if ((!IsGL(*cp) && !IsGR(*cp)) || (*cp == 0x2a) || (*cp == 0x3f)) 304 return 0; 305 } 306 ptr = (XctString)malloc((unsigned)len + 1); 307 (void) memmove((char *)ptr, (char *)enc, len); 308 ptr[len] = 0x00; 309 priv->enc_count++; 310 if (priv->encodings) 311 priv->encodings = (char **)realloc( 312 (char *)priv->encodings, 313 priv->enc_count * sizeof(char *)); 314 else 315 priv->encodings = (char **)malloc(sizeof(char *)); 316 priv->encodings[i] = (char *)ptr; 317 } 318 data->encoding = priv->encodings[i]; 319 data->char_size = c - 0x30; 320 return 1; 321} 322 323static void 324ShiftGRToGL(register XctData data, int hasCdata) 325{ 326 register XctPriv priv = data->priv; 327 register int i; 328 329 if (data->item_length > priv->buf_count) { 330 priv->buf_count = data->item_length; 331 if (priv->itembuf) 332 priv->itembuf = (XctString)realloc((char *)priv->itembuf, 333 priv->buf_count); 334 else 335 priv->itembuf = (XctString)malloc(priv->buf_count); 336 } 337 (void) memmove((char *)priv->itembuf, (char *)data->item, 338 data->item_length); 339 data->item = priv->itembuf; 340 if (hasCdata) { 341 for (i = data->item_length; --i >= 0; ) { 342 if (IsGR(data->item[i])) 343 data->item[i] &= 0x7f; 344 } 345 } else { 346 for (i = data->item_length; --i >= 0; ) 347 data->item[i] &= 0x7f; 348 } 349} 350 351/* Create an XctData structure for parsing a Compound Text string. */ 352XctData 353XctCreate(_Xconst unsigned char *string, int length, XctFlags flags) 354{ 355 register XctData data; 356 register XctPriv priv; 357 358 data = (XctData)malloc(sizeof(struct _XctRec) + sizeof(struct _XctPriv)); 359 if (!data) 360 return data; 361 data->priv = priv = (XctPriv)(data + 1); 362 data->total_string = (XctString)string; 363 data->total_length = length; 364 data->flags = flags; 365 priv->dirstack = (XctHDirection *)NULL; 366 priv->dirsize = 0; 367 priv->encodings = (char **)NULL; 368 priv->enc_count = 0; 369 priv->itembuf = (XctString)NULL; 370 priv->buf_count = 0; 371 XctReset(data); 372 return data; 373} 374 375/* Reset the XctData structure to re-parse the string from the beginning. */ 376void 377XctReset(register XctData data) 378{ 379 register XctPriv priv = data->priv; 380 381 priv->ptr = data->total_string; 382 priv->ptrend = data->total_string + data->total_length; 383 data->item = (XctString)NULL; 384 data->item_length = 0; 385 data->encoding = (char *)NULL; 386 data->char_size = 1; 387 data->horizontal = XctUnspecified; 388 data->horz_depth = 0; 389 priv->flags = 0; 390 data->GL_set_size = data->GR_set_size = 0; /* XXX */ 391 (void)HandleGL(data, (unsigned char)0x42); 392 (void)Handle96GR(data, (unsigned char)0x41); 393 data->version = 1; 394 data->can_ignore_exts = 0; 395 /* parse version, if present */ 396 if ((data->total_length >= 4) && 397 (priv->ptr[0] == ESC) && (priv->ptr[1] == 0x23) && 398 IsI2(priv->ptr[2]) && 399 ((priv->ptr[3] == 0x30) || (priv->ptr[3] == 0x31))) { 400 data->version = priv->ptr[2] - 0x1f; 401 if (priv->ptr[3] == 0x30) 402 data->can_ignore_exts = 1; 403 priv->ptr += 4; 404 } 405} 406 407/* Parse the next "item" from the Compound Text string. The return value 408 * indicates what kind of item is returned. The item itself, and the current 409 * contextual state, are reported as components of the XctData structure. 410 */ 411XctResult 412XctNextItem(register XctData data) 413{ 414 register XctPriv priv = data->priv; 415 unsigned char c; 416 int len, bits; 417 418#define NEXT data->item_length++; priv->ptr++ 419 420 while (IsMore(priv)) { 421 data->item = priv->ptr; 422 data->item_length = 0; 423 c = *priv->ptr; 424 if (c == ESC) { 425 NEXT; 426 while (IsMore(priv) && IsI2(*priv->ptr)) { 427 NEXT; 428 } 429 if (!IsMore(priv)) 430 return XctError; 431 c = *priv->ptr; 432 NEXT; 433 if (!IsESCF(c)) 434 return XctError; 435 switch (data->item[1]) { 436 case 0x24: 437 if (data->item_length > 3) { 438 if (data->item[2] == 0x28) { 439 if (HandleMultiGL(data, c)) 440 continue; 441 } else if (data->item[2] == 0x29) { 442 if (HandleMultiGR(data, c)) 443 continue; 444 } 445 } 446 break; 447 case 0x25: 448 if ((data->item_length == 4) && (data->item[2] == 0x2f) && 449 (c <= 0x3f)) { 450 if ((AmountLeft(priv) < 2) || 451 (priv->ptr[0] < 0x80) || (priv->ptr[1] < 0x80)) 452 return XctError; 453 len = *priv->ptr - 0x80; 454 NEXT; 455 len = (len << 7) + (*priv->ptr - 0x80); 456 NEXT; 457 if (AmountLeft(priv) < len) 458 return XctError; 459 data->item_length += len; 460 priv->ptr += len; 461 if (c <= 0x34) { 462 if (!HandleExtended(data, c) || 463 ((data->horz_depth == 0) && 464 (priv->flags & UsedDirection))) 465 return XctError; 466 priv->flags |= UsedGraphic; 467 return XctExtendedSegment; 468 } 469 } 470 break; 471 case 0x28: 472 if (HandleGL(data, c)) 473 continue; 474 break; 475 case 0x29: 476 if (Handle94GR(data, c)) 477 continue; 478 break; 479 case 0x2d: 480 if (Handle96GR(data, c)) 481 continue; 482 break; 483 } 484 } else if (c == CSI) { 485 NEXT; 486 while (IsMore(priv) && IsI3(*priv->ptr)) { 487 NEXT; 488 } 489 while (IsMore(priv) && IsI2(*priv->ptr)) { 490 NEXT; 491 } 492 if (!IsMore(priv)) 493 return XctError; 494 c = *priv->ptr; 495 NEXT; 496 if (!IsCSIF(c)) 497 return XctError; 498 if (c == 0x5d) { 499 if ((data->item_length == 3) && 500 ((data->item[1] == 0x31) || (data->item[1] == 0x32))) { 501 data->horz_depth++; 502 if (priv->dirsize < data->horz_depth) { 503 priv->dirsize += 10; 504 if (priv->dirstack) 505 priv->dirstack = (XctHDirection *) 506 realloc((char *)priv->dirstack, 507 priv->dirsize * 508 sizeof(XctHDirection)); 509 else 510 priv->dirstack = (XctHDirection *) 511 malloc(priv->dirsize * 512 sizeof(XctHDirection)); 513 } 514 priv->dirstack[data->horz_depth - 1] = data->horizontal; 515 if (data->item[1] == 0x31) 516 data->horizontal = XctLeftToRight; 517 else 518 data->horizontal = XctRightToLeft; 519 if ((priv->flags & UsedGraphic) && 520 !(priv->flags & UsedDirection)) 521 return XctError; 522 priv->flags |= UsedDirection; 523 if (data->flags & XctHideDirection) 524 continue; 525 return XctHorizontal; 526 } else if (data->item_length == 2) { 527 if (!data->horz_depth) 528 return XctError; 529 data->horz_depth--; 530 data->horizontal = priv->dirstack[data->horz_depth]; 531 if (data->flags & XctHideDirection) 532 continue; 533 return XctHorizontal; 534 } 535 } 536 } else if (data->flags & XctSingleSetSegments) { 537 NEXT; 538 if IsC0(c) { 539 data->encoding = (char *)NULL; 540 data->char_size = 1; 541 if (IsLegalC0(data, c)) 542 return XctC0Segment; 543 } else if (IsGL(c)) { 544 data->encoding = data->GL_encoding; 545 data->char_size = data->GL_char_size; 546 while (IsMore(priv) && IsGL(*priv->ptr)) { 547 NEXT; 548 } 549 if (((data->char_size > 1) && 550 (data->item_length % data->char_size)) || 551 ((data->horz_depth == 0) && 552 (priv->flags & UsedDirection))) 553 return XctError; 554 priv->flags |= UsedGraphic; 555 return XctGLSegment; 556 } else if (IsC1(c)) { 557 data->encoding = (char *)NULL; 558 data->char_size = 1; 559 if (IsLegalC1(data, c)) 560 return XctC1Segment; 561 } else { 562 data->encoding = data->GR_encoding; 563 data->char_size = data->GR_char_size; 564 while (IsMore(priv) && IsGR(*priv->ptr)) { 565 NEXT; 566 } 567 if (((data->char_size > 1) && 568 (data->item_length % data->char_size)) || 569 ((data->horz_depth == 0) && 570 (priv->flags & UsedDirection))) 571 return XctError; 572 priv->flags |= UsedGraphic; 573 if (!(priv->flags & ToGL)) 574 return XctGRSegment; 575 ShiftGRToGL(data, 0); 576 return XctGLSegment; 577 } 578 } else { 579 bits = 0; 580 while (1) { 581 if (IsC0(c) || IsC1(c)) { 582 if ((c == ESC) || (c == CSI)) 583 break; 584 if (IsC0(c) ? !IsLegalC0(data, c) : !IsLegalC1(data, c)) 585 break; 586 bits |= HasC; 587 NEXT; 588 } else { 589 len = data->item_length; 590 if (IsGL(c)) { 591 if ((data->flags & XctShiftMultiGRToGL) && 592 (bits & HasGR)) 593 break; 594 NEXT; 595 bits |= HasGL; 596 while (IsMore(priv) && IsGL(*priv->ptr)) { 597 NEXT; 598 } 599 if ((data->GL_char_size > 1) && 600 ((data->item_length - len) % data->GL_char_size)) 601 return XctError; 602 } else { 603 if ((data->flags & XctShiftMultiGRToGL) && 604 (bits & HasGL)) 605 break; 606 NEXT; 607 bits |= HasGR; 608 while (IsMore(priv) && IsGR(*priv->ptr)) { 609 NEXT; 610 } 611 if ((data->GR_char_size > 1) && 612 ((data->item_length - len) % data->GR_char_size)) 613 return XctError; 614 } 615 } 616 if (!IsMore(priv)) 617 break; 618 c = *priv->ptr; 619 } 620 if (data->item_length) { 621 if (bits & (HasGL|HasGR)) { 622 priv->flags |= UsedGraphic; 623 if ((data->horz_depth == 0) && 624 (priv->flags & UsedDirection)) 625 return XctError; 626 if ((data->flags & XctShiftMultiGRToGL) && (bits & HasGR)) 627 ShiftGRToGL(data, bits & HasC); 628 } 629 if ((bits == (HasGL|HasGR)) || 630 (data->GLGR_encoding && !(bits & HasC))) { 631 data->encoding = data->GLGR_encoding; 632 if (data->GL_char_size == data->GR_char_size) 633 data->char_size = data->GL_char_size; 634 else 635 data->char_size = 0; 636 } else if (bits == HasGL) { 637 data->encoding = data->GL_encoding; 638 data->char_size = data->GL_char_size; 639 } else if (bits == HasGR) { 640 data->encoding = data->GR_encoding; 641 data->char_size = data->GR_char_size; 642 } else { 643 data->encoding = (char *)NULL; 644 data->char_size = 1; 645 if ((bits & HasGL) && 646 (data->GL_char_size != data->char_size)) 647 data->char_size = 0; 648 if ((bits & HasGR) && 649 (data->GR_char_size != data->char_size)) 650 data->char_size = 0; 651 } 652 return XctSegment; 653 } 654 NEXT; 655 } 656 if (data->version <= XctVersion) 657 return XctError; 658 if (data->flags & XctProvideExtensions) 659 return XctExtension; 660 if (!data->can_ignore_exts) 661 return XctError; 662 } 663 return XctEndOfText; 664} 665 666/* Free all data associated with an XctDataStructure. */ 667void 668XctFree(register XctData data) 669{ 670 unsigned i; 671 register XctPriv priv = data->priv; 672 673 if (priv->dirstack) 674 free((char *)priv->dirstack); 675 if (data->flags & XctFreeString) 676 free((char *)data->total_string); 677 for (i = 0; i < priv->enc_count; i++) 678 free(priv->encodings[i]); 679 if (priv->encodings) 680 free((char *)priv->encodings); 681 if (priv->itembuf) 682 free((char *)priv->itembuf); 683 free((char *)data); 684} 685