1/* Copyright 1994 NEC Corporation, Tokyo, Japan. 2 * 3 * Permission to use, copy, modify, distribute and sell this software 4 * and its documentation for any purpose is hereby granted without 5 * fee, provided that the above copyright notice appear in all copies 6 * and that both that copyright notice and this permission notice 7 * appear in supporting documentation, and that the name of NEC 8 * Corporation not be used in advertising or publicity pertaining to 9 * distribution of the software without specific, written prior 10 * permission. NEC Corporation makes no representations about the 11 * suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 16 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 18 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 19 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23/************************************************************************/ 24/* THIS SOURCE CODE IS MODIFIED FOR TKO BY T.MURAI 1997 25/************************************************************************/ 26 27 28#if !defined(lint) && !defined(__CODECENTER__) 29static char rcsid[] = "$Id: bun.c 14875 2005-11-12 21:25:31Z bonefish $"; 30#endif 31 32/* LINTLIBRARY */ 33 34#include <string.h> 35#include "RKintern.h" 36 37 38#define NEED_DEF 39#ifdef RkSetErrno 40#undef RkSetErrno 41#define RkSetErrno(no) 42#endif 43 44const unsigned OVERRUN_MARGIN = 0; 45 46#define STRCMP(d, s) strcmp((char *)(d), (char *)(s)) 47 48inline void 49usncopy(WCHAR_T *dst, WCHAR_T *src, int len) 50{ 51 memcpy(dst, src, len * sizeof(WCHAR_T)); 52} 53 54static void 55freeBunStorage(struct nstore *s) 56{ 57 if (s) { 58 if (s->yomi) 59 free((s->yomi-OVERRUN_MARGIN)); 60 if (s->bunq) 61 free((s->bunq-OVERRUN_MARGIN)); 62 if (s->xq) 63 free((s->xq-OVERRUN_MARGIN)); 64 if (s->xqh) 65 free((s->xqh-OVERRUN_MARGIN)); 66 free(s); 67 } 68} 69 70static struct nstore * 71allocBunStorage(unsigned len) 72{ 73 struct nstore *s; 74 75 s = (struct nstore *)malloc((unsigned)sizeof(struct nstore)); 76 if (s) { 77 WCHAR_T *p, *q, pat; 78 int i; 79 80 s->yomi = (WCHAR_T *)0; 81 s->bunq = (struct nbun *)0; 82 s->xq = (struct nqueue *)0; 83 s->xqh = (struct nword **)0; 84 s->nyomi = (unsigned)0; 85 s->maxyomi = (unsigned)len; 86 87 s->yomi = (WCHAR_T *)calloc((s->maxyomi+1+2*OVERRUN_MARGIN), sizeof(WCHAR_T)); 88 s->maxbunq = (unsigned)len; 89 s->maxbun = (unsigned)0; 90 s->curbun = 0; 91 s->bunq = (struct nbun *)calloc((unsigned)(s->maxbunq+1+2*OVERRUN_MARGIN), 92 sizeof(struct nbun)); 93 s->maxxq = len; 94 s->xq = (struct nqueue *)calloc((unsigned)(s->maxxq+1+2*OVERRUN_MARGIN), 95 sizeof(struct nqueue)); 96 s->xqh = (struct nword **)calloc((unsigned)(s->maxxq+1+2*OVERRUN_MARGIN), 97 sizeof(struct nword *)); 98 if (!s->yomi || !s->bunq || !s->xq || !s->xqh) { 99 RkSetErrno(RK_ERRNO_ENOMEM); 100 freeBunStorage(s); 101 return (struct nstore *)0; 102 } 103 s->yomi += OVERRUN_MARGIN; 104 s->bunq += OVERRUN_MARGIN; 105 s->xq += OVERRUN_MARGIN; 106 s->xqh += OVERRUN_MARGIN; 107 p = (WCHAR_T*)&s->yomi[0]; 108 q = (WCHAR_T*)&s->yomi[s->maxyomi+1]; 109 for (i = 0; pat = (WCHAR_T)~i, i < OVERRUN_MARGIN; i++) 110 p[-i-1] = q[i] = pat; 111 p = (WCHAR_T*)&s->bunq[0]; 112 q = (WCHAR_T*)&s->bunq[s->maxbunq+1]; 113 for (i = 0; pat = (WCHAR_T)~i, i < OVERRUN_MARGIN; i++) 114 p[-i-1] = q[i] = pat; 115 p = (WCHAR_T*)&s->xq[0]; 116 q = (WCHAR_T*)&s->xq[s->maxxq+1]; 117 for (i = 0; pat = (WCHAR_T)~i, i < OVERRUN_MARGIN; i++) 118 p[-i-1] = q[i] = pat; 119 p = (WCHAR_T*)&s->xqh[0]; 120 q = (WCHAR_T*)&s->xqh[s->maxxq+1]; 121 for (i = 0; pat = (WCHAR_T)~i, i < OVERRUN_MARGIN; i++) 122 p[-i-1] = q[i] = pat; 123 s->word_in_use = 0; 124 }; 125 if (!s) /* EMPTY */RkSetErrno(RK_ERRNO_ENOMEM); 126 return s; 127} 128 129struct nstore * 130_RkReallocBunStorage(struct nstore *src, unsigned len) 131{ 132 struct nstore *dst = allocBunStorage(len); 133 134 if (dst) { 135 int i; 136 137 if (src->yomi) { 138 for (i = 0; i <= (int)src->maxyomi; i++) 139 dst->yomi[i] = src->yomi[i]; 140 free((src->yomi-OVERRUN_MARGIN)); 141 }; 142 dst->nyomi = src->nyomi; 143 if (src->bunq) { 144 for (i = 0; i <= (int)src->maxbun; i++) 145 dst->bunq[i] = src->bunq[i]; 146 free((src->bunq-OVERRUN_MARGIN)); 147 }; 148 dst->maxbun = src->maxbun; 149 dst->curbun = src->curbun; 150 if (src->xq) { 151 for (i = 0; i <= src->maxxq; i++) 152 dst->xq[i] = src->xq[i]; 153 free((src->xq-OVERRUN_MARGIN)); 154 }; 155 if (src->xqh) { 156 for (i = 0; i <= src->maxxq; i++) 157 dst->xqh[i] = src->xqh[i]; 158 free((src->xqh-OVERRUN_MARGIN)); 159 }; 160 dst->word_in_use = src->word_in_use; 161 free(src); 162 return(dst); 163 } 164 return((struct nstore *)0); 165} 166 167inline struct nbun * 168getCurrentBun(struct nstore *store) 169{ 170 if (store && 0 <= store->curbun && store->curbun < (int)store->maxbun) 171 return &store->bunq[store->curbun]; 172 return (struct nbun *)0; 173} 174 175/* RkBgnBun 176 * renbunsetu henkan wo kaishi surutameno shokisettei wo okonau 177 * reuturns: 178 * # >=0 shoki bunsetsu no kosuu 179 * -1 shoki ka sippai 180 * RK_ERRNO_ECTXNO 181 * RK_ERRNO_EINVAL 182 * RK_ERRNO_ENOMEM 183 */ 184int 185RkwBgnBun(int cx_num, WCHAR_T *yomi, int n, int kouhomode) 186{ 187 struct RkContext *cx; 188 unsigned long mask1, mask2; 189 int asset = 0; 190 191 if (!(cx = RkGetContext(cx_num))) { 192 RkSetErrno(RK_ERRNO_ECTXNO); 193 return(-1); 194 } 195 if (IS_XFERCTX(cx)) { 196 RkSetErrno(0); 197 return(-1); 198 } 199 for (mask1 = (unsigned long) kouhomode, mask2 = 0L; 200 mask1; mask1 >>= RK_XFERBITS) { 201 if ((mask1 & (unsigned long)RK_XFERMASK) == (unsigned long)RK_CTRLHENKAN) { 202 mask1 >>= RK_XFERBITS; 203 asset = 1; 204 break; 205 } 206 mask2 = (mask2 << RK_XFERBITS) | ((unsigned long)RK_XFERMASK); 207 } 208 if (!(cx->store = allocBunStorage((unsigned)n))) { 209 RkSetErrno(RK_ERRNO_ENOMEM); 210 return(-1); 211 } 212 cx->flags |= (unsigned)CTX_XFER; 213 cx->concmode = (RK_CONNECT_WORD 214 | (asset ? ((int)mask1 & ~RK_TANBUN) : 215 (RK_MAKE_KANSUUJI | RK_MAKE_WORD | RK_MAKE_EISUUJI))); 216 cx->kouhomode = ((unsigned long)kouhomode) & mask2; 217 if (yomi) { 218 int i; 219 220 if (n <= 0) { 221 RkSetErrno(RK_ERRNO_EINVAL); 222 RkwEndBun(cx_num, 0); 223 return(-1); 224 }; 225 for (i = 0; i < n; i++) 226 cx->store->yomi[i] = yomi[i]; 227 cx->store->yomi[n] = 0; 228 cx->store->nyomi = n; 229 cx->store->bunq[0].nb_yoff = 0; 230 i = _RkRenbun2(cx, mask1 & RK_TANBUN ? n : 0); 231 return(i); 232 } else { 233 cx->concmode |= RK_MAKE_WORD; 234 cx->flags |= (unsigned) CTX_XAUT; 235 if (n < 0) { 236 RkSetErrno(RK_ERRNO_EINVAL); 237 RkwEndBun(cx_num, 0); 238 return(-1); 239 }; 240 return(0); 241 } 242} 243 244/* RkEndBun 245 * bunsetsu henkan wo shuuryou suru 246 * hituyou ni oujite, henkan kekka wo motoni gakushuu wo okonau 247 * 248 * return 0 249 * -1(RK_ERRNO_ECTX) 250 */ 251int 252RkwEndBun(int cx_num, int mode) 253{ 254struct RkContext *cx; 255struct nstore *store; 256int i; 257const int DO_LEARN = 1; 258 259 if (!(cx = RkGetXContext(cx_num)) || 260 !(store = cx->store)) { 261 RkSetErrno(RK_ERRNO_ECTXNO); 262 return(-1); 263 } 264 if (mode) { 265 if (mode != DO_LEARN) { 266 RkSetErrno(RK_ERRNO_EINVAL); 267 return -1; 268 }; 269 } 270 for (i = 0; i < (int)store->maxbun; i++) 271 (void)_RkLearnBun(cx, i, mode); 272 if (cx->flags & CTX_XAUT) 273 _RkFreeQue(store, 0, store->maxxq + 1); 274 cx->concmode &= ~(RK_CONNECT_WORD | RK_MAKE_WORD | 275 RK_MAKE_KANSUUJI | RK_MAKE_EISUUJI); 276 _RkEndBun(cx); 277 freeBunStorage(store); 278 return(0); 279} 280 281/* RkRemoveBun 282 * current bunsetu made wo sakujo suru 283 * current bunsetu ha 0 ni naru. 284 */ 285 286int 287RkwRemoveBun(int cx_num, int mode) 288{ 289 struct RkContext *cx; 290 struct nstore *store; 291 int i, c; 292 293 if (!(cx = RkGetXContext(cx_num)) 294 || !(store = cx->store) 295 || !IS_XFERCTX(cx) 296 || store->maxbun <= 0) { 297 RkSetErrno(RK_ERRNO_ECTXNO); 298 return -1; 299 } 300 for (i = 0; i <= store->curbun; i++) 301 _RkLearnBun(cx, i, mode); 302 c = store->bunq[store->curbun + 1].nb_yoff; 303 for (i = store->curbun + 1; i <= (int)store->maxbun; i++) { 304 store->bunq[i - store->curbun - 1] = store->bunq[i]; 305 store->bunq[i - store->curbun - 1].nb_yoff -= c; 306 } 307 store->nyomi -= c; 308 usncopy(store->yomi, store->yomi + c, (unsigned)store->nyomi); 309 store->maxbun -= store->curbun + 1; 310 store->curbun = 0; 311 return(store->maxbun); 312} 313 314/* RkSubstYomi 315 * change the contents of hiragana buffer 316 * returns: 317 * # bunsetu 318 */ 319 320int 321RkwSubstYomi(int cx_num, int ys, int ye, WCHAR_T *yomi, int newLen) 322{ 323 struct RkContext *cx; 324 struct nstore *store; 325 struct nbun *bun; 326 327 if (!(cx = RkGetContext(cx_num))) { 328 RkSetErrno(RK_ERRNO_ECTXNO); 329 return(-1); 330 } 331 if (!(store = cx->store) || 332 !(bun = &store->bunq[store->maxbun]) || 333 !IS_XFERCTX(cx) || 334 !IS_XAUTCTX(cx) || 335 !(0 <= ys && ys <= ye && ye <= (int)(store->nyomi - bun->nb_yoff)) || 336 (newLen < 0)) { 337 RkSetErrno(RK_ERRNO_EINVAL); 338 return -1; 339 } 340 return _RkSubstYomi(cx, ys, ye, yomi, newLen); 341} 342 343/* RkFlushYomi 344 * force to convert the remaining hiragana 345 * returns: 346 * # bunsetu 347 */ 348 349int 350RkwFlushYomi(int cx_num) 351{ 352 struct RkContext *cx; 353 if (!(cx = RkGetContext(cx_num)) || 354 !IS_XFERCTX(cx) || 355 !IS_XAUTCTX(cx)) { 356 RkSetErrno(RK_ERRNO_ECTXNO); 357 return(-1); 358 } 359 return(_RkFlushYomi(cx)); 360} 361 362/* RkResize/RkEnlarge/RkShorten 363 * current bunsetsu no ookisa wo henkou 364 */ 365int 366_RkResize(int cx_num, int len, int t) 367{ 368 struct RkContext *cx; 369 struct nbun *bun; 370 struct nstore *store; 371 372 if (!(cx = RkGetXContext(cx_num)) || 373 !(store = cx->store) || 374 !(bun = getCurrentBun(store))) { 375 RkSetErrno(RK_ERRNO_ECTXNO); 376 return(-1); 377 } 378 if (t) 379 len = HowManyChars(store->yomi + store->bunq[store->curbun].nb_yoff, len); 380 if (0 < len && (unsigned)(bun->nb_yoff + len) <= store->nyomi) { 381 bun->nb_flags |= RK_REARRANGED; 382 return(_RkRenbun2(cx, len)); 383 } 384 return(store->maxbun); 385} 386 387int 388RkwResize(int cx_num, int len) 389{ 390 return(_RkResize(cx_num, len, 0)); 391} 392 393int 394RkeResize(int cx_num, int len) 395{ 396 return(_RkResize(cx_num, len, 1)); 397} 398 399int 400RkwEnlarge(int cx_num) 401{ 402 struct RkContext *cx; 403 struct nstore *store; 404 struct nbun *bun; 405 406 if (!(cx = RkGetXContext(cx_num)) || 407 !(store = cx->store)|| 408 !(bun = getCurrentBun(store))) { 409 RkSetErrno(RK_ERRNO_ENOMEM); 410 return(0); 411 } 412 if (store->nyomi > (unsigned)(bun->nb_yoff + bun->nb_curlen) && 413 store->yomi[bun->nb_yoff + bun->nb_curlen]) { 414 bun->nb_flags |= RK_REARRANGED; 415 return(_RkRenbun2(cx, (int)(bun->nb_curlen + 1))); 416 } 417 return(store->maxbun); 418} 419 420int 421RkwShorten(int cx_num) 422{ 423 struct RkContext *cx; 424 struct nstore *store; 425 struct nbun *bun; 426 427 if (!(cx = RkGetXContext(cx_num)) || 428 !(store = cx->store) || 429 !(bun = getCurrentBun(store))) { 430 RkSetErrno(RK_ERRNO_ECTXNO); 431 return 0; 432 } 433 if (bun->nb_curlen > 1) { 434 bun->nb_flags |= RK_REARRANGED; 435 return(_RkRenbun2(cx, (int)(bun->nb_curlen - 1))); 436 } 437 return(store->maxbun); 438} 439 440/* RkStoreYomi 441 * current bunsetu no yomi wo sitei sareta mono to okikaeru 442 * okikaeta noti, saihen kan suru 443 */ 444 445int 446RkwStoreYomi(int cx_num, WCHAR_T *yomi, int nlen) 447{ 448 unsigned nmax, omax, cp; 449 WCHAR_T *s, *d, *e; 450 int i, olen, diff; 451 struct RkContext *cx; 452 struct nstore *store; 453 struct nbun *bun; 454 455 if (!(cx = RkGetXContext(cx_num)) || 456 !(store = cx->store) || 457 !(bun = getCurrentBun(store))) { 458 RkSetErrno(RK_ERRNO_ECTXNO); 459 return -1; 460 } 461 if (!yomi || nlen < 0 || uslen(yomi) < nlen) { 462 RkSetErrno(RK_ERRNO_EINVAL); 463 return -1; 464 } 465 nmax = store->nyomi + (diff = nlen - (olen = bun->nb_curlen)); 466 omax = store->nyomi; 467 /* nobiru */ 468 if (nlen > olen) { 469 if (!(store = _RkReallocBunStorage(store, store->maxyomi + diff))) { 470 RkSetErrno(RK_ERRNO_ENOMEM); 471 return -1; 472 } 473 cx->store = store; 474 bun = getCurrentBun(store); 475 /* shift yomi */ 476 s = store->yomi + omax; 477 d = store->yomi + nmax; 478 e = store->yomi + bun->nb_yoff + olen; 479 while (s > e) 480 *--d = *--s; 481 } else if (nlen < olen) { /* chizimu */ 482 s = store->yomi + bun->nb_yoff + olen; 483 d = store->yomi + bun->nb_yoff + nlen; 484 e = store->yomi + omax; 485 while (s < e) 486 *d++ = *s++; 487 } 488 store->yomi[nmax] = (WCHAR_T)0; 489 store->nyomi = nmax; 490 for (i = store->curbun + 1; i <= (int)store->maxbun; i++) 491 store->bunq[i].nb_yoff += diff; 492 cp = store->curbun; 493 if (!nlen) { 494 _RkFreeBunq(store); 495 for (i = store->curbun; i < (int)store->maxbun; i++) 496 store->bunq[i] = store->bunq[i + 1]; 497 store->maxbun--; 498 cp = store->curbun; 499 if (cp >= store->maxbun && cp > 0) 500 cp -= 1; 501 } else 502 usncopy((store->yomi + bun->nb_yoff), yomi, (unsigned)nlen); 503 if ((i = _RkRenbun2(cx, 0)) != -1) 504 store->curbun = cp; 505 return(i); 506} 507 508/* RkGoTo/RkLeft/RkRight 509 * current bunsetu no idou 510 */ 511 512int 513RkwGoTo(int cx_num, int bnum) 514{ 515 struct RkContext *cx; 516 struct nstore *store; 517 518 if (!(cx = RkGetXContext(cx_num)) || 519 !(store = cx->store) || 520 !store->maxbun) { 521 RkSetErrno(RK_ERRNO_ECTXNO); 522 return 0; 523 } 524 if ((0 <= bnum) && (bnum < (int)store->maxbun)) 525 store->curbun = bnum; 526 return(store->curbun); 527} 528 529int 530RkwLeft(int cx_num) 531{ 532 struct RkContext *cx; 533 struct nstore *store; 534 535 if (!(cx = RkGetXContext(cx_num)) || 536 !(store = cx->store) || 537 !store->maxbun) { 538 RkSetErrno(RK_ERRNO_ECTXNO); 539 return 0; 540 } 541 if (--store->curbun < 0) 542 store->curbun = store->maxbun - 1; 543 return store->curbun; 544} 545 546int 547RkwRight(int cx_num) 548{ 549 struct RkContext *cx; 550 struct nstore *store; 551 552 if (!(cx = RkGetXContext(cx_num)) || 553 !(store = cx->store) || 554 !store->maxbun) { 555 RkSetErrno(RK_ERRNO_ECTXNO); 556 return 0; 557 } 558 if (++store->curbun >= (int)store->maxbun) 559 store->curbun = 0; 560 return(store->curbun); 561} 562 563/* RkXfer/RkNfer/RkNext/RkPrev 564 * current kouho wo henkou 565 */ 566static int 567countCand(struct RkContext *cx) 568{ 569 struct nbun *bun; 570 int maxcand = 0; 571 unsigned long mask; 572 573 bun = getCurrentBun(cx->store); 574 if (bun) { 575 maxcand = bun->nb_maxcand; 576 for (mask = cx->kouhomode; mask; mask >>= RK_XFERBITS) 577 maxcand++; 578 }; 579 return(maxcand); 580} 581 582static int 583getXFER(struct RkContext *cx, int cnum) 584{ 585 struct nbun *bun = getCurrentBun(cx->store); 586 587 cnum -= ((int)bun->nb_maxcand); 588 return(cnum < 0 ? RK_NFER : (cx->kouhomode>>(RK_XFERBITS*cnum))&RK_XFERMASK); 589} 590 591int 592RkwXfer(int cx_num, int knum) 593{ 594 struct RkContext *cx; 595 struct nbun *bun; 596 597 if (!(cx = RkGetXContext(cx_num)) || 598 !(cx->store) || 599 !(bun = getCurrentBun(cx->store))) { 600 RkSetErrno(RK_ERRNO_ECTXNO); 601 return 0; 602 } 603 if (0 <= knum && knum < countCand(cx)) 604 bun->nb_curcand = knum; 605 return(bun->nb_curcand); 606} 607 608int 609RkwNfer(int cx_num) 610{ 611 struct RkContext *cx; 612 struct nbun *bun; 613 614 if (!(cx = RkGetXContext(cx_num)) || 615 !(cx->store) || 616 !(bun = getCurrentBun(cx->store))) { 617 RkSetErrno(RK_ERRNO_ECTXNO); 618 return(0); 619 } 620 return(bun->nb_curcand = bun->nb_maxcand); 621} 622 623int RkwNext (int); 624 625int 626RkwNext(int cx_num) 627{ 628 struct RkContext *cx; 629 struct nbun *bun; 630 631 if (!(cx = RkGetXContext(cx_num)) || 632 !(cx->store) || 633 !(bun = getCurrentBun(cx->store))) { 634 RkSetErrno(RK_ERRNO_ECTXNO); 635 return(0); 636 } 637 if (++bun->nb_curcand >= (WCHAR_T)countCand(cx)) 638 bun->nb_curcand = 0; 639 return(bun->nb_curcand); 640} 641 642int 643RkwPrev(int cx_num) 644{ 645 struct RkContext *cx; 646 struct nbun *bun; 647 648 if (!(cx = RkGetXContext(cx_num)) || 649 !(cx->store) || 650 !(bun = getCurrentBun(cx->store))) { 651 RkSetErrno(RK_ERRNO_ECTXNO); 652 return(0); 653 } 654 655 if (!bun->nb_curcand) 656 bun->nb_curcand = countCand(cx); 657 return(--bun->nb_curcand); 658} 659 660/* findBranch 661 * shiteisareta kouho wo fukumu path wo motomeru 662 */ 663static struct nword * 664findBranch(struct nstore *store, int cnum) 665{ 666 struct nbun *bun; 667 struct nword *w; 668 669 if (!(bun = getCurrentBun(store)) || 670 (0 > cnum) || 671 (cnum >= (int)bun->nb_maxcand)) 672 return((struct nword *)0); 673 for (w = bun->nb_cand; w; w = w->nw_next) { 674 if (CanSplitWord(w) && bun->nb_curlen == w->nw_ylen) { 675 if (cnum-- <= 0) 676 return(w); 677 } 678 } 679 return((struct nword *)0); 680} 681 682/* RkGetStat 683 */ 684int 685RkwGetStat(int cx_num, RkStat *st) 686{ 687 struct RkContext *cx; 688 struct nstore *store; 689 struct nbun *bun; 690 struct nword *cw, *lw; 691 692 if (!(cx = RkGetXContext(cx_num)) || 693 !(store = cx->store) || 694 !(bun = getCurrentBun(store)) || 695 !st) { 696 RkSetErrno(RK_ERRNO_ECTXNO); 697 return -1; 698 } 699 /* set up void values */ 700 st->bunnum = st->candnum = st->maxcand = 701 st->diccand = st->ylen = st->klen = st->tlen = 0; 702 st->bunnum = store->curbun; 703 st->candnum = bun->nb_curcand; 704 705 st->maxcand = countCand(cx); 706 st->diccand = bun->nb_maxcand; 707 st->ylen = bun->nb_curlen; 708 st->klen = bun->nb_curlen; 709 st->tlen = 1; 710 /* look up the word node containing the current candidate */ 711 cw = findBranch(store, (int)bun->nb_curcand); 712 if (cw) { 713 st->klen = st->tlen = 0; 714 for (; cw; cw = cw->nw_left) { 715 if (!(lw = cw->nw_left)) 716 break; 717 if (cw->nw_klen == lw->nw_klen) 718 st->klen += (cw->nw_ylen - lw->nw_ylen); 719 else 720 st->klen += (cw->nw_klen - lw->nw_klen); 721 st->tlen++; 722 } 723 } else { 724 WCHAR_T *yomi = store->yomi + bun->nb_yoff; 725 switch(getXFER(cx, (int)bun->nb_curcand)) { 726 default: 727 case RK_XFER: 728 st->klen = RkwCvtHira((WCHAR_T *)0, 0, yomi, st->ylen); 729 break; 730 case RK_KFER: 731 st->klen = RkwCvtKana((WCHAR_T *)0, 0, yomi, st->ylen); 732 break; 733 case RK_HFER: 734 st->klen = RkwCvtHan((WCHAR_T *)0, 0, yomi, st->ylen); 735 break; 736 case RK_ZFER: 737 st->klen = RkwCvtZen((WCHAR_T *)0, 0, yomi, st->ylen); 738 break; 739 } 740 } 741 return 0; 742} 743 744/* RkGetStat 745 */ 746int 747RkeGetStat(int cx_num, RkStat *st) 748{ 749 struct RkContext *cx; 750 struct nstore *store; 751 WCHAR_T *yomi; 752 int res, klen; 753 WCHAR_T *kanji = (WCHAR_T *)malloc(sizeof(WCHAR_T) * (RK_LEN_WMAX + 1)); 754 if (!kanji) { 755 return -1; 756 } 757 758 if (!(cx = RkGetXContext(cx_num)) || !(store = cx->store)) { 759 RkSetErrno(RK_MSG_ECTXNO); 760 res = -1; 761 goto return_res; 762 } 763 764 yomi = store->yomi + store->bunq[store->curbun].nb_yoff; 765 klen = RkwGetKanji(cx_num, kanji, RK_LEN_WMAX + 1); 766 res = RkwGetStat(cx_num, st); 767 if (res < 0 || klen != st->klen) { 768 res = -1; 769 goto return_res; 770 } 771 if (st) { 772 st->ylen = HowManyBytes(yomi, st->ylen); 773 st->klen = HowManyBytes(kanji, klen); 774 } 775 return_res: 776 free(kanji); 777 return res; 778} 779 780static int 781addIt(struct nword * cw, WCHAR_T * key, int (*proc) (...), WCHAR_T * dst, int ind, int maxdst, unsigned long mode, RkContext * cx) 782{ 783 struct nword *lw; 784 WCHAR_T *y; 785 RkLex lex; 786 787 lw = cw->nw_left; 788 if (lw) { 789 ind = addIt(lw, key, proc, dst, ind, maxdst, mode, cx); 790 y = key + lw->nw_ylen; 791 lex.ylen = cw->nw_ylen - lw->nw_ylen; 792 lex.klen = cw->nw_klen - lw->nw_klen; 793 lex.rownum = cw->nw_rowcol; 794#ifdef NEED_DEF 795 lex.colnum = cw->nw_rowcol; 796#endif 797 lex.dicnum = cw->nw_class; 798 ind = (*proc) (dst, ind, maxdst, y, _RkGetKanji(cw, y, mode), &lex, cx); 799 } 800 return ind; 801} 802 803 804inline int 805getIt(RkContext * cx, int cnum, int (*proc) (...), WCHAR_T * dst, int max) 806{ 807 struct nstore *store = cx->store; 808 struct nbun *bun; 809 struct nword *w; 810 811 if (!(bun = getCurrentBun(store)) || 812 !(w = findBranch(store, cnum))) 813 return (-1); 814 return addIt(w, store->yomi + bun->nb_yoff, proc, dst, 0, max, 815 cx->concmode, cx); 816} 817 818/*ARGSUSED*/ 819inline int 820addYomi(WCHAR_T *dst, int ind, int max, WCHAR_T *yomi, WCHAR_T *kanji, RkLex *lex) 821{ 822 int ylen; 823 824 ylen = lex->ylen; 825 while (ylen--) { 826 if (ind < max) { 827 if (dst) 828 dst[ind] = *yomi++; 829 ind++; 830 } 831 } 832 return ind; 833} 834/* RkGetYomi 835 * current bunsetu no yomi wo toru 836 */ 837 838int RkwGetYomi (int, WCHAR_T *, int); 839 840int 841RkwGetYomi(int cx_num, WCHAR_T *yomi, int maxyomi) 842{ 843 struct RkContext *cx; 844 struct nbun *bun; 845 RkLex lex; 846 int i; 847 struct nstore *store; 848 849 if (!(cx = RkGetXContext(cx_num)) || 850 !(store = cx->store) || 851 !(bun = getCurrentBun(store))) { 852 RkSetErrno(RK_ERRNO_ECTXNO); 853 return -1; 854 }; 855 if (!yomi) { 856 RkSetErrno(RK_ERRNO_EINVAL); 857 return -1; 858 }; 859 lex.ylen = bun->nb_curlen; 860 i = addYomi(yomi, 0, maxyomi - 1, 861 store->yomi + bun->nb_yoff, 862 store->yomi+bun->nb_yoff, 863 &lex); 864 if (yomi && i < maxyomi) 865 yomi[i] = (WCHAR_T)0; 866 return i; 867} 868 869int 870RkwGetLastYomi(int cx_num, WCHAR_T *yomi, int maxyomi) 871{ 872 struct RkContext *cx; 873 struct nbun *bun; 874 struct nstore *store; 875 int nyomi; 876 877 if (!(cx = RkGetXContext(cx_num)) || 878 !(store = cx->store) || 879 !(bun = &store->bunq[store->maxbun])) { 880 RkSetErrno(RK_ERRNO_ECTXNO); 881 return -1; 882 } 883 if (!(cx->flags & CTX_XAUT) || maxyomi < 0) { 884 RkSetErrno(RK_ERRNO_EINVAL); 885 return -1; 886 } 887 nyomi = store->nyomi - bun->nb_yoff; 888 if (yomi) { 889 usncopy(yomi, store->yomi + bun->nb_yoff, (unsigned)(maxyomi)); 890 if (nyomi + 1 < maxyomi) { 891 yomi[nyomi] = (WCHAR_T)0; 892 } else { 893 yomi[maxyomi - 1] = (WCHAR_T)0; 894 }; 895 } 896 return nyomi; 897} 898 899/*ARGSUSED*/ 900static int 901addKanji(WCHAR_T *dst, int ind, int max, WCHAR_T *yomi, WCHAR_T *kanji, RkLex *lex, struct RkContext *cx) /* ARGSUSED */ 902{ 903 int klen; 904 905 klen = lex->klen; 906 while (klen-- > 0) { 907 if (ind < max) { 908 if (dst) 909 dst[ind] = *kanji++; 910 ind++; 911 } 912 } 913 return ind; 914} 915 916static int 917getKanji(struct RkContext *cx, int cnum, WCHAR_T *dst, int maxdst) 918{ 919 struct nbun *bun = getCurrentBun(cx->store); 920 WCHAR_T *yomi; 921 int i, ylen; 922 923 i = getIt(cx, cnum, (int(*)(...))addKanji, dst, maxdst - 1); 924 if (i < 0) { 925 yomi = cx->store->yomi + bun->nb_yoff; 926 ylen = bun->nb_curlen; 927 switch(getXFER(cx, cnum)) { 928 default: 929 case RK_XFER: 930 i = RkwCvtHira(dst, maxdst, yomi, ylen); break; 931 case RK_KFER: 932 i = RkwCvtKana(dst, maxdst, yomi, ylen); break; 933 case RK_HFER: 934 i = RkwCvtHan(dst, maxdst, yomi, ylen); break; 935 case RK_ZFER: 936 i = RkwCvtZen(dst, maxdst, yomi, ylen); break; 937 } 938 } 939 if (dst && i < maxdst) 940 dst[i] = (WCHAR_T)0; 941 return i; 942} 943 944/* RkGetKanji 945 * current bunsetu no kanji tuduri wo toru 946 */ 947 948int 949RkwGetKanji(int cx_num, WCHAR_T *dst, int maxdst) 950{ 951 RkContext *cx; 952 struct nbun *bun; 953 int i; 954 955 if (!(cx = RkGetXContext(cx_num)) || 956 !(cx->store) || 957 !(bun = getCurrentBun(cx->store))) { 958 RkSetErrno(RK_ERRNO_ECTXNO); 959 return -1; 960 } 961 962 i = getKanji(cx, (int)bun->nb_curcand, dst, maxdst); 963 if (dst && i < maxdst) 964 dst[i] = 0; 965 return i; 966} 967 968/* RkGetKanjiList 969 * genzai sentaku sareta kouho mojiretu wo toridasu 970 */ 971int 972RkwGetKanjiList(int cx_num, WCHAR_T *dst, int maxdst) 973{ 974 struct RkContext *cx; 975 int i, len, ind = 0, num = 0; 976 int maxcand; 977 978 if (!(cx = RkGetXContext(cx_num)) || 979 !(cx->store)) { 980 RkSetErrno(RK_ERRNO_ECTXNO); 981 return -1; 982 } 983 maxcand = countCand(cx); 984 for (i = 0; i < maxcand; i++) { 985 if (dst) 986 len = getKanji(cx, i, dst + ind, maxdst - ind - 1); 987 else 988 len = getKanji(cx, i, dst, maxdst - ind - 1); 989 if (0 < len && ind + len + 1 < maxdst - 1) { 990 if (dst) 991 dst[ind + len] = (WCHAR_T)0; 992 ind += len + 1; 993 num++; 994 } 995 } 996 if (dst && ind < maxdst) 997 dst[ind] = (WCHAR_T)0; 998 return num; 999} 1000 1001/* RkGetLex 1002 * current bunsetu no hishi jouhou wo toru 1003 */ 1004/*ARGSUSED*/ 1005static int 1006addLex(RkLex *dst, int ind, int max, WCHAR_T *yomi, WCHAR_T *kanji, RkLex *lex, struct RkContext *cx) /* ARGSUSED */ 1007{ 1008 if (ind + 1 <= max) { 1009 if (dst) 1010 dst[ind] = *lex; 1011 ind++; 1012 } 1013 return ind; 1014} 1015 1016int 1017RkwGetLex(int cx_num, RkLex *dst, int maxdst) 1018{ 1019 RkContext *cx; 1020 struct nbun *bun; 1021 int i; 1022 1023 if (!(cx = RkGetXContext(cx_num)) || 1024 !(cx->store) || 1025 !(bun = getCurrentBun(cx->store))) { 1026 RkSetErrno(RK_ERRNO_ECTXNO); 1027 return -1; 1028 } 1029 i = getIt(cx, (int)bun->nb_curcand, (int(*)(...))addLex, (WCHAR_T *)dst, maxdst - 1); 1030 if (i < 0) { 1031 if (dst && 1 < maxdst) { 1032 dst[0].ylen = bun->nb_curlen; 1033 dst[0].klen = bun->nb_curlen; 1034 dst[0].rownum = cx->gram->P_BB; /* ʸÀá */ 1035 dst[0].colnum = cx->gram->P_BB; /* ʸÀá */ 1036 dst[0].dicnum = ND_EMP; 1037 } 1038 i = 1; 1039 } 1040 return i; 1041} 1042 1043/* RkeGetLex -- ¤Û¤Ü RkwGetLex ¤ÈƱ¤¸¤À¤¬Ä¹¤µ¤Ï¥Ð¥¤¥ÈŤÇÊÖ¤ë */ 1044 1045int 1046RkeGetLex(int cx_num, RkLex *dst, int maxdst) 1047{ 1048 struct RkContext *cx; 1049 struct nstore *store; 1050 WCHAR_T *yomi, *kp; 1051 int nwords, i; 1052 WCHAR_T *kanji = (WCHAR_T *)malloc(sizeof(WCHAR_T) * (RK_LEN_WMAX + 1)); 1053 if (!kanji) { 1054 return -1; 1055 } 1056 1057 if (!(cx = RkGetXContext(cx_num)) || 1058 !(store = cx->store)) { 1059 RkSetErrno(RK_MSG_ECTXNO); 1060 nwords = -1; 1061 goto return_nwords; 1062 } 1063 1064 yomi = store->yomi + store->bunq[store->curbun].nb_yoff; 1065 (void)RkwGetKanji(cx_num, kanji, RK_LEN_WMAX + 1); 1066 kp = kanji; 1067 nwords = RkwGetLex(cx_num, dst, maxdst); 1068 if (dst) { 1069 for (i = 0; i < nwords; i++) { 1070 int tmp; 1071 tmp = dst[i].ylen; 1072 dst[i].ylen = HowManyBytes(yomi, tmp); yomi += tmp; 1073 tmp = dst[i].klen; 1074 dst[i].klen = HowManyBytes(kp, tmp); kp += tmp; 1075 } 1076 } 1077 return_nwords: 1078 free(kanji); 1079 return nwords; 1080} 1081 1082/*ARGSUSED*/ 1083static int 1084addHinshi(WCHAR_T *dst, int ind, int max, WCHAR_T *yomi, WCHAR_T *kanji, RkLex *lex, struct RkContext *cx) 1085{ 1086 int bytes; 1087 WCHAR_T *p; 1088#ifndef USE_MALLOC_FOR_BIG_ARRAY 1089 WCHAR_T hinshi[256]; 1090#else 1091 WCHAR_T *hinshi = (WCHAR_T *)malloc(sizeof(WCHAR_T) * 256); 1092 if (!hinshi) { 1093 return ind; 1094 } 1095#endif 1096 1097 if (cx) { 1098 p = RkUparseGramNum(cx->gram->gramdic, lex->rownum, hinshi, 256); 1099 if (p) { 1100 bytes = p - hinshi; 1101 if (ind + bytes < max) { 1102 if (dst) 1103 usncopy(dst + ind, hinshi, bytes); 1104 ind += bytes; 1105 } 1106 } 1107 } 1108#ifdef USE_MALLOC_FOR_BIG_ARRAY 1109 free(hinshi); 1110#endif 1111 return ind; 1112} 1113 1114/* RkGetHinshi 1115 * current bunsetu no hinshi mojiretu wo toru 1116 */ 1117int 1118RkwGetHinshi(int cx_num, WCHAR_T *dst, int maxdst) 1119{ 1120 struct RkContext *cx; 1121 struct nbun *bun; 1122 int i; 1123 1124 if (!(cx = RkGetXContext(cx_num)) || 1125 !(cx->store) || 1126 !(bun = getCurrentBun(cx->store))) { 1127 RkSetErrno(RK_ERRNO_ECTXNO); 1128 return(-1); 1129 } 1130 i = getIt(cx, (int)bun->nb_curcand, (int(*)(...))addHinshi, dst, maxdst - 1); 1131 if (i < 0) { 1132 if (dst && 1 < maxdst) 1133 dst[0] = (WCHAR_T)0; 1134 i = 1; 1135 } 1136 return(i); 1137} 1138 1139#include <sys/types.h> 1140#include <sys/stat.h> 1141 1142#define CloseContext(a) {if ((a) != cx_num) RkwCloseContext(a);} 1143 1144int 1145RkwQueryDic(int cx_num, char *dirname, char *dicname, struct DicInfo *status) 1146{ 1147 struct RkContext *cx; 1148 int new_cx_num, size; 1149 unsigned char *buff; 1150 char *file; 1151 struct DM *dm; 1152 struct DF *df; 1153 struct stat st; 1154 1155 if (!(cx = RkGetContext(cx_num)) 1156 || !status || !dirname || !dicname || !dicname[0]) 1157 return(-1); 1158 size = strlen(dicname) + 1; 1159 if (!(buff = (unsigned char *)malloc(size))) 1160 return(-1); 1161 (void)strcpy((char *)buff, dicname); 1162 if (*dirname && strcmp(dirname, cx->ddpath[0]->dd_name) 1163 && strcmp(dirname, (char *)SYSTEM_DDHOME_NAME)) { 1164 if((new_cx_num = RkwCreateContext()) < 0) { 1165 free(buff); 1166 return BADCONT; 1167 } 1168 if(RkwSetDicPath(new_cx_num, dirname) < 0) { 1169 CloseContext(new_cx_num); 1170 free(buff); 1171 return NOTALC; 1172 } 1173 if (!(cx = RkGetContext(new_cx_num))) { 1174 free(buff); 1175 return(-1); 1176 } 1177 } else { 1178 if (!strcmp(dirname, (char *)SYSTEM_DDHOME_NAME)) 1179 dirname = SYSTEM_DDHOME_NAME; 1180 else 1181 dirname = cx->ddpath[0]->dd_name; 1182 new_cx_num = cx_num; 1183 } 1184 if (!strcmp(dirname, (char *)SYSTEM_DDHOME_NAME)) { 1185 if (!(dm = _RkSearchDDP(cx->ddpath, dicname))) { 1186 CloseContext(new_cx_num); 1187 free(buff); 1188 return NOENT; 1189 } 1190 } else { 1191 if (!(dm = _RkSearchUDDP(cx->ddpath, (unsigned char *)dicname))) { 1192 CloseContext(new_cx_num); 1193 free(buff); 1194 return NOENT; 1195 } 1196 } 1197 df = dm->dm_file; 1198 if (df) { 1199 file = _RkCreatePath(df->df_direct, df->df_link); 1200 if (file) { 1201 status->di_dic = (unsigned char *)dm->dm_nickname; 1202 status->di_file = (unsigned char *)df->df_link; 1203 status->di_form = (DM2TYPE(dm) == DF_TEMPDIC) ? RK_TXT : RK_BIN; 1204 status->di_kind = dm->dm_class; 1205 status->di_count = stat(file, &st) >= 0 ? st.st_size : 0; 1206 status->di_time = stat(file, &st) >= 0 ? st.st_ctime : 0; 1207 status->di_mode = 0; 1208 CloseContext(new_cx_num); 1209 free(file); 1210 free(buff); 1211 return(0); 1212 } 1213 } 1214 free(buff); 1215 CloseContext(new_cx_num); 1216 return(-1); 1217} 1218 1219int 1220_RkwSync(struct RkContext *cx, char *dicname) 1221{ 1222 struct DM *dm, *qm; 1223 1224 dm = _RkSearchDicWithFreq(cx->ddpath, dicname, &qm); 1225 1226 if (dm) 1227 return(DST_SYNC(cx, dm, qm)); 1228 else 1229 return (-1); 1230} 1231 1232 1233int 1234RkwSync(int cx_num, char *dicname) 1235{ 1236 struct RkContext *cx; 1237 int ret = -1; 1238 const off_t DL_SIZE = 1024; 1239 1240 if (!(cx = RkGetContext(cx_num))) 1241 return (-1); 1242 1243 if (!dicname || !*dicname) { 1244 int i, rv; 1245 char *p; 1246#ifndef USE_MALLOC_FOR_BIG_ARRAY 1247 char diclist[DL_SIZE]; 1248#else 1249 char *diclist = (char *)malloc(DL_SIZE); 1250 if (!diclist) { 1251 return -1; 1252 } 1253#endif 1254 1255 if (!(i = RkwGetDicList(cx_num, diclist, DL_SIZE))) { 1256 ret = 0; 1257 } 1258 else { 1259 if (i > 0) { 1260 for (p = diclist, rv = 0; *p;) { 1261 rv += _RkwSync(cx, p); 1262 p += strlen(p) + 1; 1263 } 1264 if (!rv) { 1265 ret = 0; 1266 goto return_ret; 1267 } 1268 } 1269 ret = -1; 1270 } 1271 return_ret:; 1272#ifdef USE_MALLOC_FOR_BIG_ARRAY 1273 free(diclist); 1274#endif 1275 } else { 1276 ret = _RkwSync(cx, dicname); 1277 } 1278 return ret; 1279} 1280 1281/*ARGSUSED*/ 1282int RkwGetSimpleKanji(int cxnum, char *dicname, WCHAR_T *yomi, int maxyomi, WCHAR_T *kanjis, int maxkanjis, char *hinshis, int maxhinshis) 1283{ 1284 return -1; 1285} 1286 1287/*ARGSUSED*/ 1288int 1289RkwStoreRange(int cx_num, WCHAR_T *yomi, int maxyomi) 1290{ 1291 return(0); 1292} 1293 1294/*ARGSUSED*/ 1295int 1296RkwSetLocale(int cx_num, unsigned char *locale) 1297{ 1298 return(0); 1299} 1300