Esempio n. 1
0
void LineEdit::AlignChar() {
	int c = GetCursor();
	if(c == 0)
		return;
	Point pos = GetColumnLine(c);
	if(pos.x == 0)
		return;
	for(int d = 1; d <= pos.y && d < 100; d++) {
		int lny = pos.y - d;
		WString above = GetWLine(lny);
		int offset = GetGPos(lny, pos.x) - GetPos(lny);
		int end = offset;
		char ch = GetChar(c - 1);
		if(ch == ' ')
		{
			offset++;
			while(end < above.GetLength() && above[end] != ' ')
				end++;
			while(end < above.GetLength() && above[end] == ' ')
				end++;
		}
		else
			while(end < above.GetLength() && above[end] != ch)
				end++;
		if(end < above.GetLength()) {
			int count = end - offset + 1;
			WString s(' ', count);
			Insert(c - 1, s, true);
			SetCursor(c + count);
			return;
		}
	}
}
Esempio n. 2
0
bool WString::ReplaceOnce(const WString &findWhat,const WString &replaceWith)
{
  int pos = Find(findWhat);
  if (pos == -1) return false;
  (*this) = Left(pos)+replaceWith+Right(pos+replaceWith.GetLength());
  return true;
}
Esempio n. 3
0
int  DocEdit::GetCursorPos(Point p) {
	int pos = 0;
	for(int i = 0; i < para.GetCount(); i++) {
		int h = GetHeight(i);
		if(p.y < h) {
			WString text = line[i];
			Fmt fmt = Format(text);
			int x = 0;
			int l = p.y / fmt.fi.GetHeight();
			if(l < 0)
				return pos;
			if(l >= fmt.line.GetCount())
				return pos + text.GetLength();
			const int *w = fmt.width + fmt.line[l];
			const int *e = fmt.width + fmt.LineEnd(l);
			while(w < e) {
				if(p.x < x + *w / 2)
					return int(w - fmt.width) + pos;
				x += *w++;
			}
			int p = int(e - fmt.width);
			if(p > 0 && text[p - 1] == ' ' && l < fmt.line.GetCount() - 1)
			   p--;
			return p + pos;
		}
		p.y -= h;
		pos += line[i].GetLength() + 1;
	}
	return GetLength();
}
Esempio n. 4
0
void RichQtfParser::Flush() {
	if(text.GetLength()) {
		ASSERT(!istable);
		paragraph.Cat(text, format);
		text.Clear();
	}
}
Esempio n. 5
0
void AppendClipboardUnicodeText(const WString& s)
{
#ifndef PLATFORM_WINCE
	AppendClipboardText(s.ToString());
#endif
	AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength());
}
Esempio n. 6
0
static void sMergeWith(WString& dest, const wchar *delim, const WString& s)
{
	if(s.GetLength()) {
		if(dest.GetCount())
			dest.Cat(delim);
		dest.Cat(s);
	}
}
Esempio n. 7
0
bool PythonSyntax::LineHasColon(const WString& line)
{
	for(int i = line.GetLength() - 1; i >= 0; i--) {
		if(line[i] == ':')
			return true;
	}
	return false;
}
Esempio n. 8
0
bool SaveStreamBOM(Stream& out, const WString& data) {
	if(!out.IsOpen() || out.IsError()) 
		return false;
	word w = 0xfeff;
	out.Put(&w, 2);
	out.Put(~data, 2 * data.GetLength());
	out.Close();
	return out.IsOK();
}
Esempio n. 9
0
int  RichEdit::FindPos()
{
	RichFindIterator fi;
	WString w = findreplace.find.GetText();
	if(findreplace.ignorecase) {
		fi.upperw = ToUpper(w);
		fi.lowerw = ToLower(w);
	}
	else
		fi.upperw = fi.lowerw = w;
	fi.len = w.GetLength();
	fi.ww = findreplace.wholeword;
	if(w.GetLength()) {
		fi.cursor = cursor;
		if(text.Iterate(fi))
			return fi.fpos;
	}
	return -1;
}
Esempio n. 10
0
DocEdit::Fmt DocEdit::Format(const WString& text) const
{
	FontInfo fi = font.Info();
	Fmt fmt;
	int tcx = fi['x'] * 4;
	fmt.len = text.GetLength();
	fmt.text.Alloc(text.GetLength());
	memcpy(fmt.text, text, text.GetLength() * sizeof(wchar));
	fmt.width.Alloc(text.GetLength());
	fmt.line.Add(0);
	int *w = fmt.width;
	int x = 0;
	const wchar *space = NULL;
	int spacex = 0;
	for(wchar *s = fmt.text; s < fmt.text + fmt.len; s++) {
		int cw;
		if(*s == '\t')
			cw = (x + tcx) / tcx * tcx - x;
		else
			cw = fi[*s];
		*w++ = cw;
		if(*s == ' ' || *s == '\t') {
			space = s;
			spacex = x + cw;
			*s = ' ';
		}
		x += cw;
		if(x > cx) {
			if(space && space <= s) {
				space++;
				fmt.line.Add(int(space - fmt.text));
				space = NULL;
				x -= spacex;
			}
			else {
				fmt.line.Add(int(s - fmt.text));
				x = cw;
			}
		}
	}
	fmt.fi = fi;
	return fmt;
}
Esempio n. 11
0
	virtual bool operator()(int pos, const RichPara& para)
	{
		WString ptext = para.GetText();
		if(pos + ptext.GetLength() > cursor && ptext.GetLength() >= len) {
			const wchar *q = ptext;
			const wchar *e = ptext.End() - len;
			if(cursor >= pos)
				q += cursor - pos;
			while(q <= e) {
				if(compare3(q, upperw, lowerw, len) &&
				   (!ww || (q + len == e || !IsLetter(q[len])) &&
				           (q == ptext || !IsLetter(q[-1])))) {
					fpos = int(q - ~ptext + pos);
					return true;
				}
				q++;
			}
		}
		return false;
	}
Esempio n. 12
0
int PythonSyntax::CalculateLineIndetations(const WString& line, Identation::Type type)
{
	int count = 0;
	for(int i = 0; i < line.GetLength(); i++) {
		if(type == Identation::Tab && line[i] == '\t')
			count++;
		else
		if(type == Identation::Space && line[i] == ' ')
			count++;
		else
			break;
	}
	return count;
}
Esempio n. 13
0
bool WString::ReplaceAll(const WString &findWhat,const WString &replaceWith)
{
  WString process = *this;
  WString result;
  int pos;
  bool processed = false;
  while ((pos = process.Find(findWhat)) != -1)
  {
	result = result+process.Left(pos)+replaceWith;
	process = process.Right(pos+findWhat.GetLength());
	processed = true;
  }
  *this = result+process;
  return processed;
}
Esempio n. 14
0
void FileTabs::ComposeTab(Tab& tab, const Font &font, Color ink, int style)
{
	if(PaintIcons() && tab.HasIcon())
	{
		tab.AddImage(tab.img);
		tab.AddSpace(TB_SPACEICON);
	}

	WString txt = IsString(tab.value) ? tab.value : StdConvert().Format(tab.value);
	int extpos = txt.ReverseFind('.');
	tab.AddText(extpos >= 0 ? txt.Left(extpos) : txt, font, filecolor);

	if (extpos >= 0) {
		tab.AddText(txt.Right(txt.GetLength() - extpos), font, extcolor);
	}
}
Esempio n. 15
0
int PythonSyntax::CalculateSpaceIndetationSize(CodeEditor& editor)
{
	int current = 0;
	for(int i = 0; i < editor.GetLineCount(); i++) {
		WString line = editor.GetWLine(i);
		for(int j = 0; j < line.GetLength(); j++) {
			if(line[j] == ' ')
				current++;
			else
				break;
		}
		
		if(current > 0)
			break;
	}
	
	// TODO: 4 is magic numer - try to find the way to get this number from ide constants
	return current > 0 ? current : 4;
}
Esempio n. 16
0
bool Speller::CheckOld(const WString& wstr) const
{
	int len = wstr.GetLength();
	if(len == 1)
		return true;
	if(len < 64) {
		String w = FromUnicode(wstr, charset);
		String wl = FromUnicode(ToLower(wstr), charset);
		int i;
		if(len == 2) {
			w.Cat(127);
			wl.Cat(127);
		}
		i = line.Find(ToLower(wl[0], charset) +
		              (ToLower(wl[1], charset) << 8) +
		              (ToLower(wl[2], charset) << 16));
		if(i >= 0) {
			const byte *s = line[i].begin;
			const byte *e = line[i].end;
			String q;
			while(s < e)
				if(*s < dict) {
					if(q == w || q == wl)
						return true;
					q.Trim(*s++);
				}
				else {
					ASSERT(*s >= dict);
					const char *x = voc[(int)*s++ - dict];
					q.Cat(x);
				}
			if(q == w || q == wl)
				return true;
		}
	}
	return user.Find(wstr) >= 0;;
}
Esempio n. 17
0
void   LineEdit::Paint0(Draw& w) {
	int sell, selh;
	GetSelection(sell, selh);
	if(!IsEnabled())
		sell = selh = 0;
	Size sz = GetSize();
	Size fsz = GetFontSize();
	Point sc = sb;
	int ll = min(line.GetCount(), sz.cy / fsz.cy + sc.y + 1);
	int  y = 0;
	cpos = GetPos(sc.y);
	cline = sc.y;
	sell -= cpos;
	selh -= cpos;
	int pos = cpos;
	Vector<int> dx, dx2;
	int fascent = font.Info().GetAscent();
	for(int i = sc.y; i < ll; i++) {
		WString tx = line[i];
		int len = tx.GetLength();
		if(w.IsPainting(0, y, sz.cx, fsz.cy)) {
			Highlight ih;
			ih.ink = color[IsShowEnabled() ? INK_NORMAL : INK_DISABLED];
			ih.paper = color[IsReadOnly() || !IsShowEnabled() ? PAPER_READONLY : PAPER_NORMAL];
			if(nobg)
				ih.paper = Null;
			ih.font = font;
			ih.chr = 0;
			Vector<Highlight> hl;
			hl.SetCount(len + 1, ih);
			for(int q = 0; q < tx.GetCount(); q++)
				hl[q].chr = tx[q];
			HighlightLine(i, hl, pos);
			int ln = hl.GetCount() - 1;
			int l = max(sell, 0);
			int h = selh > len ? len : selh;
			if(l < h)
				for(int i = l; i < h; i++) {
					hl[i].paper = color[PAPER_SELECTED];
					hl[i].ink = color[INK_SELECTED];
				}
			if(sell <= len && selh > len)
				for(int i = len; i < hl.GetCount(); i++) {
					hl[i].paper = color[PAPER_SELECTED];
					hl[i].ink = color[INK_SELECTED];
				}
			Buffer<wchar> txt(ln);
			for(int i = 0; i < ln; i++)
				txt[i] = hl[i].chr;
			for(int pass = 0; pass < 2; pass++) {
				int gp = 0;
				int scx = fsz.cx * sc.x;
				if(ln >= 0) {
					int q = 0;
					while(q < ln) {
						Highlight& h = hl[q];
						if(txt[q] == '\t') {
							int ngp = (gp + tabsize) / tabsize * tabsize;
							int l = ngp - gp;
							LLOG("Highlight -> tab[" << q << "] paper = " << h.paper);
							if(pass == 0) {
								w.DrawRect(gp * fsz.cx - scx, y, fsz.cx * l, fsz.cy, h.paper);
								if(showtabs && h.paper != SColorHighlight && q < tx.GetLength()) {
									Color c = Blend(SColorLight, SColorHighlight);
									w.DrawRect(gp * fsz.cx - scx + 2, y + fsz.cy / 2,
									           l * fsz.cx - 4, 1, c);
									w.DrawRect(ngp * fsz.cx - scx - 3, y + 3,
									           1, fsz.cy - 6, c);
								}
								if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + l)
									w.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
							}
							q++;
							gp = ngp;
						}
						else
						if(txt[q] == ' ') {
						    LLOG("Highlight -> space[" << q << "] paper = " << h.paper);
						    if(pass == 0) {
						        w.DrawRect(gp * fsz.cx - scx, y, fsz.cx, fsz.cy, h.paper);
						        if(showspaces && h.paper != SColorHighlight && q < tx.GetLength()) {
						            Color c = Blend(SColorLight, SColorHighlight);
						            w.DrawRect(gp * fsz.cx - scx + fsz.cx / 2, y + fsz.cy / 2,
						                       2, 2, c);
						        }
						        if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + 1)
						            w.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
						    }
						    q++;
						    gp++;
						}
						else {
							bool cjk = IsCJKIdeograph(txt[q]);
							int p = q + 1;
							while(p < len && h == hl[p] && txt[p] != '\t' && txt[p] != ' ' && IsCJKIdeograph(txt[p]) == cjk && p - q < 128)
								p++;
							int l = p - q;
							int ll = cjk ? 2 * l : l;
							LLOG("Highlight -> paper[" << q << "] = " << h.paper);
							int x = gp * fsz.cx - scx;
							int xx = x + (gp + ll) * fsz.cx;
							if(max(x, 0) < min(xx, sz.cx))
								if(pass == 0) {
									w.DrawRect(x, y, fsz.cx * ll, fsz.cy, h.paper);
									if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + ll)
										w.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
								}
								else {
									if(cjk)
										dx2.At(l, 2 * fsz.cx);
									else
										dx.At(l, fsz.cx);
									w.DrawText(x,
									           y + fascent - h.font.Info().GetAscent(),
									           ~txt + q, h.font, h.ink, l, cjk ? dx2 : dx);
								}
							q = p;
							gp += ll;
							if(x > sz.cx)
								break;
						}
					}
				}
				if(pass == 0) {
					int gpx = gp * fsz.cx - scx;
					w.DrawRect(gpx, y, sz.cx - gpx, fsz.cy, hl.Top().paper);
					if(bordercolumn > 0 && bordercolumn >= gp)
						w.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
				}
			}
		}
		y += fsz.cy;
		sell -= len + 1;
		selh -= len + 1;
		pos += len + 1;
	}
	w.DrawRect(0, y, sz.cx, sz.cy - y, color[IsReadOnly() || !IsShowEnabled() ? PAPER_READONLY : PAPER_NORMAL]);
	DrawTiles(w, DropCaret(), CtrlImg::checkers());
}
Esempio n. 18
0
Size GetTextSize(const WString& text, Font font)
{
	return GetTextSize(text, font, text.GetLength());
}
Esempio n. 19
0
void Draw::DrawText(int x, int y, const String& text, Font font, Color ink, const int *dx)
{
	WString h = TextUnicode(text, text.GetLength(), CHARSET_DEFAULT, font);
	DrawText(x, y, h, font, ink, h.GetLength(), dx);
}
Esempio n. 20
0
void Draw::DrawText(int x, int y, int angle, const WString& text, Font font,
                    Color ink, const int *dx)
{
	DrawText(x, y, angle, ~text, font, ink, text.GetLength(), dx);
}
Esempio n. 21
0
void AppendClipboardUnicodeText(const WString& s)
{
	AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength());
}
Esempio n. 22
0
void RichEdit::StdBar(Bar& menu)
{
	int l, h;
	Id field;
	String fieldparam;
	String ofieldparam;
	RichObject object;
	if(GetSelection(l, h)) {
		CopyTool(menu);
		CutTool(menu);
		PasteTool(menu);
	}
	else {
		if(objectpos >= 0) {
			bar_object = GetObject();
			if(!bar_object) return;
			bar_object.Menu(menu, context);
			if(!menu.IsEmpty())
				menu.Separator();
			Size sz = bar_object.GetPhysicalSize();
			bool b = sz.cx || sz.cy;
			menu.Add(t_("Object position.."), THISBACK(AdjustObjectSize));
			menu.Separator();
			menu.Add(b, "20 %", THISBACK1(SetObjectPercent, 20));
			menu.Add(b, "40 %", THISBACK1(SetObjectPercent, 40));
			menu.Add(b, "60 %", THISBACK1(SetObjectPercent, 60));
			menu.Add(b, "80 %", THISBACK1(SetObjectPercent, 80));
			menu.Add(b, "90 %", THISBACK1(SetObjectPercent, 90));
			menu.Add(b, "100 %", THISBACK1(SetObjectPercent, 100));
			menu.Break();
			menu.Add(t_("3 pt up"), THISBACK1(SetObjectYDelta, -3));
			menu.Add(t_("2 pt up"), THISBACK1(SetObjectYDelta, -2));
			menu.Add(t_("1 pt up"), THISBACK1(SetObjectYDelta, -1));
			menu.Add(t_("Baseline"), THISBACK1(SetObjectYDelta, 0));
			menu.Add(t_("1 pt down"), THISBACK1(SetObjectYDelta, 1));
			menu.Add(t_("2 pt down"), THISBACK1(SetObjectYDelta, 2));
			menu.Add(t_("3 pt down"), THISBACK1(SetObjectYDelta, 3));
			menu.Separator();
			CopyTool(menu);
			CutTool(menu);
		}
		else {
			RichPos p = cursorp;
			field = p.field;
			bar_fieldparam = p.fieldparam;
			RichPara::FieldType *ft = RichPara::fieldtype().Get(field, NULL);
			if(ft) {
				ft->Menu(menu, &bar_fieldparam);
				if(!menu.IsEmpty())
					menu.Separator();
				CopyTool(menu);
				CutTool(menu);
			}
			else {
				WString w = GetWordAtCursor();
				if(!w.IsEmpty() && !SpellWord(w, w.GetLength(),
				                              fixedlang ? fixedlang : formatinfo.language)) {
					menu.Add(t_("Add to user dictionary"), THISBACK(AddUserDict));
					menu.Separator();
				}
				PasteTool(menu);
				ObjectTool(menu);
			}
		}
		LoadImageTool(menu);
	}
}
Esempio n. 23
0
void PythonSyntax::Highlight(const wchar *start, const wchar *end, HighlightOutput& hls, CodeEditor *editor, int line, int pos)
{
	InitKeywords();
	
	bool isComment = false;
	bool isStr = false;
	char strOpening;
	
	const wchar* p = start;
	while(p < end) {
		if((*p == '#' || isComment) && !isStr) {
			isComment = true;
			hls.Put(hl_style[INK_COMMENT]);
		}
		else
		if(*p == '\'' || *p == '\"' || isStr) {
			hls.Put(hl_style[INK_CONST_STRING]);
			if((*p == '\'' || *p == '\"') && p - 1 != start && *(p - 1) != '\\')
				if (!isStr || strOpening == *p) {
					isStr = !isStr;
					strOpening = (char)*p;
				}
		}
		else
		if(IsSeparator(p) || p == start) {
			WString w;
			bool isW = false;
			const wchar* bp = (p == start && !IsSeparator(p)) ? p : p + 1;
			while (bp != end && !IsSeparator(bp))
				w += *bp++;
			
			bool isPutted = false;
			if(IsSeparator(p)) {
				hls.Put(hl_style[INK_NORMAL]);
				isPutted = true;
			}
			if(IsKeyword(w)) {
				hls.Put(w.GetLength(), hl_style[INK_KEYWORD]);
				isW = true;
			}
			else
			if(IsSpecialVar(w)) {
				hls.Put(w.GetLength(), hl_style[INK_UPP]);
				isW = true;
			}
			else
			if(IsNumber(w)) {
				hls.Put(w.GetLength(), hl_style[INK_CONST_INT]);
				isW = true;
			}
			
			if(isW) {
				p += w.GetLength() - (isPutted ? 0 : 1);
			}
		}
		else
			hls.Put(hl_style[INK_NORMAL]);
		
		p++;
	}
}
Esempio n. 24
0
void Ctrl::EventProc(XWindow& w, XEvent *event)
{
	GuiLock __; 
	eventid++;
	Ptr<Ctrl> _this = this;
	bool pressed = false;
	int  count = 1;
	switch(event->type) {
	case NoExpose:
		LLOG("NoExpose serial " << event->xnoexpose.serial);
		break;
	case GraphicsExpose:
		LLOG("GraphicsExpose serial " << event->xgraphicsexpose.serial);
	case Expose: {
			XExposeEvent& e = event->xexpose;
			w.exposed = true;
			LLOG("Expose " << RectC(e.x, e.y, e.width, e.height));
			Invalidate(w, RectC(e.x, e.y, e.width, e.height));
		}
		return;
	case ConfigureNotify: {
			XConfigureEvent& e = event->xconfigure;
			int x, y;
			Window dummy;
// 01/12/2007 - mdelfede
// added support for windowed controls
//			if(top)
//				XTranslateCoordinates(Xdisplay, top->window, Xroot, 0, 0, &x, &y, &dummy);
			if(top) {
				Window DestW = (parent ? GetParentWindow() : Xroot);
				XTranslateCoordinates(Xdisplay, top->window, DestW, 0, 0, &x, &y, &dummy);
				Rect rect = RectC(x, y, e.width, e.height);
				LLOG("CongigureNotify " << rect);
				if(GetRect() != rect)
					SetWndRect(rect);
				// Synchronizes native windows (NOT the main one)
			}
			SyncNativeWindows();
// 01/12/2007 - END

		}
		return;
	default:
		if(!IsEnabled()) return;
	}
	LTIMING("XUserInput");
	switch(event->type) {
	case FocusIn:
		if(w.xic)
			XSetICFocus(w.xic);
		break;
	case FocusOut:
		if(w.xic)
			XUnsetICFocus(w.xic);
		break;
	case KeyPress:
		pressed = true;
		LLOG("event type:" << event->type << " state:" << event->xkey.state <<
		     "keycode:" << event->xkey.keycode);
		for(;;) {
			XEvent ev1[1], ev2[1];
			bool hasev2 = false;
			if(!IsWaitingEvent()) break;
			do
				XNextEvent(Xdisplay, ev1);
			while(ev1->type == NoExpose && IsWaitingEvent());
			LLOG("ev1 type:" << ev1->type << " state:" << ev1->xkey.state <<
			     "keycode:" << ev1->xkey.keycode);
			if(ev1->type == KeyPress)
				*ev2 = *ev1;
			else {
				if(ev1->type != KeyRelease ||
				   ev1->xkey.state != event->xkey.state ||
				   ev1->xkey.keycode != event->xkey.keycode ||
				   !IsWaitingEvent()) {
				   	XPutBackEvent(Xdisplay, ev1);
				   	break;
				}
				do
					XNextEvent(Xdisplay, ev2);
				while(ev2->type == NoExpose && IsWaitingEvent());
				LLOG("ev2 type:" << ev2->type << " state:" << ev2->xkey.state <<
				     "keycode:" << ev2->xkey.keycode);
				hasev2 = true;
			}
			if(ev2->type != KeyPress ||
			   ev2->xkey.state != event->xkey.state ||
			   ev2->xkey.keycode != event->xkey.keycode) {
				if(hasev2)
					XPutBackEvent(Xdisplay, ev2);
				XPutBackEvent(Xdisplay, ev1);
				break;
			}
			else {
				XFilterEvent(ev1, None);
				if(hasev2)
					XFilterEvent(ev2, None);
			}
			count++;
		}
	case KeyRelease: {
			mousePos = Point(event->xkey.x_root, event->xkey.y_root);
			char buff[128];
			Xeventtime = event->xkey.time;
			LLOG("Key Xeventtime: " << Xeventtime << " count:" << count);
			KeySym keysym;
			int    chr = 0;
			WString wtext;
			if(pressed && w.xic) {
				Status status;
				int len = Xutf8LookupString(w.xic, &event->xkey, buff, sizeof(buff), &keysym, &status);
				buff[len] = 0;
				if(status == XLookupChars || status == XLookupBoth) {
					chr = FromUtf8(buff, len)[0];
					if(status == XLookupChars)
						wtext = FromUtf8(buff, len);
				}
				else
				if(status != XLookupKeySym && status != XLookupBoth)
				    keysym = 0;
			}
			else {
				int len = XLookupString(&event->xkey, buff, sizeof(buff), &keysym, NULL);
				buff[len] = 0;
				chr = FromUtf8(buff, len)[0];
				if(len > 1)
					wtext = FromUtf8(buff, len);
			}
			if(keysym == XK_Control_L || keysym == XK_Control_R) {
				keysym = XK_Control_L;
				if(pressed)
					sKbdState |= ControlMask;
				else
					sKbdState &= ~ControlMask;
			}
			if(keysym == XK_Shift_L || keysym == XK_Shift_R) {
				keysym = XK_Shift_L;
				if(pressed)
					sKbdState |= ShiftMask;
				else
					sKbdState &= ~ShiftMask;
			}
			if(keysym == XK_Meta_L || keysym == XK_Meta_R || keysym == XK_Alt_L ||
			   keysym == XK_Alt_R || keysym == XK_Super_L || keysym == XK_Super_R ||
			   keysym == XK_Hyper_L || keysym == XK_Hyper_R || keysym == XK_ISO_Prev_Group) {
				keysym = XK_Meta_L;
				if(pressed)
					sKbdState |= Mod1Mask;
				else
					sKbdState &= ~Mod1Mask;
			}
			LLOG("KeySym:" << FormatIntHex(keysym) << " " << (char)keysym << " " << count);
			dword up = pressed ? 0 : K_KEYUP;
			static struct { KeySym keysym; dword key; } tab[] = {
				{ XK_ISO_Left_Tab, K_TAB|K_SHIFT },
				{ XK_BackSpace, K_BACKSPACE },
				{ XK_Tab, K_TAB },
				{ XK_Return, K_ENTER },
				{ XK_KP_Enter, K_ENTER },
				{ XK_Escape, K_ESCAPE },
				{ XK_space, K_SPACE },

				{ XK_KP_Space, K_SPACE },
				{ XK_KP_Tab, K_TAB },
				{ XK_KP_Enter, K_ENTER },
				{ XK_KP_F1, K_F1 },
				{ XK_KP_F2, K_F2 },
				{ XK_KP_F3, K_F3 },
				{ XK_KP_F4, K_F4 },
				{ XK_KP_Home, K_HOME },
				{ XK_KP_Left, K_LEFT },
				{ XK_KP_Up, K_UP },
				{ XK_KP_Right, K_RIGHT },
				{ XK_KP_Down, K_DOWN },
				{ XK_KP_Page_Up, K_PAGEUP },
				{ XK_KP_Page_Down, K_PAGEDOWN },
				{ XK_KP_End, K_END },
				{ XK_KP_Begin, K_HOME },
				{ XK_KP_Insert, K_INSERT },
				{ XK_KP_Delete, K_DELETE },
			};
			for(int i = 0; i < __countof(tab); i++)
				if(tab[i].keysym == keysym) {
					DispatchKey(KEYtoK(tab[i].key)|up, count);
					return;
				}
			if(GetShift() && chr == 0) {
				static dword k[] = { 41, 33, 64, 35, 36, 37, 94, 38, 42, 40 };
				for(int i = 0; i < 10; i++)
					if(keysym == k[i]) {
						DispatchKey(KEYtoK(i + K_0)|up, count);
						return;
					}
			}
			if(keysym >= 48 && keysym <= 57 && chr == 0) {
				DispatchKey(KEYtoK(keysym - 48 + K_0)|up, count);
				return;
			}
			if(chr >= 1 && chr < 32) {
				DispatchKey(KEYtoK(chr - 1 + K_CTRL_A)|up, count);
				return;
			}
			if(keysym >= 0xff80 && keysym <= 0xffb9 && chr) {
				DispatchKey(KEYtoK(chr)|up, count);
				return;
			}
			if(keysym >= 0xff00 && chr < 128 ||
			   (GetCtrl() || GetAlt()) && keysym >= 0x20 && keysym < 0x7f) {
				if(keysym >= 'a' && keysym <= 'z')
					keysym = keysym - 'a' + 'A';
				DispatchKey(KEYtoK(keysym|K_DELTA)|up, count);
				return;
			}

			if((chr == 32 || chr == 9 || chr == 13) && !pressed)
				DispatchKey(chr|K_KEYUP, count);
			if(chr && pressed) {
				DispatchKey(chr, count);
				for(int ii = 1; ii < wtext.GetLength(); ii++)
					DispatchKey(wtext[ii], count);
			}
		}
		break;
	case ButtonPress: {
			if(!HasWndFocus() && !popup)
				SetWndFocus();
			ClickActivateWnd();
			mousePos = Point(event->xbutton.x_root, event->xbutton.y_root);
			ReleaseGrab();
			XButtonEvent& e = event->xbutton;
			sModState = e.state;
			Xeventtime = e.time;
			if(ignoreclick) break;
			Point p = Point(e.x, e.y);
			dword action = DOWN;
			if((dword)e.time - (dword)Xbuttontime < 800) {
				action = DOUBLE;
				Xbuttontime = Xeventtime - 0x80000000;
			}
			else {
				Xbuttontime = e.time;
				Xbuttonpos = mousePos;
			}
			switch(e.button) {
			case Button1:
				sModState |= Button1Mask;
				DispatchMouse(LEFT|action, p, 0);
				break;
			case Button2:
				sModState |= Button2Mask;
				if(Xbuttons < 3)
					DispatchMouse(RIGHT|action, p, 0);
				else
					DispatchMouse(MIDDLE|action, p, 0);
				break;
			case Button3:
				sModState |= Button3Mask;
				DispatchMouse(RIGHT|action, p, 0);
				break;
			}
			if(_this) PostInput();
		}
		break;
	case ButtonRelease: {
			mousePos = Point(event->xbutton.x_root, event->xbutton.y_root);
			XButtonEvent& e = event->xbutton;
			sModState = e.state;
			Xeventtime = e.time;
			Point p = Point(e.x, e.y);
			switch(e.button) {
			case Button1:
				sModState &= ~Button1Mask;
				break;
			case Button2:
				sModState &= ~Button2Mask;
				break;
			case Button3:
				sModState &= ~Button3Mask;
				break;
			}
			if(ignoreclick)
				EndIgnore();
			else
				switch(e.button) {
				case Button1:
					DispatchMouse(LEFTUP, p, 0);
					break;
				case Button2:
					if(Xbuttons < 3)
						DispatchMouse(RIGHTUP, p, 0);
					else
						DispatchMouse(MIDDLEUP, p, 0);
					break;
				case Button3:
					DispatchMouse(RIGHTUP, p, 0);
					break;
				case Button4:
					DispatchMouse(MOUSEWHEEL, p, 120);
					break;
				case Button5:
					DispatchMouse(MOUSEWHEEL, p, -120);
					break;
				}
			if(_this) PostInput();
		}
		break;
	case MotionNotify:
		while(XCheckWindowEvent(Xdisplay, top->window, PointerMotionMask, event));
		EndIgnore();
		mousePos = Point(event->xmotion.x_root, event->xmotion.y_root);
		Xeventtime = event->xmotion.time;
		Point p = mousePos - Xbuttonpos;
		if(max(abs(p.x), abs(p.y)) > 4)
			Xbuttontime = Xeventtime - 0x80000000;
		sModState = event->xmotion.state;
		DispatchMouse(MOUSEMOVE, Point(event->xmotion.x, event->xmotion.y));
		DoCursorShape();
		break;
	}
	DropEvent(w, event);
}
Esempio n. 25
0
void RichQtfParser::Parse(const char *qtf, int _accesskey)
{
	accesskey = _accesskey;
	term = qtf;
	while(*term) {
		if(Key('[')) {
			Flush();
			fstack.Add(format);
			for(;;) {
				int c = *term;
				if(!c)
					Error("Unexpected end of text");
				term++;
				if(c == ' ' || c == '\n') break;
				switch(c) {
				case 's': {
					Uuid id;
					c = *term;
					if(Key('\"') || Key('\''))
						id = target.GetStyleId(GetText(c));
					else {
						int i = ReadNumber();
						if(i >= 0 && i < styleid.GetCount())
							id = styleid[i];
						else
							id = RichStyle::GetDefaultId();
					}
					const RichStyle& s = target.GetStyle(id);
					bool p = format.newpage;
					int lng = format.language;
					(RichPara::Format&) format = s.format;
					format.styleid = id;
					format.language = lng;
					format.newpage = p;
					break;
				}
				case '/': format.Italic(!format.IsItalic()); break;
				case '*': format.Bold(!format.IsBold()); break;
				case '_': format.Underline(!format.IsUnderline()); break;
				case 'T': format.NonAntiAliased(!format.IsNonAntiAliased()); break;
				case '-': format.Strikeout(!format.IsStrikeout()); break;
				case 'c': format.capitals = !format.capitals; break;
				case 'd': format.dashed = !format.dashed; break;
				case '`': format.sscript = format.sscript == 1 ? 0 : 1; break;
				case ',': format.sscript = format.sscript == 2 ? 0 : 2; break;
				case '^': format.link = GetText('^'); break;
				case 'I': format.indexentry = FromUtf8(GetText(';')); break;
				case '+': format.Height(GetNumber()); break;
				case '@': format.ink = GetColor(); break;
				case '$': format.paper = GetColor(); break;
				case 'A': format.Face(Font::ARIAL); break;
				case 'R': format.Face(Font::ROMAN); break;
				case 'C': format.Face(Font::COURIER); break;
				case 'G': format.Face(Font::STDFONT); break;
				case 'S':
#ifdef PLATFORM_WIN32
					format.Face(Font::SYMBOL);
#endif
					break;
				case '.': {
					int n = GetNumber();
					if(n >= Font::GetFaceCount())
						Error("Invalid face number");
					format.Face(n); break;
				}
				case '!': {
						String fn = GetText('!');
						int i = Font::FindFaceNameIndex(fn);
						if(i < 0)
							i = Font::ARIAL;
						format.Face(i);
					}
					break;
				case '{': {
						String cs = GetText('}');
						if(cs.GetLength() == 1) {
							int c = *cs;
							if(c == '_')
								format.charset = CHARSET_UTF8;
							if(c >= '0' && c <= '8')
								format.charset = c - '0' + CHARSET_WIN1250;
							if(c >= 'A' && c <= 'Z')
								format.charset = c - '0' + CHARSET_ISO8859_1;
						}
						else {
							for(int i = 0; i < CharsetCount(); i++)
								if(stricmp(CharsetName(i), cs) == 0) {
									format.charset = i;
									break;
								}
						}
						break;
					}
				case '%': {
						String h;
						if(*term == '-') {
							format.language = 0;
							term++;
						}
						else
						if(*term == '%') {
							format.language = LNG_ENGLISH;
							term++;
						}
						else {
							while(*term && h.GetLength() < 5)
								h.Cat(*term++);
							format.language = LNGFromText(h);
						}
						break;
					}
				case 'g':
					format.Face(Font::STDFONT);
					format.Height(GetRichTextScreenStdFontHeight());
					break;
				default:
					if(c >= '0' && c <= '9') {
						format.Height(QTFFontHeight[c - '0']);
						break;
					}
					switch(c) {
					case ':': format.label = GetText(':'); break;
					case '<': format.align = ALIGN_LEFT; break;
					case '>': format.align = ALIGN_RIGHT; break;
					case '=': format.align = ALIGN_CENTER; break;
					case '#': format.align = ALIGN_JUSTIFY; break;
					case 'l': format.lm = GetNumber(); break;
					case 'r': format.rm = GetNumber(); break;
					case 'i': format.indent = GetNumber(); break;
					case 'b': format.before = GetNumber(); break;
					case 'a': format.after = GetNumber(); break;
					case 'P': format.newpage = !format.newpage; break;
					case 'k': format.keep = !format.keep; break;
					case 'K': format.keepnext = !format.keepnext; break;
					case 'H': format.ruler = GetNumber(); break;
					case 'h': format.rulerink = GetColor(); break;
					case 'L': format.rulerstyle = GetNumber(); break;
					case 'Q': format.orphan = !format.orphan; break;
					case 'n': format.before_number = GetText(';'); break;
					case 'm': format.after_number = GetText(';'); break;
					case 'N': {
						memset(format.number, 0, sizeof(format.number));
						format.reset_number = false;
						int i = 0;
						while(i < 8) {
							int c;
							if(Key('-'))
								c = RichPara::NUMBER_NONE;
							else
							if(Key('1'))
								c = RichPara::NUMBER_1;
							else
							if(Key('0'))
								c = RichPara::NUMBER_0;
							else
							if(Key('a'))
								c = RichPara::NUMBER_a;
							else
							if(Key('A'))
								c = RichPara::NUMBER_A;
							else
							if(Key('i'))
								c = RichPara::NUMBER_i;
							else
							if(Key('I'))
								c = RichPara::NUMBER_I;
							else
								break;
							format.number[i++] = c;
						}
						if(Key('!'))
							format.reset_number = true;
						break;
					}
					case 'o': format.bullet = RichPara::BULLET_ROUND;
					          format.indent = 150; break;
					case 'O':
						if(Key('_'))
							format.bullet = RichPara::BULLET_NONE;
						else {
							int c = *term++;
							if(!c)
								Error("Unexpected end of text");
							format.bullet =
							                c == '1' ? RichPara::BULLET_ROUNDWHITE :
							                c == '2' ? RichPara::BULLET_BOX :
							                c == '3' ? RichPara::BULLET_BOXWHITE :
							                c == '9' ? RichPara::BULLET_TEXT :
							                           RichPara::BULLET_ROUND;
						}
						break;
					case 'p':
						switch(*term++) {
						case 0:   Error("Unexpected end of text");
						case 'h': format.linespacing = RichPara::LSP15; break;
						case 'd': format.linespacing = RichPara::LSP20; break;
						default:  format.linespacing = RichPara::LSP10;
						}
						break;
					case 't':
						if(IsDigit(*term)) //temporary fix... :(
							format.tabsize = ReadNumber();
						break;
					case '~': {
							if(Key('~'))
								format.tab.Clear();
							else {
								RichPara::Tab tab;
								Key('<');
								if(Key('>'))
									tab.align = ALIGN_RIGHT;
								if(Key('='))
									tab.align = ALIGN_CENTER;
								if(Key('.'))
									tab.fillchar = 1;
								if(Key('-'))
									tab.fillchar = 2;
								if(Key('_'))
									tab.fillchar = 3;
								int rightpos = Key('>') ? RichPara::TAB_RIGHTPOS : 0;
								tab.pos = rightpos | ReadNumber();
								format.tab.Add(tab);
							}
						}
						break;
					default:
						continue;
					}
				}
			}
			SetFormat();
		}
		else
		if(Key(']')) {
			Flush();
			if(fstack.GetCount()) {
				format = fstack.Top();
				fstack.Drop();
			}
			else
				Error("Unmatched ']'");
		}
		else
		if(Key2('{')) {
			if(oldtab)
				Error("{{ in ++ table");
			if(text.GetLength() || paragraph.GetCount())
				EndPart();
			table.Add();
			int r = IsDigit(*term) ? ReadNumber() : 1;
			Table().AddColumn(r);
			while(Key(':'))
				Table().AddColumn(ReadNumber());
			TableFormat();
			SetFormat();
		}
		else
		if(Key2('}')) {
			if(oldtab)
				Error("}} in ++ table");
			FinishTable();
		}
		else
		if(Key2('+'))
			if(oldtab)
				FinishOldTable();
			else {
				Flush();
				if(text.GetLength() || paragraph.GetCount())
					EndPart();
				Tab& b = table.Add();
				b.rown.Add(0);
				b.hspan = 1;
				b.Old();
				oldtab = true;
			}
		else
		if(Key2('|'))
			FinishCell();
		else
		if(Key2('-')) {
			FinishCell();
			table.Top().rown.Add(0);
		}
		else
		if(Key2(':')) {
			if(!oldtab)
				FinishCell();
			TableFormat(oldtab);
		}
		else
		if(Key2('^')) {
			EndPart();
			breakpage = true;
		}
		else
		if(Key2('@')) {
			ReadObject();
		}
		else
		if(Key2('@', '$')) {
			String xu;
			while(isxdigit(*term))
				xu.Cat(*term++);
			int c = stou(~xu, NULL, 16);
			if(c >= 32)
				Cat(c);
			if(*term == ';')
				term++;
			SetFormat();
		}
		else
		if(Key2('^', 'H'))
			target.SetHeaderQtf(GetText2('^', '^'));
		else
		if(Key2('^', 'F'))
			target.SetFooterQtf(GetText2('^', '^'));
		else
		if(Key2('{', ':')) {
			Flush();
			String field = GetText(':');
			String param = GetText(':');
			Id fid(field);
			if(RichPara::fieldtype().Find(fid) >= 0)
				paragraph.Cat(fid, param, format);
			Key('}');
		}
		else
		if(Key('&')) {
			SetFormat();
			EndPart();
		}
		else
		if(Key2('$')) {
			Flush();
			int i = GetNumber();
			Uuid id;
			RichStyle style;
			style.format = format;
			if(Key(','))
				stylenext.At(i, 0) = GetNumber();
			else
				stylenext.At(i, 0) = i;
			if(Key('#')) {
				String xu;
				while(isxdigit(*term))
					xu.Cat(*term++);
				if(xu.GetLength() != 32)
					Error("Invalid UUID !");
				id = ScanUuid(xu);
			}
			else
				if(i)
					id = Uuid::Create();
				else
					id = RichStyle::GetDefaultId();
			if(Key(':'))
				style.name = GetText(']');
			if(fstack.GetCount()) {
				format = fstack.Top();
				fstack.Drop();
			}
			target.SetStyle(id, style);
			styleid.At(i, RichStyle::GetDefaultId()) = id;
			if(id == RichStyle::GetDefaultId()) {
				bool p = format.newpage;
				int lng = format.language;
				(RichPara::Format&) format = style.format;
				format.styleid = id;
				format.language = lng;
				format.newpage = p;
			}
		}
		else
		if(*term == '_') {
			SetFormat();
			text.Cat(160);
			term++;
		}
		else
		if(Key2('-', '|')) {
			SetFormat();
			text.Cat(9);
		}
		else
		if(*term == '\1') {
			if(istable)
				EndPart();
			SetFormat();
			const char *b = ++term;
			for(; *term && *term != '\1'; term++) {
				if((byte)*term == '\n') {
					text.Cat(ToUnicode(b, (int)(term - b), format.charset));
					EndPart();
					b = term + 1;
				}
				if((byte)*term == '\t') {
					text.Cat(ToUnicode(b, (int)(term - b), format.charset));
					text.Cat(9);
					b = term + 1;
				}
			}
			text.Cat(ToUnicode(b, (int)(term - b), format.charset));
			if(*term == '\1')
				term++;
		}
		else {
			if(!Key('`')) Key('\\');
			if((byte)*term >= ' ') {
				SetFormat();
				do {
					if(istable)
						EndPart();
					if(format.charset == CHARSET_UTF8) {
						word code = (byte)*term++;
						if(code <= 0x7F)
							Cat(code);
						else
						if(code <= 0xDF) {
							if(*term == '\0') break;
							int c0 = (byte)*term++;
							if(c0 < 0x80)
								Error("Invalid UTF-8 sequence");
							Cat(((code - 0xC0) << 6) + c0 - 0x80);
						}
						else
						if(code <= 0xEF) {
							int c0 = (byte)*term++;
							int c1 = (byte)*term++;
							if(c0 < 0x80 || c1 < 0x80)
								Error("Invalid UTF-8 sequence");
							Cat(((code - 0xE0) << 12) + ((c0 - 0x80) << 6) + c1 - 0x80);
						}
						else
							Error("Invalid UTF-8 sequence");
					}
					else
						Cat(ToUnicode((byte)*term++, format.charset));
				}
				while((byte)*term >= 128 || s_nodeqtf[(byte)*term]);
			}
			else
			if(*term)
				term++;
		}
	}
//	if(paragraph.GetCount() == 0) // TRC 11/02/15: kills formatting of last paragraph in text
//		SetFormat();
	if(oldtab)
		FinishOldTable();
	else
		while(table.GetCount())
			FinishTable();
	EndPart();
	FlushStyles();
}
Esempio n. 26
0
void   LineEdit::Paint0(Draw& w) {
	LTIMING("LineEdit::Paint0");
	int sell, selh;
	GetSelection(sell, selh);
	if(!IsEnabled())
		sell = selh = 0;
	Rect rect;
	bool rectsel = IsRectSelection();
	if(IsRectSelection())
		rect = GetRectSelection();
	Size sz = GetSize();
	Size fsz = GetFontSize();
	Point sc = sb;
	int ll = min(line.GetCount(), sz.cy / fsz.cy + sc.y + 1);
	int  y = 0;
	sc.y = minmax(sc.y, 0, line.GetCount() - 1);
	cpos = GetPos(sc.y);
	cline = sc.y;
	sell -= cpos;
	selh -= cpos;
	int pos = cpos;
	int fascent = font.Info().GetAscent();
	int cursorline = GetLine(cursor);
	Highlight ih;
	ih.ink = color[IsShowEnabled() ? INK_NORMAL : INK_DISABLED];
	ih.paper = color[IsReadOnly() && showreadonly || !IsShowEnabled() ? PAPER_READONLY : PAPER_NORMAL];
	if(nobg)
		ih.paper = Null;
	ih.font = font;
	ih.chr = 0;
	for(int i = sc.y; i < ll; i++) {
		Color showcolor = color[WHITESPACE];
		WString tx = line[i];
		bool warn_whitespace = false;
		if(warnwhitespace && !IsSelection()) {
			int pos = GetCursor();
			int linei = GetLinePos(pos);
			if(linei != i || pos < tx.GetCount()) {
				int wkind = 0;
				bool empty = true;
				for(const wchar *s = tx; *s; s++) {
					if(*s == '\t') {
						if(wkind == ' ') {
							warn_whitespace = true;
							break;
						}
						wkind = '\t';
					}
					else
					if(*s == ' ')
						wkind = ' ';
					else
					if(*s > ' ') {
						empty = false;
						wkind = 0;
					}
				}
				if(wkind && !empty)
					warn_whitespace = true;
				if(warn_whitespace)
					showcolor = color[WARN_WHITESPACE];
			}
		}
		bool do_highlight = tx.GetCount() < 100000;
		int len = tx.GetLength();
		if(w.IsPainting(0, y, sz.cx, fsz.cy)) {
			LTIMING("PaintLine");
			Vector<Highlight> hl;
			int ln;
			if(do_highlight) {
				hl.SetCount(len + 1, ih);
				for(int q = 0; q < tx.GetCount(); q++)
					hl[q].chr = tx[q];
				LTIMING("HighlightLine");
				HighlightLine(i, hl, pos);
				ln = hl.GetCount() - 1;
			}
			else
				ln = tx.GetCount();
			int lgp = -1;
			for(int pass = 0; pass < 2; pass++) {
				int gp = 0;
				int scx = fsz.cx * sc.x;
				sOptimizedRectRenderer rw(w);
				if(ln >= 0) {
					int q = 0;
					int x = 0;
					int scx2 = scx - max(2, tabsize) * fsz.cx;
					while(q < ln && x < scx2) { // Skip part before left border
						wchar chr = do_highlight ? hl[q++].chr : tx[q++];
						if(chr == '\t') {
							gp = (gp + tabsize) / tabsize * tabsize;
							x = fsz.cx * gp;
						}
						else
						if(IsCJKIdeograph(chr)) {
							x += 2 * fsz.cx;
							gp += 2;
						}
						else {
							x += fsz.cx;
							gp++;
						}
					}
					sOptimizedTextRenderer tw(w);
					while(q < ln) {
						if(q == tx.GetCount())
							lgp = gp;
						Highlight h;
						if(do_highlight)
							h = hl[q];
						else {
							h = ih;
							h.chr = tx[q];
						}
						int pos = min(q, len); // Highligting can add chars at the end of line
						if(rectsel ? i >= rect.top && i <= rect.bottom && gp >= rect.left && gp < rect.right
						           : pos >= sell && pos < selh) {
							h.paper = color[PAPER_SELECTED];
							h.ink = color[INK_SELECTED];
						}
						int x = gp * fsz.cx - scx;
						if(h.chr == '\t') {
							int ngp = (gp + tabsize) / tabsize * tabsize;
							int l = ngp - gp;
							LLOG("Highlight -> tab[" << q << "] paper = " << h.paper);
							if(pass == 0 && x >= -fsz.cy * tabsize) {
								rw.DrawRect(x, y, fsz.cx * l, fsz.cy, h.paper);
								if((showtabs || warn_whitespace) &&
								   h.paper != SColorHighlight && q < tx.GetLength()) {
									rw.DrawRect(x + 2, y + fsz.cy / 2, l * fsz.cx - 4, 1, showcolor);
									rw.DrawRect(ngp * fsz.cx - scx - 3, y + 3, 1, fsz.cy - 6, showcolor);
								}
								if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + l)
									rw.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
							}
							q++;
							gp = ngp;
						}
						else
						if(h.chr == ' ') {
							LLOG("Highlight -> space[" << q << "] paper = " << h.paper);
							if(pass == 0 && x >= -fsz.cy) {
								rw.DrawRect(x, y, fsz.cx, fsz.cy, h.paper);
								if((showspaces || warn_whitespace)
								   && h.paper != SColorHighlight && q < tx.GetLength()) {
									int n = fsz.cy / 10 + 1;
									rw.DrawRect(x + fsz.cx / 2, y + fsz.cy / 2, n, n, showcolor);
								}
								if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + 1)
									rw.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
							}
							q++;
							gp++;
						}
						else {
							bool cjk = IsCJKIdeograph(h.chr);
							LLOG("Highlight -> paper[" << q << "] = " << h.paper);
							int xx = x + (gp + 1 + cjk) * fsz.cx;
							if(max(x, 0) < min(xx, sz.cx) && fsz.cx >= -fsz.cy) {
								if(pass == 0) {
									rw.DrawRect(x, y, (cjk + 1) * fsz.cx, fsz.cy, h.paper);
									if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + 1 + cjk)
										rw.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
								}
								else
									tw.DrawChar(x + (h.flags & SHIFT_L ? -fsz.cx / 6 : h.flags & SHIFT_R ? fsz.cx / 6 : 0),
									            y + fascent - h.font.GetAscent(),
									            h.chr, (cjk + 1) * fsz.cx, h.font, h.ink);
							}
							q++;
							gp += 1 + cjk;
							if(x > sz.cx)
								break;
						}
					}
				}
				if(pass == 0) {
					int gpx = gp * fsz.cx - scx;
					rw.DrawRect(gpx, y, sz.cx - gpx, fsz.cy,
					            !rectsel && sell <= len && len < selh ? color[PAPER_SELECTED]
					            : (do_highlight ? hl.Top() : ih).paper);
					if(bordercolumn > 0 && bordercolumn >= gp)
						rw.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
				}
				if(pass == 0 && (showlines || warn_whitespace)) {
					int yy = 2 * fsz.cy / 3;
					int x = (lgp >= 0 ? lgp : gp) * fsz.cx - scx;
					rw.DrawRect(x, y + yy, fsz.cx / 2, 1, showcolor);
					if(fsz.cx > 2)
						rw.DrawRect(x + 1, y + yy - 1, 1, 3, showcolor);
					if(fsz.cx > 5)
						rw.DrawRect(x + 2, y + yy - 2, 1, 5, showcolor);
					rw.DrawRect(x + fsz.cx / 2, y + yy / 2, 1, yy - yy / 2, showcolor);
				}
				if(pass == 0 && !IsNull(hline) && sell == selh && i == cursorline) {
					rw.DrawRect(0, y, sz.cx, 1, hline);
					rw.DrawRect(0, y + fsz.cy - 1, sz.cx, 1, hline);
				}
				if(pass == 0 && rectsel && rect.left == rect.right && i >= rect.top && i <= rect.bottom)
					rw.DrawRect(rect.left * fsz.cx - scx, y, 2, fsz.cy, Blend(color[PAPER_SELECTED], color[PAPER_NORMAL]));
			}
		}
		y += fsz.cy;
		sell -= len + 1;
		selh -= len + 1;
		pos += len + 1;
	}
	
	w.DrawRect(0, y, sz.cx, sz.cy - y, color[IsReadOnly() && showreadonly || !IsShowEnabled() ? PAPER_READONLY : PAPER_NORMAL]);
	DrawTiles(w, DropCaret(), CtrlImg::checkers());
}