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; } } }
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; }
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(); }
void RichQtfParser::Flush() { if(text.GetLength()) { ASSERT(!istable); paragraph.Cat(text, format); text.Clear(); } }
void AppendClipboardUnicodeText(const WString& s) { #ifndef PLATFORM_WINCE AppendClipboardText(s.ToString()); #endif AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); }
static void sMergeWith(WString& dest, const wchar *delim, const WString& s) { if(s.GetLength()) { if(dest.GetCount()) dest.Cat(delim); dest.Cat(s); } }
bool PythonSyntax::LineHasColon(const WString& line) { for(int i = line.GetLength() - 1; i >= 0; i--) { if(line[i] == ':') return true; } return false; }
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(); }
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; }
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; }
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; }
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; }
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; }
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); } }
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; }
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;; }
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()); }
Size GetTextSize(const WString& text, Font font) { return GetTextSize(text, font, text.GetLength()); }
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); }
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); }
void AppendClipboardUnicodeText(const WString& s) { AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); }
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); } }
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++; } }
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); }
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(); }
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()); }