4 * Miscellaneous utility functions.
6 * Copyright (c) 1995 Christian Werner.
8 * See the file "license.terms" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
22 char type; /* Type of char, see definitions above. */
23 char width; /* Width if replaced by backslash sequence. */
27 char *name; /* Name for this encoding table. */
28 struct charType ct[256]; /* Encoding table. */
32 * For ISO8859, codes 0x81..0x99 are mapped to ACS characters
33 * according to this table:
36 static char *gcharTab[] = {
37 "ulcorner", "llcorner", "urcorner", "lrcorner",
38 "ltee", "rtee", "btee", "ttee",
39 "hline", "vline", "plus", "s1",
40 "s9", "diamond", "ckboard", "degree",
41 "plminus", "bullet", "larrow", "rarrow",
42 "darrow", "uarrow", "board", "lantern",
46 static struct charEncoding EncodingTable[] = {
49 *----------------------------------------------------------------------
53 *----------------------------------------------------------------------
59 { REPLACE, 4 }, /* \x00 */
60 { REPLACE, 4 }, /* \x01 */
61 { REPLACE, 4 }, /* \x02 */
62 { REPLACE, 4 }, /* \x03 */
63 { REPLACE, 4 }, /* \x04 */
64 { REPLACE, 4 }, /* \x05 */
65 { REPLACE, 4 }, /* \x06 */
66 { REPLACE, 4 }, /* \x07 */
67 { REPLACE, 2 }, /* \b */
69 { NEWLINE, 2 }, /* \n */
70 { REPLACE, 4 }, /* \x0b */
71 { REPLACE, 2 }, /* \f */
72 { REPLACE, 2 }, /* \r */
73 { REPLACE, 4 }, /* 0x0e */
74 { REPLACE, 4 }, /* 0x0f */
77 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
78 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
79 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
80 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
83 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
84 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
85 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
86 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
89 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
90 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
91 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
92 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
95 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
96 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
97 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
98 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
101 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
102 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
103 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
104 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
107 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
108 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
109 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
110 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
113 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
114 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
115 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
116 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
118 { REPLACE, 4 }, /* 0x7f */
121 { REPLACE, 4 }, { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 },
122 { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 },
123 { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 },
124 { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 },
127 { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 },
128 { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 }, { GCHAR, 1 },
129 { GCHAR, 1 }, { GCHAR, 1 }, { REPLACE, 4 }, { REPLACE, 4 },
130 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
133 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
134 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
135 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
136 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
139 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
140 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
141 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
142 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
145 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
146 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
147 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
148 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
151 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
152 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
153 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
154 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
157 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
158 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
159 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
160 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
163 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
164 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
165 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
166 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
172 *----------------------------------------------------------------------
174 * IBM code page 437 encoding.
176 *----------------------------------------------------------------------
182 { REPLACE, 4 }, /* \x00 */
183 { REPLACE, 4 }, /* \x01 */
184 { REPLACE, 4 }, /* \x02 */
185 { REPLACE, 4 }, /* \x03 */
186 { REPLACE, 4 }, /* \x04 */
187 { REPLACE, 4 }, /* \x05 */
188 { REPLACE, 4 }, /* \x06 */
189 { REPLACE, 4 }, /* \x07 */
190 { REPLACE, 2 }, /* \b */
192 { NEWLINE, 2 }, /* \n */
193 { REPLACE, 4 }, /* \x0b */
194 { REPLACE, 2 }, /* \f */
195 { REPLACE, 2 }, /* \r */
196 { REPLACE, 4 }, /* 0x0e */
197 { REPLACE, 4 }, /* 0x0f */
200 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
201 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
202 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
203 { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 }, { REPLACE, 4 },
206 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
207 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
208 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
209 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
212 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
213 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
214 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
215 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
218 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
219 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
220 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
221 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
224 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
225 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
226 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
227 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
230 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
231 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
232 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
233 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
236 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
237 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
238 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
239 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
241 { REPLACE, 4 }, /* 0x7f */
244 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
245 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
246 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
247 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
250 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
251 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
252 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
254 { NORMAL, 1 }, /* 0x9b */
257 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
260 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
261 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
262 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
263 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
266 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
267 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
268 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
269 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
272 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
273 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
274 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
275 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
278 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
279 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
280 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
281 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
284 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
285 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
286 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
287 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
290 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
291 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
292 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
293 { NORMAL, 1 }, { NORMAL, 1 }, { NORMAL, 1 },
295 { NORMAL, 1 } /* 0xff */
303 * This is the switch for char encoding.
306 static int Encoding = 0;
308 #define CHARTYPE(x) EncodingTable[Encoding].ct[(x)]
311 * Characters used when displaying control sequences.
314 static char hexChars[] = "0123456789abcdefxtnvr\\";
317 * The following table maps some control characters to sequences
318 * like '\n' rather than '\x10'. A zero entry in the table means
319 * no such mapping exists, and the table only maps characters
323 static char mapChars[] = {
324 0, 0, 0, 0, 0, 0, 0, 0,
325 'b', 't', 'n', 0, 'f', 'r', 0
330 *----------------------------------------------------------------------
332 * CkCopyAndGlobalEval --
334 * This procedure makes a copy of a script then calls Tcl_GlobalEval
335 * to evaluate it. It's used in situations where the execution of
336 * a command may cause the original command string to be reallocated.
339 * Returns the result of evaluating script, including both a standard
340 * Tcl completion code and a string in interp->result.
345 *----------------------------------------------------------------------
349 CkCopyAndGlobalEval(interp, script)
350 Tcl_Interp *interp; /* Interpreter in which to evaluate
352 char *script; /* Script to evaluate. */
357 Tcl_DStringInit(&buffer);
358 Tcl_DStringAppend(&buffer, script, -1);
359 code = Tcl_GlobalEval(interp, Tcl_DStringValue(&buffer));
360 Tcl_DStringFree(&buffer);
365 *----------------------------------------------------------------------
367 * Ck_GetScrollInfo --
369 * This procedure is invoked to parse "xview" and "yview"
370 * scrolling commands for widgets using the new scrolling
371 * command syntax ("moveto" or "scroll" options).
374 * The return value is either CK_SCROLL_MOVETO, CK_SCROLL_PAGES,
375 * CK_SCROLL_UNITS, or CK_SCROLL_ERROR. This indicates whether
376 * the command was successfully parsed and what form the command
377 * took. If CK_SCROLL_MOVETO, *dblPtr is filled in with the
378 * desired position; if CK_SCROLL_PAGES or CK_SCROLL_UNITS,
379 * *intPtr is filled in with the number of lines to move (may be
380 * negative); if CK_SCROLL_ERROR, interp->result contains an
386 *----------------------------------------------------------------------
390 Ck_GetScrollInfo(interp, argc, argv, dblPtr, intPtr)
391 Tcl_Interp *interp; /* Used for error reporting. */
392 int argc; /* # arguments for command. */
393 char **argv; /* Arguments for command. */
394 double *dblPtr; /* Filled in with argument "moveto"
396 int *intPtr; /* Filled in with number of pages
397 * or lines to scroll, if any. */
402 length = strlen(argv[2]);
404 if ((c == 'm') && (strncmp(argv[2], "moveto", length) == 0)) {
406 Tcl_AppendResult(interp, "wrong # args: should be \"",
407 argv[0], " ", argv[1], " moveto fraction\"",
409 return CK_SCROLL_ERROR;
411 if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) {
412 return CK_SCROLL_ERROR;
414 return CK_SCROLL_MOVETO;
415 } else if ((c == 's')
416 && (strncmp(argv[2], "scroll", length) == 0)) {
418 Tcl_AppendResult(interp, "wrong # args: should be \"",
419 argv[0], " ", argv[1], " scroll number units|pages\"",
421 return CK_SCROLL_ERROR;
423 if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) {
424 return CK_SCROLL_ERROR;
426 length = strlen(argv[4]);
428 if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) {
429 return CK_SCROLL_PAGES;
430 } else if ((c == 'u')
431 && (strncmp(argv[4], "units", length) == 0)) {
432 return CK_SCROLL_UNITS;
434 Tcl_AppendResult(interp, "bad argument \"", argv[4],
435 "\": must be units or pages", (char *) NULL);
436 return CK_SCROLL_ERROR;
439 Tcl_AppendResult(interp, "unknown option \"", argv[2],
440 "\": must be moveto or scroll", (char *) NULL);
441 return CK_SCROLL_ERROR;
445 *--------------------------------------------------------------
449 *--------------------------------------------------------------
453 Ck_SetEncoding(interp, name)
459 for (i = 0; i < sizeof (EncodingTable) / sizeof (EncodingTable[0]); i++)
460 if (strcmp(name, EncodingTable[i].name) == 0) {
464 Tcl_AppendResult(interp, "no encoding \"", name, "\"", (char *) NULL);
469 *--------------------------------------------------------------
473 *--------------------------------------------------------------
477 Ck_GetEncoding(interp)
480 interp->result = EncodingTable[Encoding].name;
486 *--------------------------------------------------------------
490 * Procedure to convert UTF-8 representation to
491 * ISO8859-1 for printing on screen.
493 *--------------------------------------------------------------
497 MakeISO(mainPtr, string, numChars, lenPtr)
505 Tcl_DStringFree(&mainPtr->isoBuffer);
506 p = Tcl_UtfToExternalDString(mainPtr->isoEncoding, string,
507 numChars, &mainPtr->isoBuffer);
509 *lenPtr = Tcl_DStringLength(&mainPtr->isoBuffer);
516 *--------------------------------------------------------------
520 * Measure the number of characters from a string that
521 * will fit in a given horizontal span. The measurement
522 * is done under the assumption that CkDisplayChars will
523 * be used to actually display the characters.
526 * The return value is the number of characters from source
527 * that fit in the span given by startX and maxX. *nextXPtr
528 * is filled in with the x-coordinate at which the first
529 * character that didn't fit would be drawn, if it were to
536 *--------------------------------------------------------------
540 CkMeasureChars(mainPtr, source, maxChars, startX, maxX,
541 tabOrigin, flags, nextXPtr, nextCPtr)
542 CkMainInfo *mainPtr; /* Needed for encoding. */
543 char *source; /* Characters to be displayed. Need not
544 * be NULL-terminated. */
545 int maxChars; /* Maximum # of characters to consider from
547 int startX; /* X-position at which first character will
549 int maxX; /* Don't consider any character that would
550 * cross this x-position. */
551 int tabOrigin; /* X-location that serves as "origin" for
553 int flags; /* Various flag bits OR-ed together.
554 * CK_WHOLE_WORDS means stop on a word boundary
555 * (just before a space character) if
556 * possible. CK_AT_LEAST_ONE means always
557 * return a value of at least one, even
558 * if the character doesn't fit.
559 * CK_PARTIAL_OK means it's OK to display only
560 * a part of the last character in the line.
561 * CK_NEWLINES_NOT_SPECIAL means that newlines
562 * are treated just like other control chars:
563 * they don't terminate the line.
564 * CK_IGNORE_TABS means give all tabs zero
566 int *nextXPtr; /* Return x-position of terminating
568 int *nextCPtr; /* Return byte position of terminating
569 character in source. */
571 register char *p; /* Current character. */
573 char *term; /* Pointer to most recent character that
574 * may legally be a terminating character. */
575 int termX; /* X-position just after term. */
576 int curX; /* X-position corresponding to p. */
577 int newX; /* X-position corresponding to p+1. */
580 int n, m, srcRead, dstWrote, dstChars, nChars = 0;
582 char buf[TCL_UTF_MAX], buf2[TCL_UTF_MAX];
585 * Scan the input string one character at a time, until a character
586 * is found that crosses maxX.
589 newX = curX = startX;
592 for (p = source; *p != '\0' && maxChars > 0;) {
595 n = Tcl_UtfToUniChar(p, &uch);
599 m = Tcl_UniCharToUtf(uch, buf);
600 Tcl_UtfToExternal(NULL, mainPtr->isoEncoding, buf, m,
601 TCL_ENCODING_START | TCL_ENCODING_END,
602 NULL, buf2, sizeof (buf2), &srcRead,
603 &dstWrote, &dstChars);
604 if (buf2[0] == '\0') {
608 if ((CHARTYPE(c).type == NORMAL) || (CHARTYPE(c).type == REPLACE) ||
609 (CHARTYPE(c).type == GCHAR)) {
610 newX += CHARTYPE(c).width;
611 } else if (CHARTYPE(c).type == TAB) {
612 if (!(flags & CK_IGNORE_TABS)) {
614 rem = (newX - tabOrigin) % 8;
620 } else if (CHARTYPE(c).type == NEWLINE) {
621 if (flags & CK_NEWLINES_NOT_SPECIAL) {
622 newX += CHARTYPE(c).width;
632 n = Tcl_UtfToUniChar(p, &uch);
633 m = Tcl_UniCharToUtf(uch, buf);
634 Tcl_UtfToExternal(NULL, mainPtr->isoEncoding, buf, m,
635 TCL_ENCODING_START | TCL_ENCODING_END,
636 NULL, buf2, sizeof (buf2), &srcRead,
637 &dstWrote, &dstChars);
638 if (buf2[0] == '\0') {
645 if (isspace(c) || (c == 0)) {
653 * P points to the first character that doesn't fit in the desired
654 * span. Use the flags to figure out what to return.
657 if ((flags & CK_PARTIAL_OK) && (curX < maxX)) {
659 n = Tcl_UtfToUniChar(p, &uch);
663 if ((flags & CK_AT_LEAST_ONE) && (term == source) && (maxChars > 0)
664 && !isspace((unsigned char) *term)) {
667 if (term == source) {
668 n = Tcl_UtfToUniChar(term, &uch);
672 } else if ((maxChars == 0) || !(flags & CK_WHOLE_WORDS)) {
677 *nextCPtr = term - source;
681 * Scan the input string one character at a time, until a character
682 * is found that crosses maxX.
685 newX = curX = startX;
688 for (p = source, c = *p & 0xff; c != '\0' && maxChars > 0;
690 if ((CHARTYPE(c).type == NORMAL) || (CHARTYPE(c).type == REPLACE) ||
691 (CHARTYPE(c).type == GCHAR)) {
692 newX += CHARTYPE(c).width;
693 } else if (CHARTYPE(c).type == TAB) {
694 if (!(flags & CK_IGNORE_TABS)) {
696 rem = (newX - tabOrigin) % 8;
702 } else if (CHARTYPE(c).type == NEWLINE) {
703 if (flags & CK_NEWLINES_NOT_SPECIAL) {
704 newX += CHARTYPE(c).width;
717 if (isspace(c) || (c == 0)) {
725 * P points to the first character that doesn't fit in the desired
726 * span. Use the flags to figure out what to return.
729 if ((flags & CK_PARTIAL_OK) && (curX < maxX)) {
733 if ((flags & CK_AT_LEAST_ONE) && (term == source) && (maxChars > 0)
734 && !isspace((unsigned char) *term)) {
737 if (term == source) {
741 } else if ((maxChars == 0) || !(flags & CK_WHOLE_WORDS)) {
747 return term - source;
752 *--------------------------------------------------------------
756 * Draw a string of characters on the screen, converting
757 * tabs to the right number of spaces and control characters
758 * to sequences of the form "\xhh" where hh are two hex
765 * Information gets drawn on the screen.
767 *--------------------------------------------------------------
771 CkDisplayChars(mainPtr, window, string, numChars, x, y, tabOrigin, flags)
772 CkMainInfo *mainPtr; /* Needed for encoding. */
773 WINDOW *window; /* Curses window. */
774 char *string; /* Characters to be displayed. */
775 int numChars; /* Number of characters to display from
777 int x, y; /* Coordinates at which to draw string. */
778 int tabOrigin; /* X-location that serves as "origin" for
780 int flags; /* Flags to control display. Only
781 * CK_NEWLINES_NOT_SPECIAL, CK_IGNORE_TABS
782 * and CK_FILL_UNTIL_EOL are supported right
783 * now. See CkMeasureChars for information
786 register char *p; /* Current character being scanned. */
788 int startX; /* X-coordinate corresponding to start. */
789 int curX; /* X-coordinate corresponding to p. */
791 int rem, dummy, maxX;
794 string = MakeISO(mainPtr, string, numChars, &numChars);
798 * Scan the string one character at a time and display the
802 getmaxyx(window, dummy, maxX);
814 for (; numChars > 0; numChars--, p++) {
818 if (CHARTYPE(c).type == NORMAL) {
823 if (CHARTYPE(c).type == TAB) {
824 if (!(flags & CK_IGNORE_TABS)) {
826 rem = (curX - tabOrigin) % 8;
832 while (startX < curX) {
837 } else if (CHARTYPE(c).type == GCHAR) {
840 if (Ck_GetGChar(NULL, gcharTab[c - 0x81], &gchar) != TCL_OK)
842 waddch(window, gchar);
845 } else if (CHARTYPE(c).type == REPLACE || (CHARTYPE(c).type == NEWLINE
846 && (flags & CK_NEWLINES_NOT_SPECIAL))) {
848 if ((c < sizeof(mapChars)) && (mapChars[c] != 0)) {
850 replace[1] = mapChars[c];
852 waddstr(window, replace);
857 replace[2] = hexChars[(c >> 4) & 0xf];
858 replace[3] = hexChars[c & 0xf];
860 waddstr(window, replace);
863 } else if (CHARTYPE(c).type == NEWLINE) {
870 if (flags & CK_FILL_UNTIL_EOL) {
871 while (startX < maxX) {
879 *--------------------------------------------------------------
881 * CkUnderlineChars --
883 * Draw a range of string of characters on the screen,
884 * converting tabs to the right number of spaces and control
885 * characters to sequences of the form "\xhh" where hh are two hex
892 * Information gets drawn on the screen.
894 *--------------------------------------------------------------
898 CkUnderlineChars(mainPtr, window, string, numChars, x, y, tabOrigin,
900 CkMainInfo *mainPtr; /* Needed for encoding. */
901 WINDOW *window; /* Curses window. */
902 char *string; /* Characters to be displayed. */
903 int numChars; /* Number of characters to display from
905 int x, y; /* Coordinates at which to draw string. */
906 int tabOrigin; /* X-location that serves as "origin" for
908 int flags; /* Flags to control display. Only
909 * CK_NEWLINES_NOT_SPECIAL, CK_IGNORE_TABS
910 * and CK_FILL_UNTIL_EOL are supported right
911 * now. See CkMeasureChars for information
913 int first, last; /* Range: First and last characters to
916 register char *p; /* Current character being scanned. */
917 register int c, count;
918 int startX; /* X-coordinate corresponding to start. */
919 int curX; /* X-coordinate corresponding to p. */
921 int rem, dummy, maxX;
924 string = MakeISO(mainPtr, string, numChars, &numChars);
928 * Scan the string one character at a time and display the
933 getmaxyx(window, dummy, maxX);
946 for (; numChars > 0 && count <= last; numChars--, count++, p++) {
950 if (CHARTYPE(c).type == NORMAL) {
955 wmove(window, y, startX);
958 if (CHARTYPE(c).type == TAB) {
959 if (!(flags & CK_IGNORE_TABS)) {
961 rem = (curX - tabOrigin) % 8;
967 while (startX < curX) {
972 wmove(window, y, startX);
975 } else if (CHARTYPE(c).type == GCHAR) {
978 if (Ck_GetGChar(NULL, gcharTab[c - 0x81], &gchar) != TCL_OK)
982 waddch(window, gchar);
984 wmove(window, y, startX);
986 } else if (CHARTYPE(c).type == REPLACE || (CHARTYPE(c).type == NEWLINE
987 && (flags & CK_NEWLINES_NOT_SPECIAL))) {
989 if ((c < sizeof(mapChars)) && (mapChars[c] != 0)) {
991 replace[1] = mapChars[c];
995 waddstr(window, replace);
997 wmove(window, y, curX);
1001 replace[2] = hexChars[(c >> 4) & 0xf];
1002 replace[3] = hexChars[c & 0xf];
1006 waddstr(window, replace);
1008 wmove(window, y, curX);
1010 } else if (CHARTYPE(c).type == NEWLINE) {
1012 wmove(window, y, x);