1 /* liblouis Braille Translation and Back-Translation Library
3 Based on the Linux screenreader BRLTTY, copyright (C) 1999-2006 by
6 Copyright (C) 2004, 2005, 2006
7 ViewPlus Technologies, Inc. www.viewplus.com
9 abilitiessoft, Inc. www.abilitiessoft.com
12 This file is part of Liblouis.
14 Liblouis is free software: you can redistribute it and/or modify it
15 under the terms of the GNU Lesser General Public License as
16 published by the Free Software Foundation, either version 3 of the
17 License, or (at your option) any later version.
19 Liblouis is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
24 You should have received a copy of the GNU Lesser General Public
25 License along with Liblouis. If not, see
26 <http://www.gnu.org/licenses/>.
28 Maintained by John J. Boyer john.boyer@abilitiessoft.com
36 #include "transcommon.ci"
38 #define MIN(a,b) (((a)<(b))?(a):(b))
40 static int translateString ();
41 static int compbrlStart = 0;
42 static int compbrlEnd = 0;
45 lou_translateString (const char *tableList, const widechar
47 int *inlen, widechar * outbuf, int *outlen,
49 *typeform, char *spacing, int mode)
52 lou_translate (tableList, inbufx, inlen, outbuf, outlen, typeform,
53 spacing, NULL, NULL, NULL, mode);
57 lou_translate (const char *tableList, const widechar
59 int *inlen, widechar * outbuf, int *outlen,
60 formtype *typeform, char *spacing, int *outputPos,
61 int *inputPos, int *cursorPos, int modex)
63 return trace_translate (tableList, inbufx, inlen, outbuf, outlen,
64 typeform, spacing, outputPos, inputPos, cursorPos,
69 trace_translate (const char *tableList, const widechar * inbufx,
70 int *inlen, widechar * outbuf, int *outlen,
71 formtype *typeform, char *spacing, int *outputPos,
72 int *inputPos, int *cursorPos,
73 const TranslationTableRule ** rules, int *rulesLen,
78 if (tableList == NULL || inbufx == NULL || inlen == NULL || outbuf ==
79 NULL || outlen == NULL)
81 logMessage(LOG_DEBUG, "Performing translation: tableList=%s, inlen=%d", tableList, *inlen);
82 logWidecharBuf(LOG_DEBUG, "Inbuf=", inbufx, *inlen);
83 if ((modex & otherTrans))
84 return other_translate (tableList, inbufx,
85 inlen, outbuf, outlen,
86 typeform, spacing, outputPos, inputPos, cursorPos,
88 table = lou_getTable (tableList);
89 if (table == NULL || *inlen < 0 || *outlen < 0)
91 currentInput = (widechar *) inbufx;
93 while (srcmax < *inlen && currentInput[srcmax])
97 if (!(typebuf = liblouis_allocMem (alloc_typebuf, srcmax, destmax)))
101 for (k = 0; k < srcmax; k++)
102 if ((typebuf[k] = typeform[k] & EMPHASIS))
106 memset (typebuf, 0, srcmax * sizeof (unsigned short));
107 if (!(spacing == NULL || *spacing == 'X'))
108 srcSpacing = (unsigned char *) spacing;
109 outputPositions = outputPos;
110 if (outputPos != NULL)
111 for (k = 0; k < srcmax; k++)
113 inputPositions = inputPos;
115 if (cursorPos != NULL && *cursorPos >= 0)
118 cursorPosition = *cursorPos;
119 if ((mode & (compbrlAtCursor | compbrlLeftCursor)))
121 compbrlStart = cursorPosition;
122 if (checkAttr (currentInput[compbrlStart], CTC_Space, 0))
123 compbrlEnd = compbrlStart + 1;
126 while (compbrlStart >= 0 && !checkAttr
127 (currentInput[compbrlStart], CTC_Space, 0))
130 compbrlEnd = cursorPosition;
131 if (!(mode & compbrlLeftCursor))
132 while (compbrlEnd < srcmax && !checkAttr
133 (currentInput[compbrlEnd], CTC_Space, 0))
141 cursorStatus = 1; /*so it won't check cursor position */
143 if (!(passbuf1 = liblouis_allocMem (alloc_passbuf1, srcmax, destmax)))
145 if (!(srcMapping = liblouis_allocMem (alloc_srcMapping, srcmax, destmax)))
149 liblouis_allocMem (alloc_prevSrcMapping, srcmax, destmax)))
151 for (k = 0; k <= srcmax; k++)
153 srcMapping[srcmax] = srcmax;
154 if ((!(mode & pass1Only)) && (table->numPasses > 1 || table->corrections))
156 if (!(passbuf2 = liblouis_allocMem (alloc_passbuf2, srcmax, destmax)))
159 if (srcSpacing != NULL)
161 if (!(destSpacing = liblouis_allocMem (alloc_destSpacing, srcmax,
165 memset (destSpacing, '*', destmax);
167 appliedRulesCount = 0;
168 if (rules != NULL && rulesLen != NULL)
170 appliedRules = rules;
171 maxAppliedRules = *rulesLen;
179 if ((mode & pass1Only))
181 currentOutput = passbuf1;
182 memcpy (prevSrcMapping, srcMapping, destmax * sizeof (int));
183 goodTrans = translateString ();
184 currentPass = 5; /*Certainly > table->numPasses */
186 while (currentPass <= table->numPasses && goodTrans)
188 memcpy (prevSrcMapping, srcMapping, destmax * sizeof (int));
192 if (table->corrections)
194 currentOutput = passbuf2;
195 goodTrans = makeCorrections ();
196 currentInput = passbuf2;
201 currentOutput = passbuf1;
202 goodTrans = translateString ();
206 currentInput = passbuf1;
207 currentOutput = passbuf2;
208 goodTrans = translatePass ();
212 currentInput = passbuf2;
213 currentOutput = passbuf1;
214 goodTrans = translatePass ();
218 currentInput = passbuf1;
219 currentOutput = passbuf2;
220 goodTrans = translatePass ();
229 for (k = 0; k < dest; k++)
231 if (typeform != NULL)
233 if ((currentOutput[k] & (B7 | B8)))
241 outbuf[k] = ((currentOutput[k] & 0xff) | 0x2800);
243 outbuf[k] = currentOutput[k];
246 outbuf[k] = getCharFromDots (currentOutput[k]);
250 if (inputPositions != NULL)
251 memcpy (inputPositions, srcMapping, dest * sizeof (int));
252 if (outputPos != NULL)
255 for (k = 0; k < *inlen; k++)
256 if (outputPos[k] == -1)
257 outputPos[k] = lastpos;
259 lastpos = outputPos[k];
262 if (destSpacing != NULL)
264 memcpy (srcSpacing, destSpacing, srcmax);
265 srcSpacing[srcmax] = 0;
267 if (cursorPos != NULL && *cursorPos != -1)
269 if (outputPos != NULL)
270 *cursorPos = outputPos[*cursorPos];
272 *cursorPos = cursorPosition;
274 if (rulesLen != NULL)
275 *rulesLen = appliedRulesCount;
276 logMessage(LOG_DEBUG, "Translation complete: outlen=%d", *outlen);
277 logWidecharBuf(LOG_DEBUG, "Outbuf=", (const widechar *)outbuf, *outlen);
282 lou_translatePrehyphenated (const char *tableList,
283 const widechar * inbufx, int *inlen,
284 widechar * outbuf, int *outlen,
285 formtype *typeform, char *spacing,
286 int *outputPos, int *inputPos, int *cursorPos,
287 char *inputHyphens, char *outputHyphens,
291 int *alloc_inputPos = NULL;
292 if (inputHyphens != NULL)
294 if (outputHyphens == NULL)
296 if (inputPos == NULL)
298 if ((alloc_inputPos = malloc (*outlen * sizeof (int))) == NULL)
300 inputPos = alloc_inputPos;
303 if (lou_translate (tableList, inbufx, inlen, outbuf, outlen, typeform,
304 spacing, outputPos, inputPos, cursorPos, modex))
306 if (inputHyphens != NULL)
310 for (outpos = 0; outpos < *outlen; outpos++)
312 int new_inpos = inputPos[outpos];
313 if (new_inpos < inpos)
318 if (new_inpos > inpos)
319 outputHyphens[outpos] = inputHyphens[new_inpos];
321 outputHyphens[outpos] = '0';
326 if (alloc_inputPos != NULL)
327 free (alloc_inputPos);
331 static TranslationTableOpcode indicOpcode;
332 static const TranslationTableRule *indicRule;
333 static int dontContract = 0;
336 hyphenate (const widechar * word, int wordSize, char *hyphens)
342 HyphenationState *statesArray = (HyphenationState *)
343 & table->ruleArea[table->hyphenStatesArray];
344 HyphenationState *currentState;
345 HyphenationTrans *transitionsArray;
348 if (!table->hyphenStatesArray || (wordSize + 3) > MAXSTRING)
350 prepWord = (widechar *) calloc (wordSize + 3, sizeof (widechar));
351 /* prepWord is of the format ".hello."
352 * hyphens is the length of the word "hello" "00000" */
354 for (i = 0; i < wordSize; i++)
356 prepWord[i + 1] = (findCharOrDots (word[i], 0))->lowercase;
359 prepWord[wordSize + 1] = '.';
361 /* now, run the finite state machine */
364 // we need to walk all of ".hello."
365 for (i = 0; i < wordSize + 2; i++)
370 if (stateNum == 0xffff)
375 currentState = &statesArray[stateNum];
376 if (currentState->trans.offset)
378 transitionsArray = (HyphenationTrans *) &
379 table->ruleArea[currentState->trans.offset];
380 for (k = 0; k < currentState->numTrans; k++)
382 if (transitionsArray[k].ch == ch)
384 stateNum = transitionsArray[k].newState;
389 stateNum = currentState->fallbackState;
392 currentState = &statesArray[stateNum];
393 if (currentState->hyphenPattern)
396 (char *) &table->ruleArea[currentState->hyphenPattern];
397 patternOffset = i + 1 - strlen (hyphenPattern);
399 /* Need to ensure that we don't overrun hyphens,
400 * in some cases hyphenPattern is longer than the remaining letters,
401 * and if we write out all of it we would have overshot our buffer. */
402 limit = MIN (strlen (hyphenPattern), wordSize - patternOffset);
403 for (k = 0; k < limit; k++)
405 if (hyphens[patternOffset + k] < hyphenPattern[k])
406 hyphens[patternOffset + k] = hyphenPattern[k];
411 hyphens[wordSize] = 0;
418 static int doCompTrans (int start, int end);
421 for_updatePositions (const widechar * outChars, int inLength, int outLength)
424 if ((dest + outLength) > destmax || (src + inLength) > srcmax)
426 memcpy (¤tOutput[dest], outChars, outLength * CHARSIZE);
429 if ((mode & (compbrlAtCursor | compbrlLeftCursor)))
431 if (src >= compbrlStart)
434 return (doCompTrans (compbrlStart, compbrlEnd));
437 else if (cursorPosition >= src && cursorPosition < (src + inLength))
439 cursorPosition = dest;
442 else if (currentInput[cursorPosition] == 0 &&
443 cursorPosition == (src + inLength))
445 cursorPosition = dest + outLength / 2 + 1;
449 else if (cursorStatus == 2 && cursorPosition == src)
450 cursorPosition = dest;
451 if (inputPositions != NULL || outputPositions != NULL)
453 if (outLength <= inLength)
455 for (k = 0; k < outLength; k++)
457 if (inputPositions != NULL)
458 srcMapping[dest + k] = prevSrcMapping[src];
459 if (outputPositions != NULL)
460 outputPositions[prevSrcMapping[src + k]] = dest;
462 for (k = outLength; k < inLength; k++)
463 if (outputPositions != NULL)
464 outputPositions[prevSrcMapping[src + k]] = dest;
468 for (k = 0; k < inLength; k++)
470 if (inputPositions != NULL)
471 srcMapping[dest + k] = prevSrcMapping[src];
472 if (outputPositions != NULL)
473 outputPositions[prevSrcMapping[src + k]] = dest;
475 for (k = inLength; k < outLength; k++)
476 if (inputPositions != NULL)
477 srcMapping[dest + k] = prevSrcMapping[src];
491 char *hyphens = NULL;
492 for (wordStart = src; wordStart >= 0; wordStart--)
493 if (!((findCharOrDots (currentInput[wordStart], 0))->attributes &
501 for (wordEnd = src; wordEnd < srcmax; wordEnd++)
502 if (!((findCharOrDots (currentInput[wordEnd], 0))->attributes &
508 if (wordEnd == srcmax)
510 /* At this stage wordStart is the 0 based index of the first letter in the word,
511 * wordEnd is the 0 based index of the last letter in the word.
512 * example: "hello" wordstart=0, wordEnd=4. */
513 wordSize = wordEnd - wordStart + 1;
514 hyphens = (char *) calloc (wordSize + 1, sizeof (char));
515 if (!hyphenate (¤tInput[wordStart], wordSize, hyphens))
520 for (k = src - wordStart + 1; k < (src - wordStart + transCharslen); k++)
530 static TranslationTableCharacter *curCharDef;
531 static widechar before, after;
532 static TranslationTableCharacterAttributes beforeAttributes;
533 static TranslationTableCharacterAttributes afterAttributes;
537 if (src >= 2 && currentInput[src - 1] == ENDSEGMENT)
538 before = currentInput[src - 2];
540 before = (src == 0) ? ' ' : currentInput[src - 1];
541 beforeAttributes = (findCharOrDots (before, 0))->attributes;
545 setAfter (int length)
547 if ((src + length + 2) < srcmax && currentInput[src + 1] == ENDSEGMENT)
548 after = currentInput[src + 2];
550 after = (src + length < srcmax) ? currentInput[src + length] : ' ';
551 afterAttributes = (findCharOrDots (after, 0))->attributes;
554 static int prevTypeform = plain_text;
555 static int prevSrc = 0;
556 static TranslationTableRule pseudoRule = {
561 brailleIndicatorDefined (TranslationTableOffset offset)
565 indicRule = (TranslationTableRule *) & table->ruleArea[offset];
566 indicOpcode = indicRule->opcode;
570 static int prevType = plain_text;
571 static int curType = plain_text;
585 static int wordsMarked = 0;
586 static int finishEmphasis = 0;
587 static int wordCount = 0;
588 static int lastWord = 0;
589 static int startType = -1;
590 static int endType = 0;
593 markWords (const TranslationTableOffset * offset)
595 /*Mark the beginnings of words*/
599 numWords = offset[lenPhrase];
602 if (wordCount < numWords)
604 for (k = src; k < endType; k++)
605 if (!checkAttr (currentInput[k - 1], CTC_Letter | CTC_Digit, 0) &&
606 checkAttr (currentInput[k], CTC_Digit | CTC_Letter, 0))
607 typebuf[k] |= STARTWORD;
613 for (k = src; k < endType; k++)
615 if (!checkAttr (currentInput[k - 1], CTC_Letter | CTC_Digit, 0)
616 && checkAttr (currentInput[k], CTC_Digit | CTC_Letter, 0))
620 typebuf[k] |= FIRSTWORD;
627 typebuf[lastWord] |= STARTWORD;
634 /*Insert italic, bold, etc. indicators before words*/
637 if (!wordsMarked || !haveEmphasis)
639 typeMark = typebuf[src] & (STARTWORD | FIRSTWORD);
642 switch (typebuf[src] & EMPHASIS)
645 if ((typeMark & FIRSTWORD))
646 ruleFound = brailleIndicatorDefined (table->firstWordItal);
648 ruleFound = brailleIndicatorDefined (table->lastWordItalBefore);
651 if ((typeMark & FIRSTWORD))
652 ruleFound = brailleIndicatorDefined (table->firstWordBold);
654 ruleFound = brailleIndicatorDefined (table->lastWordBoldBefore);
657 if ((typeMark & FIRSTWORD))
658 ruleFound = brailleIndicatorDefined (table->firstWordUnder);
660 ruleFound = brailleIndicatorDefined (table->lastWordUnderBefore);
668 if (!for_updatePositions
669 (&indicRule->charsdots[0], 0, indicRule->dotslen))
678 /*Analyze the typeform parameter and also check for capitalization*/
679 TranslationTableCharacter *currentInputChar;
680 TranslationTableCharacter *ruleChar;
681 TranslationTableCharacterAttributes prevAttr = 0;
686 for (k = src; k < src + transCharslen; k++)
688 if (currentInput[k] == ENDSEGMENT)
690 if (k == src && transCharslen == 1)
695 currentInputChar = findCharOrDots (currentInput[k], 0);
697 prevAttr = currentInputChar->attributes;
698 ruleChar = findCharOrDots (transRule->charsdots[kk++], 0);
699 if ((currentInputChar->lowercase != ruleChar->lowercase))
701 if (typebuf != NULL && (typebuf[src] & capsemph) == 0 &&
702 (typebuf[k] | typebuf[src]) != (typebuf[src]))
704 if (currentInputChar->attributes != CTC_Letter)
706 if (k != (src + 1) && (prevAttr &
708 && (currentInputChar->attributes & CTC_Letter)
711 attributes & (CTC_LowerCase | CTC_UpperCase |
713 (prevAttr & (CTC_LowerCase | CTC_UpperCase | CTC_Letter))))
716 prevAttr = currentInputChar->attributes;
725 for (k = 0; k < table->lenBeginCaps; k++)
726 if (k >= srcmax - src ||
727 !checkAttr (currentInput[src + k], CTC_UpperCase, 0))
732 static int prevPrevType = 0;
733 static int nextType = 0;
734 static TranslationTableCharacterAttributes prevPrevAttr = 0;
737 beginEmphasis (const TranslationTableOffset * offset)
739 if (src != startType)
741 wordCount = finishEmphasis = wordsMarked = 0;
742 startType = lastWord = src;
743 for (endType = src; endType < srcmax; endType++)
745 if ((typebuf[endType] & EMPHASIS) != curType)
747 if (checkAttr (currentInput[endType - 1], CTC_Space, 0)
748 && !checkAttr (currentInput[endType], CTC_Space, 0))
755 if ((beforeAttributes & CTC_Letter) && (endType - startType) ==
756 1 && brailleIndicatorDefined (offset[singleLetter]))
759 if ((beforeAttributes & CTC_Letter) && brailleIndicatorDefined
760 (offset[firstLetter]))
762 else if (brailleIndicatorDefined (offset[lastWordBefore]))
768 return (brailleIndicatorDefined (offset[firstWord]));
773 endEmphasis (const TranslationTableOffset * offset)
777 if (prevPrevType != prevType && nextType != prevType &&
778 brailleIndicatorDefined (offset[singleLetter]))
781 if ((finishEmphasis || (src < srcmax && ((findCharOrDots
782 (currentInput[src + 1],
785 && brailleIndicatorDefined (offset[lastLetter]))
788 return (brailleIndicatorDefined (offset[lastWordAfter]));
796 for (endEmph = src; (typebuf[endEmph] & computer_braille) && endEmph
797 <= srcmax; endEmph++);
798 return doCompTrans (src, endEmph);
802 insertBrailleIndicators (int finish)
804 /*Insert braille indicators such as italic, bold, capital,
805 * letter, number, etc.*/
818 checkThis checkWhat = checkNothing;
823 while (dest > 0 && (currentOutput[dest - 1] == 0 ||
824 currentOutput[dest - 1] == B16))
827 prevType = prevPrevType;
828 curType = plain_text;
829 checkWhat = checkEndTypeform;
833 if (src == prevSrc && !finish)
837 if (haveEmphasis && src < srcmax)
838 nextType = typebuf[src + 1] & EMPHASIS;
840 nextType = plain_text;
844 prevPrevType = typebuf[src - 2] & EMPHASIS;
846 prevPrevType = plain_text;
848 (findCharOrDots (currentInput[src - 2], 0))->attributes;
852 prevPrevType = plain_text;
853 prevPrevAttr = CTC_Space;
855 if (haveEmphasis && (typebuf[src] & EMPHASIS) != prevTypeform)
857 prevType = prevTypeform & EMPHASIS;
858 curType = typebuf[src] & EMPHASIS;
859 checkWhat = checkEndTypeform;
862 checkWhat = checkNothing;
864 checkWhat = checkNumber;
867 checkWhat = checkNumber;
877 case checkBeginTypeform:
885 ok = beginEmphasis (&table->firstWordItal);
889 ok = beginEmphasis (&table->firstWordBold);
893 ok = beginEmphasis (&table->firstWordUnder);
896 case computer_braille:
901 case italic + underline:
902 ok = beginEmphasis (&table->firstWordUnder);
903 curType -= underline;
906 ok = beginEmphasis (&table->firstWordBold);
909 case italic + computer_braille:
912 curType -= computer_braille;
914 case underline + bold:
915 beginEmphasis (&table->firstWordBold);
918 case underline + computer_braille:
921 curType -= computer_braille;
923 case bold + computer_braille:
926 curType -= computer_braille;
936 checkWhat = checkNothing;
938 checkWhat = checkNumber;
941 case checkEndTypeform:
949 ok = endEmphasis (&table->firstWordItal);
953 ok = endEmphasis (&table->firstWordBold);
957 ok = endEmphasis (&table->firstWordUnder);
960 case computer_braille:
964 case italic + underline:
965 ok = endEmphasis (&table->firstWordUnder);
966 prevType -= underline;
969 ok = endEmphasis (&table->firstWordBold);
972 case italic + computer_braille:
974 prevType -= computer_braille;
976 case underline + bold:
977 ok = endEmphasis (&table->firstWordBold);
980 case underline + computer_braille:
982 prevType -= computer_braille;
984 case bold + computer_braille:
985 ok = endEmphasis (&table->firstWordBold);
993 if (prevType == plain_text)
995 checkWhat = checkBeginTypeform;
996 prevTypeform = typebuf[src] & EMPHASIS;
1000 if (brailleIndicatorDefined
1001 (table->numberSign) &&
1002 checkAttr (currentInput[src], CTC_Digit, 0) &&
1003 (prevTransOpcode == CTO_ExactDots
1004 || !(beforeAttributes & CTC_Digit))
1005 && prevTransOpcode != CTO_MidNum)
1008 checkWhat = checkNothing;
1011 checkWhat = checkLetter;
1014 if (!brailleIndicatorDefined (table->letterSign))
1017 checkWhat = checkBeginMultCaps;
1020 if (transOpcode == CTO_Contraction)
1023 checkWhat = checkBeginMultCaps;
1026 if ((checkAttr (currentInput[src], CTC_Letter, 0)
1027 && !(beforeAttributes & CTC_Letter))
1028 && (!checkAttr (currentInput[src + 1], CTC_Letter, 0)
1029 || (beforeAttributes & CTC_Digit)))
1033 for (k = 0; k < table->noLetsignBeforeCount; k++)
1034 if (currentInput[src - 1] == table->noLetsignBefore[k])
1039 for (k = 0; k < table->noLetsignCount; k++)
1040 if (currentInput[src] == table->noLetsign[k])
1045 if ((src + 1) < srcmax)
1046 for (k = 0; k < table->noLetsignAfterCount; k++)
1047 if (currentInput[src + 1] == table->noLetsignAfter[k])
1053 checkWhat = checkBeginMultCaps;
1055 case checkBeginMultCaps:
1056 if (brailleIndicatorDefined (table->beginCapitalSign) &&
1057 !(beforeAttributes & CTC_UpperCase) && checkMultCaps ())
1060 if (table->capsNoCont)
1062 checkWhat = checkNothing;
1065 checkWhat = checkSingleCap;
1067 case checkEndMultCaps:
1068 if (brailleIndicatorDefined (table->endCapitalSign) &&
1069 (prevPrevAttr & CTC_UpperCase)
1070 && (beforeAttributes & CTC_UpperCase)
1071 && checkAttr (currentInput[src], CTC_LowerCase, 0))
1074 if (table->capsNoCont)
1077 checkWhat = checkNothing;
1079 case checkSingleCap:
1080 if (brailleIndicatorDefined (table->capitalSign) && src < srcmax
1081 && checkAttr (currentInput[src], CTC_UpperCase, 0) &&
1082 (!(beforeAttributes & CTC_UpperCase) ||
1083 table->beginCapitalSign == 0))
1086 checkWhat = checkNothing;
1088 checkWhat = checkEndMultCaps;
1092 checkWhat = checkNothing;
1095 if (ok && indicRule != NULL)
1097 if (!for_updatePositions
1098 (&indicRule->charsdots[0], 0, indicRule->dotslen))
1100 if (cursorStatus == 2)
1101 checkWhat = checkNothing;
1104 while (checkWhat != checkNothing);
1110 onlyLettersBehind ()
1112 /* Actually, spaces, then letters */
1114 if (!(beforeAttributes & CTC_Space))
1116 for (k = src - 2; k >= 0; k--)
1118 TranslationTableCharacterAttributes attr = (findCharOrDots
1121 if ((attr & CTC_Space))
1123 if ((attr & CTC_Letter))
1134 /* Actullly, spaces, then letters */
1136 if (!(afterAttributes & CTC_Space))
1138 for (k = src + transCharslen + 1; k < srcmax; k++)
1140 TranslationTableCharacterAttributes attr = (findCharOrDots
1143 if ((attr & CTC_Space))
1145 if ((attr & (CTC_Letter | CTC_LitDigit)))
1156 int start = src + transCharslen;
1159 if (start >= srcmax)
1161 while (start < srcmax && checkAttr (currentInput[start], CTC_Space, 0))
1163 if (start == srcmax || (transOpcode == CTO_JoinableWord && (!checkAttr
1176 while (end < srcmax && !checkAttr (currentInput[end], CTC_Space, 0))
1178 if ((mode & (compbrlAtCursor | compbrlLeftCursor)) && cursorPosition
1179 >= start && cursorPosition < end)
1181 /* Look ahead for rules with CTO_CompBrl */
1182 for (curSrc = start; curSrc < end; curSrc++)
1184 int length = srcmax - curSrc;
1186 const TranslationTableCharacter *character1;
1187 const TranslationTableCharacter *character2;
1189 character1 = findCharOrDots (currentInput[curSrc], 0);
1190 for (tryThis = 0; tryThis < 2; tryThis++)
1192 TranslationTableOffset ruleOffset = 0;
1193 TranslationTableRule *testRule;
1194 unsigned long int makeHash = 0;
1200 /*Hash function optimized for forward translation */
1201 makeHash = (unsigned long int) character1->lowercase << 8;
1202 character2 = findCharOrDots (currentInput[curSrc + 1], 0);
1203 makeHash += (unsigned long int) character2->lowercase;
1204 makeHash %= HASHNUM;
1205 ruleOffset = table->forRules[makeHash];
1211 ruleOffset = character1->otherRules;
1217 (TranslationTableRule *) & table->ruleArea[ruleOffset];
1218 for (k = 0; k < testRule->charslen; k++)
1220 character1 = findCharOrDots (testRule->charsdots[k], 0);
1221 character2 = findCharOrDots (currentInput[curSrc + k], 0);
1222 if (character1->lowercase != character2->lowercase)
1225 if (tryThis == 1 || k == testRule->charslen)
1227 if (testRule->opcode == CTO_CompBrl
1228 || testRule->opcode == CTO_Literal)
1231 ruleOffset = testRule->charsnext;
1238 static widechar const *repwordStart;
1239 static int repwordLength;
1244 if (src == 0 || !checkAttr (currentInput[src - 1], CTC_Letter, 0))
1246 if ((src + transCharslen) >= srcmax || !checkAttr (currentInput[src +
1250 for (start = src - 2;
1251 start >= 0 && checkAttr (currentInput[start], CTC_Letter, 0); start--);
1253 repwordStart = ¤tInput[start];
1254 repwordLength = src - start;
1255 if (compareChars (repwordStart, ¤tInput[src
1265 /*check for valid Translations. Return value is in transRule. */
1266 int length = srcmax - src;
1268 const TranslationTableCharacter *character2;
1270 curCharDef = findCharOrDots (currentInput[src], 0);
1271 for (tryThis = 0; tryThis < 3; tryThis++)
1273 TranslationTableOffset ruleOffset = 0;
1274 unsigned long int makeHash = 0;
1280 /*Hash function optimized for forward translation */
1281 makeHash = (unsigned long int) curCharDef->lowercase << 8;
1282 character2 = findCharOrDots (currentInput[src + 1], 0);
1283 makeHash += (unsigned long int) character2->lowercase;
1284 makeHash %= HASHNUM;
1285 ruleOffset = table->forRules[makeHash];
1291 ruleOffset = curCharDef->otherRules;
1293 case 2: /*No rule found */
1294 transRule = &pseudoRule;
1295 transOpcode = pseudoRule.opcode = CTO_None;
1296 transCharslen = pseudoRule.charslen = 1;
1297 pseudoRule.charsdots[0] = currentInput[src];
1298 pseudoRule.dotslen = 0;
1304 transRule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
1305 transOpcode = transRule->opcode;
1306 transCharslen = transRule->charslen;
1307 if (tryThis == 1 || ((transCharslen <= length) && validMatch ()))
1309 /* check this rule */
1310 setAfter (transCharslen);
1311 if ((!transRule->after || (beforeAttributes
1312 & transRule->after)) &&
1313 (!transRule->before || (afterAttributes
1314 & transRule->before)))
1315 switch (transOpcode)
1316 { /*check validity of this Translation */
1323 case CTO_Punctuation:
1332 if ((mode & (compbrlAtCursor | compbrlLeftCursor))
1333 && src >= compbrlStart && src <= compbrlEnd)
1337 if (dontContract || (mode & noContractions))
1339 if (isRepeatedWord ())
1343 if (dontContract || (mode & noContractions))
1347 transOpcode = CTO_Always;
1349 if (dontContract || (mode & noContractions))
1355 if (syllableBreak ())
1359 if (!srcIncremented || !passDoTest ())
1363 if (dontContract || (mode & noContractions))
1365 if (!((beforeAttributes & (CTC_Space
1367 || onlyLettersBehind ())
1368 || !((afterAttributes & CTC_Space)
1369 || prevTransOpcode == CTO_LargeSign)
1370 || (afterAttributes & CTC_Letter)
1371 || !noCompbrlAhead ())
1372 transOpcode = CTO_Always;
1375 if (dontContract || (mode & noContractions))
1377 case CTO_Contraction:
1378 if ((beforeAttributes & (CTC_Space | CTC_Punctuation))
1379 && (afterAttributes & (CTC_Space | CTC_Punctuation)))
1383 if (dontContract || (mode & noContractions))
1385 if ((beforeAttributes & CTC_Letter)
1386 || (afterAttributes & CTC_Letter))
1390 if (dontContract || (mode & noContractions))
1392 if ((beforeAttributes & (CTC_Space | CTC_Punctuation))
1394 (afterAttributes & CTC_Space) &&
1395 (dest + transRule->dotslen < destmax))
1397 int cursrc = src + transCharslen + 1;
1398 while (cursrc < srcmax)
1401 (currentInput[cursrc], CTC_Space, 0))
1404 (currentInput[cursrc], CTC_Digit, 0))
1413 if (dontContract || (mode & noContractions))
1415 if ((beforeAttributes & CTC_Space)
1416 && (afterAttributes & CTC_Space)
1417 && (prevTransOpcode != CTO_JoinableWord))
1420 case CTO_JoinableWord:
1421 if (dontContract || (mode & noContractions))
1423 if (beforeAttributes & (CTC_Space | CTC_Punctuation)
1424 && onlyLettersAhead () && noCompbrlAhead ())
1427 case CTO_SuffixableWord:
1428 if (dontContract || (mode & noContractions))
1430 if ((beforeAttributes & (CTC_Space | CTC_Punctuation))
1431 && (afterAttributes &
1432 (CTC_Space | CTC_Letter | CTC_Punctuation)))
1435 case CTO_PrefixableWord:
1436 if (dontContract || (mode & noContractions))
1438 if ((beforeAttributes &
1439 (CTC_Space | CTC_Letter | CTC_Punctuation))
1440 && (afterAttributes & (CTC_Space | CTC_Punctuation)))
1444 if (dontContract || (mode & noContractions))
1446 if ((beforeAttributes & (CTC_Space | CTC_Punctuation))
1447 && (afterAttributes & CTC_Letter))
1450 case CTO_BegMidWord:
1451 if (dontContract || (mode & noContractions))
1453 if ((beforeAttributes &
1454 (CTC_Letter | CTC_Space | CTC_Punctuation))
1455 && (afterAttributes & CTC_Letter))
1459 if (dontContract || (mode & noContractions))
1461 if (beforeAttributes & CTC_Letter
1462 && afterAttributes & CTC_Letter)
1465 case CTO_MidEndWord:
1466 if (dontContract || (mode & noContractions))
1468 if (beforeAttributes & CTC_Letter
1469 && afterAttributes & (CTC_Letter | CTC_Space |
1474 if (dontContract || (mode & noContractions))
1476 if (beforeAttributes & CTC_Letter
1477 && afterAttributes & (CTC_Space | CTC_Punctuation))
1481 if (beforeAttributes & (CTC_Space | CTC_Punctuation)
1482 && afterAttributes & CTC_Digit)
1486 if (prevTransOpcode != CTO_ExactDots
1487 && beforeAttributes & CTC_Digit
1488 && afterAttributes & CTC_Digit)
1492 if (beforeAttributes & CTC_Digit &&
1493 prevTransOpcode != CTO_ExactDots)
1497 if (!(afterAttributes & CTC_Digit))
1499 if (beforeAttributes & CTC_Digit)
1500 transOpcode = CTO_MidNum;
1503 if (!checkAttr (currentInput[src], CTC_Punctuation, 0)
1505 && checkAttr (currentInput[src - 1], CTC_Letter,
1508 for (k = src + transCharslen; k < srcmax; k++)
1511 (currentInput[k], (CTC_Letter | CTC_Digit), 0))
1513 if (checkAttr (currentInput[k], CTC_Space, 0))
1518 if (!checkAttr (currentInput[src], CTC_Punctuation, 0)
1519 || (src < (srcmax - 1)
1520 && checkAttr (currentInput[src + 1], CTC_Letter,
1523 for (k = src; k >= 0; k--)
1526 (currentInput[k], (CTC_Letter | CTC_Digit), 0))
1528 if (checkAttr (currentInput[k], CTC_Space, 0))
1536 /*Done with checking this rule */
1537 ruleOffset = transRule->charsnext;
1543 undefinedCharacter (widechar c)
1545 /*Display an undefined character in the output buffer*/
1548 widechar displayDots[20];
1549 if (table->undefined)
1551 TranslationTableRule *transRule = (TranslationTableRule *)
1552 & table->ruleArea[table->undefined];
1553 if (!for_updatePositions
1554 (&transRule->charsdots[transRule->charslen],
1555 transRule->charslen, transRule->dotslen))
1559 display = showString (&c, 1);
1560 for (k = 0; k < strlen (display); k++)
1561 displayDots[k] = getDotsForChar (display[k]);
1562 if (!for_updatePositions (displayDots, 1, strlen(display)))
1568 putCharacter (widechar character)
1570 /*Insert the dots equivalent of a character into the output buffer */
1571 TranslationTableCharacter *chardef;
1572 TranslationTableOffset offset;
1573 if (cursorStatus == 2)
1575 chardef = (findCharOrDots (character, 0));
1576 if ((chardef->attributes & CTC_Letter) && (chardef->attributes &
1578 chardef = findCharOrDots (chardef->lowercase, 0);
1579 offset = chardef->definitionRule;
1582 const TranslationTableRule *rule = (TranslationTableRule *)
1583 & table->ruleArea[offset];
1585 return for_updatePositions (&rule->charsdots[1], 1, rule->dotslen);
1587 widechar d = getDotsForChar (character);
1588 return for_updatePositions (&d, 1, 1);
1591 return undefinedCharacter (character);
1595 putCharacters (const widechar * characters, int count)
1597 /*Insert the dot equivalents of a series of characters in the output
1600 for (k = 0; k < count; k++)
1601 if (!putCharacter (characters[k]))
1609 /*Handle strings containing substrings defined by the compbrl opcode*/
1610 int stringStart, stringEnd;
1611 if (checkAttr (currentInput[src], CTC_Space, 0))
1623 for (stringStart = src; stringStart >= 0; stringStart--)
1624 if (checkAttr (currentInput[stringStart], CTC_Space, 0))
1627 for (stringEnd = src; stringEnd < srcmax; stringEnd++)
1628 if (checkAttr (currentInput[stringEnd], CTC_Space, 0))
1630 return (doCompTrans (stringStart, stringEnd));
1634 putCompChar (widechar character)
1636 /*Insert the dots equivalent of a character into the output buffer */
1637 TranslationTableOffset offset = (findCharOrDots
1638 (character, 0))->definitionRule;
1641 const TranslationTableRule *rule = (TranslationTableRule *)
1642 & table->ruleArea[offset];
1644 return for_updatePositions (&rule->charsdots[1], 1, rule->dotslen);
1646 widechar d = getDotsForChar (character);
1647 return for_updatePositions (&d, 1, 1);
1650 return undefinedCharacter (character);
1654 doCompTrans (int start, int end)
1657 int haveEndsegment = 0;
1658 if (cursorStatus != 2 && brailleIndicatorDefined (table->begComp))
1659 if (!for_updatePositions
1660 (&indicRule->charsdots[0], 0, indicRule->dotslen))
1662 for (k = start; k < end; k++)
1664 TranslationTableOffset compdots = 0;
1665 if (currentInput[k] == ENDSEGMENT)
1671 if (currentInput[k] < 256)
1672 compdots = table->compdotsPattern[currentInput[k]];
1675 transRule = (TranslationTableRule *) & table->ruleArea[compdots];
1676 if (!for_updatePositions
1677 (&transRule->charsdots[transRule->charslen],
1678 transRule->charslen, transRule->dotslen))
1681 else if (!putCompChar (currentInput[k]))
1684 if (cursorStatus != 2 && brailleIndicatorDefined (table->endComp))
1685 if (!for_updatePositions
1686 (&indicRule->charsdots[0], 0, indicRule->dotslen))
1691 widechar endSegment = ENDSEGMENT;
1692 if (!for_updatePositions (&endSegment, 0, 1))
1701 /*Handle strings containing substrings defined by the nocont opcode*/
1702 if (checkAttr (currentInput[src], CTC_Space, 0) || dontContract
1703 || (mode & noContractions))
1723 int syllableMarker = 0;
1724 int currentMark = 0;
1725 if (typebuf == NULL || !table->syllables)
1728 while (src < srcmax)
1729 { /*the main multipass translation loop */
1730 int length = srcmax - src;
1731 const TranslationTableCharacter *character = findCharOrDots
1732 (currentInput[src], 0);
1733 const TranslationTableCharacter *character2;
1737 TranslationTableOffset ruleOffset = 0;
1738 unsigned long int makeHash = 0;
1744 makeHash = (unsigned long int) character->lowercase << 8;
1745 character2 = findCharOrDots (currentInput[src + 1], 0);
1746 makeHash += (unsigned long int) character2->lowercase;
1747 makeHash %= HASHNUM;
1748 ruleOffset = table->forRules[makeHash];
1754 ruleOffset = character->otherRules;
1756 case 2: /*No rule found */
1757 transOpcode = CTO_Always;
1764 (TranslationTableRule *) & table->ruleArea[ruleOffset];
1765 transOpcode = transRule->opcode;
1766 transCharslen = transRule->charslen;
1767 if (tryThis == 1 || (transCharslen <= length &&
1768 compareChars (&transRule->
1773 if (transOpcode == CTO_Syllable)
1779 ruleOffset = transRule->charsnext;
1783 switch (transOpcode)
1788 if (typebuf != NULL)
1789 typebuf[src++] |= currentMark;
1793 if (syllableMarker > 3)
1795 currentMark = syllableMarker << 6;
1796 /*The syllable marker is bits 6 and 7 of typebuf. */
1797 if ((src + transCharslen) > srcmax)
1799 for (k = 0; k < transCharslen; k++)
1800 typebuf[src++] |= currentMark;
1812 /*Main translation routine */
1816 destword = 0; /* last word translated */
1818 prevTransOpcode = CTO_None;
1820 prevType = prevPrevType = curType = nextType = prevTypeform = plain_text;
1821 startType = prevSrc = -1;
1824 memset (passVariables, 0, sizeof(int) * NUMVAR);
1825 if (typebuf && table->capitalSign)
1826 for (k = 0; k < srcmax; k++)
1827 if (checkAttr (currentInput[k], CTC_UpperCase, 0))
1828 typebuf[k] |= capsemph;
1829 while (src < srcmax)
1830 { /*the main translation loop */
1832 if (!insertBrailleIndicators (0))
1836 if (!insertIndicators ())
1839 if (appliedRules != NULL && appliedRulesCount < maxAppliedRules)
1840 appliedRules[appliedRulesCount++] = transRule;
1843 switch (transOpcode) /*Rules that pre-empt context and swap */
1853 if (!insertBrailleIndicators (1))
1855 if (transOpcode == CTO_Context || findAttribOrSwapRules ())
1856 switch (transOpcode)
1859 if (appliedRules != NULL && appliedRulesCount < maxAppliedRules)
1860 appliedRules[appliedRulesCount++] = transRule;
1861 if (!passDoAction ())
1863 if (endReplace == src)
1871 /*Processing before replacement*/
1872 switch (transOpcode)
1875 if (table->letterSign && checkAttr (currentInput[src],
1884 if (prevTransOpcode == CTO_LargeSign)
1886 int hasEndSegment = 0;
1887 while (dest > 0 && checkAttr (currentOutput[dest - 1], CTC_Space, 1))
1889 if (currentOutput[dest - 1] == ENDSEGMENT)
1895 if (hasEndSegment != 0)
1897 currentOutput[dest] = 0xffff;
1903 if (table->numberSign)
1905 TranslationTableRule *numRule = (TranslationTableRule *)
1906 & table->ruleArea[table->numberSign];
1907 if (!for_updatePositions
1908 (&numRule->charsdots[numRule->charslen],
1909 numRule->charslen, numRule->dotslen))
1912 transOpcode = CTO_MidNum;
1920 } /*end of action */
1922 /* replacement processing */
1923 switch (transOpcode)
1926 src += transCharslen;
1928 (&transRule->charsdots[transCharslen], transRule->dotslen))
1932 if (!undefinedCharacter (currentInput[src]))
1937 /* Only needs special handling if not within compbrl and
1938 *the table defines a capital sign. */
1940 (mode & (compbrlAtCursor | compbrlLeftCursor) && src >=
1942 && src <= compbrlEnd) && (transRule->dotslen == 1
1943 && table->capitalSign))
1945 putCharacter (curCharDef->lowercase);
1950 if (cursorStatus == 2)
1954 if (transRule->dotslen)
1956 if (!for_updatePositions
1957 (&transRule->charsdots[transCharslen],
1958 transCharslen, transRule->dotslen))
1963 for (k = 0; k < transCharslen; k++)
1965 if (!putCharacter (currentInput[src]))
1970 if (cursorStatus == 2)
1972 else if (transRule->dotslen)
1973 src += transCharslen;
1978 /* processing after replacement */
1979 switch (transOpcode)
1983 /* Skip repeated characters. */
1984 int srclim = srcmax - transCharslen;
1985 if (mode & (compbrlAtCursor | compbrlLeftCursor) &&
1986 compbrlStart < srclim)
1987 /* Don't skip characters from compbrlStart onwards. */
1988 srclim = compbrlStart - 1;
1989 while ((src <= srclim)
1990 && compareChars (&transRule->charsdots[0],
1991 ¤tInput[src], transCharslen, 0))
1993 /* Map skipped input positions to the previous output position. */
1994 if (outputPositions != NULL)
1997 for (tcc = 0; tcc < transCharslen; tcc++)
1998 outputPositions[prevSrcMapping[src + tcc]] = dest - 1;
2000 if (!cursorStatus && src <= cursorPosition
2001 && cursorPosition < src + transCharslen)
2004 cursorPosition = dest - 1;
2006 src += transCharslen;
2012 /* Skip repeated characters. */
2013 int srclim = srcmax - transCharslen;
2014 if (mode & (compbrlAtCursor | compbrlLeftCursor) &&
2015 compbrlStart < srclim)
2016 /* Don't skip characters from compbrlStart onwards. */
2017 srclim = compbrlStart - 1;
2018 while ((src <= srclim)
2019 && compareChars (repwordStart,
2020 ¤tInput[src], repwordLength, 0))
2022 /* Map skipped input positions to the previous output position. */
2023 if (outputPositions != NULL)
2026 for (tcc = 0; tcc < transCharslen; tcc++)
2027 outputPositions[prevSrcMapping[src + tcc]] = dest - 1;
2029 if (!cursorStatus && src <= cursorPosition
2030 && cursorPosition < src + transCharslen)
2033 cursorPosition = dest - 1;
2035 src += repwordLength + transCharslen;
2037 src -= transCharslen;
2041 case CTO_JoinableWord:
2043 && checkAttr (currentInput[src], CTC_Space, 0) &&
2044 currentInput[src] != ENDSEGMENT)
2050 if (((src > 0) && checkAttr (currentInput[src - 1], CTC_Space, 0)
2051 && (transOpcode != CTO_JoinableWord)))
2056 if (srcSpacing != NULL && srcSpacing[src] >= '0' && srcSpacing[src] <=
2058 destSpacing[dest] = srcSpacing[src];
2059 if ((transOpcode >= CTO_Always && transOpcode <= CTO_None) ||
2060 (transOpcode >= CTO_Digit && transOpcode <= CTO_LitDigit))
2061 prevTransOpcode = transOpcode;
2062 } /*end of translation loop */
2063 if (haveEmphasis && !wordsMarked && prevPrevType != plain_text)
2064 insertBrailleIndicators (2);
2066 if (destword != 0 && src < srcmax
2067 && !checkAttr (currentInput[src], CTC_Space, 0))
2074 while (checkAttr (currentInput[src], CTC_Space, 0))
2075 if (++src == srcmax)
2080 } /*first pass translation completed */
2083 lou_hyphenate (const char *tableList, const widechar
2084 * inbuf, int inlen, char *hyphens, int mode)
2086 #define HYPHSTRING 100
2087 widechar workingBuffer[HYPHSTRING];
2091 table = lou_getTable (tableList);
2092 if (table == NULL || inbuf == NULL || hyphens
2093 == NULL || table->hyphenStatesArray == 0 || inlen >= HYPHSTRING)
2099 if (!lou_backTranslate (tableList, inbuf, &k,
2101 &kk, NULL, NULL, NULL, NULL, NULL, 0))
2106 memcpy (&workingBuffer[0], inbuf, CHARSIZE * inlen);
2109 for (wordStart = 0; wordStart < kk; wordStart++)
2110 if (((findCharOrDots (workingBuffer[wordStart], 0))->attributes &
2113 if (wordStart == kk)
2115 for (wordEnd = kk - 1; wordEnd >= 0; wordEnd--)
2116 if (((findCharOrDots (workingBuffer[wordEnd], 0))->attributes &
2119 for (k = wordStart; k <= wordEnd; k++)
2121 TranslationTableCharacter *c = findCharOrDots (workingBuffer[k], 0);
2122 if (!(c->attributes & CTC_Letter))
2126 (&workingBuffer[wordStart], wordEnd - wordStart + 1,
2127 &hyphens[wordStart]))
2129 for (k = 0; k <= wordStart; k++)
2133 widechar workingBuffer2[HYPHSTRING];
2134 int outputPos[HYPHSTRING];
2135 char hyphens2[HYPHSTRING];
2136 kk = wordEnd - wordStart + 1;
2138 if (!lou_translate (tableList, &workingBuffer[wordStart], &kk,
2139 &workingBuffer2[0], &k, NULL,
2140 NULL, &outputPos[0], NULL, NULL, 0))
2142 for (kk = 0; kk < k; kk++)
2144 int hyphPos = outputPos[kk];
2145 if (hyphPos > k || hyphPos < 0)
2147 if (hyphens[wordStart + kk] & 1)
2148 hyphens2[hyphPos] = '1';
2150 hyphens2[hyphPos] = '0';
2152 for (kk = wordStart; kk < wordStart + k; kk++)
2153 if (!table->noBreak || hyphens2[kk] == '0')
2154 hyphens[kk] = hyphens2[kk];
2157 TranslationTableRule *noBreakRule = (TranslationTableRule *)
2158 & table->ruleArea[table->noBreak];
2161 for (kkk = 0; kkk < noBreakRule->charslen; kkk++)
2162 if (workingBuffer2[kk - 1] == noBreakRule->charsdots[kkk])
2167 for (kkk = 0; kkk < noBreakRule->dotslen; kkk++);
2168 if (workingBuffer2[kk] ==
2169 noBreakRule->charsdots[noBreakRule->charslen + kkk])
2176 for (k = 0; k < inlen; k++)
2186 lou_dotsToChar (const char *tableList, widechar * inbuf, widechar * outbuf,
2187 int length, int mode)
2191 if (tableList == NULL || inbuf == NULL || outbuf == NULL)
2193 if ((mode & otherTrans))
2194 return other_dotsToChar (tableList, inbuf, outbuf, length, mode);
2195 table = lou_getTable (tableList);
2196 if (table == NULL || length <= 0)
2198 for (k = 0; k < length; k++)
2201 if (!(dots & B16) && (dots & 0xff00) == 0x2800) /*Unicode braille */
2202 dots = (dots & 0x00ff) | B16;
2203 outbuf[k] = getCharFromDots (dots);
2209 lou_charToDots (const char *tableList, const widechar * inbuf, widechar *
2210 outbuf, int length, int mode)
2213 if (tableList == NULL || inbuf == NULL || outbuf == NULL)
2215 if ((mode & otherTrans))
2216 return other_charToDots (tableList, inbuf, outbuf, length, mode);
2218 table = lou_getTable (tableList);
2219 if (table == NULL || length <= 0)
2221 for (k = 0; k < length; k++)
2223 outbuf[k] = ((getDotsForChar (inbuf[k]) & 0xff) | 0x2800);
2225 outbuf[k] = getDotsForChar (inbuf[k]);