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