diff options
author | Thomas E. Dickey <dickey@invisible-island.net> | 1998-12-16 22:06:07 -0500 |
---|---|---|
committer | Thomas E. Dickey <dickey@invisible-island.net> | 1998-12-16 22:06:07 -0500 |
commit | 10f6c5df5fbd3e8a2be8a0640035680235b3f8a3 (patch) | |
tree | f46df4582b5b527aff7ed4294e065bc5b6076a33 /src | |
parent | 08fc6e5c6582f05f43c968931b04d698cf7abc86 (diff) | |
download | lynx-snapshots-10f6c5df5fbd3e8a2be8a0640035680235b3f8a3.tar.gz |
snapshot of project "lynx", label v2-8-2dev_10
Diffstat (limited to 'src')
-rw-r--r-- | src/GridText.c | 450 | ||||
-rw-r--r-- | src/HTInit.c | 93 | ||||
-rw-r--r-- | src/HTML.c | 19 | ||||
-rw-r--r-- | src/LYCookie.c | 237 | ||||
-rw-r--r-- | src/LYGetFile.c | 3 | ||||
-rw-r--r-- | src/LYHistory.c | 8 | ||||
-rw-r--r-- | src/LYKeymap.c | 19 | ||||
-rw-r--r-- | src/LYKeymap.h | 5 | ||||
-rw-r--r-- | src/LYMainLoop.c | 16 | ||||
-rw-r--r-- | src/LYOptions.c | 9 | ||||
-rw-r--r-- | src/LYOptions.h | 7 | ||||
-rw-r--r-- | src/LYStrings.c | 262 | ||||
-rw-r--r-- | src/chrtrans/caselower.h | 737 | ||||
-rw-r--r-- | src/chrtrans/makefile.dos | 5 | ||||
-rw-r--r-- | src/makefile.in | 2 |
15 files changed, 1595 insertions, 277 deletions
diff --git a/src/GridText.c b/src/GridText.c index f31d8d1f..2fee3cb9 100644 --- a/src/GridText.c +++ b/src/GridText.c @@ -1680,7 +1680,9 @@ PRIVATE void split_line ARGS2( int HeadTrim = 0; int SpecialAttrChars = 0; int TailTrim = 0; + int s; +#define DEBUG_SPLITLINE /* * Make new line. */ @@ -1700,108 +1702,24 @@ PRIVATE void split_line ARGS2( CTRACE(tfp," bold_on=%d, underline_on=%d\n", bold_on, underline_on); #endif + if (split > previous->size) { + CTRACE(tfp, + "*** split_line: split==%d greater than last_line->size==%d !\n", + split, previous->size); + if (split > MAX_LINE) { + split = previous->size; + if ((cp = strrchr(previous->data, ' ')) && + cp - previous->data > 1) + split = cp - previous->data; + CTRACE(tfp, " split adjusted to %d.\n", split); + } + } + text->Lines++; previous->next->prev = line; line->prev = previous; line->next = previous->next; -#if defined(USE_COLOR_STYLE) -#define LastStyle (previous->numstyles-1) - line->numstyles = 0; - inew = MAX_STYLES_ON_LINE - 1; - spare = previous->numstyles; - while (previous->numstyles && inew >= 0) { - if (previous->numstyles >= 2 && - previous->styles[LastStyle].style - == previous->styles[previous->numstyles-2].style && - previous->styles[LastStyle].horizpos - == previous->styles[previous->numstyles-2].horizpos && - ((previous->styles[LastStyle].direction == STACK_OFF && - previous->styles[previous->numstyles-2].direction == STACK_ON) || - (previous->styles[LastStyle].direction == ABS_OFF && - previous->styles[previous->numstyles-2].direction == ABS_ON) || - (previous->styles[LastStyle].direction == ABS_ON && - previous->styles[previous->numstyles-2].direction == ABS_OFF) - )) { - /* - * Discard pairs of ON/OFF for the same color style, but only - * if they appear at the same position. - kw - */ - previous->numstyles -= 2; - if (spare > previous->numstyles) - spare = previous->numstyles; - } else if (spare > 0 && previous->styles[spare - 1].direction && - previous->numstyles < MAX_STYLES_ON_LINE) { - /* - * The index variable spare walks backwards through the - * list of color style changes on the previous line, trying - * to find an ON change which isn't followed by a - * corresponding OFF. When it finds one, the missing OFF - * change is appended to the end, and an ON change is added - * at the beginning of the current line. The OFF change - * appended to the previous line may get removed again in - * the next iteration. - kw - */ - line->styles[inew].horizpos = 0; - line->styles[inew].direction = ON; - line->styles[inew].style = previous->styles[spare - 1].style; - inew --; - line->numstyles ++; - previous->styles[previous->numstyles].style = line->styles[inew + 1].style; - - previous->styles[previous->numstyles].direction = ABS_OFF; - previous->styles[previous->numstyles].horizpos = previous->size; - previous->numstyles++; - spare --; - } else if (spare >= 2 && - previous->styles[spare - 1].style == previous->styles[spare - 2].style && - ((previous->styles[spare - 1].direction == STACK_OFF && - previous->styles[spare - 2].direction == STACK_ON) || - (previous->styles[spare - 1].direction == ABS_OFF && - previous->styles[spare - 2].direction == ABS_ON) || - (previous->styles[spare - 1].direction == STACK_ON && - previous->styles[spare - 2].direction == STACK_OFF) || - (previous->styles[spare - 1].direction == ABS_ON && - previous->styles[spare - 2].direction == ABS_OFF) - )) { - /* - * Skip pairs of adjacent ON/OFF or OFF/ON changes. - */ - spare -= 2; - } else if (spare && !previous->styles[spare - 1].direction) { - /* - * Found an OFF change not part of a matched pair. - * Assume it is safer to leave whatever comes before - * it on the previous line alone. Setting spare to 0 - * ensures that it won't be used in a following - * iteration. - kw - */ - spare = 0; - } else { - /* - * Nothing applied, so we are done with the loop. - kw - */ - break; - } - } - if (previous->numstyles > 0 && previous->styles[LastStyle].direction) { - - CTRACE(tfp, "%s\n%s%s\n", - "........... Too many character styles on line:", - "........... ", previous->data); - } - if (line->numstyles > 0 && line->numstyles < MAX_STYLES_ON_LINE) { - int n; - inew ++; - for (n = 0; n < line->numstyles; n++) - line->styles[n] = line->styles[n + inew]; - } else - if (line->numstyles == 0) - /* FIXME: RJP - shouldn't use 0xffffffff for largest integer */ - line->styles[0].horizpos = 0xffffffff; - if (previous->numstyles == 0) - previous->styles[0].horizpos = 0xffffffff; -#endif /*USE_COLOR_STYLE*/ previous->next = line; text->last_line = line; line->size = 0; @@ -1866,15 +1784,13 @@ PRIVATE void split_line ARGS2( * Make sure our global flag is correct. - FM */ underline_on = NO; - if (split) { - for (i = (split-1); i >= 0; i--) { - if (prevdata[i] == LY_UNDERLINE_END_CHAR) { - break; - } - if (prevdata[i] == LY_UNDERLINE_START_CHAR) { - underline_on = YES; - break; - } + for (i = (split-1); i >= 0; i--) { + if (prevdata[i] == LY_UNDERLINE_END_CHAR) { + break; + } + if (prevdata[i] == LY_UNDERLINE_START_CHAR) { + underline_on = YES; + break; } } /* @@ -1911,15 +1827,13 @@ PRIVATE void split_line ARGS2( * sure that our global flag is correct. - FM */ bold_on = NO; - if (split) { - for (i = (split - 1); i >= 0; i--) { - if (prevdata[i] == LY_BOLD_END_CHAR) { - break; - } - if (prevdata[i] == LY_BOLD_START_CHAR) { - bold_on = YES; - break; - } + for (i = (split - 1); i >= 0; i--) { + if (prevdata[i] == LY_BOLD_END_CHAR) { + break; + } + if (prevdata[i] == LY_BOLD_START_CHAR) { + bold_on = YES; + break; } } /* @@ -1979,6 +1893,151 @@ PRIVATE void split_line ARGS2( previous->size--; TailTrim++; } + /* + * s is the effective split position, given by either a non-zero + * value of split or by the size of the previous line before + * trimming. - kw + */ + if (split == 0) { + s = previous->size + TailTrim; /* the original size */ + } else { + s = split; + } +#ifdef DEBUG_SPLITLINE +#ifdef DEBUG_APPCH + if (s != (int)split) +#endif + CTRACE(tfp,"GridText: split_line(%d [now:%d]) called\n", split, s); +#endif + +#if defined(USE_COLOR_STYLE) +#define LastStyle (previous->numstyles-1) + line->numstyles = 0; + inew = MAX_STYLES_ON_LINE - 1; + /* + * Color style changes after the split position + possible trimmed + * head characters are transferred to the new line. Ditto for changes + * within the trimming region, but be stop when we reach an OFF change. + * The second while loop below may then handle remaining changes. - kw + */ + while (previous->numstyles && inew >= 0) { + if (previous->styles[LastStyle].horizpos > s + HeadTrim) { + line->styles[inew].horizpos = + previous->styles[LastStyle].horizpos + - (s + HeadTrim) + SpecialAttrChars; + line->styles[inew].direction = previous->styles[LastStyle].direction; + line->styles[inew].style = previous->styles[LastStyle].style; + inew --; + line->numstyles ++; + previous->numstyles --; + } else if (previous->styles[LastStyle].horizpos > s - TailTrim && + (previous->styles[LastStyle].direction == STACK_ON || + previous->styles[LastStyle].direction == ABS_ON)) { + line->styles[inew].horizpos = + (previous->styles[LastStyle].horizpos < s) ? + 0 : SpecialAttrChars; + line->styles[inew].direction = previous->styles[LastStyle].direction; + line->styles[inew].style = previous->styles[LastStyle].style; + inew --; + line->numstyles ++; + previous->numstyles --; + } else + break; + } + spare = previous->numstyles; + while (previous->numstyles && inew >= 0) { + if (previous->numstyles >= 2 && + previous->styles[LastStyle].style + == previous->styles[previous->numstyles-2].style && + previous->styles[LastStyle].horizpos + == previous->styles[previous->numstyles-2].horizpos && + ((previous->styles[LastStyle].direction == STACK_OFF && + previous->styles[previous->numstyles-2].direction == STACK_ON) || + (previous->styles[LastStyle].direction == ABS_OFF && + previous->styles[previous->numstyles-2].direction == ABS_ON) || + (previous->styles[LastStyle].direction == ABS_ON && + previous->styles[previous->numstyles-2].direction == ABS_OFF) + )) { + /* + * Discard pairs of ON/OFF for the same color style, but only + * if they appear at the same position. - kw + */ + previous->numstyles -= 2; + if (spare > previous->numstyles) + spare = previous->numstyles; + } else if (spare > 0 && previous->styles[spare - 1].direction && + previous->numstyles < MAX_STYLES_ON_LINE) { + /* + * The index variable spare walks backwards through the + * list of color style changes on the previous line, trying + * to find an ON change which isn't followed by a + * corresponding OFF. When it finds one, the missing OFF + * change is appended to the end, and an ON change is added + * at the beginning of the current line. The OFF change + * appended to the previous line may get removed again in + * the next iteration. - kw + */ + line->styles[inew].horizpos = 0; + line->styles[inew].direction = ON; + line->styles[inew].style = previous->styles[spare - 1].style; + inew --; + line->numstyles ++; + previous->styles[previous->numstyles].style = line->styles[inew + 1].style; + + previous->styles[previous->numstyles].direction = ABS_OFF; + previous->styles[previous->numstyles].horizpos = previous->size; + previous->numstyles++; + spare --; + } else if (spare >= 2 && + previous->styles[spare - 1].style == previous->styles[spare - 2].style && + ((previous->styles[spare - 1].direction == STACK_OFF && + previous->styles[spare - 2].direction == STACK_ON) || + (previous->styles[spare - 1].direction == ABS_OFF && + previous->styles[spare - 2].direction == ABS_ON) || + (previous->styles[spare - 1].direction == STACK_ON && + previous->styles[spare - 2].direction == STACK_OFF) || + (previous->styles[spare - 1].direction == ABS_ON && + previous->styles[spare - 2].direction == ABS_OFF) + )) { + /* + * Skip pairs of adjacent ON/OFF or OFF/ON changes. + */ + spare -= 2; + } else if (spare && !previous->styles[spare - 1].direction) { + /* + * Found an OFF change not part of a matched pair. + * Assume it is safer to leave whatever comes before + * it on the previous line alone. Setting spare to 0 + * ensures that it won't be used in a following + * iteration. - kw + */ + spare = 0; + } else { + /* + * Nothing applied, so we are done with the loop. - kw + */ + break; + } + } + if (previous->numstyles > 0 && previous->styles[LastStyle].direction) { + + CTRACE(tfp, "%s\n%s%s\n", + "........... Too many character styles on line:", + "........... ", previous->data); + } + if (line->numstyles > 0 && line->numstyles < MAX_STYLES_ON_LINE) { + int n; + inew ++; + for (n = 0; n < line->numstyles; n++) + line->styles[n] = line->styles[n + inew]; + } else + if (line->numstyles == 0) + /* FIXME: RJP - shouldn't use 0xffffffff for largest integer */ + line->styles[0].horizpos = 0xffffffff; + if (previous->numstyles == 0) + previous->styles[0].horizpos = 0xffffffff; +#endif /*USE_COLOR_STYLE*/ + temp = (HTLine *)LY_CALLOC(1, LINE_SIZE(previous->size)); if (temp == NULL) outofmem(__FILE__, "split_line_2"); @@ -2041,20 +2100,152 @@ PRIVATE void split_line ARGS2( * If we split the line, adjust the anchor * structure values for the new line. - FM */ - if (split > 0) { - for (a = text->first_anchor; a; a = a->next) { + + if (split > 0 || s > 0) { /* if not completely empty */ + TextAnchor * prev_a = NULL; + for (a = text->first_anchor; a; prev_a = a, a = a->next) { if (a->line_num == CurLine) { - if ((unsigned)a->line_pos >= split) { - a->start += (1 + SpecialAttrChars - HeadTrim - TailTrim); - a->line_pos -= (split - SpecialAttrChars + HeadTrim); - a->line_num = text->Lines; - } else if ((a->link_type & HYPERTEXT_ANCHOR) && - (unsigned)(a->line_pos + a->extent) >= split) { - a->extent -= (TailTrim + HeadTrim); - if (a->extent < 0) { - a->extent = 0; + int old_e = a->extent; + int a0 = a->line_pos, a1 = a->line_pos + a->extent; + int S, d, new_pos, new_ext; + if (a->link_type == INPUT_ANCHOR) { + if (a->line_pos >= s) { + a->start += (1 + SpecialAttrChars - HeadTrim - TailTrim); + a->line_pos -= (s - SpecialAttrChars + HeadTrim); + a->line_num = text->Lines; } + continue; + } + if (a0 < s - TailTrim && a1 <= s - TailTrim) { + continue; /* unaffected, leave it where it is. */ } + S = s + a->start - a->line_pos; + d = S - s; /* == a->start - a->line_pos */ + new_ext = old_e = a->extent; + + if (!old_e && + (!a->number || a->show_anchor) && + a0 <= s + HeadTrim) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,1); +#endif + /* + * It is meant to be empty, and/or endAnchor + * has seen it and recognized it as empty. + */ + new_pos = (a0 <= s) ? s - TailTrim : + s - TailTrim + 1; + if (prev_a && new_pos + d < prev_a->start) { + if (prev_a->start <= S - TailTrim + 1 + SpecialAttrChars) + new_pos = prev_a->start - d; + else + new_pos = s - TailTrim + 1 + SpecialAttrChars; + } + } else if (old_e && + a0 >= s - TailTrim && a0 <= s + HeadTrim && + a1 <= s + HeadTrim) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,2); +#endif + /* + * endAnchor has seen it, it is effectively empty + * after our trimming, but endAnchor has for some + * reason not recognized this. In other words, + * this should not happen. + * Should we not adjust the extent and let it "leak" + * into the new line? + */ + new_pos = (a0 < s) ? s - TailTrim : + s - TailTrim + 1; + if (prev_a && new_pos + d < prev_a->start) { + if (prev_a->start <= S - TailTrim + 1 + SpecialAttrChars) + new_pos = prev_a->start - d; + else + new_pos = s - TailTrim + 1 + SpecialAttrChars; + } + new_ext = 0; + } else if (a0 >= s + HeadTrim) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,3); +#endif + /* + * Completely after split, just shift. + */ + new_pos = a0 - TailTrim + 1 - HeadTrim + SpecialAttrChars; + } else if (!old_e) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,4); +#endif + /* + * No extent set, we may still be growing it. + */ + new_pos = s - TailTrim + 1 + SpecialAttrChars; + + /* + * Ok, it's neither empty, nor is it completely + * before or after the split region (including trimmed + * stuff). So the anchor is either being split in + * the middle, with stuff remaining on both lines, + * or something is being nibbled off, either at + * the end (anchor stays on previous line) or at + * the beginning (anchor is on new line). Let's + * try in that order. + */ + } else if (a0 < s - TailTrim && + a1 > s + HeadTrim) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,5); +#endif + new_pos = a0; + new_ext = old_e - TailTrim - HeadTrim + SpecialAttrChars; + } else if (a0 < s - TailTrim) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,6); +#endif + new_pos = a0; + new_ext = s - TailTrim - a0; + } else if (a1 > s + HeadTrim) { +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "anchor %d case %d: ", + a->number,7); +#endif + new_pos = s - TailTrim + 1 + SpecialAttrChars; + new_ext = old_e - (s + HeadTrim - a0); + } else { + CTRACE(tfp, "split_line anchor %d line %d: This should not happen!\n", + a->number, a->line_num); + CTRACE(tfp, + "anchor %d: (T,H,S)=(%d,%d,%d); (line,start,pos,ext):(%d,%d,%d,%d)!\n", + a->number, + TailTrim,HeadTrim,SpecialAttrChars, + a->line_num,a->start,a->line_pos,a->extent); + continue; + } +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, "(T,H,S)=(%d,%d,%d); (line,start,pos,ext):(%d,%d,%d,%d", + TailTrim,HeadTrim,SpecialAttrChars, + a->line_num,a->start,a->line_pos,a->extent); +#endif + if (new_pos != a->line_pos) + a->start = new_pos + d; + if (new_pos > s - TailTrim) { + new_pos -= s - TailTrim + 1; + a->line_num = text->Lines; + } + a->line_pos = new_pos; + a->extent = new_ext; + +#ifdef DEBUG_SPLITLINE + CTRACE(tfp, ")->(%d,%d,%d,%d)\n", + a->line_num,a->start,a->line_pos,a->extent); +#endif + } } } @@ -2177,6 +2368,7 @@ PUBLIC void HText_appendCharacter ARGS2( CTRACE(tfp, "add(%c) %d/%d\n", ch, HTisDocumentSource(), HTOutputFormat != WWW_SOURCE); } + FREE(special); } /* trace only */ #endif /* DEBUG_APPCH */ @@ -3467,9 +3659,9 @@ re_parse: * The last line is probably still not finished. - kw */ if (cur_line >= text->Lines) - break; + break; if (anchor_ptr->start >= text->chars - 1) - break; + break; /* * Also skip this anchor if it looks like HText_endAnchor * is not yet done with it. - kw @@ -6548,6 +6740,7 @@ PUBLIC int HText_beginInput ARGS3( a->start = text->chars + text->last_line->size; a->inUnderline = underline; + a->line_num = text->Lines; a->line_pos = text->last_line->size; @@ -6907,6 +7100,7 @@ PUBLIC int HText_beginInput ARGS3( */ HText_appendCharacter(text, '['); a->start = text->chars + text->last_line->size; + a->line_num = text->Lines; a->line_pos = text->last_line->size; } diff --git a/src/HTInit.c b/src/HTInit.c index 74403779..222a581f 100644 --- a/src/HTInit.c +++ b/src/HTInit.c @@ -471,6 +471,52 @@ PRIVATE void BuildCommand ARGS5( *to = '\0'; } +#define RTR_forget 0 +#define RTR_lookup 1 +#define RTR_add 2 + +PRIVATE int RememberTestResult ARGS3( + int, mode, + char *, cmd, + int, result) +{ + struct cmdlist_s { + char *cmd; + int result; + struct cmdlist_s *next; + }; + static struct cmdlist_s *cmdlist = NULL; + struct cmdlist_s *cur; + + switch(mode) { + case RTR_forget: + while(cmdlist) { + cur = cmdlist->next; + FREE(cmdlist->cmd); + FREE(cmdlist); + cmdlist = cur; + } + break; + case RTR_lookup: + for(cur = cmdlist; cur; cur = cur->next) + if(!strcmp(cmd, cur->cmd)) + return cur->result; + return -1; + case RTR_add: + cur = calloc(1, sizeof(struct cmdlist_s)); + cur->next = cmdlist; + cur->cmd = (char *)malloc(strlen(cmd) + 1); + if(cur->cmd) + strcpy(cur->cmd, cmd); + else + ExitWithError("Out of memory"); + cur->result = result; + cmdlist = cur; + break; + } + return 0; +} + PRIVATE int PassesTest ARGS1( struct MailcapEntry *, mc) { @@ -528,28 +574,32 @@ PRIVATE int PassesTest ARGS1( return(-1 == 0); } - /* - * Build the command and execute it. - */ - if (strchr(mc->testcommand, '%')) { - if (LYOpenTemp(TmpFileName, HTML_SUFFIX, "w") == 0) - ExitWithError(CANNOT_OPEN_TEMP); - LYCloseTemp(TmpFileName); - } else { - /* We normally don't need a temp file name - kw */ - TmpFileName[0] = '\0'; + result = RememberTestResult(RTR_lookup, mc->testcommand, 0); + if(result == -1) { + /* + * Build the command and execute it. + */ + if (strchr(mc->testcommand, '%')) { + if (LYOpenTemp(TmpFileName, HTML_SUFFIX, "w") == 0) + ExitWithError(CANNOT_OPEN_TEMP); + LYCloseTemp(TmpFileName); + } else { + /* We normally don't need a temp file name - kw */ + TmpFileName[0] = '\0'; + } + cmd = (char *)malloc(1024); + if (!cmd) + ExitWithError(MEMORY_EXHAUSTED_ABORT); + BuildCommand(&cmd, 1024, + mc->testcommand, + TmpFileName, + strlen(TmpFileName)); + CTRACE(tfp, "PassesTest: Executing test command: %s\n", cmd); + result = LYSystem(cmd); + FREE(cmd); + LYRemoveTemp(TmpFileName); + RememberTestResult(RTR_add, mc->testcommand, result ? 1 : 0); } - cmd = (char *)malloc(1024); - if (!cmd) - ExitWithError(MEMORY_EXHAUSTED_ABORT); - BuildCommand(&cmd, 1024, - mc->testcommand, - TmpFileName, - strlen(TmpFileName)); - CTRACE(tfp, "PassesTest: Executing test command: %s\n", cmd); - result = LYSystem(cmd); - FREE(cmd); - LYRemoveTemp(TmpFileName); /* * Free the test command as well since @@ -584,6 +634,7 @@ PRIVATE int ProcessMailcapFile ARGS1( ProcessMailcapEntry(fp, &mc); } fclose(fp); + RememberTestResult(RTR_forget, NULL, 0); return(0 == 0); } diff --git a/src/HTML.c b/src/HTML.c index 6c3ff556..fa12456d 100644 --- a/src/HTML.c +++ b/src/HTML.c @@ -11,7 +11,6 @@ ** Being Overidden ** */ -#define DICKEY_TEST #include <HTUtils.h> @@ -5217,10 +5216,7 @@ PRIVATE void HTML_start_element ARGS6( } /* end switch */ -#if defined(DICKEY_TEST) - if (HTML_dtd.tags[ElementNumber].contents != SGML_EMPTY) -#endif - { + if (HTML_dtd.tags[ElementNumber].contents != SGML_EMPTY) { if (me->skip_stack > 0) { CTRACE(tfp, "HTML:begin_element: internal call (level %d), leaving on stack - %s\n", me->skip_stack, me->sp->style->name); @@ -5250,9 +5246,12 @@ PRIVATE void HTML_start_element ARGS6( me->sp[0].tag_number = ElementNumber; } -#if defined(DICKEY_TEST) && defined(USE_COLOR_STYLE) -/* end empty tags straight away */ - if (HTML_dtd.tags[ElementNumber].contents == SGML_EMPTY) +#if defined(USE_COLOR_STYLE) +/* end really empty tags straight away */ +#define REALLY_EMPTY(e) ((HTML_dtd.tags[e].contents == SGML_EMPTY) && \ + !(HTML_dtd.tags[e].flags & Tgf_nreie)) + + if (REALLY_EMPTY(element_number)) { CTRACE(tfp, "STYLE:begin_element:ending EMPTY element style\n"); #if !defined(USE_HASH) @@ -6651,9 +6650,7 @@ End_Object: CTRACE(tfp, "CSS:%s (trimmed %s, END_ELEMENT)\n", Style_className, tmp); } -#if defined(DICKEY_TEST) - if (HTML_dtd.tags[element_number].contents != SGML_EMPTY) -#endif + if (!REALLY_EMPTY(element_number)) { CTRACE(tfp, "STYLE:end_element: ending non-EMPTY style\n"); #if !defined(USE_HASH) diff --git a/src/LYCookie.c b/src/LYCookie.c index 4c0053cc..869f3d8d 100644 --- a/src/LYCookie.c +++ b/src/LYCookie.c @@ -16,7 +16,20 @@ ** ftp://ds.internic.net/internet-drafts/draft-ietf-http-state-man-mec-03.txt ** - FM 1997-08-02 ** +** Partially checked against: +** http://www.ietf.org/internet-drafts/draft-ietf-http-state-man-mec-10.txt +** - kw 1998-12-11 +** ** TO DO: (roughly in order of decreasing priority) + * Persistent cookies are still experimental. Presently cookies + lose many pieces of information that distinguish + version 1 from version 0 cookies. There is no easy way around + that with the current cookie file format. Ports are currently + not stored persistently at all which is clearly wrong. + * We currently don't do anything special for unverifiable + transactions to third-party hosts. + * We currently don't use effective host names or check for + Domain=.local. * Hex escaping isn't considered at all. Any semi-colons, commas, or spaces actually in cookie names or values (i.e., not serving as punctuation for the overall Set-Cookie value) should be hex @@ -92,7 +105,6 @@ struct _cookie { int flags; /* Various flags */ time_t expires;/* The time when this cookie expires */ BOOL quoted; /* Was a value quoted in the Set-Cookie header? */ - BOOL from_file; /* Was this cookie loaded from the file jar? - RP */ }; typedef struct _cookie cookie; @@ -101,7 +113,7 @@ typedef struct _cookie cookie; #define COOKIE_FLAG_EXPIRES_SET 4 /* If set, an expiry date was set */ #define COOKIE_FLAG_DOMAIN_SET 8 /* If set, an non-default domain was set */ #define COOKIE_FLAG_PATH_SET 16 /* If set, an non-default path was set */ -#define COOKIE_FLAG_PERSISTENT 32 /* If set, this cookie was persistent */ +#define COOKIE_FLAG_FROM_FILE 32 /* If set, this cookie was persistent */ struct _HTStream { @@ -177,6 +189,7 @@ PRIVATE void LYCookieJar_free NOARGS FREE(de->domain); HTList_delete(de->cookie_list); de->cookie_list = NULL; + FREE(dl->object); } dl = dl->next; } @@ -203,9 +216,9 @@ PRIVATE BOOLEAN host_matches ARGS2( /* * The following will pass a "dotted tail" match to "a.b.c.e" - * as described in Section 2 of the -05 draft. + * as described in Section 2 of draft-ietf-http-state-man-mec-10.txt. */ - if (*B == '.') { + if (*B == '.' && B[1] != '\0' && B[1] != '.' && *A != '.') { int diff = (strlen(A) - strlen(B)); if (diff > 0) { if (!strcmp((A + diff), B)) @@ -385,7 +398,7 @@ PRIVATE void store_cookie ARGS3( de = (domain_entry *)calloc(1, sizeof(domain_entry)); if (de == NULL) outofmem(__FILE__, "store_cookie"); -#ifdef EXP_PERSISTENT_COOKIES +#if 0 /* was: ifdef EXP_PERSISTENT_COOKIES */ /* * Ok, this is a problem. The first cookie for a domain * effectively sets the policy for that whole domain - for @@ -396,7 +409,7 @@ PRIVATE void store_cookie ARGS3( * and the path in conjunction makes more sense? - RP */ if (persistent_cookies - && (co->flags & COOKIE_FLAG_PERSISTENT)) + && (co->flags & COOKIE_FLAG_FROM_FILE)) de->bv = FROM_FILE; else #endif @@ -419,7 +432,7 @@ PRIVATE void store_cookie ARGS3( */ if ((c2 != NULL) && (c2->flags & COOKIE_FLAG_EXPIRES_SET) && - c2->expires < now) { + c2->expires <= now) { HTList_removeObject(cookie_list, c2); freeCookie(c2); c2 = NULL; @@ -438,7 +451,23 @@ PRIVATE void store_cookie ARGS3( total_cookies--; Replacement = TRUE; - } else if ((c2) && (c2->pathlen) > (co->pathlen)) { + } else if ((c2) && (c2->pathlen) >= (co->pathlen)) { + /* + * This comparison determines the (tentative) position + * of the new cookie in the list such that it comes + * before existing cookies with a less specific path, + * but after existing cookies of equal (or greater) + * path length. Thus it should normally preserve + * the order of new cookies with the same path as + * they are received, although this is not required. + * From RFC 2109 4.3.4: + + If multiple cookies satisfy the criteria above, they are ordered in + the Cookie header such that those with more specific Path + attributes precede those with less specific. Ordering with respect + to other attributes (e.g., Domain) is unspecified. + + */ pos++; } hl = next; @@ -447,7 +476,7 @@ PRIVATE void store_cookie ARGS3( /* * Don't bother to add the cookie if it's already expired. */ - if ((co->flags & COOKIE_FLAG_EXPIRES_SET) && co->expires < now) { + if ((co->flags & COOKIE_FLAG_EXPIRES_SET) && co->expires <= now) { freeCookie(co); co = NULL; @@ -487,26 +516,21 @@ PRIVATE void store_cookie ARGS3( /* * Get confirmation if we need it, and add cookie * if confirmed or 'allow' is set to always. - FM + * + * Cookies read from file are accepted without confirmation + * prompting. (Prompting may actually not be possible if + * LYLoadCookies is called before curses is setup.) Maybe + * this should instead depend on LYSetCookies and/or + * LYCookieAcceptDomains and/or LYCookieRejectDomains and/or + * LYAcceptAllCookies and/or some other settings. -kw */ - } else if (HTConfirmCookie(de, hostname, co->name, co->value)) { - -#ifdef EXP_PERSISTENT_COOKIES + } else if ((persistent_cookies && (co->flags & COOKIE_FLAG_FROM_FILE)) + || HTConfirmCookie(de, hostname, co->name, co->value)) { /* - * If the cookie domain came from persistent cookie file, - * we want to add new cookies to the end of the cookie list - * to maintain their order for servers that need cookies in - * a particular order. This is a hack. + * Insert the new cookie so that more specific paths (longer + * pathlen) come first in the list. - kw */ - if (persistent_cookies) { - if ((de->bv = FROM_FILE) != 0) { - HTList_appendObject(cookie_list, co); - } else { - HTList_insertObjectAt(cookie_list, co, pos); - } - } -#else HTList_insertObjectAt(cookie_list, co, pos); -#endif /* EXP_PERSISTENT_COOKIES */ total_cookies++; } else { freeCookie(co); @@ -542,7 +566,7 @@ PRIVATE char * scan_cookie_sublist ARGS6( (long)hl, (co->name ? co->name : "(no name)"), (co->value ? co->value : "(no value)")); - CTRACE(tfp, "%s %s %d %s %s %d%s\n", + CTRACE(tfp, "\t%s %s %d %s %s %d%s\n", hostname, (co->domain ? co->domain : "(no domain)"), host_matches(hostname, co->domain), @@ -555,7 +579,7 @@ PRIVATE char * scan_cookie_sublist ARGS6( * Check if this cookie has expired, and if so, delete it. */ if (((co) && (co->flags & COOKIE_FLAG_EXPIRES_SET)) && - co->expires < now) { + co->expires <= now) { HTList_removeObject(sublist, co); freeCookie(co); co = NULL; @@ -708,6 +732,7 @@ PRIVATE void LYProcessSetCookies ARGS6( int NumCookies = 0; BOOL MaxAgeAttrSet = FALSE; BOOL Quoted = FALSE; + BOOLEAN invalidport = FALSE; if (!(SetCookie && *SetCookie) && !(SetCookie2 && *SetCookie2)) { @@ -1052,7 +1077,10 @@ PRIVATE void LYProcessSetCookies ARGS6( *cp == ',' || *cp == ' ')) { cp++; } - if (*cp == '\0') { + if (*cp == '\0' && !port_matches(port, value)) { + invalidport = TRUE; + known_attr = YES; + } else if (*cp == '\0') { StrAllocCopy(cur_cookie->PortList, value); length += strlen(cur_cookie->PortList); known_attr = YES; @@ -1112,7 +1140,6 @@ PRIVATE void LYProcessSetCookies ARGS6( known_attr = YES; if ((cur_cookie != NULL && !MaxAgeAttrSet) && !(cur_cookie->flags & COOKIE_FLAG_EXPIRES_SET)) { - known_attr = YES; if (value) { cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET; cur_cookie->expires = LYmktime(value, FALSE); @@ -1145,7 +1172,8 @@ PRIVATE void LYProcessSetCookies ARGS6( * If we've started a cookie, and it's not too big, * save it in the CombinedCookies list. - FM */ - if (length <= max_cookies_buffer && cur_cookie != NULL) { + if (length <= max_cookies_buffer && cur_cookie != NULL && + !invalidport) { /* * Assume version 1 if not set to that or higher. - FM */ @@ -1161,7 +1189,12 @@ PRIVATE void LYProcessSetCookies ARGS6( (cur_cookie->value ? cur_cookie->value : "[no value]")); CTRACE(tfp, - " due to excessive length!\n"); + invalidport ? + " due to excessive length!\n" + : " due to invalid port!\n"); + if (invalidport) { + NumCookies --; + } freeCookie(cur_cookie); cur_cookie = NULL; } @@ -1169,6 +1202,7 @@ PRIVATE void LYProcessSetCookies ARGS6( * Start a new cookie. - FM */ cur_cookie = newCookie(); + invalidport = FALSE; length = 0; NumCookies++; MemAllocCopy(&(cur_cookie->name), attr_start, attr_end); @@ -1193,12 +1227,12 @@ PRIVATE void LYProcessSetCookies ARGS6( */ if (NumCookies <= max_cookies_domain && length <= max_cookies_buffer - && cur_cookie != NULL) { + && cur_cookie != NULL && !invalidport) { if (cur_cookie->version < 1) { cur_cookie->version = 1; } HTList_appendObject(CombinedCookies, cur_cookie); - } else if (cur_cookie != NULL) { + } else if (cur_cookie != NULL && !invalidport) { CTRACE(tfp, "LYProcessSetCookies: Rejecting Set-Cookie2: %s=%s\n", (cur_cookie->name ? cur_cookie->name : "[no name]"), (cur_cookie->value ? cur_cookie->value : "[no value]")); @@ -1211,6 +1245,14 @@ PRIVATE void LYProcessSetCookies ARGS6( (NumCookies > max_cookies_domain ? "number!\n" : "!\n")); freeCookie(cur_cookie); cur_cookie = NULL; + } else if (cur_cookie != NULL) { /* invalidport */ + CTRACE(tfp, "LYProcessSetCookies: Rejecting Set-Cookie2: %s=%s\n", + (cur_cookie->name ? cur_cookie->name : "[no name]"), + (cur_cookie->value ? cur_cookie->value : "[no value]")); + CTRACE(tfp, " due to invalid port!\n"); + NumCookies --; + freeCookie(cur_cookie); + cur_cookie = NULL; } /* @@ -1536,7 +1578,7 @@ PRIVATE void LYProcessSetCookies ARGS6( *cp == ',' || *cp == ' ')) { cp++; } - if (*cp == '\0') { + if (*cp == '\0' && port_matches(port, value)) { StrAllocCopy(cur_cookie->PortList, value); length += strlen(cur_cookie->PortList); known_attr = YES; @@ -1559,7 +1601,7 @@ PRIVATE void LYProcessSetCookies ARGS6( /* * Don't process a repeat version. - FM */ - cur_cookie->version < 0) { + cur_cookie->version < 1) { int temp = strtol(value, NULL, 10); if (errno != -ERANGE) { cur_cookie->version = temp; @@ -1839,7 +1881,7 @@ PUBLIC char * LYCookie ARGS4( HTList_delete(de->cookie_list); de->cookie_list = NULL; HTList_removeObject(domain_list, de); - de = NULL; + FREE(de); } } hl = next; @@ -1847,21 +1889,12 @@ PUBLIC char * LYCookie ARGS4( if (header) return(header); - /* - * If we didn't set a header, perhaps all the cookies have - * expired and we deleted the last of them above, so check - * if we should delete and NULL the domain_list. - FM - */ - if (domain_list) { - if (HTList_isEmpty(domain_list)) { - HTList_delete(domain_list); - domain_list = NULL; - } - } return(NULL); } #ifdef EXP_PERSISTENT_COOKIES +PRIVATE int number_of_file_cookies = 0; + /* rjp - experiment cookie loading */ PUBLIC void LYLoadCookies ARGS1 ( char *, cookie_file) @@ -1891,6 +1924,7 @@ PUBLIC void LYLoadCookies ARGS1 ( CTRACE(tfp, "LYLoadCookies: reading cookies from %s\n", cookie_file); + number_of_file_cookies = 0; while (!feof(cookie_handle)) { cookie *moo; unsigned i = 0; @@ -1901,9 +1935,13 @@ PUBLIC void LYLoadCookies ARGS1 ( j = fgets(buf, sizeof(buf)-1, cookie_handle); if((j == NULL) || (buf[0] == '\0' || buf[0] == '\n' || buf[0] == '#')) { + if (j == NULL && ferror(cookie_handle)) + break; continue; } + number_of_file_cookies ++; + /* * Strip out the newline that fgets() puts at the end of a * cookie. @@ -1929,7 +1967,7 @@ PUBLIC void LYLoadCookies ARGS1 ( tok_out = LYstrsep(&tok_ptr, "\t"); for (tok_loop = 0; tok_out && tok_values[tok_loop].s; tok_loop++) { CTRACE(tfp, "\t%d:%p:%p:[%s]\n", - tok_loop, tok_values[tok_loop].s, tok_out, tok_out); + tok_loop, tok_values[tok_loop].s, tok_out, tok_out); LYstrncpy(tok_values[tok_loop].s, tok_out, tok_values[tok_loop].n); /* * It looks like strtok ignores a leading delimiter, @@ -1957,13 +1995,51 @@ PUBLIC void LYLoadCookies ARGS1 ( StrAllocCopy(moo->name, name); StrAllocCopy(moo->value, value); moo->pathlen = strlen(moo->path); - moo->flags |= COOKIE_FLAG_PERSISTENT; + /* + * Justification for following flags: + * COOKIE_FLAG_FROM_FILE So we know were it comes from. + * COOKIE_FLAG_EXPIRES_SET It must have had an explicit + * expiration originally, otherwise + * it would not be in the file. + * COOKIE_FLAG_DOMAN_SET, We don't know whether these were + * COOKIE_FLAG_PATH_SET explicit or implicit, but this + * only matters for sending version 1 + * cookies; the cookies read from the + * file are currently treated all like + * version 0 (we don't set moo->version) + * so $Domain= and $Path= will normally + * not be sent to the server. But if + * these cookies somehow get mixed with + * new version 1 cookies we may end up + * sending version 1 to the server, and + * in that case we should send $Domain + * and $Path. The state-man-mec drafts + * and RFC 2109 say that $Domain and + * $Path SHOULD be omitted if they were + * not given explicitly, but not that + * they MUST be omitted. + * See 8.2 Cookie Spoofing in draft -10 + * for a good reason to send them. + * However, an explicit domain should be + * now prefixed with a dot (unless it is + * for a single host), so we check for + * that. + * COOKIE_FLAG_SECURE Should have "FALSE" for normal, + * otherwise set it. + */ + moo->flags |= COOKIE_FLAG_FROM_FILE | COOKIE_FLAG_EXPIRES_SET | + COOKIE_FLAG_PATH_SET; + if (domain[0] == '.') + moo->flags |= COOKIE_FLAG_DOMAIN_SET; + if (secure[0] != 'F') + moo->flags |= COOKIE_FLAG_SECURE; + /* @@@ Should we set port to 443 if secure is set? @@@ */ moo->expires = expires; /* * I don't like using this to store the cookies because it's * designed to store cookies that have been received from an * HTTP request, not from a persistent cookie jar. Hence the - * mucking about with the COOKIE_FLAG_PERSISTENT above. - RP + * mucking about with the COOKIE_FLAG_FROM_FILE above. - RP */ store_cookie(moo, domain, path); } @@ -1986,11 +2062,16 @@ PUBLIC void LYStoreCookies ARGS1 ( /* * Check whether we have something to do. - FM */ - if (HTList_isEmpty(domain_list)) { - /* No cookies, so don't bother updating the file */ + if (HTList_isEmpty(domain_list) && + number_of_file_cookies == 0) { + /* No cookies now, and haven't read any, + * so don't bother updating the file. + */ return; } + CTRACE(tfp, "LYStoreCookies: save cookies to %s on exit\n", cookie_file); + cookie_handle = LYNewTxtFile (cookie_file); for (dl = domain_list; dl != NULL; dl = dl->next) { de = dl->object; @@ -2011,7 +2092,7 @@ PUBLIC void LYStoreCookies ARGS1 ( case (QUERY_USER): HTSprintf0(&buf, COOKIES_ALLOWED_VIA_PROMPT); break; - case (FROM_FILE): + case (FROM_FILE): /* not used any more - kw */ HTSprintf0(&buf, gettext("(From Cookie Jar)")); break; } @@ -2028,12 +2109,26 @@ PUBLIC void LYStoreCookies ARGS1 ( if ((co = (cookie *)cl->object) == NULL) continue; - CTRACE(tfp, "LYStoreCookies: %ld cf %ld\n", (long) now, (long) co->expires); + CTRACE(tfp, "LYStoreCookies: %ld cf %ld ", (long) now, (long) co->expires); + + if ((co->flags & COOKIE_FLAG_DISCARD)) { + CTRACE(tfp, "not stored - DISCARD\n"); + continue; + } else if (!(co->flags & COOKIE_FLAG_EXPIRES_SET)) { + CTRACE(tfp, "not stored - no expiration time\n"); + continue; + } else if (co->expires <= now) { + CTRACE(tfp, "not stored - EXPIRED\n"); + continue; + } + fprintf(cookie_handle, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n", de->domain, "FALSE", co->path, co->flags & COOKIE_FLAG_SECURE ? "TRUE" : "FALSE", (long) co->expires, co->name, co->value); + + CTRACE(tfp, "STORED\n"); } } fclose(cookie_handle); @@ -2081,7 +2176,7 @@ PRIVATE int LYHandleCookies ARGS4 ( /* * Check whether we have something to do. - FM */ - if (domain_list == NULL) { + if (HTList_isEmpty(domain_list)) { HTProgress(COOKIE_JAR_IS_EMPTY); sleep(MessageSecs); return(HT_NO_DATA); @@ -2120,6 +2215,7 @@ PRIVATE int LYHandleCookies ARGS4 ( */ continue; if (!strcmp(domain, de->domain)) { + FREE(domain); /* * We found the domain. Check * whether a lynxID is present. - FM @@ -2159,7 +2255,7 @@ PRIVATE int LYHandleCookies ARGS4 ( HTList_delete(de->cookie_list); de->cookie_list = NULL; HTList_removeObject(domain_list, de); - de = NULL; + FREE(de); HTProgress(DOMAIN_EATEN); } else { HTProgress(COOKIE_EATEN); @@ -2194,7 +2290,7 @@ PRIVATE int LYHandleCookies ARGS4 ( * Set to accept all cookies * from this domain. - FM */ - de->bv = QUERY_USER; + de->bv = ACCEPT_ALWAYS; HTUserMsg2(ALWAYS_ALLOWING_COOKIES, de->domain); return(HT_NO_DATA); @@ -2218,7 +2314,7 @@ PRIVATE int LYHandleCookies ARGS4 ( HTList_delete(de->cookie_list); de->cookie_list = NULL; HTList_removeObject(domain_list, de); - de = NULL; + FREE(de); HTProgress(DOMAIN_EATEN); sleep(MessageSecs); break; @@ -2258,7 +2354,7 @@ Delete_all_cookies_in_domain: HTList_delete(de->cookie_list); de->cookie_list = NULL; HTList_removeObject(domain_list, de); - de = NULL; + FREE(de); HTProgress(DOMAIN_EATEN); sleep(MessageSecs); } @@ -2298,14 +2394,14 @@ Delete_all_cookies_in_domain: } if (HTList_isEmpty(domain_list)) { /* - * There are no more domains left, - * so delete the domain_list. - FM + * There are no more domains left. + * Don't delete the domain_list, otherwise + * atexit may be called multiple times. - kw */ - HTList_delete(domain_list); - domain_list = NULL; HTProgress(ALL_COOKIES_EATEN); sleep(MessageSecs); } + FREE(domain); return(HT_NO_DATA); } @@ -2336,7 +2432,7 @@ Delete_all_cookies_in_domain: (*target->isa->put_block)(target, buf, strlen(buf)); HTSprintf0(&buf, "<h1>%s (%s)%s<a href=\"%s%s\">%s</a></h1>\n", LYNX_NAME, LYNX_VERSION, - HELP_ON_SEGMENT, + HELP_ON_SEGMENT, helpfilepath, COOKIE_JAR_HELP, COOKIE_JAR_TITLE); (*target->isa->put_block)(target, buf, strlen(buf)); @@ -2372,7 +2468,9 @@ Delete_all_cookies_in_domain: HTSprintf0(&buf, COOKIES_ALLOWED_VIA_PROMPT); break; case (FROM_FILE): +#if 0 /* not used any more - kw */ HTSprintf0(&buf, COOKIES_READ_FROM_FILE); +#endif break; } (*target->isa->put_block)(target, buf, strlen(buf)); @@ -2410,6 +2508,11 @@ Delete_all_cookies_in_domain: FREE(value); (*target->isa->put_block)(target, buf, strlen(buf)); + if (co->flags & COOKIE_FLAG_FROM_FILE) { + HTSprintf0(&buf, "%s\n", gettext("(from a previous session)")); + (*target->isa->put_block)(target, buf, strlen(buf)); + } + /* * Show the path, port, secure and discard setting. - FM */ @@ -2467,12 +2570,10 @@ Delete_all_cookies_in_domain: */ HTSprintf0(&buf, "<DD><EM>%s</EM> %s%s", gettext("Maximum Gobble Date:"), - ((co->expires > 0 && - !(co->flags & COOKIE_FLAG_DISCARD)) + ((co->flags & COOKIE_FLAG_EXPIRES_SET) ? ctime(&co->expires) : END_OF_SESSION), - ((co->expires > 0 && - !(co->flags & COOKIE_FLAG_DISCARD)) + ((co->flags & COOKIE_FLAG_EXPIRES_SET) ? "" : "\n")); (*target->isa->put_block)(target, buf, strlen(buf)); diff --git a/src/LYGetFile.c b/src/LYGetFile.c index 5ea77c2e..64109c8a 100644 --- a/src/LYGetFile.c +++ b/src/LYGetFile.c @@ -354,7 +354,8 @@ Try_Redirected_URL: * Bug puts slash on end if none is in the string. */ char *last_slash = strrchr(doc->address,'/'); - if (last_slash-doc->address==strlen(doc->address)-1) + if (last_slash - doc->address + == (int)strlen(doc->address) - 1) doc->address[strlen(doc->address)-1] = '\0'; p = doc->address; diff --git a/src/LYHistory.c b/src/LYHistory.c index 874099e2..494d6152 100644 --- a/src/LYHistory.c +++ b/src/LYHistory.c @@ -394,6 +394,10 @@ PUBLIC int showhistory ARGS1( if (history[x].title != NULL) { StrAllocCopy(Title, history[x].title); LYEntify(&Title, TRUE); + LYTrimLeading(Title); + LYTrimTrailing(Title); + if (*Title == '\0') + StrAllocCopy(Title , gettext("(no title)")); } else { StrAllocCopy(Title, gettext("(no title)")); } @@ -542,6 +546,10 @@ PUBLIC int LYShowVisitedLinks ARGS1( if (vl->title != NULL && *vl->title != '\0') { StrAllocCopy(Title, vl->title); LYEntify(&Title, TRUE); + LYTrimLeading(Title); + LYTrimTrailing(Title); + if (*Title == '\0') + StrAllocCopy(Title , gettext("(no title)")); } else { StrAllocCopy(Title , gettext("(no title)")); } diff --git a/src/LYKeymap.c b/src/LYKeymap.c index 2d01e830..852799e9 100644 --- a/src/LYKeymap.c +++ b/src/LYKeymap.c @@ -41,7 +41,7 @@ struct _HTStream /* the character gets 1 added to it before lookup, * so that EOF maps to 0 */ -unsigned short keymap[] = { +unsigned short keymap[KEYMAP_SIZE] = { 0, /* EOF */ @@ -362,7 +362,7 @@ LYK_DO_NOTHING, 0, 0, 0, 0, 0, 0, 0, 0, /* 290...293 */ - 0, 0, 0, 0, + LYK_CHANGE_LINK, 0, 0, 0, }; #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) @@ -372,7 +372,7 @@ LYK_DO_NOTHING, * allowed at compile time. */ -unsigned short key_override[TABLESIZE(keymap)] = { +unsigned short key_override[KEYMAP_SIZE] = { 0, /* EOF */ @@ -606,6 +606,7 @@ PRIVATE struct rmap revmap[] = { { "CLEAR_AUTH", "clear all authorization info for this session" }, { "SWITCH_DTD", "switch between two ways of parsing HTML" }, { "ELGOTO", "edit the current link's URL or ACTION and go to it" }, +{ "CHANGE_LINK", "force reset of the current link on the page" }, #ifdef USE_EXTERNALS { "EXTERN", "run external program with url" }, #endif @@ -664,6 +665,8 @@ PRIVATE char *pretty ARGS1 (int, c) sprintf(buf, "^%c", c|0100); else if (c >= 0400 && (c - 0400) < (int) TABLESIZE(funckey)) sprintf(buf, "%s", funckey[c-0400]); + else if (c >= 0400) + sprintf(buf, "%#x", c); else return 0; @@ -745,11 +748,11 @@ PRIVATE int LYLoadKeymap ARGS4 ( i-' '); /* uppercase mapping is different */ } } - for (i = 1; i < (int) TABLESIZE(keymap); i++) { + for (i = 1; i < KEYMAP_SIZE; i++) { /* * LYK_PIPE not implemented yet. */ - if ((i > (int) TABLESIZE(keymap) || i <= ' ' || !isalpha(i-1)) && + if ((i >= 0400 || i <= ' ' || !isalpha(i-1)) && strcmp(revmap[keymap[i]].name, "PIPE")) { print_binding(target, buf, i); } @@ -926,7 +929,7 @@ PUBLIC int lookup_keymap ARGS1( { size_t i; - for (i = 1; i < TABLESIZE(keymap); i++) { + for (i = 1; i < KEYMAP_SIZE; i++) { if (LYisNonAlnumKeyname(i, func)) { return i; } @@ -961,7 +964,7 @@ PUBLIC BOOL LYisNonAlnumKeyname ARGS2( { if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'z') || - ch < 0 || ch > 269) + ch < 0 || ch >= KEYMAP_SIZE) return (FALSE); return(keymap[ch+1] == key_name); @@ -976,7 +979,7 @@ PUBLIC int LYReverseKeymap ARGS1( { int i; - for (i = 1; i < (int) TABLESIZE(keymap); i++) { + for (i = 1; i < KEYMAP_SIZE; i++) { if (keymap[i] == key_name) { return(i - 1); } diff --git a/src/LYKeymap.h b/src/LYKeymap.h index a1acced8..2fc192e8 100644 --- a/src/LYKeymap.h +++ b/src/LYKeymap.h @@ -17,7 +17,8 @@ extern void set_numbers_as_arrows NOPARAMS; extern void set_vi_keys NOPARAMS; extern void set_vms_keys NOPARAMS; -extern unsigned short keymap[]; /* main keymap matrix */ +#define KEYMAP_SIZE 661 +extern unsigned short keymap[KEYMAP_SIZE]; /* main keymap matrix */ #ifdef EXP_KEYBOARD_LAYOUT extern int current_layout; @@ -138,4 +139,6 @@ extern unsigned short key_override[]; #define LYK_FORM_DOWN 83 #endif /* NOT_USED */ +#define LYK_CHANGE_LINK 90 /* FIXME: make these an enum */ + #endif /* LYKEYMAP_H */ diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c index c38a5d4b..1b5b2739 100644 --- a/src/LYMainLoop.c +++ b/src/LYMainLoop.c @@ -166,6 +166,18 @@ PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr) return TRUE; } +PRIVATE void do_change_link ARGS1( + char *, prev_target) +{ + /* Is there a mouse-clicked link waiting? */ + int mouse_tmp = get_mouse_link(); + /* If yes, use it as the link */ + if (mouse_tmp != -1) { + highlight(OFF, curdoc.link, prev_target); + curdoc.link = mouse_tmp; + } +} + /* * Here's where we do all the work. * mainloop is basically just a big switch dependent on the users input. @@ -2461,6 +2473,10 @@ new_cmd: /* } break; + case LYK_CHANGE_LINK: + do_change_link(prev_target); + break; + case LYK_RIGHT_LINK: if (curdoc.link<nlinks-1 && links[curdoc.link].ly == links[curdoc.link+1].ly) { diff --git a/src/LYOptions.c b/src/LYOptions.c index 6ac5fa41..7b76c618 100644 --- a/src/LYOptions.c +++ b/src/LYOptions.c @@ -33,13 +33,6 @@ PRIVATE int boolean_choice PARAMS(( int line, int column, char ** choices)); -PRIVATE int popup_choice PARAMS(( - int cur_choice, - int line, - int column, - char ** choices, - int i_length, - int disabled)); #define MAXCHOICES 10 @@ -2217,7 +2210,7 @@ PRIVATE int get_popup_choice_number ARGS1( * option via a popup window which functions like * that for selection of options in a form. - FM */ -PRIVATE int popup_choice ARGS6( +PUBLIC int popup_choice ARGS6( int, cur_choice, int, line, int, column, diff --git a/src/LYOptions.h b/src/LYOptions.h index c8fdccbd..5fab617d 100644 --- a/src/LYOptions.h +++ b/src/LYOptions.h @@ -6,6 +6,13 @@ extern BOOLEAN term_options; /* for LYgetstr() */ extern void edit_bookmarks NOPARAMS; +extern int popup_choice PARAMS(( + int cur_choice, + int line, + int column, + char ** choices, + int i_length, + int disabled)); #ifndef NO_OPTION_FORMS extern int postoptions PARAMS((document *newdoc)); diff --git a/src/LYStrings.c b/src/LYStrings.c index ac24013a..f02c22c5 100644 --- a/src/LYStrings.c +++ b/src/LYStrings.c @@ -11,6 +11,7 @@ #include <LYNews.h> #include <LYOptions.h> #include <LYCharSets.h> +#include <HTAlert.h> #include <HTString.h> #ifdef DJGPP_KEYHANDLER @@ -157,6 +158,24 @@ PUBLIC int fancy_mouse ARGS3( return cmd; } +PRIVATE int XYdist ARGS5( + int, x1, + int, y1, + int, x2, + int, y2, + int, dx2) +{ + int xerr = x2 - x1, yerr = y2 - y1; + + if (xerr < 0) + xerr = x1 - x2 - dx2; + if (xerr < 0) + xerr = 0; + if (yerr < 0) + yerr = -yerr; + return xerr + yerr; +} + /* Given X and Y coordinates of a mouse event, set mouse_link to the ** index of the corresponding hyperlink, or set mouse_link to -1 if no ** link matches the event. Returns -1 if no link matched the click, @@ -164,7 +183,10 @@ PUBLIC int fancy_mouse ARGS3( ** link. **/ -PRIVATE int set_clicked_link ARGS3(int,x,int,y,int,code) +PRIVATE int set_clicked_link ARGS3( + int, x, + int, y, + int, code) { int left = 6; int right = LYcols-6; @@ -183,6 +205,8 @@ PRIVATE int set_clicked_link ARGS3(int,x,int,y,int,code) else if (x > right) c = '\b'; else c = PGUP; } else { + int mouse_err = -1, cur_err; + /* Loop over the links and see if we can get a match */ for (i = 0; i < nlinks; i++) { int len, lx = links[i].lx, is_text = 0; @@ -199,26 +223,41 @@ PRIVATE int set_clicked_link ARGS3(int,x,int,y,int,code) len = strlen(links[i].hightext ); /* Check the first line of the link */ - if ( links[i].hightext != NULL && - links[i].ly == y && (x - lx) < len && (x >= lx)) { - int cury, curx; - - if (code != FOR_INPUT - /* Do not pick up the current input field */ - || !(LYGetYX(cury,curx), - (cury == y && (curx >= lx) && ((curx - lx) <= len)))) { - if (is_text) - have_levent = 1; + if ( links[i].hightext != NULL) { + cur_err = XYdist(x, y, links[i].lx, links[i].ly, len); + if (cur_err == 0) { + int cury, curx; + + if (code != FOR_INPUT + /* Do not pick up the current input field */ + || !(LYGetYX(cury,curx), + (cury == y && (curx >= lx) && ((curx - lx) <= len)))) { + if (is_text) + have_levent = 1; + mouse_link = i; + } else + mouse_link = -1; + mouse_err = 0; + break; + } else if (cur_err < mouse_err) { + mouse_err = cur_err; mouse_link = i; } - break; } /* Check the second line */ - if (links[i].hightext2 != NULL && - 1+links[i].ly == y && - (x - links[i].hightext2_offset) < (int)strlen(links[i].hightext2) ) { - mouse_link = i; - break; + if (links[i].hightext2 != NULL) { + cur_err = XYdist(x, y, + links[i].hightext2_offset, + links[i].ly+1, + strlen(links[i].hightext2)); + if (cur_err == 0) { + mouse_link = i; + mouse_err = 0; + break; + } else if (cur_err < mouse_err) { + mouse_err = cur_err; + mouse_link = i; + } } } /* @@ -226,8 +265,12 @@ PRIVATE int set_clicked_link ARGS3(int,x,int,y,int,code) * LYK_ACTIVATE We expect to find LYK_ACTIVATE (it's usually mapped to * the Enter key). */ - if (mouse_link >= 0) - c = lookup_keymap(LYK_ACTIVATE); + if (mouse_link >= 0) { + if (mouse_err == 0) + c = lookup_keymap(LYK_ACTIVATE); + else if (mouse_err >= 0) + c = lookup_keymap(LYK_CHANGE_LINK); + } } return c; } @@ -911,6 +954,89 @@ PUBLIC int lynx_initialize_keymaps NOARGS #endif /* USE_KEYMAPS */ +#ifdef NCURSES_MOUSE_VERSION +PRIVATE int LYmouse_menu ARGS3(int, x, int, y, int, atlink) +{ + char *choices[] = { + "Quit", + "Home page", + "Previous document", + "Beginning of document", + "Page up", + "Half page up", + "Two lines up", + "History", + "Help", + "Do nothing (refresh)", + "Load again", + "Edit URL and load", + "Show info", + "Search", + "Print", + "Two lines down", + "Half page down", + "Page down", + "End of document", + "Bookmarks", + "Cookie jar", + "Search index", + "Set Options", + NULL + }; + char *choices_link[] = { + "Help", + "Do nothing", + "Activate this link", + "Show info", + "Download", + NULL + }; + int actions[] = { + LYK_ABORT, + LYK_MAIN_MENU, + LYK_PREV_DOC, + LYK_HOME, + LYK_PREV_PAGE, + LYK_UP_HALF, + LYK_UP_TWO, + LYK_HISTORY, + LYK_HELP, + LYK_REFRESH, + LYK_RELOAD, + LYK_ECGOTO, + LYK_INFO, + LYK_WHEREIS, + LYK_PRINT, + LYK_DOWN_TWO, + LYK_DOWN_HALF, + LYK_NEXT_PAGE, + LYK_END, + LYK_VIEW_BOOKMARK, + LYK_COOKIE_JAR, + LYK_INDEX_SEARCH, + LYK_OPTIONS + }; + int actions_link[] = { + LYK_HELP, + LYK_REFRESH, + LYK_ACTIVATE, + LYK_INFO, + LYK_DOWNLOAD + }; + int c; + + /* Somehow the mouse is over the number instead of being over the + name, so we decrease x. */ + c = popup_choice((atlink ? 2 : 9) - 1, y, (x >= 5 ? x-5 : 0), + (atlink ? choices_link : choices), + (atlink + ? (sizeof(actions_link)/sizeof(int)) + : (sizeof(actions)/sizeof(int))), FALSE); + + return atlink ? (actions_link[c]) : (actions[c]); +} +#endif + #if defined(USE_KEYMAPS) && defined(USE_SLANG) /* We cannot guarantee the type for 'GetChar', and should not use a cast. */ @@ -1274,6 +1400,23 @@ re_read: c = LYReverseKeymap(LYK_MAIN_MENU); } else if (event.bstate & BUTTON3_CLICKED) { c = LYReverseKeymap (LYK_PREV_DOC); + } else if (event.bstate & BUTTON2_CLICKED) { + int atlink; + + c = set_clicked_link(event.x, event.y, code); + atlink = c == LYReverseKeymap (LYK_ACTIVATE); + if (!atlink) + mouse_link = -1; /* Forget about approx stuff. */ + + c = LYmouse_menu(event.x, event.y, atlink); + if (c == LYK_ACTIVATE && mouse_link == -1) { + HTAlert("No link chosen"); + c = LYK_DO_NOTHING; + c = LYK_REFRESH; /* refresh() below does not work... */ + } + c = LYReverseKeymap(c); + lynx_force_repaint(); + refresh(); } if (code == FOR_INPUT && mouse_link == -1) { ungetmouse(&event); /* Caller will process this. */ @@ -1369,12 +1512,7 @@ re_read: } #endif /* USE_SLANG && __DJGPP__ && !DJGPP_KEYHANDLER && !USE_KEYMAPS */ -#if (defined(__DJGPP__) || defined(_WINDOWS)) - if (c > 659) -#else - if (c > DO_NOTHING) -#endif /* __DJGPP__ || _WINDOWS */ - { + if ((c+1) >= KEYMAP_SIZE) { /* * Don't return raw values for KEYPAD symbols which we may have * missed in the switch above if they are obviously invalid when @@ -2425,6 +2563,44 @@ PUBLIC char * SNACat ARGS3( return *dest; } +#include <caselower.h> + +/* + * Returns lowercase equivalent for unicode, + * transparent output if no equivalent found. + */ +PRIVATE long UniToLowerCase ARGS1(long, upper) +{ + size_t i, high, low; + long diff = 0; + + /* + * Make check for sure. + */ + if (upper <= 0) + return(upper); + + /* + * Try unicode_to_lower_case[]. + */ + low = 0; + high = sizeof(unicode_to_lower_case)/sizeof(unicode_to_lower_case[0]); + while (low < high) { + /* + ** Binary search. + */ + i = (low + (high-low)/2); + diff = (unicode_to_lower_case[i].upper - upper); + if (diff < 0) + low = i+1; + if (diff > 0) + high = i; + if (diff == 0) + return (unicode_to_lower_case[i].lower); + } + + return(upper); /* if we came here */ +} /* ** UPPER8 ? @@ -2432,11 +2608,40 @@ PUBLIC char * SNACat ARGS3( ** ** It was realized that case-insensitive user search ** got information about upper/lower mapping from TOUPPER -** (precisely from "(TOUPPER(a) - TOUPPER(b))==0"). -** This function depends on locale in its 8bit mapping -** and usually fails with DOS/WINDOWS display charsets +** (precisely from "(TOUPPER(a) - TOUPPER(b))==0") +** and depends on locale in its 8bit mapping. - +** Usually fails with DOS/WINDOWS display charsets ** as well as on non-UNIX systems. ** +** So use unicode case mapping. +*/ +PUBLIC int UPPER8 ARGS2(int,ch1, int,ch2) +{ + + /* case-insensitive match for us-ascii */ + if ((unsigned char)TOASCII(ch1) < 128 && (unsigned char)TOASCII(ch2) < 128) + return(TOUPPER(ch1) - TOUPPER(ch2)); + + /* case-insensitive match for upper half */ + if ((unsigned char)TOASCII(ch1) > 127 && /* S/390 -- gil -- 2066 */ + (unsigned char)TOASCII(ch2) > 127) + { + if (DisplayCharsetMatchLocale) + return(TOUPPER(ch1) - TOUPPER(ch2)); /* old-style */ + else + { + long uni_ch1 = UCTransToUni(ch1, current_char_set); + long uni_ch2 = UCTransToUni(ch2, current_char_set); + return(UniToLowerCase(uni_ch1) - UniToLowerCase(uni_ch2)); + } + } + + return(-10); /* mismatch, if we come to here */ +} + + +#ifdef NOTUSED +/* ** We extend this function for 8bit letters ** using Lynx internal chartrans feature: ** we assume that upper/lower case letters @@ -2496,3 +2701,4 @@ PUBLIC int UPPER8 ARGS2(int,ch1, int,ch2) return(-10); /* mismatch, if we come to here */ } +#endif /* NOTUSED */ diff --git a/src/chrtrans/caselower.h b/src/chrtrans/caselower.h new file mode 100644 index 00000000..df42c073 --- /dev/null +++ b/src/chrtrans/caselower.h @@ -0,0 +1,737 @@ +/* + Lynx uses this info for 8bit case-insensitive user search. + + This table is generated from Unicode Character Database, Version 2.1.5 + available from ftp.unicode.org, and looks as natural way to get case mapping + equivalents for unicodes. (well, too much characters the cost of 3 Kb only). + Few words from the original README.txt quoted: + + +UNICODE 2.1 CHARACTER DATABASE + +Copyright (c) 1991-1998 Unicode, Inc. +All Rights reserved. + + +CASE MAPPINGS + +The case mapping is an informative, default mapping. Certain languages, such +as Turkish, German, French, or Greek may have small deviations from the +default mappings listed in the Unicode Character Database. + + */ + + +typedef struct { + long upper; + long lower; +} unipair; + +static CONST unipair unicode_to_lower_case[] = +{ + {0x0041, 0x0061}, /* LATIN CAPITAL LETTER A */ + {0x0042, 0x0062}, /* LATIN CAPITAL LETTER B */ + {0x0043, 0x0063}, /* LATIN CAPITAL LETTER C */ + {0x0044, 0x0064}, /* LATIN CAPITAL LETTER D */ + {0x0045, 0x0065}, /* LATIN CAPITAL LETTER E */ + {0x0046, 0x0066}, /* LATIN CAPITAL LETTER F */ + {0x0047, 0x0067}, /* LATIN CAPITAL LETTER G */ + {0x0048, 0x0068}, /* LATIN CAPITAL LETTER H */ + {0x0049, 0x0069}, /* LATIN CAPITAL LETTER I */ + {0x004A, 0x006A}, /* LATIN CAPITAL LETTER J */ + {0x004B, 0x006B}, /* LATIN CAPITAL LETTER K */ + {0x004C, 0x006C}, /* LATIN CAPITAL LETTER L */ + {0x004D, 0x006D}, /* LATIN CAPITAL LETTER M */ + {0x004E, 0x006E}, /* LATIN CAPITAL LETTER N */ + {0x004F, 0x006F}, /* LATIN CAPITAL LETTER O */ + {0x0050, 0x0070}, /* LATIN CAPITAL LETTER P */ + {0x0051, 0x0071}, /* LATIN CAPITAL LETTER Q */ + {0x0052, 0x0072}, /* LATIN CAPITAL LETTER R */ + {0x0053, 0x0073}, /* LATIN CAPITAL LETTER S */ + {0x0054, 0x0074}, /* LATIN CAPITAL LETTER T */ + {0x0055, 0x0075}, /* LATIN CAPITAL LETTER U */ + {0x0056, 0x0076}, /* LATIN CAPITAL LETTER V */ + {0x0057, 0x0077}, /* LATIN CAPITAL LETTER W */ + {0x0058, 0x0078}, /* LATIN CAPITAL LETTER X */ + {0x0059, 0x0079}, /* LATIN CAPITAL LETTER Y */ + {0x005A, 0x007A}, /* LATIN CAPITAL LETTER Z */ + {0x00C0, 0x00E0}, /* LATIN CAPITAL LETTER A WITH GRAVE */ + {0x00C1, 0x00E1}, /* LATIN CAPITAL LETTER A WITH ACUTE */ + {0x00C2, 0x00E2}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + {0x00C3, 0x00E3}, /* LATIN CAPITAL LETTER A WITH TILDE */ + {0x00C4, 0x00E4}, /* LATIN CAPITAL LETTER A WITH DIAERESIS */ + {0x00C5, 0x00E5}, /* LATIN CAPITAL LETTER A WITH RING ABOVE */ + {0x00C6, 0x00E6}, /* LATIN CAPITAL LETTER AE */ + {0x00C7, 0x00E7}, /* LATIN CAPITAL LETTER C WITH CEDILLA */ + {0x00C8, 0x00E8}, /* LATIN CAPITAL LETTER E WITH GRAVE */ + {0x00C9, 0x00E9}, /* LATIN CAPITAL LETTER E WITH ACUTE */ + {0x00CA, 0x00EA}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + {0x00CB, 0x00EB}, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ + {0x00CC, 0x00EC}, /* LATIN CAPITAL LETTER I WITH GRAVE */ + {0x00CD, 0x00ED}, /* LATIN CAPITAL LETTER I WITH ACUTE */ + {0x00CE, 0x00EE}, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + {0x00CF, 0x00EF}, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ + {0x00D0, 0x00F0}, /* LATIN CAPITAL LETTER ETH */ + {0x00D1, 0x00F1}, /* LATIN CAPITAL LETTER N WITH TILDE */ + {0x00D2, 0x00F2}, /* LATIN CAPITAL LETTER O WITH GRAVE */ + {0x00D3, 0x00F3}, /* LATIN CAPITAL LETTER O WITH ACUTE */ + {0x00D4, 0x00F4}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + {0x00D5, 0x00F5}, /* LATIN CAPITAL LETTER O WITH TILDE */ + {0x00D6, 0x00F6}, /* LATIN CAPITAL LETTER O WITH DIAERESIS */ + {0x00D8, 0x00F8}, /* LATIN CAPITAL LETTER O WITH STROKE */ + {0x00D9, 0x00F9}, /* LATIN CAPITAL LETTER U WITH GRAVE */ + {0x00DA, 0x00FA}, /* LATIN CAPITAL LETTER U WITH ACUTE */ + {0x00DB, 0x00FB}, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + {0x00DC, 0x00FC}, /* LATIN CAPITAL LETTER U WITH DIAERESIS */ + {0x00DD, 0x00FD}, /* LATIN CAPITAL LETTER Y WITH ACUTE */ + {0x00DE, 0x00FE}, /* LATIN CAPITAL LETTER THORN */ + {0x0100, 0x0101}, /* LATIN CAPITAL LETTER A WITH MACRON */ + {0x0102, 0x0103}, /* LATIN CAPITAL LETTER A WITH BREVE */ + {0x0104, 0x0105}, /* LATIN CAPITAL LETTER A WITH OGONEK */ + {0x0106, 0x0107}, /* LATIN CAPITAL LETTER C WITH ACUTE */ + {0x0108, 0x0109}, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + {0x010A, 0x010B}, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */ + {0x010C, 0x010D}, /* LATIN CAPITAL LETTER C WITH CARON */ + {0x010E, 0x010F}, /* LATIN CAPITAL LETTER D WITH CARON */ + {0x0110, 0x0111}, /* LATIN CAPITAL LETTER D WITH STROKE */ + {0x0112, 0x0113}, /* LATIN CAPITAL LETTER E WITH MACRON */ + {0x0114, 0x0115}, /* LATIN CAPITAL LETTER E WITH BREVE */ + {0x0116, 0x0117}, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ + {0x0118, 0x0119}, /* LATIN CAPITAL LETTER E WITH OGONEK */ + {0x011A, 0x011B}, /* LATIN CAPITAL LETTER E WITH CARON */ + {0x011C, 0x011D}, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + {0x011E, 0x011F}, /* LATIN CAPITAL LETTER G WITH BREVE */ + {0x0120, 0x0121}, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */ + {0x0122, 0x0123}, /* LATIN CAPITAL LETTER G WITH CEDILLA */ + {0x0124, 0x0125}, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + {0x0126, 0x0127}, /* LATIN CAPITAL LETTER H WITH STROKE */ + {0x0128, 0x0129}, /* LATIN CAPITAL LETTER I WITH TILDE */ + {0x012A, 0x012B}, /* LATIN CAPITAL LETTER I WITH MACRON */ + {0x012C, 0x012D}, /* LATIN CAPITAL LETTER I WITH BREVE */ + {0x012E, 0x012F}, /* LATIN CAPITAL LETTER I WITH OGONEK */ + {0x0130, 0x0069}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ + {0x0132, 0x0133}, /* LATIN CAPITAL LIGATURE IJ */ + {0x0134, 0x0135}, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + {0x0136, 0x0137}, /* LATIN CAPITAL LETTER K WITH CEDILLA */ + {0x0139, 0x013A}, /* LATIN CAPITAL LETTER L WITH ACUTE */ + {0x013B, 0x013C}, /* LATIN CAPITAL LETTER L WITH CEDILLA */ + {0x013D, 0x013E}, /* LATIN CAPITAL LETTER L WITH CARON */ + {0x013F, 0x0140}, /* LATIN CAPITAL LETTER L WITH MIDDLE DOT */ + {0x0141, 0x0142}, /* LATIN CAPITAL LETTER L WITH STROKE */ + {0x0143, 0x0144}, /* LATIN CAPITAL LETTER N WITH ACUTE */ + {0x0145, 0x0146}, /* LATIN CAPITAL LETTER N WITH CEDILLA */ + {0x0147, 0x0148}, /* LATIN CAPITAL LETTER N WITH CARON */ + {0x014A, 0x014B}, /* LATIN CAPITAL LETTER ENG */ + {0x014C, 0x014D}, /* LATIN CAPITAL LETTER O WITH MACRON */ + {0x014E, 0x014F}, /* LATIN CAPITAL LETTER O WITH BREVE */ + {0x0150, 0x0151}, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + {0x0152, 0x0153}, /* LATIN CAPITAL LIGATURE OE */ + {0x0154, 0x0155}, /* LATIN CAPITAL LETTER R WITH ACUTE */ + {0x0156, 0x0157}, /* LATIN CAPITAL LETTER R WITH CEDILLA */ + {0x0158, 0x0159}, /* LATIN CAPITAL LETTER R WITH CARON */ + {0x015A, 0x015B}, /* LATIN CAPITAL LETTER S WITH ACUTE */ + {0x015C, 0x015D}, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + {0x015E, 0x015F}, /* LATIN CAPITAL LETTER S WITH CEDILLA */ + {0x0160, 0x0161}, /* LATIN CAPITAL LETTER S WITH CARON */ + {0x0162, 0x0163}, /* LATIN CAPITAL LETTER T WITH CEDILLA */ + {0x0164, 0x0165}, /* LATIN CAPITAL LETTER T WITH CARON */ + {0x0166, 0x0167}, /* LATIN CAPITAL LETTER T WITH STROKE */ + {0x0168, 0x0169}, /* LATIN CAPITAL LETTER U WITH TILDE */ + {0x016A, 0x016B}, /* LATIN CAPITAL LETTER U WITH MACRON */ + {0x016C, 0x016D}, /* LATIN CAPITAL LETTER U WITH BREVE */ + {0x016E, 0x016F}, /* LATIN CAPITAL LETTER U WITH RING ABOVE */ + {0x0170, 0x0171}, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + {0x0172, 0x0173}, /* LATIN CAPITAL LETTER U WITH OGONEK */ + {0x0174, 0x0175}, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ + {0x0176, 0x0177}, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ + {0x0178, 0x00FF}, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ + {0x0179, 0x017A}, /* LATIN CAPITAL LETTER Z WITH ACUTE */ + {0x017B, 0x017C}, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + {0x017D, 0x017E}, /* LATIN CAPITAL LETTER Z WITH CARON */ + {0x0181, 0x0253}, /* LATIN CAPITAL LETTER B WITH HOOK */ + {0x0182, 0x0183}, /* LATIN CAPITAL LETTER B WITH TOPBAR */ + {0x0184, 0x0185}, /* LATIN CAPITAL LETTER TONE SIX */ + {0x0186, 0x0254}, /* LATIN CAPITAL LETTER OPEN O */ + {0x0187, 0x0188}, /* LATIN CAPITAL LETTER C WITH HOOK */ + {0x0189, 0x0256}, /* LATIN CAPITAL LETTER AFRICAN D */ + {0x018A, 0x0257}, /* LATIN CAPITAL LETTER D WITH HOOK */ + {0x018B, 0x018C}, /* LATIN CAPITAL LETTER D WITH TOPBAR */ + {0x018E, 0x01DD}, /* LATIN CAPITAL LETTER REVERSED E */ + {0x018F, 0x0259}, /* LATIN CAPITAL LETTER SCHWA */ + {0x0190, 0x025B}, /* LATIN CAPITAL LETTER OPEN E */ + {0x0191, 0x0192}, /* LATIN CAPITAL LETTER F WITH HOOK */ + {0x0193, 0x0260}, /* LATIN CAPITAL LETTER G WITH HOOK */ + {0x0194, 0x0263}, /* LATIN CAPITAL LETTER GAMMA */ + {0x0196, 0x0269}, /* LATIN CAPITAL LETTER IOTA */ + {0x0197, 0x0268}, /* LATIN CAPITAL LETTER I WITH STROKE */ + {0x0198, 0x0199}, /* LATIN CAPITAL LETTER K WITH HOOK */ + {0x019C, 0x026F}, /* LATIN CAPITAL LETTER TURNED M */ + {0x019D, 0x0272}, /* LATIN CAPITAL LETTER N WITH LEFT HOOK */ + {0x019F, 0x0275}, /* LATIN CAPITAL LETTER O WITH MIDDLE TILDE */ + {0x01A0, 0x01A1}, /* LATIN CAPITAL LETTER O WITH HORN */ + {0x01A2, 0x01A3}, /* LATIN CAPITAL LETTER OI */ + {0x01A4, 0x01A5}, /* LATIN CAPITAL LETTER P WITH HOOK */ + {0x01A7, 0x01A8}, /* LATIN CAPITAL LETTER TONE TWO */ + {0x01A9, 0x0283}, /* LATIN CAPITAL LETTER ESH */ + {0x01AC, 0x01AD}, /* LATIN CAPITAL LETTER T WITH HOOK */ + {0x01AE, 0x0288}, /* LATIN CAPITAL LETTER T WITH RETROFLEX HOOK */ + {0x01AF, 0x01B0}, /* LATIN CAPITAL LETTER U WITH HORN */ + {0x01B1, 0x028A}, /* LATIN CAPITAL LETTER UPSILON */ + {0x01B2, 0x028B}, /* LATIN CAPITAL LETTER V WITH HOOK */ + {0x01B3, 0x01B4}, /* LATIN CAPITAL LETTER Y WITH HOOK */ + {0x01B5, 0x01B6}, /* LATIN CAPITAL LETTER Z WITH STROKE */ + {0x01B7, 0x0292}, /* LATIN CAPITAL LETTER EZH */ + {0x01B8, 0x01B9}, /* LATIN CAPITAL LETTER EZH REVERSED */ + {0x01BC, 0x01BD}, /* LATIN CAPITAL LETTER TONE FIVE */ + {0x01C4, 0x01C6}, /* LATIN CAPITAL LETTER DZ WITH CARON */ + {0x01C5, 0x01C6}, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON */ + {0x01C7, 0x01C9}, /* LATIN CAPITAL LETTER LJ */ + {0x01C8, 0x01C9}, /* LATIN CAPITAL LETTER L WITH SMALL LETTER J */ + {0x01CA, 0x01CC}, /* LATIN CAPITAL LETTER NJ */ + {0x01CB, 0x01CC}, /* LATIN CAPITAL LETTER N WITH SMALL LETTER J */ + {0x01CD, 0x01CE}, /* LATIN CAPITAL LETTER A WITH CARON */ + {0x01CF, 0x01D0}, /* LATIN CAPITAL LETTER I WITH CARON */ + {0x01D1, 0x01D2}, /* LATIN CAPITAL LETTER O WITH CARON */ + {0x01D3, 0x01D4}, /* LATIN CAPITAL LETTER U WITH CARON */ + {0x01D5, 0x01D6}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */ + {0x01D7, 0x01D8}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */ + {0x01D9, 0x01DA}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */ + {0x01DB, 0x01DC}, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */ + {0x01DE, 0x01DF}, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */ + {0x01E0, 0x01E1}, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */ + {0x01E2, 0x01E3}, /* LATIN CAPITAL LETTER AE WITH MACRON */ + {0x01E4, 0x01E5}, /* LATIN CAPITAL LETTER G WITH STROKE */ + {0x01E6, 0x01E7}, /* LATIN CAPITAL LETTER G WITH CARON */ + {0x01E8, 0x01E9}, /* LATIN CAPITAL LETTER K WITH CARON */ + {0x01EA, 0x01EB}, /* LATIN CAPITAL LETTER O WITH OGONEK */ + {0x01EC, 0x01ED}, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */ + {0x01EE, 0x01EF}, /* LATIN CAPITAL LETTER EZH WITH CARON */ + {0x01F1, 0x01F3}, /* LATIN CAPITAL LETTER DZ */ + {0x01F2, 0x01F3}, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z */ + {0x01F4, 0x01F5}, /* LATIN CAPITAL LETTER G WITH ACUTE */ + {0x01FA, 0x01FB}, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */ + {0x01FC, 0x01FD}, /* LATIN CAPITAL LETTER AE WITH ACUTE */ + {0x01FE, 0x01FF}, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */ + {0x0200, 0x0201}, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */ + {0x0202, 0x0203}, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */ + {0x0204, 0x0205}, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */ + {0x0206, 0x0207}, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */ + {0x0208, 0x0209}, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */ + {0x020A, 0x020B}, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */ + {0x020C, 0x020D}, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */ + {0x020E, 0x020F}, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */ + {0x0210, 0x0211}, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */ + {0x0212, 0x0213}, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */ + {0x0214, 0x0215}, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */ + {0x0216, 0x0217}, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */ + {0x0386, 0x03AC}, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */ + {0x0388, 0x03AD}, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ + {0x0389, 0x03AE}, /* GREEK CAPITAL LETTER ETA WITH TONOS */ + {0x038A, 0x03AF}, /* GREEK CAPITAL LETTER IOTA WITH TONOS */ + {0x038C, 0x03CC}, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */ + {0x038E, 0x03CD}, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */ + {0x038F, 0x03CE}, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */ + {0x0391, 0x03B1}, /* GREEK CAPITAL LETTER ALPHA */ + {0x0392, 0x03B2}, /* GREEK CAPITAL LETTER BETA */ + {0x0393, 0x03B3}, /* GREEK CAPITAL LETTER GAMMA */ + {0x0394, 0x03B4}, /* GREEK CAPITAL LETTER DELTA */ + {0x0395, 0x03B5}, /* GREEK CAPITAL LETTER EPSILON */ + {0x0396, 0x03B6}, /* GREEK CAPITAL LETTER ZETA */ + {0x0397, 0x03B7}, /* GREEK CAPITAL LETTER ETA */ + {0x0398, 0x03B8}, /* GREEK CAPITAL LETTER THETA */ + {0x0399, 0x03B9}, /* GREEK CAPITAL LETTER IOTA */ + {0x039A, 0x03BA}, /* GREEK CAPITAL LETTER KAPPA */ + {0x039B, 0x03BB}, /* GREEK CAPITAL LETTER LAMDA */ + {0x039C, 0x03BC}, /* GREEK CAPITAL LETTER MU */ + {0x039D, 0x03BD}, /* GREEK CAPITAL LETTER NU */ + {0x039E, 0x03BE}, /* GREEK CAPITAL LETTER XI */ + {0x039F, 0x03BF}, /* GREEK CAPITAL LETTER OMICRON */ + {0x03A0, 0x03C0}, /* GREEK CAPITAL LETTER PI */ + {0x03A1, 0x03C1}, /* GREEK CAPITAL LETTER RHO */ + {0x03A3, 0x03C3}, /* GREEK CAPITAL LETTER SIGMA */ + {0x03A4, 0x03C4}, /* GREEK CAPITAL LETTER TAU */ + {0x03A5, 0x03C5}, /* GREEK CAPITAL LETTER UPSILON */ + {0x03A6, 0x03C6}, /* GREEK CAPITAL LETTER PHI */ + {0x03A7, 0x03C7}, /* GREEK CAPITAL LETTER CHI */ + {0x03A8, 0x03C8}, /* GREEK CAPITAL LETTER PSI */ + {0x03A9, 0x03C9}, /* GREEK CAPITAL LETTER OMEGA */ + {0x03AA, 0x03CA}, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + {0x03AB, 0x03CB}, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + {0x03E2, 0x03E3}, /* COPTIC CAPITAL LETTER SHEI */ + {0x03E4, 0x03E5}, /* COPTIC CAPITAL LETTER FEI */ + {0x03E6, 0x03E7}, /* COPTIC CAPITAL LETTER KHEI */ + {0x03E8, 0x03E9}, /* COPTIC CAPITAL LETTER HORI */ + {0x03EA, 0x03EB}, /* COPTIC CAPITAL LETTER GANGIA */ + {0x03EC, 0x03ED}, /* COPTIC CAPITAL LETTER SHIMA */ + {0x03EE, 0x03EF}, /* COPTIC CAPITAL LETTER DEI */ + {0x0401, 0x0451}, /* CYRILLIC CAPITAL LETTER IO */ + {0x0402, 0x0452}, /* CYRILLIC CAPITAL LETTER DJE */ + {0x0403, 0x0453}, /* CYRILLIC CAPITAL LETTER GJE */ + {0x0404, 0x0454}, /* CYRILLIC CAPITAL LETTER UKRAINIAN IE */ + {0x0405, 0x0455}, /* CYRILLIC CAPITAL LETTER DZE */ + {0x0406, 0x0456}, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ + {0x0407, 0x0457}, /* CYRILLIC CAPITAL LETTER YI */ + {0x0408, 0x0458}, /* CYRILLIC CAPITAL LETTER JE */ + {0x0409, 0x0459}, /* CYRILLIC CAPITAL LETTER LJE */ + {0x040A, 0x045A}, /* CYRILLIC CAPITAL LETTER NJE */ + {0x040B, 0x045B}, /* CYRILLIC CAPITAL LETTER TSHE */ + {0x040C, 0x045C}, /* CYRILLIC CAPITAL LETTER KJE */ + {0x040E, 0x045E}, /* CYRILLIC CAPITAL LETTER SHORT U */ + {0x040F, 0x045F}, /* CYRILLIC CAPITAL LETTER DZHE */ + {0x0410, 0x0430}, /* CYRILLIC CAPITAL LETTER A */ + {0x0411, 0x0431}, /* CYRILLIC CAPITAL LETTER BE */ + {0x0412, 0x0432}, /* CYRILLIC CAPITAL LETTER VE */ + {0x0413, 0x0433}, /* CYRILLIC CAPITAL LETTER GHE */ + {0x0414, 0x0434}, /* CYRILLIC CAPITAL LETTER DE */ + {0x0415, 0x0435}, /* CYRILLIC CAPITAL LETTER IE */ + {0x0416, 0x0436}, /* CYRILLIC CAPITAL LETTER ZHE */ + {0x0417, 0x0437}, /* CYRILLIC CAPITAL LETTER ZE */ + {0x0418, 0x0438}, /* CYRILLIC CAPITAL LETTER I */ + {0x0419, 0x0439}, /* CYRILLIC CAPITAL LETTER SHORT I */ + {0x041A, 0x043A}, /* CYRILLIC CAPITAL LETTER KA */ + {0x041B, 0x043B}, /* CYRILLIC CAPITAL LETTER EL */ + {0x041C, 0x043C}, /* CYRILLIC CAPITAL LETTER EM */ + {0x041D, 0x043D}, /* CYRILLIC CAPITAL LETTER EN */ + {0x041E, 0x043E}, /* CYRILLIC CAPITAL LETTER O */ + {0x041F, 0x043F}, /* CYRILLIC CAPITAL LETTER PE */ + {0x0420, 0x0440}, /* CYRILLIC CAPITAL LETTER ER */ + {0x0421, 0x0441}, /* CYRILLIC CAPITAL LETTER ES */ + {0x0422, 0x0442}, /* CYRILLIC CAPITAL LETTER TE */ + {0x0423, 0x0443}, /* CYRILLIC CAPITAL LETTER U */ + {0x0424, 0x0444}, /* CYRILLIC CAPITAL LETTER EF */ + {0x0425, 0x0445}, /* CYRILLIC CAPITAL LETTER HA */ + {0x0426, 0x0446}, /* CYRILLIC CAPITAL LETTER TSE */ + {0x0427, 0x0447}, /* CYRILLIC CAPITAL LETTER CHE */ + {0x0428, 0x0448}, /* CYRILLIC CAPITAL LETTER SHA */ + {0x0429, 0x0449}, /* CYRILLIC CAPITAL LETTER SHCHA */ + {0x042A, 0x044A}, /* CYRILLIC CAPITAL LETTER HARD SIGN */ + {0x042B, 0x044B}, /* CYRILLIC CAPITAL LETTER YERU */ + {0x042C, 0x044C}, /* CYRILLIC CAPITAL LETTER SOFT SIGN */ + {0x042D, 0x044D}, /* CYRILLIC CAPITAL LETTER E */ + {0x042E, 0x044E}, /* CYRILLIC CAPITAL LETTER YU */ + {0x042F, 0x044F}, /* CYRILLIC CAPITAL LETTER YA */ + {0x0460, 0x0461}, /* CYRILLIC CAPITAL LETTER OMEGA */ + {0x0462, 0x0463}, /* CYRILLIC CAPITAL LETTER YAT */ + {0x0464, 0x0465}, /* CYRILLIC CAPITAL LETTER IOTIFIED E */ + {0x0466, 0x0467}, /* CYRILLIC CAPITAL LETTER LITTLE YUS */ + {0x0468, 0x0469}, /* CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS */ + {0x046A, 0x046B}, /* CYRILLIC CAPITAL LETTER BIG YUS */ + {0x046C, 0x046D}, /* CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS */ + {0x046E, 0x046F}, /* CYRILLIC CAPITAL LETTER KSI */ + {0x0470, 0x0471}, /* CYRILLIC CAPITAL LETTER PSI */ + {0x0472, 0x0473}, /* CYRILLIC CAPITAL LETTER FITA */ + {0x0474, 0x0475}, /* CYRILLIC CAPITAL LETTER IZHITSA */ + {0x0476, 0x0477}, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ + {0x0478, 0x0479}, /* CYRILLIC CAPITAL LETTER UK */ + {0x047A, 0x047B}, /* CYRILLIC CAPITAL LETTER ROUND OMEGA */ + {0x047C, 0x047D}, /* CYRILLIC CAPITAL LETTER OMEGA WITH TITLO */ + {0x047E, 0x047F}, /* CYRILLIC CAPITAL LETTER OT */ + {0x0480, 0x0481}, /* CYRILLIC CAPITAL LETTER KOPPA */ + {0x0490, 0x0491}, /* CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ + {0x0492, 0x0493}, /* CYRILLIC CAPITAL LETTER GHE WITH STROKE */ + {0x0494, 0x0495}, /* CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK */ + {0x0496, 0x0497}, /* CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */ + {0x0498, 0x0499}, /* CYRILLIC CAPITAL LETTER ZE WITH DESCENDER */ + {0x049A, 0x049B}, /* CYRILLIC CAPITAL LETTER KA WITH DESCENDER */ + {0x049C, 0x049D}, /* CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */ + {0x049E, 0x049F}, /* CYRILLIC CAPITAL LETTER KA WITH STROKE */ + {0x04A0, 0x04A1}, /* CYRILLIC CAPITAL LETTER BASHKIR KA */ + {0x04A2, 0x04A3}, /* CYRILLIC CAPITAL LETTER EN WITH DESCENDER */ + {0x04A4, 0x04A5}, /* CYRILLIC CAPITAL LIGATURE EN GHE */ + {0x04A6, 0x04A7}, /* CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK */ + {0x04A8, 0x04A9}, /* CYRILLIC CAPITAL LETTER ABKHASIAN HA */ + {0x04AA, 0x04AB}, /* CYRILLIC CAPITAL LETTER ES WITH DESCENDER */ + {0x04AC, 0x04AD}, /* CYRILLIC CAPITAL LETTER TE WITH DESCENDER */ + {0x04AE, 0x04AF}, /* CYRILLIC CAPITAL LETTER STRAIGHT U */ + {0x04B0, 0x04B1}, /* CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */ + {0x04B2, 0x04B3}, /* CYRILLIC CAPITAL LETTER HA WITH DESCENDER */ + {0x04B4, 0x04B5}, /* CYRILLIC CAPITAL LIGATURE TE TSE */ + {0x04B6, 0x04B7}, /* CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */ + {0x04B8, 0x04B9}, /* CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */ + {0x04BA, 0x04BB}, /* CYRILLIC CAPITAL LETTER SHHA */ + {0x04BC, 0x04BD}, /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE */ + {0x04BE, 0x04BF}, /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER */ + {0x04C1, 0x04C2}, /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */ + {0x04C3, 0x04C4}, /* CYRILLIC CAPITAL LETTER KA WITH HOOK */ + {0x04C7, 0x04C8}, /* CYRILLIC CAPITAL LETTER EN WITH HOOK */ + {0x04CB, 0x04CC}, /* CYRILLIC CAPITAL LETTER KHAKASSIAN CHE */ + {0x04D0, 0x04D1}, /* CYRILLIC CAPITAL LETTER A WITH BREVE */ + {0x04D2, 0x04D3}, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */ + {0x04D4, 0x04D5}, /* CYRILLIC CAPITAL LIGATURE A IE */ + {0x04D6, 0x04D7}, /* CYRILLIC CAPITAL LETTER IE WITH BREVE */ + {0x04D8, 0x04D9}, /* CYRILLIC CAPITAL LETTER SCHWA */ + {0x04DA, 0x04DB}, /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */ + {0x04DC, 0x04DD}, /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */ + {0x04DE, 0x04DF}, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */ + {0x04E0, 0x04E1}, /* CYRILLIC CAPITAL LETTER ABKHASIAN DZE */ + {0x04E2, 0x04E3}, /* CYRILLIC CAPITAL LETTER I WITH MACRON */ + {0x04E4, 0x04E5}, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */ + {0x04E6, 0x04E7}, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */ + {0x04E8, 0x04E9}, /* CYRILLIC CAPITAL LETTER BARRED O */ + {0x04EA, 0x04EB}, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */ + {0x04EE, 0x04EF}, /* CYRILLIC CAPITAL LETTER U WITH MACRON */ + {0x04F0, 0x04F1}, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */ + {0x04F2, 0x04F3}, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */ + {0x04F4, 0x04F5}, /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */ + {0x04F8, 0x04F9}, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */ + {0x0531, 0x0561}, /* ARMENIAN CAPITAL LETTER AYB */ + {0x0532, 0x0562}, /* ARMENIAN CAPITAL LETTER BEN */ + {0x0533, 0x0563}, /* ARMENIAN CAPITAL LETTER GIM */ + {0x0534, 0x0564}, /* ARMENIAN CAPITAL LETTER DA */ + {0x0535, 0x0565}, /* ARMENIAN CAPITAL LETTER ECH */ + {0x0536, 0x0566}, /* ARMENIAN CAPITAL LETTER ZA */ + {0x0537, 0x0567}, /* ARMENIAN CAPITAL LETTER EH */ + {0x0538, 0x0568}, /* ARMENIAN CAPITAL LETTER ET */ + {0x0539, 0x0569}, /* ARMENIAN CAPITAL LETTER TO */ + {0x053A, 0x056A}, /* ARMENIAN CAPITAL LETTER ZHE */ + {0x053B, 0x056B}, /* ARMENIAN CAPITAL LETTER INI */ + {0x053C, 0x056C}, /* ARMENIAN CAPITAL LETTER LIWN */ + {0x053D, 0x056D}, /* ARMENIAN CAPITAL LETTER XEH */ + {0x053E, 0x056E}, /* ARMENIAN CAPITAL LETTER CA */ + {0x053F, 0x056F}, /* ARMENIAN CAPITAL LETTER KEN */ + {0x0540, 0x0570}, /* ARMENIAN CAPITAL LETTER HO */ + {0x0541, 0x0571}, /* ARMENIAN CAPITAL LETTER JA */ + {0x0542, 0x0572}, /* ARMENIAN CAPITAL LETTER GHAD */ + {0x0543, 0x0573}, /* ARMENIAN CAPITAL LETTER CHEH */ + {0x0544, 0x0574}, /* ARMENIAN CAPITAL LETTER MEN */ + {0x0545, 0x0575}, /* ARMENIAN CAPITAL LETTER YI */ + {0x0546, 0x0576}, /* ARMENIAN CAPITAL LETTER NOW */ + {0x0547, 0x0577}, /* ARMENIAN CAPITAL LETTER SHA */ + {0x0548, 0x0578}, /* ARMENIAN CAPITAL LETTER VO */ + {0x0549, 0x0579}, /* ARMENIAN CAPITAL LETTER CHA */ + {0x054A, 0x057A}, /* ARMENIAN CAPITAL LETTER PEH */ + {0x054B, 0x057B}, /* ARMENIAN CAPITAL LETTER JHEH */ + {0x054C, 0x057C}, /* ARMENIAN CAPITAL LETTER RA */ + {0x054D, 0x057D}, /* ARMENIAN CAPITAL LETTER SEH */ + {0x054E, 0x057E}, /* ARMENIAN CAPITAL LETTER VEW */ + {0x054F, 0x057F}, /* ARMENIAN CAPITAL LETTER TIWN */ + {0x0550, 0x0580}, /* ARMENIAN CAPITAL LETTER REH */ + {0x0551, 0x0581}, /* ARMENIAN CAPITAL LETTER CO */ + {0x0552, 0x0582}, /* ARMENIAN CAPITAL LETTER YIWN */ + {0x0553, 0x0583}, /* ARMENIAN CAPITAL LETTER PIWR */ + {0x0554, 0x0584}, /* ARMENIAN CAPITAL LETTER KEH */ + {0x0555, 0x0585}, /* ARMENIAN CAPITAL LETTER OH */ + {0x0556, 0x0586}, /* ARMENIAN CAPITAL LETTER FEH */ + {0x10A0, 0x10D0}, /* GEORGIAN CAPITAL LETTER AN */ + {0x10A1, 0x10D1}, /* GEORGIAN CAPITAL LETTER BAN */ + {0x10A2, 0x10D2}, /* GEORGIAN CAPITAL LETTER GAN */ + {0x10A3, 0x10D3}, /* GEORGIAN CAPITAL LETTER DON */ + {0x10A4, 0x10D4}, /* GEORGIAN CAPITAL LETTER EN */ + {0x10A5, 0x10D5}, /* GEORGIAN CAPITAL LETTER VIN */ + {0x10A6, 0x10D6}, /* GEORGIAN CAPITAL LETTER ZEN */ + {0x10A7, 0x10D7}, /* GEORGIAN CAPITAL LETTER TAN */ + {0x10A8, 0x10D8}, /* GEORGIAN CAPITAL LETTER IN */ + {0x10A9, 0x10D9}, /* GEORGIAN CAPITAL LETTER KAN */ + {0x10AA, 0x10DA}, /* GEORGIAN CAPITAL LETTER LAS */ + {0x10AB, 0x10DB}, /* GEORGIAN CAPITAL LETTER MAN */ + {0x10AC, 0x10DC}, /* GEORGIAN CAPITAL LETTER NAR */ + {0x10AD, 0x10DD}, /* GEORGIAN CAPITAL LETTER ON */ + {0x10AE, 0x10DE}, /* GEORGIAN CAPITAL LETTER PAR */ + {0x10AF, 0x10DF}, /* GEORGIAN CAPITAL LETTER ZHAR */ + {0x10B0, 0x10E0}, /* GEORGIAN CAPITAL LETTER RAE */ + {0x10B1, 0x10E1}, /* GEORGIAN CAPITAL LETTER SAN */ + {0x10B2, 0x10E2}, /* GEORGIAN CAPITAL LETTER TAR */ + {0x10B3, 0x10E3}, /* GEORGIAN CAPITAL LETTER UN */ + {0x10B4, 0x10E4}, /* GEORGIAN CAPITAL LETTER PHAR */ + {0x10B5, 0x10E5}, /* GEORGIAN CAPITAL LETTER KHAR */ + {0x10B6, 0x10E6}, /* GEORGIAN CAPITAL LETTER GHAN */ + {0x10B7, 0x10E7}, /* GEORGIAN CAPITAL LETTER QAR */ + {0x10B8, 0x10E8}, /* GEORGIAN CAPITAL LETTER SHIN */ + {0x10B9, 0x10E9}, /* GEORGIAN CAPITAL LETTER CHIN */ + {0x10BA, 0x10EA}, /* GEORGIAN CAPITAL LETTER CAN */ + {0x10BB, 0x10EB}, /* GEORGIAN CAPITAL LETTER JIL */ + {0x10BC, 0x10EC}, /* GEORGIAN CAPITAL LETTER CIL */ + {0x10BD, 0x10ED}, /* GEORGIAN CAPITAL LETTER CHAR */ + {0x10BE, 0x10EE}, /* GEORGIAN CAPITAL LETTER XAN */ + {0x10BF, 0x10EF}, /* GEORGIAN CAPITAL LETTER JHAN */ + {0x10C0, 0x10F0}, /* GEORGIAN CAPITAL LETTER HAE */ + {0x10C1, 0x10F1}, /* GEORGIAN CAPITAL LETTER HE */ + {0x10C2, 0x10F2}, /* GEORGIAN CAPITAL LETTER HIE */ + {0x10C3, 0x10F3}, /* GEORGIAN CAPITAL LETTER WE */ + {0x10C4, 0x10F4}, /* GEORGIAN CAPITAL LETTER HAR */ + {0x10C5, 0x10F5}, /* GEORGIAN CAPITAL LETTER HOE */ + {0x1E00, 0x1E01}, /* LATIN CAPITAL LETTER A WITH RING BELOW */ + {0x1E02, 0x1E03}, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */ + {0x1E04, 0x1E05}, /* LATIN CAPITAL LETTER B WITH DOT BELOW */ + {0x1E06, 0x1E07}, /* LATIN CAPITAL LETTER B WITH LINE BELOW */ + {0x1E08, 0x1E09}, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */ + {0x1E0A, 0x1E0B}, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */ + {0x1E0C, 0x1E0D}, /* LATIN CAPITAL LETTER D WITH DOT BELOW */ + {0x1E0E, 0x1E0F}, /* LATIN CAPITAL LETTER D WITH LINE BELOW */ + {0x1E10, 0x1E11}, /* LATIN CAPITAL LETTER D WITH CEDILLA */ + {0x1E12, 0x1E13}, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */ + {0x1E14, 0x1E15}, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */ + {0x1E16, 0x1E17}, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */ + {0x1E18, 0x1E19}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */ + {0x1E1A, 0x1E1B}, /* LATIN CAPITAL LETTER E WITH TILDE BELOW */ + {0x1E1C, 0x1E1D}, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */ + {0x1E1E, 0x1E1F}, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */ + {0x1E20, 0x1E21}, /* LATIN CAPITAL LETTER G WITH MACRON */ + {0x1E22, 0x1E23}, /* LATIN CAPITAL LETTER H WITH DOT ABOVE */ + {0x1E24, 0x1E25}, /* LATIN CAPITAL LETTER H WITH DOT BELOW */ + {0x1E26, 0x1E27}, /* LATIN CAPITAL LETTER H WITH DIAERESIS */ + {0x1E28, 0x1E29}, /* LATIN CAPITAL LETTER H WITH CEDILLA */ + {0x1E2A, 0x1E2B}, /* LATIN CAPITAL LETTER H WITH BREVE BELOW */ + {0x1E2C, 0x1E2D}, /* LATIN CAPITAL LETTER I WITH TILDE BELOW */ + {0x1E2E, 0x1E2F}, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */ + {0x1E30, 0x1E31}, /* LATIN CAPITAL LETTER K WITH ACUTE */ + {0x1E32, 0x1E33}, /* LATIN CAPITAL LETTER K WITH DOT BELOW */ + {0x1E34, 0x1E35}, /* LATIN CAPITAL LETTER K WITH LINE BELOW */ + {0x1E36, 0x1E37}, /* LATIN CAPITAL LETTER L WITH DOT BELOW */ + {0x1E38, 0x1E39}, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */ + {0x1E3A, 0x1E3B}, /* LATIN CAPITAL LETTER L WITH LINE BELOW */ + {0x1E3C, 0x1E3D}, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */ + {0x1E3E, 0x1E3F}, /* LATIN CAPITAL LETTER M WITH ACUTE */ + {0x1E40, 0x1E41}, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */ + {0x1E42, 0x1E43}, /* LATIN CAPITAL LETTER M WITH DOT BELOW */ + {0x1E44, 0x1E45}, /* LATIN CAPITAL LETTER N WITH DOT ABOVE */ + {0x1E46, 0x1E47}, /* LATIN CAPITAL LETTER N WITH DOT BELOW */ + {0x1E48, 0x1E49}, /* LATIN CAPITAL LETTER N WITH LINE BELOW */ + {0x1E4A, 0x1E4B}, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */ + {0x1E4C, 0x1E4D}, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */ + {0x1E4E, 0x1E4F}, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */ + {0x1E50, 0x1E51}, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */ + {0x1E52, 0x1E53}, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */ + {0x1E54, 0x1E55}, /* LATIN CAPITAL LETTER P WITH ACUTE */ + {0x1E56, 0x1E57}, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */ + {0x1E58, 0x1E59}, /* LATIN CAPITAL LETTER R WITH DOT ABOVE */ + {0x1E5A, 0x1E5B}, /* LATIN CAPITAL LETTER R WITH DOT BELOW */ + {0x1E5C, 0x1E5D}, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */ + {0x1E5E, 0x1E5F}, /* LATIN CAPITAL LETTER R WITH LINE BELOW */ + {0x1E60, 0x1E61}, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */ + {0x1E62, 0x1E63}, /* LATIN CAPITAL LETTER S WITH DOT BELOW */ + {0x1E64, 0x1E65}, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */ + {0x1E66, 0x1E67}, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */ + {0x1E68, 0x1E69}, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */ + {0x1E6A, 0x1E6B}, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */ + {0x1E6C, 0x1E6D}, /* LATIN CAPITAL LETTER T WITH DOT BELOW */ + {0x1E6E, 0x1E6F}, /* LATIN CAPITAL LETTER T WITH LINE BELOW */ + {0x1E70, 0x1E71}, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */ + {0x1E72, 0x1E73}, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */ + {0x1E74, 0x1E75}, /* LATIN CAPITAL LETTER U WITH TILDE BELOW */ + {0x1E76, 0x1E77}, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */ + {0x1E78, 0x1E79}, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */ + {0x1E7A, 0x1E7B}, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */ + {0x1E7C, 0x1E7D}, /* LATIN CAPITAL LETTER V WITH TILDE */ + {0x1E7E, 0x1E7F}, /* LATIN CAPITAL LETTER V WITH DOT BELOW */ + {0x1E80, 0x1E81}, /* LATIN CAPITAL LETTER W WITH GRAVE */ + {0x1E82, 0x1E83}, /* LATIN CAPITAL LETTER W WITH ACUTE */ + {0x1E84, 0x1E85}, /* LATIN CAPITAL LETTER W WITH DIAERESIS */ + {0x1E86, 0x1E87}, /* LATIN CAPITAL LETTER W WITH DOT ABOVE */ + {0x1E88, 0x1E89}, /* LATIN CAPITAL LETTER W WITH DOT BELOW */ + {0x1E8A, 0x1E8B}, /* LATIN CAPITAL LETTER X WITH DOT ABOVE */ + {0x1E8C, 0x1E8D}, /* LATIN CAPITAL LETTER X WITH DIAERESIS */ + {0x1E8E, 0x1E8F}, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */ + {0x1E90, 0x1E91}, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */ + {0x1E92, 0x1E93}, /* LATIN CAPITAL LETTER Z WITH DOT BELOW */ + {0x1E94, 0x1E95}, /* LATIN CAPITAL LETTER Z WITH LINE BELOW */ + {0x1EA0, 0x1EA1}, /* LATIN CAPITAL LETTER A WITH DOT BELOW */ + {0x1EA2, 0x1EA3}, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */ + {0x1EA4, 0x1EA5}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ + {0x1EA6, 0x1EA7}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ + {0x1EA8, 0x1EA9}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1EAA, 0x1EAB}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ + {0x1EAC, 0x1EAD}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ + {0x1EAE, 0x1EAF}, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ + {0x1EB0, 0x1EB1}, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ + {0x1EB2, 0x1EB3}, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ + {0x1EB4, 0x1EB5}, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ + {0x1EB6, 0x1EB7}, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ + {0x1EB8, 0x1EB9}, /* LATIN CAPITAL LETTER E WITH DOT BELOW */ + {0x1EBA, 0x1EBB}, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */ + {0x1EBC, 0x1EBD}, /* LATIN CAPITAL LETTER E WITH TILDE */ + {0x1EBE, 0x1EBF}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ + {0x1EC0, 0x1EC1}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ + {0x1EC2, 0x1EC3}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1EC4, 0x1EC5}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ + {0x1EC6, 0x1EC7}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ + {0x1EC8, 0x1EC9}, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */ + {0x1ECA, 0x1ECB}, /* LATIN CAPITAL LETTER I WITH DOT BELOW */ + {0x1ECC, 0x1ECD}, /* LATIN CAPITAL LETTER O WITH DOT BELOW */ + {0x1ECE, 0x1ECF}, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */ + {0x1ED0, 0x1ED1}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ + {0x1ED2, 0x1ED3}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ + {0x1ED4, 0x1ED5}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ + {0x1ED6, 0x1ED7}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ + {0x1ED8, 0x1ED9}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ + {0x1EDA, 0x1EDB}, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ + {0x1EDC, 0x1EDD}, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ + {0x1EDE, 0x1EDF}, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ + {0x1EE0, 0x1EE1}, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */ + {0x1EE2, 0x1EE3}, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ + {0x1EE4, 0x1EE5}, /* LATIN CAPITAL LETTER U WITH DOT BELOW */ + {0x1EE6, 0x1EE7}, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */ + {0x1EE8, 0x1EE9}, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ + {0x1EEA, 0x1EEB}, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ + {0x1EEC, 0x1EED}, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ + {0x1EEE, 0x1EEF}, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */ + {0x1EF0, 0x1EF1}, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ + {0x1EF2, 0x1EF3}, /* LATIN CAPITAL LETTER Y WITH GRAVE */ + {0x1EF4, 0x1EF5}, /* LATIN CAPITAL LETTER Y WITH DOT BELOW */ + {0x1EF6, 0x1EF7}, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ + {0x1EF8, 0x1EF9}, /* LATIN CAPITAL LETTER Y WITH TILDE */ + {0x1F08, 0x1F00}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI */ + {0x1F09, 0x1F01}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA */ + {0x1F0A, 0x1F02}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */ + {0x1F0B, 0x1F03}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */ + {0x1F0C, 0x1F04}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */ + {0x1F0D, 0x1F05}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */ + {0x1F0E, 0x1F06}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */ + {0x1F0F, 0x1F07}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */ + {0x1F18, 0x1F10}, /* GREEK CAPITAL LETTER EPSILON WITH PSILI */ + {0x1F19, 0x1F11}, /* GREEK CAPITAL LETTER EPSILON WITH DASIA */ + {0x1F1A, 0x1F12}, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */ + {0x1F1B, 0x1F13}, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */ + {0x1F1C, 0x1F14}, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */ + {0x1F1D, 0x1F15}, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */ + {0x1F28, 0x1F20}, /* GREEK CAPITAL LETTER ETA WITH PSILI */ + {0x1F29, 0x1F21}, /* GREEK CAPITAL LETTER ETA WITH DASIA */ + {0x1F2A, 0x1F22}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */ + {0x1F2B, 0x1F23}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */ + {0x1F2C, 0x1F24}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */ + {0x1F2D, 0x1F25}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */ + {0x1F2E, 0x1F26}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */ + {0x1F2F, 0x1F27}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */ + {0x1F38, 0x1F30}, /* GREEK CAPITAL LETTER IOTA WITH PSILI */ + {0x1F39, 0x1F31}, /* GREEK CAPITAL LETTER IOTA WITH DASIA */ + {0x1F3A, 0x1F32}, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */ + {0x1F3B, 0x1F33}, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */ + {0x1F3C, 0x1F34}, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */ + {0x1F3D, 0x1F35}, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */ + {0x1F3E, 0x1F36}, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */ + {0x1F3F, 0x1F37}, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */ + {0x1F48, 0x1F40}, /* GREEK CAPITAL LETTER OMICRON WITH PSILI */ + {0x1F49, 0x1F41}, /* GREEK CAPITAL LETTER OMICRON WITH DASIA */ + {0x1F4A, 0x1F42}, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */ + {0x1F4B, 0x1F43}, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */ + {0x1F4C, 0x1F44}, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */ + {0x1F4D, 0x1F45}, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */ + {0x1F59, 0x1F51}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA */ + {0x1F5B, 0x1F53}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */ + {0x1F5D, 0x1F55}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */ + {0x1F5F, 0x1F57}, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */ + {0x1F68, 0x1F60}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI */ + {0x1F69, 0x1F61}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA */ + {0x1F6A, 0x1F62}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */ + {0x1F6B, 0x1F63}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */ + {0x1F6C, 0x1F64}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */ + {0x1F6D, 0x1F65}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */ + {0x1F6E, 0x1F66}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */ + {0x1F6F, 0x1F67}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */ + {0x1F88, 0x1F80}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */ + {0x1F89, 0x1F81}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */ + {0x1F8A, 0x1F82}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + {0x1F8B, 0x1F83}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + {0x1F8C, 0x1F84}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + {0x1F8D, 0x1F85}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + {0x1F8E, 0x1F86}, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1F8F, 0x1F87}, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1F98, 0x1F90}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */ + {0x1F99, 0x1F91}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */ + {0x1F9A, 0x1F92}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + {0x1F9B, 0x1F93}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + {0x1F9C, 0x1F94}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + {0x1F9D, 0x1F95}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + {0x1F9E, 0x1F96}, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1F9F, 0x1F97}, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1FA8, 0x1FA0}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */ + {0x1FA9, 0x1FA1}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */ + {0x1FAA, 0x1FA2}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ + {0x1FAB, 0x1FA3}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ + {0x1FAC, 0x1FA4}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ + {0x1FAD, 0x1FA5}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ + {0x1FAE, 0x1FA6}, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1FAF, 0x1FA7}, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ + {0x1FB8, 0x1FB0}, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */ + {0x1FB9, 0x1FB1}, /* GREEK CAPITAL LETTER ALPHA WITH MACRON */ + {0x1FBA, 0x1F70}, /* GREEK CAPITAL LETTER ALPHA WITH VARIA */ + {0x1FBB, 0x1F71}, /* GREEK CAPITAL LETTER ALPHA WITH OXIA */ + {0x1FBC, 0x1FB3}, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */ + {0x1FC8, 0x1F72}, /* GREEK CAPITAL LETTER EPSILON WITH VARIA */ + {0x1FC9, 0x1F73}, /* GREEK CAPITAL LETTER EPSILON WITH OXIA */ + {0x1FCA, 0x1F74}, /* GREEK CAPITAL LETTER ETA WITH VARIA */ + {0x1FCB, 0x1F75}, /* GREEK CAPITAL LETTER ETA WITH OXIA */ + {0x1FCC, 0x1FC3}, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */ + {0x1FD8, 0x1FD0}, /* GREEK CAPITAL LETTER IOTA WITH VRACHY */ + {0x1FD9, 0x1FD1}, /* GREEK CAPITAL LETTER IOTA WITH MACRON */ + {0x1FDA, 0x1F76}, /* GREEK CAPITAL LETTER IOTA WITH VARIA */ + {0x1FDB, 0x1F77}, /* GREEK CAPITAL LETTER IOTA WITH OXIA */ + {0x1FE8, 0x1FE0}, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */ + {0x1FE9, 0x1FE1}, /* GREEK CAPITAL LETTER UPSILON WITH MACRON */ + {0x1FEA, 0x1F7A}, /* GREEK CAPITAL LETTER UPSILON WITH VARIA */ + {0x1FEB, 0x1F7B}, /* GREEK CAPITAL LETTER UPSILON WITH OXIA */ + {0x1FEC, 0x1FE5}, /* GREEK CAPITAL LETTER RHO WITH DASIA */ + {0x1FF8, 0x1F78}, /* GREEK CAPITAL LETTER OMICRON WITH VARIA */ + {0x1FF9, 0x1F79}, /* GREEK CAPITAL LETTER OMICRON WITH OXIA */ + {0x1FFA, 0x1F7C}, /* GREEK CAPITAL LETTER OMEGA WITH VARIA */ + {0x1FFB, 0x1F7D}, /* GREEK CAPITAL LETTER OMEGA WITH OXIA */ + {0x1FFC, 0x1FF3}, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */ + {0x2160, 0x2170}, /* ROMAN NUMERAL ONE */ + {0x2161, 0x2171}, /* ROMAN NUMERAL TWO */ + {0x2162, 0x2172}, /* ROMAN NUMERAL THREE */ + {0x2163, 0x2173}, /* ROMAN NUMERAL FOUR */ + {0x2164, 0x2174}, /* ROMAN NUMERAL FIVE */ + {0x2165, 0x2175}, /* ROMAN NUMERAL SIX */ + {0x2166, 0x2176}, /* ROMAN NUMERAL SEVEN */ + {0x2167, 0x2177}, /* ROMAN NUMERAL EIGHT */ + {0x2168, 0x2178}, /* ROMAN NUMERAL NINE */ + {0x2169, 0x2179}, /* ROMAN NUMERAL TEN */ + {0x216A, 0x217A}, /* ROMAN NUMERAL ELEVEN */ + {0x216B, 0x217B}, /* ROMAN NUMERAL TWELVE */ + {0x216C, 0x217C}, /* ROMAN NUMERAL FIFTY */ + {0x216D, 0x217D}, /* ROMAN NUMERAL ONE HUNDRED */ + {0x216E, 0x217E}, /* ROMAN NUMERAL FIVE HUNDRED */ + {0x216F, 0x217F}, /* ROMAN NUMERAL ONE THOUSAND */ + {0x24B6, 0x24D0}, /* CIRCLED LATIN CAPITAL LETTER A */ + {0x24B7, 0x24D1}, /* CIRCLED LATIN CAPITAL LETTER B */ + {0x24B8, 0x24D2}, /* CIRCLED LATIN CAPITAL LETTER C */ + {0x24B9, 0x24D3}, /* CIRCLED LATIN CAPITAL LETTER D */ + {0x24BA, 0x24D4}, /* CIRCLED LATIN CAPITAL LETTER E */ + {0x24BB, 0x24D5}, /* CIRCLED LATIN CAPITAL LETTER F */ + {0x24BC, 0x24D6}, /* CIRCLED LATIN CAPITAL LETTER G */ + {0x24BD, 0x24D7}, /* CIRCLED LATIN CAPITAL LETTER H */ + {0x24BE, 0x24D8}, /* CIRCLED LATIN CAPITAL LETTER I */ + {0x24BF, 0x24D9}, /* CIRCLED LATIN CAPITAL LETTER J */ + {0x24C0, 0x24DA}, /* CIRCLED LATIN CAPITAL LETTER K */ + {0x24C1, 0x24DB}, /* CIRCLED LATIN CAPITAL LETTER L */ + {0x24C2, 0x24DC}, /* CIRCLED LATIN CAPITAL LETTER M */ + {0x24C3, 0x24DD}, /* CIRCLED LATIN CAPITAL LETTER N */ + {0x24C4, 0x24DE}, /* CIRCLED LATIN CAPITAL LETTER O */ + {0x24C5, 0x24DF}, /* CIRCLED LATIN CAPITAL LETTER P */ + {0x24C6, 0x24E0}, /* CIRCLED LATIN CAPITAL LETTER Q */ + {0x24C7, 0x24E1}, /* CIRCLED LATIN CAPITAL LETTER R */ + {0x24C8, 0x24E2}, /* CIRCLED LATIN CAPITAL LETTER S */ + {0x24C9, 0x24E3}, /* CIRCLED LATIN CAPITAL LETTER T */ + {0x24CA, 0x24E4}, /* CIRCLED LATIN CAPITAL LETTER U */ + {0x24CB, 0x24E5}, /* CIRCLED LATIN CAPITAL LETTER V */ + {0x24CC, 0x24E6}, /* CIRCLED LATIN CAPITAL LETTER W */ + {0x24CD, 0x24E7}, /* CIRCLED LATIN CAPITAL LETTER X */ + {0x24CE, 0x24E8}, /* CIRCLED LATIN CAPITAL LETTER Y */ + {0x24CF, 0x24E9}, /* CIRCLED LATIN CAPITAL LETTER Z */ + {0xFF21, 0xFF41}, /* FULLWIDTH LATIN CAPITAL LETTER A */ + {0xFF22, 0xFF42}, /* FULLWIDTH LATIN CAPITAL LETTER B */ + {0xFF23, 0xFF43}, /* FULLWIDTH LATIN CAPITAL LETTER C */ + {0xFF24, 0xFF44}, /* FULLWIDTH LATIN CAPITAL LETTER D */ + {0xFF25, 0xFF45}, /* FULLWIDTH LATIN CAPITAL LETTER E */ + {0xFF26, 0xFF46}, /* FULLWIDTH LATIN CAPITAL LETTER F */ + {0xFF27, 0xFF47}, /* FULLWIDTH LATIN CAPITAL LETTER G */ + {0xFF28, 0xFF48}, /* FULLWIDTH LATIN CAPITAL LETTER H */ + {0xFF29, 0xFF49}, /* FULLWIDTH LATIN CAPITAL LETTER I */ + {0xFF2A, 0xFF4A}, /* FULLWIDTH LATIN CAPITAL LETTER J */ + {0xFF2B, 0xFF4B}, /* FULLWIDTH LATIN CAPITAL LETTER K */ + {0xFF2C, 0xFF4C}, /* FULLWIDTH LATIN CAPITAL LETTER L */ + {0xFF2D, 0xFF4D}, /* FULLWIDTH LATIN CAPITAL LETTER M */ + {0xFF2E, 0xFF4E}, /* FULLWIDTH LATIN CAPITAL LETTER N */ + {0xFF2F, 0xFF4F}, /* FULLWIDTH LATIN CAPITAL LETTER O */ + {0xFF30, 0xFF50}, /* FULLWIDTH LATIN CAPITAL LETTER P */ + {0xFF31, 0xFF51}, /* FULLWIDTH LATIN CAPITAL LETTER Q */ + {0xFF32, 0xFF52}, /* FULLWIDTH LATIN CAPITAL LETTER R */ + {0xFF33, 0xFF53}, /* FULLWIDTH LATIN CAPITAL LETTER S */ + {0xFF34, 0xFF54}, /* FULLWIDTH LATIN CAPITAL LETTER T */ + {0xFF35, 0xFF55}, /* FULLWIDTH LATIN CAPITAL LETTER U */ + {0xFF36, 0xFF56}, /* FULLWIDTH LATIN CAPITAL LETTER V */ + {0xFF37, 0xFF57}, /* FULLWIDTH LATIN CAPITAL LETTER W */ + {0xFF38, 0xFF58}, /* FULLWIDTH LATIN CAPITAL LETTER X */ + {0xFF39, 0xFF59}, /* FULLWIDTH LATIN CAPITAL LETTER Y */ + {0xFF3A, 0xFF5A} /* FULLWIDTH LATIN CAPITAL LETTER Z */ +}; \ No newline at end of file diff --git a/src/chrtrans/makefile.dos b/src/chrtrans/makefile.dos index 57c45dfc..dba0d787 100644 --- a/src/chrtrans/makefile.dos +++ b/src/chrtrans/makefile.dos @@ -14,9 +14,10 @@ CFLAGS = $(MCFLAGS) CC = gcc MCFLAGS = -O3 -DDOSPATH -DNO_TTYTYP \ -I. \ --I../../WWW/library/implement \ +-I../../WWW/Library/Implementation \ -I../../djgpp/tcplib/include \ --I../../djgpp/tcplib/include/tcp +-I../../djgpp/tcplib/include/tcp \ +-I../.. .SUFFIXES: .tbl # diff --git a/src/makefile.in b/src/makefile.in index 2b7c5d46..0136a49f 100644 --- a/src/makefile.in +++ b/src/makefile.in @@ -99,7 +99,7 @@ do_chartrans_stuff: CC="$(CC)" tables lint: - $(LINT) $(LINTOPTS) $(CPP_OPTS) *.c > $(top_builddir) + $(LINT) $(LINTOPTS) $(CPP_OPTS) *.c > $(top_builddir)/lint.lynx clean: rm -f lynx$x core *.[ob] *.bak |