TextAnchor *a;   if (number <= 0 || number == text->last_anchor->number) { a = text->last_anchor; } else { for (a = text->first_anchor; a; a = a->next) { if (a->number == number) { break; } } if (a == NULL) {  a = text->last_anchor; } }  CTRACE(tfp, "HText_endAnchor: number:%d link_type:%d\n", a->number, a->link_type); if (a->link_type == INPUT_ANCHOR) {   CTRACE(tfp, "HText_endAnchor: internal error: last anchor was input field!\n"); return; } if (a->number) {  int i, j, k, l; BOOL remove_numbers_on_empty = ((keypad_mode == LINKS_ARE_NUMBERED || keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) && (text->hiddenlinkflag != HIDDENLINKS_MERGE || (LYNoISMAPifUSEMAP && !(text->node_anchor && text->node_anchor->bookmark) && HTAnchor_isISMAPScript( HTAnchor_followMainLink((HTAnchor *)a->anchor))))); HTLine *last = text->last_line; HTLine *prev = text->last_line->prev; HTLine *start = last; int CurBlankExtent = 0; int BlankExtent = 0;   a->extent += (text->chars + last->size) - a->start - (text->Lines - a->line_num); if (a->extent > (int)last->size) {  i = last->size; } else {  i = a->extent; } k = j = (last->size - i); while (j < (int)last->size) { if (!IsSpecialAttrChar(last->data[j]) && !isspace((unsigned char)last->data[j]) && last->data[j] != HT_NON_BREAK_SPACE && last->data[j] != HT_EN_SPACE) break; i--; j++; } if (i == 0) { if (a->extent > (int)last->size) {  CurBlankExtent = BlankExtent = last->size; } else {  CurBlankExtent = BlankExtent = a->extent; } }  while (i == 0 && (a->extent > CurBlankExtent || (a->extent == CurBlankExtent && k == 0 && prev != text->last_line && (prev->size == 0 || prev->data[prev->size - 1] == ']')))) { start = prev; k = j = prev->size - a->extent + CurBlankExtent; if (j < 0) {  j = 0; i = prev->size; } else {  i = a->extent - CurBlankExtent; } while (j < (int)prev->size) { if (!IsSpecialAttrChar(prev->data[j]) && !isspace((unsigned char)prev->data[j]) && prev->data[j] != HT_NON_BREAK_SPACE && prev->data[j] != HT_EN_SPACE) break; i--; j++; } if (i == 0) { if (a->extent > (CurBlankExtent + (int)prev->size) || (a->extent == CurBlankExtent + (int)prev->size && k == 0 && prev->prev != text->last_line && (prev->prev->size == 0 || prev->prev->data[prev->prev->size - 1] == ']'))) {  CurBlankExtent += prev->size; BlankExtent = CurBlankExtent; prev = prev->prev; } else {  BlankExtent = a->extent; break; } } } if (i == 0) {  a->show_anchor = NO;  CTRACE(tfp, "HText_endAnchor: hidden (line,start,pos,ext,BlankExtent):(%d,%d,%d,%d,%d)", a->line_num,a->start,a->line_pos,a->extent, BlankExtent);   if (remove_numbers_on_empty) { int NumSize = 0; TextAnchor *anc;   if (start == last) {  j = (last->size - a->extent - 1); } else {  prev = start->prev; j = (start->size - a->extent + CurBlankExtent - 1); } if (j < 0) j = 0; i = j;   if (start->data[j] == ']') { j--; NumSize++; while (j >= 0 && isdigit((unsigned char)start->data[j])) { j--; NumSize++; } while (j < 0) { j++; NumSize--; } if (start->data[j] == '[') {  NumSize++; if (start==last && (int)text->permissible_split > j) { if ((int)text->permissible_split - NumSize < j) text->permissible_split = j; else text->permissible_split -= NumSize; } k = j + NumSize; while (k < (int)start->size) start->data[j++] = start->data[k++]; if (start != last) text->chars -= NumSize; for (anc = a; anc; anc = anc->next) { anc->start -= NumSize; if (anc->line_num == a->line_num && anc->line_pos >= NumSize) { anc->line_pos -= NumSize; } } start->size = j; start->data[j++] = '\0'; while (j < k) start->data[j++] = '\0'; } else if (prev && prev->size > 1) { k = (i + 1); j = (prev->size - 1); while ((j >= 0) && IsSpecialAttrChar(prev->data[j])) j--; i = (j + 1); while (j >= 0 && isdigit((unsigned char)prev->data[j])) { j--; NumSize++; } while (j < 0) { j++; NumSize--; } if (prev->data[j] == '[') {  NumSize++; l = (i - j); while (i < (int)prev->size) prev->data[j++] = prev->data[i++]; text->chars -= l; for (anc = a; anc; anc = anc->next) { anc->start -= l; } prev->size = j; prev->data[j] = '\0'; while (j < i) prev->data[j++] = '\0'; if (start == last && text->permissible_split > 0) { if ((int)text->permissible_split < k) text->permissible_split = 0; else text->permissible_split -= k; } j = 0; i = k; while (k < (int)start->size) start->data[j++] = start->data[k++]; if (start != last) text->chars -= i; for (anc = a; anc; anc = anc->next) { anc->start -= i; if (anc->line_num == a->line_num && anc->line_pos >= i) { anc->line_pos -= i; } } start->size = j; start->data[j++] = '\0'; while (j < k) start->data[j++] = '\0'; } else {  a->show_anchor = YES; } } else {  a->show_anchor = YES; } } else if (prev && prev->size > 2) { j = (prev->size - 1); while ((j >= 0) && IsSpecialAttrChar(prev->data[j])) j--; if (j < 0) j = 0; i = (j + 1); if ((j >= 2) && (prev->data[j] == ']' && isdigit((unsigned char)prev->data[j - 1]))) { j--; NumSize++; k = (j + 1); while (j >= 0 && isdigit((unsigned char)prev->data[j])) { j--; NumSize++; } while (j < 0) { j++; NumSize--; } if (prev->data[j] == '[') {  NumSize++; k = j + NumSize; while (k < (int)prev->size) prev->data[j++] = prev->data[k++]; text->chars -= NumSize; for (anc = a; anc; anc = anc->next) { anc->start -= NumSize; } prev->size = j; prev->data[j++] = '\0'; while (j < k) prev->data[j++] = '\0'; } else {  a->show_anchor = YES; } } else {  a->show_anchor = YES; } } else {  a->show_anchor = YES; } } } else {  a->show_anchor = YES; if (BlankExtent) { CTRACE(tfp, "HText_endAnchor: blanks (line,start,pos,ext,BlankExtent):(%d,%d,%d,%d,%d)", a->line_num,a->start,a->line_pos,a->extent, BlankExtent); } } if (a->show_anchor == NO) {  a->extent = 0; if (text->hiddenlinkflag != HIDDENLINKS_MERGE) { a->number = 0; text->last_anchor_number--; HText_AddHiddenLink(text, a); } } else {  a->extent -= ((BlankExtent < a->extent) ? BlankExtent : 0); } if (BlankExtent || a->extent <= 0 || a->number <= 0) { CTRACE(tfp, "->[%d](%d,%d,%d,%d,%d)\n", a->number, a->line_num,a->start,a->line_pos,a->extent, BlankExtent); } } else {  a->show_anchor = NO; a->extent = 0; }
HText_endAnchor0(text, number, 1);
PUBLIC void HText_endAnchor ARGS2(	HText *,	text,	int,		number){    TextAnchor *a;    /*     *  The number argument is set to 0 in HTML.c and     *  LYCharUtils.c when we want to end the anchor     *  for the immediately preceding HText_beginAnchor()     *  call.  If it's greater than 0, we want to handle     *  a particular anchor.  This allows us to set links     *  for positions indicated by NAME or ID attributes,     *  without needing to close any anchor with an HREF     *  within which that link might be embedded. - FM     */    if (number <= 0 || number == text->last_anchor->number) {	a = text->last_anchor;    } else {	for (a = text->first_anchor; a; a = a->next) {	    if (a->number == number) {		break;	    }	}	if (a == NULL) {	    /*	     *  There's no anchor with that number,	     *  so we'll default to the last anchor,	     *  and cross our fingers. - FM	     */	    a = text->last_anchor;	}    }    CTRACE(tfp, "HText_endAnchor: number:%d link_type:%d\n",			a->number, a->link_type);    if (a->link_type == INPUT_ANCHOR) {	/*	 *  Shouldn't happen, but put test here anyway to be safe. - LE	 */	CTRACE(tfp,	   "HText_endAnchor: internal error: last anchor was input field!\n");	return;    }    if (a->number) {	/*	 *  If it goes somewhere...	 */	int i, j, k, l;	BOOL remove_numbers_on_empty =	    ((keypad_mode == LINKS_ARE_NUMBERED ||	      keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) &&	     (text->hiddenlinkflag != HIDDENLINKS_MERGE ||	      (LYNoISMAPifUSEMAP &&	       !(text->node_anchor && text->node_anchor->bookmark) &&	       HTAnchor_isISMAPScript(		   HTAnchor_followMainLink((HTAnchor *)a->anchor)))));	HTLine *last = text->last_line;	HTLine *prev = text->last_line->prev;	HTLine *start = last;	int CurBlankExtent = 0;	int BlankExtent = 0;	/*	 *  Check if the anchor content has only	 *  white and special characters, starting	 *  with the content on the last line. - FM	 */	a->extent += (text->chars + last->size) - a->start -		     (text->Lines - a->line_num);	if (a->extent > (int)last->size) {	    /*	     *  The anchor extends over more than one line,	     *  so set up to check the entire last line. - FM	     */	    i = last->size;	} else {	    /*	     *  The anchor is restricted to the last line,	     *  so check from the start of the anchor. - FM	     */	    i = a->extent;	}	k = j = (last->size - i);	while (j < (int)last->size) {	    if (!IsSpecialAttrChar(last->data[j]) &&		!isspace((unsigned char)last->data[j]) &&		last->data[j] != HT_NON_BREAK_SPACE &&		last->data[j] != HT_EN_SPACE)		break;	    i--;	    j++;	}	if (i == 0) {	    if (a->extent > (int)last->size) {		/*		 *  The anchor starts on a preceding line, and		 *  the last line has only white and special		 *  characters, so declare the entire extent		 *  of the last line as blank. - FM		 */		CurBlankExtent = BlankExtent = last->size;	    } else {		/*		 *  The anchor starts on the last line, and		 *  has only white or special characters, so		 *  declare the anchor's extent as blank. - FM		 */		CurBlankExtent = BlankExtent = a->extent;	    }	}	/*	 *  While the anchor starts on a line preceding	 *  the one we just checked, and the one we just	 *  checked has only white and special characters,	 *  check whether the anchor's content on the	 *  immediately preceding line also has only	 *  white and special characters. - FM	 */	while (i == 0 &&	       (a->extent > CurBlankExtent ||		(a->extent == CurBlankExtent &&		 k == 0 &&		 prev != text->last_line &&		 (prev->size == 0 ||		  prev->data[prev->size - 1] == ']')))) {	    start = prev;	    k = j = prev->size - a->extent + CurBlankExtent;	    if (j < 0) {		/*		 *  The anchor starts on a preceding line,		 *  so check all of this line. - FM		 */		j = 0;		i = prev->size;	    } else {		/*		 *  The anchor starts on this line. - FM		 */		i = a->extent - CurBlankExtent;	    }	    while (j < (int)prev->size) {		if (!IsSpecialAttrChar(prev->data[j]) &&		    !isspace((unsigned char)prev->data[j]) &&		    prev->data[j] != HT_NON_BREAK_SPACE &&		    prev->data[j] != HT_EN_SPACE)		    break;		i--;		j++;	    }	    if (i == 0) {		if (a->extent > (CurBlankExtent + (int)prev->size) ||		    (a->extent == CurBlankExtent + (int)prev->size &&		     k == 0 &&		     prev->prev != text->last_line &&		     (prev->prev->size == 0 ||		      prev->prev->data[prev->prev->size - 1] == ']'))) {		    /*		     *  This line has only white and special		     *  characters, so treat its entire extent		     *  as blank, and decrement the pointer for		     *  the line to be analyzed. - FM		     */		    CurBlankExtent += prev->size;		    BlankExtent = CurBlankExtent;		    prev = prev->prev;		} else {		    /*		     *  The anchor starts on this line, and it		     *  has only white or special characters, so		     *  declare the anchor's extent as blank. - FM		     */		    BlankExtent = a->extent;		    break;		}	    }	}	if (i == 0) {	    /*	     *  It's an invisible anchor probably from an ALT=""	     *  or an ignored ISMAP attribute due to a companion	     *  USEMAP. - FM	     */	    a->show_anchor = NO;	    CTRACE(tfp,		   "HText_endAnchor: hidden (line,start,pos,ext,BlankExtent):(%d,%d,%d,%d,%d)",		   a->line_num,a->start,a->line_pos,a->extent,		   BlankExtent);	    /*	     *  If links are numbered, then try to get rid of the	     *  numbered bracket and adjust the anchor count. - FM	     *	     * Well, let's do this only if -hiddenlinks=merged is not in	     * effect, or if we can be reasonably sure that	     * this is the result of an intentional non-generation of	     * anchor text via NO_ISMAP_IF_USEMAP.  In other cases it can	     * actually be a feature that numbered links alert the viewer	     * to the presence of a link which is otherwise not selectable -	     * possibly caused by HTML errors. - kw	     */	    if (remove_numbers_on_empty) {		int NumSize = 0;		TextAnchor *anc;		/*		 *  Set start->data[j] to the close-square-bracket,		 *  or to the beginning of the line on which the		 *  anchor start. - FM		 */		if (start == last) {		    /*		     *  The anchor starts on the last line. - FM		     */		    j = (last->size - a->extent - 1);		} else {		    /*		     *  The anchor starts on a previous line. - FM		     */		    prev = start->prev;		    j = (start->size - a->extent + CurBlankExtent - 1);		}		if (j < 0)		    j = 0;		i = j;		/*		 *  If start->data[j] is a close-square-bracket, verify		 *  that it's the end of the numbered bracket, and if so,		 *  strip the numbered bracket.  If start->data[j] is not		 *  a close-square-bracket, check whether we had a wrap		 *  and the close-square-bracket is at the end of the		 *  previous line.  If so, strip the numbered bracket		 *  from that line. - FM		 */		if (start->data[j] == ']') {		    j--;		    NumSize++;		    while (j >= 0 && isdigit((unsigned char)start->data[j])) {			j--;			NumSize++;		    }		    while (j < 0) {			j++;			NumSize--;		    }		    if (start->data[j] == '[') {			/*			 *  The numbered bracket is entirely			 *  on this line. - FM			 */			NumSize++;			if (start==last && (int)text->permissible_split > j) {			    if ((int)text->permissible_split - NumSize < j)				text->permissible_split = j;			    else				text->permissible_split -= NumSize;			}			k = j + NumSize;			while (k < (int)start->size)			    start->data[j++] = start->data[k++];			if (start != last)			    text->chars -= NumSize;			for (anc = a; anc; anc = anc->next) {			    anc->start -= NumSize;			    if (anc->line_num == a->line_num &&				anc->line_pos >= NumSize) {			    anc->line_pos -= NumSize;			    }			}			start->size = j;			start->data[j++] = '\0';			while (j < k)			     start->data[j++] = '\0';		    } else if (prev && prev->size > 1) {			k = (i + 1);			j = (prev->size - 1);			while ((j >= 0) && IsSpecialAttrChar(prev->data[j]))			    j--;			i = (j + 1);			while (j >= 0 &&			       isdigit((unsigned char)prev->data[j])) {			    j--;			    NumSize++;			}			while (j < 0) {			    j++;			    NumSize--;			}			if (prev->data[j] == '[') {			    /*			     *  The numbered bracket started on the			     *  previous line, and part of it was			     *  wrapped to this line. - FM			     */			    NumSize++;			    l = (i - j);			    while (i < (int)prev->size)				prev->data[j++] = prev->data[i++];			    text->chars -= l;			    for (anc = a; anc; anc = anc->next) {				anc->start -= l;			    }			    prev->size = j;			    prev->data[j] = '\0';			    while (j < i)				prev->data[j++] = '\0';			    if (start == last && text->permissible_split > 0) {				if ((int)text->permissible_split < k)				    text->permissible_split = 0;				else				    text->permissible_split -= k;			    }			    j = 0;			    i = k;			    while (k < (int)start->size)				start->data[j++] = start->data[k++];			    if (start != last)				text->chars -= i;			    for (anc = a; anc; anc = anc->next) {				anc->start -= i;				if (anc->line_num == a->line_num &&				    anc->line_pos >= i) {				    anc->line_pos -= i;				}			    }			    start->size = j;			    start->data[j++] = '\0';			    while (j < k)				start->data[j++] = '\0';			} else {			    /*			     *  Shucks!  We didn't find the			     *  numbered bracket. - FM			     */			    a->show_anchor = YES;			}		    } else {			/*			 *  Shucks!  We didn't find the			 *  numbered bracket. - FM			 */			a->show_anchor = YES;		    }		} else if (prev && prev->size > 2) {		    j = (prev->size - 1);		    while ((j >= 0) && IsSpecialAttrChar(prev->data[j]))			j--;		    if (j < 0)			j = 0;		    i = (j + 1);		    if ((j >= 2) &&			(prev->data[j] == ']' &&			 isdigit((unsigned char)prev->data[j - 1]))) {			j--;			NumSize++;			k = (j + 1);			while (j >= 0 &&			       isdigit((unsigned char)prev->data[j])) {			    j--;			    NumSize++;			}			while (j < 0) {			    j++;			    NumSize--;			}			if (prev->data[j] == '[') {			    /*			     *  The numbered bracket is all on the			     *  previous line, and the anchor content			     *  was wrapped to the last line. - FM			     */			    NumSize++;			    k = j + NumSize;			    while (k < (int)prev->size)				prev->data[j++] = prev->data[k++];			    text->chars -= NumSize;			    for (anc = a; anc; anc = anc->next) {				anc->start -= NumSize;			    }			    prev->size = j;			    prev->data[j++] = '\0';			    while (j < k)				prev->data[j++] = '\0';			} else {			    /*			     *  Shucks!  We didn't find the			     *  numbered bracket. - FM			     */			    a->show_anchor = YES;			}		    } else {			/*			 *  Shucks!  We didn't find the			 *  numbered bracket. - FM			 */			a->show_anchor = YES;		    }		} else {		    /*		     *  Shucks!  We didn't find the		     *  numbered bracket. - FM		     */		    a->show_anchor = YES;		}	    }	} else {	    /*	     *  The anchor's content is not restricted to only	     *  white and special characters, so we'll show it	     *  as a link. - FM	     */	    a->show_anchor = YES;	    if (BlankExtent) {		CTRACE(tfp,		   "HText_endAnchor: blanks (line,start,pos,ext,BlankExtent):(%d,%d,%d,%d,%d)",		   a->line_num,a->start,a->line_pos,a->extent,		   BlankExtent);	    }	}	if (a->show_anchor == NO) {	    /*	     *  The anchor's content is restricted to white	     *  and special characters, so set it's number	     *  and extent to zero, decrement the visible	     *  anchor number counter, and add this anchor	     *  to the hidden links list. - FM	     */	    a->extent = 0;	    if (text->hiddenlinkflag != HIDDENLINKS_MERGE) {		a->number = 0;		text->last_anchor_number--;		HText_AddHiddenLink(text, a);	    }	} else {	    /*	     *  The anchor's content is not restricted to white	     *  and special characters, so we'll display the	     *  content, but shorten it's extent by any trailing	     *  blank lines we've detected. - FM	     */	    a->extent -= ((BlankExtent < a->extent) ?					BlankExtent : 0);	}	if (BlankExtent || a->extent <= 0 || a->number <= 0) {	    CTRACE(tfp,		   "->[%d](%d,%d,%d,%d,%d)\n",		   a->number,		   a->line_num,a->start,a->line_pos,a->extent,		   BlankExtent);	}    } else {	/*	 *  It's a named anchor without an HREF, so it	 *  should be registered but not shown as a	 *  link. - FM	 */	a->show_anchor = NO;	a->extent = 0;    }}