#help_index "DolDoc"

I64 DocWordWrapDel(CDoc *doc, CDocEntry *doc_e, Bool full_refresh, Bool same_win, I64 left_margin, I64 right_margin, 
				   CDocEntry **_best_doc_e, I64 *_best_col)
{
	CDocEntry	*doc_e2;
	U8			*ptr;
	I64			 j, k;

	if (doc_e->de_flags & DOCEF_TAG && doc_e->tag)
		k = StrLen(doc_e->tag);
	else
		k = 0;
	if (full_refresh)
		while (TRUE)
		{
			doc_e2 = doc_e->next;
			if (doc_e2->type_u8 == DOCT_SOFT_NEW_LINE && !same_win)
			{
				if (doc->cur_entry == doc_e2)
				{
					doc->cur_entry	= doc_e2->next;
					doc->cur_col	= doc->cur_entry->min_col;
				}
				if (*_best_doc_e == doc_e2)
				{
					*_best_doc_e = doc_e2->next;
					*_best_col = 0;
				}
				DocEntryDel(doc, doc_e2);
			}
			else if (IsEditableText(doc_e) && doc_e->de_flags == doc_e2->de_flags && doc_e->type == doc_e2->type)
			{
				j = StrLen(doc_e2->tag);
				ptr =  MAlloc(k + j + 1, doc->mem_task);
				MemCopy(ptr, doc_e->tag, k);
				MemCopy(ptr + k, doc_e2->tag, j + 1);
				Free(doc_e->tag);
				doc_e->tag = ptr;
				if (doc->cur_entry == doc_e2)
				{
					doc->cur_entry	=  doc_e;
					doc->cur_col	+= k;
				}
				if (*_best_doc_e == doc_e2)
				{
					*_best_doc_e = doc_e;
					*_best_col = 0;
				}
				DocEntryDel(doc, doc_e2);
				k += j;
				if (k > (right_margin - left_margin + 1) << 1)
					break;
			}
			else
				break;
		}
	if (doc_e->de_flags & DOCEF_SCROLLING_X)
		k = doc_e->scroll_len;

	return k;
}

U0 DocRecalcXY(CDoc *doc, CDocEntry *doc_e, I64 k, I64 left, I64 width, I64 height, I64 left_margin, I64 right_margin, 
			   I64 x0, I64 y0, I64 *_x, I64 *_y)
{
	I64 i, x = *_x, y = *_y;

	if (doc_e->de_flags & DOCEF_MARGIN_REL_X)
	{
		if (doc_e->de_flags & DOCEF_LEFT_X)
			x = left_margin - left;
		else if (doc_e->de_flags & DOCEF_RIGHT_X)
			x = right_margin - (k - 1) - left;
		else if (doc_e->de_flags & DOCEF_CENTER_X)
			x = (right_margin + left_margin) >> 1 - k >> 1 - left;
	}
	else
	{
		if (doc_e->de_flags & DOCEF_LEFT_X)
			x = x0;
		else if (doc_e->de_flags & DOCEF_RIGHT_X)
			x = width + x0 - k;
		else if (doc_e->de_flags & DOCEF_CENTER_X)
			x = (width + x0 - k) >> 1;
	}
	i = y;
	if (doc_e->de_flags & DOCEF_PAGE_REL_Y)
	{
		doc->flags |= DOCF_BWD_MOVEMENT;
		if (doc_e->de_flags & DOCEF_TOP_Y)
			y -= doc_e->page_line_num;
		else if (doc_e->de_flags & DOCEF_BOTTOM_Y)
			y += doc_e->settings.page_len - doc_e->page_line_num;
		else if (doc_e->de_flags & DOCEF_CENTER_Y)
			y += doc_e->settings.page_len >> 1 - doc_e->page_line_num;
	}
	else
	{
		doc->flags |= DOCF_BWD_MOVEMENT;
		if (doc_e->de_flags & DOCEF_TOP_Y)
			y = y0;
		else if (doc_e->de_flags & DOCEF_BOTTOM_Y)
			y = height - 1 + y0;
		else if (doc_e->de_flags & DOCEF_CENTER_Y)
			y = height >> 1 + y0;
	}
	if (y != i)
	{
		doc->page_line_num += y - i;
		if (doc->page_line_num < 0)
			doc->page_line_num = doc_e->settings.page_len + doc->page_line_num % doc_e->settings.page_len;
		else
			doc->page_line_num = doc->page_line_num % doc_e->settings.page_len;
		if (doc_e->settings.header != DOC_DEFAULT && doc->page_line_num < doc_e->settings.header)
		{
			y += doc_e->settings.header - doc->page_line_num;
			doc->page_line_num = doc_e->settings.header;
		}
		if (doc_e->settings.footer == DOC_DEFAULT)
		{
			if (doc->page_line_num >= doc_e->settings.page_len)
			{
				if (doc_e->settings.header == DOC_DEFAULT)
					doc->page_line_num = 0;
				else
				{
					doc->page_line_num = doc_e->settings.header;
					y += doc_e->settings.header;
				}
			}
		}
		else
		{
			if (doc->page_line_num >= doc_e->settings.page_len - doc_e->settings.footer)
			{
				y += doc_e->settings.footer;
				if (doc_e->settings.header == DOC_DEFAULT)
					doc->page_line_num = 0;
				else
				{
					doc->page_line_num = doc_e->settings.header;
					y += doc_e->settings.header;
				}
			}
		}
	}
	*_x = x;
	*_y = y;
}

CDocEntry *DocSplitTag(CDoc *doc, CDocEntry *doc_e, I64 i, I64 x, I64 y, I64 type_u8)
{//Split tag at i, insert DOCT_SOFT_NEW_LINE, DOCT_MARKER or DOCT_CURSOR
	U8			*ptr;
	CDocEntry	*doc_e2;

	if (doc_e->type_u8 == DOCT_TEXT && i)
	{
		if (i < StrLen(doc_e->tag))
		{
			doc_e2 = MAllocIdent(doc_e, doc->mem_task);
			doc_e2->tag		 = StrNew(doc_e->tag + i, doc->mem_task);
			doc_e2->de_flags = doc_e->de_flags & ~DOCEG_HAS_ALLOC | DOCEF_TAG;
			QueueInsert(doc_e2, doc_e);
			if (doc->cur_entry == doc_e && doc->cur_col>=i)
			{
				doc->cur_entry	= doc_e2;
				doc->cur_col	= doc->cur_col - i;
			}
			doc_e->tag[i] = 0;
			ptr = StrNew(doc_e->tag, doc->mem_task);
			Free(doc_e->tag);
			doc_e->tag = ptr;
		}
	}
	else
		doc_e = doc_e->last;
	doc_e2 = DocEntryNewBase(doc, type_u8 | doc_e->type & 0xFFFFFF00, doc_e->de_flags & ~DOCEG_HAS_ARG,
							 x, y, doc_e->page_line_num);
	MemCopy(&doc_e2->settings, &doc_e->settings, sizeof(CDocSettings));
	QueueInsert(doc_e2, doc_e);

	return doc_e2;
}

CDocEntry *DocWordWrapAdd(CDoc *doc, CDocEntry *doc_e, I64 *_k, I64 left, I64 right_margin, I64 x, I64 y)
{
	CDocEntry	*doc_e2;
	I64			 j,
				 i = right_margin + 1 - (x + left), //Space left on line
				 ii = x + 1 - doc_e->settings.left_margin;

	if (IsEditableText(doc_e))
	{
		if (doc->cur_entry == doc_e->next)
		{
			if (doc->cur_col == doc_e->next->min_col)
				i--;
		}
		else
		{
			if (doc->cur_entry == doc_e && doc->cur_col == i)
				i--;
		}
		if (*_k > i)
		{
			for (j = i; j > 8 - ii && j >= 0; j--)
				if (doc_e->tag[j] == CH_SPACE)
				{
					i = j + 1;
					break;
				}
			if (0 < i < *_k)
			{
				DocSplitTag(doc, doc_e, i, x, y, DOCT_SOFT_NEW_LINE);
				*_k = StrLen(doc_e->tag);
				return NULL;
			}
		}
		if (*_k == i)
			return NULL;
	}
	if (*_k >= i)
	{
		doc_e2 = doc_e->last;
		if (doc_e2->type_u8 != DOCT_SOFT_NEW_LINE &&
			doc_e2->type_u8 != DOCT_NEW_LINE &&
			doc_e2->type_u8 != DOCT_CURSOR_MOVEMENT)
		{
			doc_e2 = DocEntryNewBase(doc, DOCT_SOFT_NEW_LINE | doc_e->type & 0xFFFFFF00, 
					   DOCEF_WORD_WRAP | doc_e->de_flags & (DOCEF_HIGHLIGHT | DOCG_BL_IV_UL | DOCEF_SKIP | DOCEF_FILTER_SKIP),
					   x, y, doc_e->last->page_line_num);
			MemCopy(&doc_e2->settings, &doc_e->settings, sizeof(CDocSettings));
			QueueInsert(doc_e2, doc_e->last);
			return doc_e2;
		}
	}

	return NULL;
}

I64 DocTmpAttr(CDoc *doc, CDocEntry *doc_e, I64 cur_u8_attr)
{
	I64 tmp_u32_attr;

	doc_e->de_flags = doc->flags & (DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT) |
					  doc_e->de_flags & ~(DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT);

	tmp_u32_attr =  (cur_u8_attr & 0xF0) << 8 |
					doc->flags & DOCG_BL_IV_UL |
					(doc_e->settings.shifted_x & 0x1F) << 16 |
					(doc_e->settings.shifted_y & 0x1F) << 21;

	if (doc_e->de_flags & DOCEF_HAS_BIN && *doc_e->tag == '<')
		tmp_u32_attr.u8[1] |= DOC_COLOR_BIN;
	else
		switch (doc_e->type_u8)
		{
			case DOCT_SPRITE:
				if (doc_e->de_flags & DOCEF_LEFT_EXP)
					tmp_u32_attr.u8[1] |= cur_u8_attr & 15;
				else if (doc_e->de_flags & DOCEF_LINK)
					tmp_u32_attr.u8[1] |= DOC_COLOR_LINK;
				else if (doc_e->de_flags & DOCEF_LEFT_MACRO)
					tmp_u32_attr.u8[1] |= DOC_COLOR_MACRO;
				else if (doc_e->de_flags & (DOCEF_TREE | DOCEF_LIST))
					tmp_u32_attr.u8[1] |= DOC_COLOR_TREE;
				else
					tmp_u32_attr.u8[1] |= DOC_COLOR_BIN;
				break;

			case DOCT_HTML_CODE:
				tmp_u32_attr.u8[1] |= DOC_COLOR_BIN;
				break;

			case DOCT_LINK:
				tmp_u32_attr.u8[1] |= DOC_COLOR_LINK;
				break;

			case DOCT_MACRO:
				tmp_u32_attr.u8[1] |= DOC_COLOR_MACRO;
				break;

			case DOCT_ANCHOR:
				tmp_u32_attr.u8[1] |= DOC_COLOR_ANCHOR;
				break;

			case DOCT_TREE:
			case DOCT_LIST:
				tmp_u32_attr.u8[1] |= DOC_COLOR_TREE;
				break;

			default:
				tmp_u32_attr.u8[1] |= cur_u8_attr & 15;
		}
	doc_e->type.u8[1] = tmp_u32_attr.u8[1];
	tmp_u32_attr |= doc_e->type & 0xFFFF0000;
	if (doc_e == doc->cur_entry && !(doc->flags & DOCF_DONT_HIGHLIGHT_CURSOR) && doc_e->type_u8 != DOCT_TEXT)
		tmp_u32_attr ^= 0xFF00;
	doc_e->settings.final_u32_attr = tmp_u32_attr;

	return tmp_u32_attr;
}

public Bool DocRecalc(CDoc *doc, I64 recalc_flags=RECALCt_NORMAL)
{//Recalc and format.  Also used by WinMgr to draw on screen.
	I64				 i, ii, j, k, x, x0, y, y0, D, d2, col, col2, best_col = 0, best_d = I64_MAX, xx, yy, zz, 
					 num_entries = 0, i_jif, cur_u8_attr, tmp_u32_attr, 
					 cursor_y = I64_MIN, left_margin, right_margin, y_plot_top, y_plot_bottom, 
					 top, left, bottom, right, width, height, scroll_x, scroll_y, pix_top, pix_left;
	CDocEntry	reg *doc_e, reg *doc_e2, *best_doc_e, *next_clear_found = NULL, *added_cursor = NULL;
	CDocBin			*tmpb;
	CDocSettings	*s;
	Bool			 del_doc_e, skipped_update, tree_collapsed, same_win, more = FALSE, 
					 find_cursor = FALSE, blink_flag, full_refresh = TRUE, unlock, clear_holds;
	CTask			*win_task, *mem_task;
	CDC				*dc;
	U8				*bptr, *ptr, buf[STR_LEN], ch;
	U32				*u32_ptr, *hl;
	I32				*depth_buf = NULL;
	F64				 cur_time = tS;
	CWinScroll		*vss, *hss;
	CHashDefineStr	*tmph;

	if (!doc || doc->doc_signature != DOC_SIGNATURE_VAL)
		return FALSE;

		//WinMgr updates all wins $TX,"(60000.0 / 1001)",D="WINMGR_FPS"$, 33.33333mS
	if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && doc->owning_task != Fs)
	{
		i_jif = counts.jiffies + JIFFY_FREQ / 250; //4 mouse
		while (Bt(&doc->locked_flags, DOClf_LOCKED))
		{
			if (counts.jiffies >= i_jif)
				return FALSE; //Bail-out if doc locked.
			Yield;
		}
	}

	unlock = DocLock(doc);
	if (doc->doc_signature != DOC_SIGNATURE_VAL)
	{
		DocUnlock(doc);
		return FALSE;
	}

	win_task = doc->win_task;
	mem_task = doc->mem_task;
	blink_flag = Blink;
	dc = NULL;
	switch [recalc_flags & RECALCG_MASK]
	{
		case RECALCt_FIND_CURSOR:
			find_cursor = TRUE;
			if (win_task)
				dc = DCAlias(gr.dc2, win_task); //Necessary for sprites
			break;

		case RECALCt_TO_SCREEN:
			if (doc->updates_count++ % (ToI64(winmgr.fps / 10) + 1) &&
					!Bt(&doc->flags, DOCf_DO_FULL_REFRESH) &&
					!(doc->flags & DOCF_BWD_MOVEMENT))
				full_refresh = FALSE;
			if (win_task)
				dc = DCAlias(gr.dc2, win_task);
			break;
	}

	PUSHFD
	CLI
	left			= win_task->win_left;
	right			= win_task->win_right;
	width			= win_task->win_width;
	scroll_x		= win_task->scroll_x;
	scroll_y		= win_task->scroll_y;
	top				= win_task->win_top;
	bottom			= win_task->win_bottom;
	height			= win_task->win_height;
	pix_left		= win_task->pix_left;
	pix_top			= win_task->pix_top;
	left_margin		= left;
	right_margin	= right;
	POPFD
	if (doc->flags & DOCF_BORDER_DOC)
	{
		scroll_x = 0;
		scroll_y = 0;
	}
	best_doc_e = doc->cur_entry;

	if (!(doc->flags & (DOCF_PLAIN_TEXT | DOCF_PLAIN_TEXT_TABS)) && FilesFindMatch(doc->filename.name, FILEMASK_SRC))
		doc->flags |= DOCF_HIGHLIGHT;
	else
		doc->flags &= ~DOCF_HIGHLIGHT;

	x = y = 0;
	doc->page_line_num = 0;
	if (full_refresh && !find_cursor)
	{
		doc->x = x;
		doc->y = y;
	}

	hss = &win_task->horz_scroll;
	vss = &win_task->vert_scroll;
	if (doc->flags & DOCF_BORDER_DOC)
	{
		doc->top_line_num	= 0;
		doc->line_start_col	= 0;
		recalc_flags &= ~RECALCF_HAS_CURSOR;
		if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN)
			doc->settings_head.cur_text_attr = doc->settings_head.default_text_attr = win_task->border_attr;
	}
	else
	{
		if (recalc_flags & RECALCF_HAS_CURSOR && full_refresh)
		{
			if (Bt(&hss->flags, WSSf_SET_TO_POS) || Bt(&vss->flags, WSSf_SET_TO_POS))
			{
				if (!(doc->flags & DOCF_NO_SCROLL_BARS))
				{
					if (Bt(&hss->flags, WSSf_SET_TO_POS))
					{
						doc->line_start_col = hss->pos;
						LBtr(&hss->flags, WSSf_SET_TO_POS);
					}
					if (Bt(&vss->flags, WSSf_SET_TO_POS))
					{
						doc->top_line_num = vss->pos;
						LBtr(&vss->flags, WSSf_SET_TO_POS);
					}
				}
				doc->x = doc->line_start_col + width  / 2;
				doc->y = doc->top_line_num   + height / 2;
				find_cursor = TRUE;
			}
		}
		if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN)
			doc->settings_head.cur_text_attr = doc->settings_head.default_text_attr = win_task->text_attr;
	}
	x0 = doc->line_start_col;
	y0 = doc->top_line_num;
	same_win =	top				== doc->old_win_top		&&
				bottom			== doc->old_win_bottom	&&
				left			== doc->old_win_left	&&
				right			== doc->old_win_right	&&
				doc->cur_entry	== doc->old_cur_entry	&&
				doc->cur_col	== doc->old_cur_col;

	if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN)
	{
		y_plot_top = y0 - scroll_y / FONT_HEIGHT;
		y_plot_bottom = y0 + height - 1 - scroll_y / FONT_HEIGHT;
		if (!(doc->flags & DOCF_BORDER_DOC) && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
			DocBorderListDraw(doc);
	}

	if (doc->cur_col <= doc->cur_entry->min_col)
		doc->cur_col = doc->cur_entry->min_col;
	doc_e = doc->head.next;
	doc_e->de_flags &= ~(DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT);
	if (doc_e == doc->head.next)
		s = &doc->settings_head;
	else
		s = &doc_e->last->settings;
	doc->flags = doc_e->de_flags & (DOCG_BL_IV_UL | DOCEF_WORD_WRAP) | doc->flags & ~(DOCG_BL_IV_UL | DOCEF_WORD_WRAP);
	cur_u8_attr = s->cur_text_attr;
	if (doc_e == doc->head.next)
	{
		doc->flags &= ~DOCF_BWD_MOVEMENT;
		if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && full_refresh)
			doc->flags &= ~DOCF_HAS_SONG;
	}
	else
		doc->flags = doc_e->de_flags & DOCEF_HIGHLIGHT | doc->flags & ~DOCEF_HIGHLIGHT;

	if (doc->head.next == doc)
	{
		best_doc_e = doc;
		best_col = 0;
		doc->cur_entry	= doc;
		doc->cur_col	= 0;
		doc_e = doc;
	}
	skipped_update = doc_e == doc && doc->head.next != doc;

	if (full_refresh)
	{
		doc->min_x = I32_MAX;
		doc->min_y = I32_MAX;
		doc->max_x = I32_MIN;
		doc->max_y = I32_MIN;
	}
	while (doc_e != doc)
	{
		while (TRUE)
		{
			del_doc_e = FALSE;
			if (doc_e->de_flags & (DOCEF_SKIP | DOCEF_FILTER_SKIP))
			{
				doc_e2 = doc_e;
				goto rc_skip;
			}
			MemCopy(&doc_e->settings, s, sizeof(CDocSettings));
			s = &doc_e->settings;
			if (doc_e->de_flags & (DOCEF_TAG_CB | DOCEF_DEFINE) && !(doc_e->de_flags & DOCEF_LIST))
			{
				Free(doc_e->tag);
				if (doc_e->de_flags & DOCEF_TAG_CB)
				{
					if (doc_e->tag_cb)
						doc_e->tag = (*doc_e->tag_cb)(doc, doc_e, mem_task);
					else
						doc_e->tag = StrNew("", mem_task);
				}
				else
				{
					if (tmph = HashFind(doc_e->define_str, win_task->hash_table, HTT_DEFINE_STR))
						doc_e->tag = StrNew(tmph->data, mem_task);
					else
						doc_e->tag = CAlloc(1, mem_task);
				}
				doc_e->max_col = StrLen(doc_e->tag);
				if (doc->cur_entry == doc_e && doc->cur_col >= doc_e->max_col)
				{
					if (doc_e->max_col)
						doc->cur_col = doc_e->max_col - 1;
					else
						doc->cur_col = 0;
				}
			}
			k = DocWordWrapDel(doc, doc_e, full_refresh, same_win, left_margin, right_margin, &best_doc_e, &best_col);
			if (doc_e->de_flags &
					(DOCEF_LEFT_X | DOCEF_RIGHT_X | DOCEF_CENTER_X | DOCEF_TOP_Y | DOCEF_BOTTOM_Y | DOCEF_CENTER_Y))
				DocRecalcXY(doc, doc_e, k, left, width, height, left_margin, right_margin, x0, y0, &x, &y);
			if (full_refresh && k > 0 && doc->flags & DOCF_WORD_WRAP &&
					(doc_e2 = DocWordWrapAdd(doc, doc_e, &k, left, right_margin, x, y)))
				doc_e = doc_e2;
			else
				break;
		}

		if (full_refresh)
		{
			doc_e->x			 = x;
			doc_e->y			 = y;
			doc_e->page_line_num = doc->page_line_num;
			if (x < doc->min_x)
				doc->min_x = x;
			if (y < doc->min_y)
				doc->min_y = y;
			if (find_cursor)
			{
				D = DocCharDist(doc, x, y);
				col = 0;
			}
		}
		col2 = 0;

		tmp_u32_attr = DocTmpAttr(doc, doc_e, cur_u8_attr);
		if (doc_e == doc->cur_entry)
		{
			cursor_y = doc_e->y;
			if (recalc_flags & RECALCF_ADD_CURSOR && !added_cursor)
			{
				if (doc_e->type_u8 == DOCT_TEXT && 0 < doc->cur_col < k &&
					!(doc_e->de_flags &
						~(DOCEF_TAG|DOCG_BL_IV_UL|DOCEF_WORD_WRAP|DOCEF_HIGHLIGHT|DOCEF_SKIP|DOCEF_FILTER_SKIP)) &&
					!(doc_e->type & DOCG_BL_IV_UL))
				{
					added_cursor = DocSplitTag(doc, doc_e, doc->cur_col, x, y, DOCT_CURSOR);
					k = StrLen(doc_e->tag);
				}
				else
				{
					added_cursor = doc_e2 = DocEntryNewBase(doc, DOCT_CURSOR | doc_e->type & 0xFFFFFF00, 
																 doc_e->de_flags & ~DOCEG_HAS_ARG, x, y, doc->page_line_num);
					MemCopy(&doc_e2->settings, &doc_e->settings, sizeof(CDocSettings));
					if (doc_e->type_u8 == DOCT_TEXT && doc->cur_col >= k)
						QueueInsert(doc_e2, doc_e);
					else
						QueueInsertRev(doc_e2, doc_e);
				}
			}
		}

		if (doc_e->de_flags & DOCEF_REFRESH_DATA &&
			(doc_e->type_u8 == DOCT_DATA || doc_e->type_u8 == DOCT_CHECK_BOX || doc_e->de_flags & DOCEF_LIST))
		{
			DocDataFormat(doc, doc_e);
			k = StrLen(doc_e->tag);
		}
		if (doc_e->de_flags & DOCEF_TAG)
		{
			ptr = doc_e->tag;
			if (doc_e->de_flags & DOCEF_TREE)
			{
				if (k >= 2)
				{
					if (doc_e->de_flags & DOCEF_CHECKED_COLLAPSED)
						*ptr++ = '+';
					else
						*ptr++ = '-';
					*ptr++ = ']';
					ptr = doc_e->tag;
				}
			}
			else if (doc_e->de_flags & DOCEF_HAS_BIN)
			{
				if (*ptr == '<' && full_refresh && '0' <= ptr[1] <= '9')
				{
					ptr = MStrPrint("<%d>", doc_e->bin_num);
					Free(doc_e->tag);
					doc_e->tag = StrNew(ptr, mem_task);
					Free(ptr);
					ptr = doc_e->tag;
					k = StrLen(ptr);
				}
			}
			else if (doc_e->type_u8 == DOCT_CHECK_BOX)
			{
				if (k >= 3)
				{
					*ptr++ = '[';
					if (doc_e->de_flags & DOCEF_CHECKED_COLLAPSED)
						*ptr++ = 'X';
					else
						*ptr++ = CH_SPACE;
					*ptr++ = ']';
					ptr = doc_e->tag;
				}
			}
			if (doc_e->de_flags & DOCEF_SCROLLING_X)
			{
				j = StrLen(doc_e->tag);
				if (j && doc_e->scroll_len)
				{
					i_jif = ToI64(cur_time * FONT_WIDTH * DOC_SCROLL_SPEED) % (j * FONT_WIDTH);
					tmp_u32_attr = tmp_u32_attr & 0xFFE0FF00 | (FONT_WIDTH - 1 - i_jif & (FONT_WIDTH - 1)) << 16;
#assert FONT_WIDTH == 8
					i_jif >>= 3;
					for (k = 0; k < doc_e->scroll_len; k++)
					{
						ch = ptr[(i_jif + k) % j];
						if (!Bt(char_bmp_displayable, ch))
							ch = '.';
						if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
						{
							if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
								TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch);
							else
								TextChar(win_task, FALSE, x - x0, y - y0, tmp_u32_attr + ch);
						}
						x++;
					}
				}
				if (find_cursor)
				{
					D = DocCharDist(doc, doc_e->x, doc_e->y);
					col = doc_e->min_col;
				}
				col2 = doc_e->scroll_len; //TODO This is flawed
			}
			else
			{
				if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
				{
					while (ch = *ptr++)
					{
						if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
							TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch);
						else
							if (find_cursor)
							{
								d2 = DocCharDist(doc, x, y);
								if (d2 < D)
								{
									D = d2;
									col = col2;
								}
							}
						col2++;
						x++;
					}
				}
				else
				{
					if (doc_e->type_u8 == DOCT_TEXT && doc_e->de_flags & DOCEF_HIGHLIGHT)
						hl = DocHighlight(doc_e, ptr, k, tmp_u32_attr);
					else
						hl = NULL;
					if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
					{
//Technically we should do this for scrolling_x, too.
						if (y > y_plot_bottom)
							more = TRUE;
						else if (y >= y_plot_top)
						{
							if (hl)
								TextLenAttrStr(win_task, x - x0, y - y0, k, hl);
							else
								TextLenStr(win_task, x - x0, y - y0, k, tmp_u32_attr, ptr);
						}
						col2 += k;
						x += k;
					}
					else
					{
						if (find_cursor)
						{
							while (k--)
							{
								d2 = DocCharDist(doc, x, y);
								if (d2 < D)
								{
									D = d2;
									col = col2;
								}
								col2++;
								x++;
							}
						}
						else
						{
							col2 += k;
							x += k;
						}
					}
					Free(hl);
				}
			}
		}
		switch [doc_e->type_u8]
		{
			case DOCT_TEXT:
				if (!col2 &&
						!(doc_e->de_flags &
						(DOCEF_TREE | DOCEF_LIST | DOCEF_TAG_CB |
						 DOCEF_DEFINE | DOCEF_AUX_STR | DOCEF_HTML_LINK | DOCEF_BIN_PTR_LINK)))
					del_doc_e = TRUE;
				break;

			case DOCT_HEX_ED:
				if (doc_e->de_flags & DOCEF_DEREF_DATA && !(doc_e->de_flags & DOCEF_REMALLOC_DATA))
					bptr = doc_e->data;
				else
					bptr = &doc_e->data;
				k = doc_e->hex_ed_width; //columns
				for (i = 0; i < doc_e->len; i += k)
				{
					if (doc_e->de_flags & DOCEF_ZERO_BASED)
						StrPrint(buf, "%08tX ", i);
					else
						StrPrint(buf, "%08tX ", bptr);
					ptr = buf;
					while (ch = *ptr++)
					{
						if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
						{
							if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
								TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch);
							else
								TextChar(win_task, FALSE, x - x0, y - y0, tmp_u32_attr + ch);
						}
						if (find_cursor)
						{
							d2 = DocCharDist(doc, x, y);
							if (d2 < D)
							{
								D = d2;
								col = i * 3;
							}
						}
						x++;
					}
					if (i + k > doc_e->len)
						k = doc_e->len - i;
					for (j = 0; j < k; j++)
					{
						StrPrint(buf, "%02tX", *bptr++);
						ptr = buf;
						while (ch = *ptr++)
						{
							if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
							{
								if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
									TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch);
								else
									TextChar(win_task, FALSE, x - x0, y - y0, tmp_u32_attr + ch);
							}
							if (find_cursor)
							{
								d2 = DocCharDist(doc, x, y);
								if (d2 < D)
								{
									D = d2;
									col = col2;
								}
							}
							col2++;
							x++;
						}
						x++;
					}
					bptr -= j;
					x += (doc_e->hex_ed_width - k) * 3;
					for (j = 0; j < k; j++)
					{
						ch = *bptr++;
						if (!Bt(char_bmp_displayable, ch))
							ch = '.';
						if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
						{
							if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
								TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch);
							else
								TextChar(win_task, FALSE, x - x0, y - y0, tmp_u32_attr + ch);
						}
						if (find_cursor)
						{
							d2 = DocCharDist(doc, x, y);
							if (d2 < D)
							{
								D = d2;
								col = col2;
							}
						}
						col2++;
						x++;
					}
					y++;
					x -= doc_e->hex_ed_width * 3 + k + 9;
				}
				break;

			case DOCT_NEW_LINE:
			case DOCT_SOFT_NEW_LINE:
				if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW)&&
						y_plot_top <= y <= y_plot_bottom)
					TextLenAttr(win_task, x - x0, y - y0, width - (x - x0), cur_u8_attr << 8);
				if (doc_e->de_flags & DOCEF_HIGHLIGHT && s->state == DOCSS_CPP_Z_COMMENT)
					s->state = DOCSS_NORMAL;
				y++;
				doc->page_line_num++;
rc_start_of_line:
				if (s->left_margin == DOC_DEFAULT)
					x = s->indent;
				else
					x = s->indent + s->left_margin;
rc_adjust_xy:
				i = s->indent + s->left_margin;
				if (x < i)
					x = i;
				if (doc->page_line_num < 0)
					doc->page_line_num = s->page_len + doc->page_line_num % s->page_len;
				else
				{
					if (doc->page_line_num >= s->page_len)
					{
						doc->page_line_num -= s->page_len;
						if (doc->page_line_num >= s->page_len) //avoid extra divide
							doc->page_line_num = doc->page_line_num % s->page_len;
					}
				}
				if (s->header != DOC_DEFAULT)
				{
					if (doc->page_line_num < s->header)
					{
						y += s->header - doc->page_line_num;
						doc->page_line_num = s->header;
						goto rc_start_of_line;
					}
				}
				if (s->footer == DOC_DEFAULT)
				{
					if (doc->page_line_num >= s->page_len)
					{
						if (s->header == DOC_DEFAULT)
							doc->page_line_num = 0;
						else
						{
							doc->page_line_num = s->header;
							y += s->header;
						}
						goto rc_start_of_line;
					}
				}
				else
				{
					if (doc->page_line_num >= s->page_len - s->footer)
					{
						y += s->footer;
						if (s->header == DOC_DEFAULT)
							doc->page_line_num = 0;
						else
						{
							doc->page_line_num = s->header;
							y += s->header;
						}
						goto rc_start_of_line;
					}
				}
				break;

			case DOCT_TAB:
				k = (x + 4) & ~3;
				if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
				{
					while (x < k)
					{
						if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
							TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + CH_SPACE);
						if (find_cursor)
						{
							d2 = DocCharDist(doc, x, y);
							if (d2 < D)
								D = d2;
						}
						x++;
					}
				}
				else
				{
					k -= x;
					if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW))
					{
						if (y_plot_top <= y <= y_plot_bottom)
							TextLenStr(win_task, x - x0, y - y0, k, tmp_u32_attr, "    ");
						x += k;
					}
					else
					{
						if (find_cursor)
						{
							while (k--)
							{
								d2 = DocCharDist(doc, x, y);
								if (d2 < D)
									D = d2;
								x++;
							}
						}
						else
							x += k;
					}
				}
				break;

			case DOCT_PAGE_BREAK:
				doc->flags |= DOCF_BWD_MOVEMENT;
				y += s->page_len - doc_e->page_line_num;
				doc->page_line_num = 0;
				goto rc_start_of_line;

			case DOCT_CURSOR:
				if (!find_cursor && !(doc->flags & DOCF_NO_CURSOR))
				{
					doc->cur_entry	= doc_e->next;
					doc->cur_col	= doc->cur_entry->min_col;
				}
				if (doc_e != added_cursor)
					del_doc_e = TRUE;
				break;

			case DOCT_PROMPT:
				cur_u8_attr = cur_u8_attr & 0xF0 | DOC_COLOR_PROMPT;
				if (y == cursor_y)
				{
					doc->cur_entry	= doc_e->next;
					doc->cur_col	= doc->cur_entry->min_col;
				}
				break;

			case DOCT_CLEAR:
				next_clear_found = doc_e;
				if (doc_e->de_flags & DOCEF_HOLD)
					clear_holds = TRUE;
				else
					clear_holds = FALSE;
				break;

			case DOCT_PAGE_LEN:
				s->page_len = doc_e->attr;
				if (doc_e->de_flags & DOCEF_WIN_REL)
					s->page_len += height;
				goto rc_adjust_xy;

			case DOCT_LEFT_MARGIN:
				i = doc_e->attr;
				left_margin = left+i;
				s->left_margin = i;
				goto rc_start_of_line;

			case DOCT_RIGHT_MARGIN:
				if (doc_e->de_flags & DOCEF_WIN_REL)
					i = width - 1 - doc_e->attr;
				else
					i = doc_e->attr;
				right_margin = left + i;
				s->right_margin = i;
				goto rc_adjust_xy;

			case DOCT_HEADER:
				s->header = doc_e->attr;
				goto rc_adjust_xy;

			case DOCT_FOOTER:
				s->footer = doc_e->attr;
				goto rc_adjust_xy;

			case DOCT_INDENT:
				if (doc_e->de_flags & DOCEF_LEFT_X)
					i = doc_e->attr;
				else
					i = s->indent + doc_e->attr;
				s->indent=i;
				goto rc_start_of_line;

			case DOCT_FOREGROUND:
				cur_u8_attr &= 0xF0;
				if (doc_e->attr == DOC_DEFAULT)
					cur_u8_attr |= s->default_text_attr & 0x0F;
				else
					cur_u8_attr |= doc_e->attr;
				s->cur_text_attr = cur_u8_attr;
				break;

			case DOCT_BACKGROUND:
				cur_u8_attr &= 0x0F;
				if (doc_e->attr == DOC_DEFAULT)
					cur_u8_attr |= s->default_text_attr & 0xF0;
				else
					cur_u8_attr |= doc_e->attr << 4;
				s->cur_text_attr = cur_u8_attr;
				break;

			case DOCT_DEFAULT_FOREGROUND:
				cur_u8_attr &= 0xF0;
				if (doc_e->attr == DOC_DEFAULT)
					cur_u8_attr |= s->default_text_attr & 0xF;
				else
					cur_u8_attr |= doc_e->attr;
				s->default_text_attr = s->default_text_attr & 0xF0 | cur_u8_attr & 0x0F;
				s->cur_text_attr	 = cur_u8_attr;
				break;

			case DOCT_DEFAULT_BACKGROUND:
				cur_u8_attr &= 0x0F;
				if (doc_e->attr == DOC_DEFAULT)
					cur_u8_attr |= s->default_text_attr & 0xF0;
				else
					cur_u8_attr |= doc_e->attr << 4;
				s->default_text_attr = s->default_text_attr & 0x0F | cur_u8_attr & 0xF0;
				s->cur_text_attr	 = cur_u8_attr;
				break;


			case DOCT_WORD_WRAP:
				if (doc_e->attr)
					doc->flags |= DOCF_WORD_WRAP;
				else
					doc->flags &= ~DOCF_WORD_WRAP;
				break;


			case DOCT_HIGHLIGHT:
				if (doc_e->attr)
					doc->flags |= DOCF_HIGHLIGHT;
				else
					doc->flags &= ~DOCF_HIGHLIGHT;
				break;

			case DOCT_BLINK:
				if (doc_e->attr)
					doc->flags |= DOCF_BLINK;
				else
					doc->flags &= ~DOCF_BLINK;
				break;

			case DOCT_INVERT:
				if (doc_e->attr)
					doc->flags |= DOCF_INVERT;
				else
					doc->flags &= ~DOCF_INVERT;
				break;

			case DOCT_UNDERLINE:
				if (doc_e->attr)
					doc->flags |= DOCF_UNDERLINE;
				else
					doc->flags &= ~DOCF_UNDERLINE;
				break;

			case DOCT_SHIFTED_X:
				s->shifted_x = doc_e->attr;
				break;

			case DOCT_SHIFTED_Y:
				s->shifted_y = doc_e->attr;
				break;

			case DOCT_CURSOR_MOVEMENT:
				doc->flags |= DOCF_BWD_MOVEMENT;
				x += doc_e->cursor_x_offset;
				if (doc_e->de_flags & DOCEF_PAGE_REL_Y)
				{
					i = doc->page_line_num;
					if (doc_e->de_flags & DOCEF_TOP_Y)
						doc->page_line_num = 0;
					else if (doc_e->de_flags & DOCEF_BOTTOM_Y)
						doc->page_line_num = s->page_len - 1;
					else if (doc_e->de_flags & DOCEF_CENTER_Y)
						doc->page_line_num = s->page_len >> 1;
					y += doc->page_line_num - i;
				}
				y += doc_e->cursor_y_offset;
				doc->page_line_num += doc_e->cursor_y_offset;
				goto rc_adjust_xy;

			case DOCT_SPRITE:
				if (!doc_e->bin_data && doc->flags & DOCEF_HAS_BIN)
					doc_e->bin_data = DocBinFindNum(doc, doc_e->bin_num);
				if ((tmpb = doc_e->bin_data) && !tmpb->tag && doc_e->tag && *doc_e->tag)
					tmpb->tag = StrNew(doc_e->tag, mem_task);
				if (tmpb && dc)
				{
					DCReset(dc);
					dc->flags &= ~(DCF_DONT_DRAW | DCF_LOCATE_NEAREST);
					if (recalc_flags & RECALCG_MASK != RECALCt_TO_SCREEN || doc_e->de_flags & DOCEF_DONT_DRAW)
						dc->flags |= DCF_DONT_DRAW;
					bptr = tmpb->data;
					ii = SpriteTypeMask(bptr);
					if (ii & 1 << SPT_TYPES_NUM)
					{
						bptr = gr.empty_sprite;
						ii = SpriteTypeMask(bptr);
					}
					if (ii & (1 << SPT_FLOOD_FILL | 1 << SPT_FLOOD_FILL_NOT))
						i = cur_u8_attr >> 4 & 0xF ^ win_task->text_attr >> 4 & 0xF;
					else
					{
						i = tmp_u32_attr >> 12 & 0xF ^ win_task->text_attr >> 4 & 0xF;
						if (tmp_u32_attr & DOCET_SEL)
							i ^= 0xF;
						if (tmp_u32_attr & DOCET_INVERT)
							i ^= 0xF;
						if (blink_flag && (doc_e == doc->cur_entry || tmp_u32_attr & DOCET_BLINK))
							i ^= 0xF;
					}
					dc->color = i;
					if (find_cursor)
						dc->flags |= DCF_LOCATE_NEAREST;
					dc->cur_x = (doc->x - x0) * FONT_WIDTH  + pix_left + scroll_x;
					dc->cur_y = (doc->y - y0) * FONT_HEIGHT + pix_top  + scroll_y;
					dc->cur_z = 0;
					dc->bkcolor = i;
					if (doc_e->de_flags & DOCEF_FROM_START)
					{
						xx = (x -k - x0) * FONT_WIDTH; //TODO: scrolling text is not length k
						yy = (y - y0) * FONT_HEIGHT;
						zz = 0;
					}
					else
					{
						xx = (x - x0) * FONT_WIDTH;
						yy = (y - y0) * FONT_HEIGHT;
						zz = 0;
					}
					if (ii & (1 << SPT_MESH | 1 << SPT_SHIFTABLE_MESH))
					{
						if (!depth_buf)
						{
							DCDepthBufAlloc(dc);
							depth_buf = dc->depth_buf;
						}
						else
							dc->depth_buf = depth_buf;
						Mat4x4IdentEqu(dc->r);
						Mat4x4RotZ(dc->r, cur_time * 3.1);
						Mat4x4RotY(dc->r, cur_time * 1.9);
						Mat4x4RotX(dc->r, cur_time);
						dc->flags |= DCF_TRANSFORMATION;
						dc->x = xx;
						dc->y = yy;
						dc->z = GR_Z_ALL;
						xx = 0;
						yy = 0;
						zz = 0;
					}
					Sprite3(dc, xx, yy, zz, bptr);
					dc->depth_buf = NULL;
					dc->flags &= ~(DCF_LOCATE_NEAREST | DCF_DONT_DRAW | DCF_TRANSFORMATION);
					if (dc->nearest_dist <= D)
					{
						D = dc->nearest_dist;
						col = doc_e->min_col;
					}
				}
				break;

			case DOCT_SONG:
				if (sys_focus_task == win_task && recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN &&
					!(doc_e->de_flags & DOCEF_DONT_DRAW))
				{
					if (doc_e->aux_str && (!music.cur_song || StrCompare(music.cur_song, doc_e->aux_str)))
					{
						Free(music.cur_song);
						MusicSettingsReset;
						music.cur_song = ZStrNew(doc_e->aux_str);
					}
				}
				doc->flags |= DOCF_HAS_SONG;
				break;
			case DOCT_HTML_CODE:
				if (recalc_flags & RECALCF_TO_HTML && doc_e->de_flags & DOCEF_TAG && doc_e->tag)
					x -= StrLen(doc_e->tag);
				break;
			case DOCT_TYPES_NUM - 1: //nobound switch
			default:
				break;
		}

		if (doc_e->de_flags & DOCEF_HAS_BORDER)
			TextBorder(win_task, doc_e->x - x0, x - x0 - 1, doc_e->y - y0, y - y0,
					   tmp_u32_attr.u8[1], ToBool(doc_e->de_flags & DOCEF_SOLID_BORDER));
		if (full_refresh)
		{
			switch (doc_e->type_u8)
			{
				case DOCT_CHECK_BOX:
					doc_e->max_col = 2;
					break;

				case DOCT_LIST:
				case DOCT_TREE:
				case DOCT_BTTN:
				case DOCT_LINK:
				case DOCT_MENU_VAL:
				case DOCT_MACRO:
					doc_e->max_col = 1;
					break;

				default:
					if (doc_e->de_flags & (DOCEF_TREE | DOCEF_LIST))
						doc_e->max_col = 1;
					else
						doc_e->max_col = col2;
			}

			if (x > doc->max_x)
				doc->max_x = x;
			if (y > doc->max_y)
				doc->max_y = y;
			if (D <= best_d && !(doc_e->de_flags & DOCEF_NO_CLICK_ON))
			{
				best_d = D;
				best_doc_e = doc_e;
				best_col = col;
			}
			if (doc_e->de_flags & DOCEF_TREE)
			{
				if (doc_e->de_flags & DOCEF_CHECKED_COLLAPSED)
					tree_collapsed = TRUE;
				else
					tree_collapsed = FALSE;
				doc_e2 = doc_e->next;
				while (doc_e2 != doc && doc_e2->type_u8 != DOCT_INDENT && !(doc_e2->de_flags & DOCEF_TREE))
					doc_e2 = doc_e2->next;
				if (doc_e2->type_u8 == DOCT_INDENT)
				{
					j = i = s->indent;
					do
					{
						if (tree_collapsed)
							doc_e2->de_flags |= DOCEF_SKIP;
						else
							doc_e2->de_flags &= ~DOCEF_SKIP;
						if (doc_e2->type_u8 == DOCT_INDENT)
						{
							if (doc_e2->de_flags & DOCEF_LEFT_X)
								j = doc_e2->attr;
							else
								j += doc_e2->attr;
						}
						doc_e2 = doc_e2->next;
					}
					while (doc_e2 != doc && j > i);
				}
			}
		}

		doc_e2 = doc_e->next;
rc_skip:
		while (doc_e2 != doc && doc_e2->de_flags & (DOCEF_SKIP | DOCEF_FILTER_SKIP))
		{
			if (doc_e2 == doc->cur_entry)
			{
				doc->cur_entry	= doc_e2->next;
				doc->cur_col	= doc->cur_entry->min_col;
			}
			if (full_refresh)
			{
				doc_e2->x				= x;
				doc_e2->y				= y;
				doc_e2->page_line_num	= doc->page_line_num;
				MemCopy(&doc_e2->settings, s, sizeof(CDocSettings));
				doc_e2->type.u8[1]		= cur_u8_attr;
				doc_e2->de_flags		= doc->flags &
											(DOCG_BL_IV_UL|DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT) |
											doc_e2->de_flags & ~(DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT);
			}
			doc_e2 = doc_e2->next;
		}

		if (full_refresh)
		{
			if (del_doc_e)
			{
				if (!(doc_e->de_flags & (DOCEF_HOLD | DOCEF_FILTER_SKIP)))
				{
					if (doc_e == doc->cur_entry)
					{
						doc->cur_entry	= doc_e2;
						doc->cur_col	= doc_e2->min_col;
					}
					if (best_doc_e == doc_e)
					{
						best_doc_e	= doc_e2;
						best_col	= doc_e2->min_col;  //TODO: might be bug
					}
					DocEntryDel(doc, doc_e);
				}
			}
		}
		num_entries++;
		if (!full_refresh && doc_e->y > y_plot_bottom)
			break;
		doc_e = doc_e2;
	}

	if (full_refresh)
	{
		if (doc->cur_entry == doc && recalc_flags & RECALCF_ADD_CURSOR)
		{
			doc_e2 = DocEntryNewBase(doc, DOCT_CURSOR,, x, y, doc->page_line_num);
			MemCopy(&doc_e2->settings, s, sizeof(CDocSettings));
			QueueInsertRev(doc_e2, doc);
		}

		if (doc->min_x > doc->max_x)
		{
			doc->max_x = 0;
			doc->min_x = 0;
		}
		if (doc->min_y > doc->max_y)
		{
			doc->max_y = 0;
			doc->min_y = 0;
		}

		//Update header
		if (!skipped_update)
		{
			doc_e->x				= x;
			doc_e->y				= y;
			doc_e->page_line_num	= doc->page_line_num;
			MemCopy(&doc_e->settings, s, sizeof(CDocSettings));
			doc_e->type.u8[1]		= cur_u8_attr;
			if (find_cursor)
			{
				D = DocCharDist(doc, x, y);
				if (D < best_d && !(doc_e->de_flags & DOCEF_NO_CLICK_ON))
				{
					best_d = D;
					best_doc_e = doc_e;
					best_col = 0;
				}
			}
		}
		if (doc->flags & DOCF_SIZE_MIN)
		{
			if (Bt(&win_task->display_flags, DISPLAYf_NO_BORDER))
			{
				if (left < 0)
					left = 0;
				i = left + doc->max_x - doc->min_x;
				if (i > TEXT_COLS - 1)
					i = TEXT_COLS - 1;
				WinHorz(left, i, win_task);
				if (top < 0)
					top = 0;
				i = top + doc->max_y - doc->min_y;
				if (i > TEXT_ROWS - 1)
					i = TEXT_ROWS - 1;
				WinVert(top, i, win_task);
			}
			else
			{
				if (left < 1)
					left = 1;
				i = left + doc->max_x - doc->min_x;
				if (i > TEXT_COLS - 2)
					i = TEXT_COLS - 2;
				WinHorz(left, i, win_task);
				if (top < 1)
					top = 1;
				i = top + doc->max_y - doc->min_y;
				if (i > TEXT_ROWS - 2)
					i = TEXT_ROWS - 2;
				WinVert(top, i, win_task);
			}
		}
		if (find_cursor)
		{
			doc->cur_entry	= best_doc_e;
			doc->cur_col	= best_col;
			DocFormBwd(doc);
//We need this because text coordinates are used
			if (best_d < FONT_WIDTH)
				best_d = 0;
			doc->best_d = best_d;
		}

		if (doc->cur_entry->type_u8 != DOCT_HEX_ED)
		{
			doc->y = doc->cur_entry->y;
			doc->x = doc->cur_entry->x + doc->cur_col;
		}
		else
		{
			doc->y = doc->cur_entry->y + doc->cur_col / 3 / doc->cur_entry->hex_ed_width;
			x = doc->cur_col % (doc->cur_entry->hex_ed_width * 3);
			i = x / doc->cur_entry->hex_ed_width;
			doc->x = doc->cur_entry->x + 9;
			if (i < 2)
				doc->x += x >> 1 * 3 + x & 1;
			else
				doc->x += doc->cur_entry->hex_ed_width * 3 + (x - doc->cur_entry->hex_ed_width << 1);
		}
		doc->line = doc->y + 1;
		doc->col  = doc->x + 1;

		if (recalc_flags & RECALCF_HAS_CURSOR)
		{
			if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN)
			{
				x = 0;
				y = 0;
			}
			else
			{
				x = scroll_x / FONT_WIDTH;
				y = scroll_y / FONT_HEIGHT;
			}
			if (doc->top_line_num - y + height - 1 > doc->max_y)
				doc->top_line_num = doc->max_y - (height - 1) + y;
			if (doc->top_line_num - y < doc->min_y)
				doc->top_line_num = doc->min_y + y;

			if (doc->y - doc->top_line_num + y > height - 1)
				doc->top_line_num = doc->y - (height - 1) + y;
			if (doc->y - doc->top_line_num + y < 0)
				doc->top_line_num = doc->y + y;

			if (doc->line_start_col - x + width - 1 > doc->max_x)
				doc->line_start_col = doc->max_x - (width - 1) + x;
			if (doc->line_start_col - x < doc->min_x)
				doc->line_start_col = doc->min_x + x;

			if (doc->x - doc->line_start_col + x > width - 1)
				doc->line_start_col = doc->x-(width - 1) + x;
			if (doc->x - doc->line_start_col + x < 0)
				doc->line_start_col = doc->x + x;
		}
	}
	if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && recalc_flags & RECALCF_HAS_CURSOR)
	{
		x = doc->x - doc->line_start_col + left + scroll_x / FONT_WIDTH;
		y = doc->y - doc->top_line_num	 + top  + scroll_y / FONT_HEIGHT;
		if (0 <= x <= right && 0 <= y <= bottom && x < TEXT_COLS && y < TEXT_ROWS && !(doc->flags & DOCF_HIDE_CURSOR))
		{
			u32_ptr = gr.text_base + y * TEXT_COLS + x;
			*u32_ptr |= DOCET_BLINK;
			*u32_ptr ^= 0xFF00;
		}
		if (full_refresh)
		{
			if (!(doc->flags & DOCF_NO_SCROLL_BARS))
			{
				if (!Bt(&hss->flags, WSSf_SET_TO_POS))
				{
					hss->min = doc->min_x;
					if (doc->max_x - width + 1 < hss->min)
						hss->max = hss->min;
					else
						hss->max = doc->max_x - width + 1;
					hss->pos = doc->line_start_col;
				}
				if (!Bt(&vss->flags, WSSf_SET_TO_POS))
				{
					vss->min = doc->min_y;
					if (doc->max_y - height + 1 < vss->min)
						vss->max = vss->min;
					else
						vss->max = doc->max_y - height + 1;
					vss->pos = doc->top_line_num;
				}
			}
			LBEqual(&doc->flags, DOCf_MORE, more);
		}
	}
	if (!same_win)
	{
		doc->old_win_top	= top;
		doc->old_win_bottom	= bottom;
		doc->old_win_left	= left;
		doc->old_win_right	= right;
		doc->old_cur_entry	= doc->cur_entry;
		doc->old_cur_col	= doc->old_cur_col;
	}
	if (doc->flags & DOCF_HAS_SONG)
		LBts(&win_task->task_flags, TASKf_HAS_SONG);
	if (full_refresh)
	{
		i = num_entries - doc->max_entries;
		if (next_clear_found)
		{
			DocDelToEntry(doc, next_clear_found, clear_holds);
			DocRecalc(doc, recalc_flags);
		}
		else if (i > 1024)
		{
			DocDelToNum(doc, i);
			DocRecalc(doc, recalc_flags);
		}
	}
	DCDel(dc);
	Free(depth_buf);
	if (unlock)
		DocUnlock(doc);

	return TRUE;
}
