.developing Turtle

git-svn-id: svn://ultimatepp.org/upp/trunk@6812 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-01-26 21:32:54 +00:00
parent 184ec3274a
commit c364742944
15 changed files with 596 additions and 320 deletions

View file

@ -2,11 +2,9 @@
private: private:
static Ptr<Ctrl> desktop; static Ptr<Ctrl> desktop;
static Vector<Ctrl *> topctrl; static Vector<Ctrl *> topctrl;
static bool invalid;
static Point fbCursorPos; static Point fbCursorPos;
static Image fbCursorImage; static Image fbCursorImage;
static bool sdlMouseIsIn;
static Rect fbCaretRect; static Rect fbCaretRect;
static int fbCaretTm; static int fbCaretTm;
@ -14,8 +12,29 @@ private:
static bool fbEndSession; static bool fbEndSession;
static int64 fbEventLoop; static int64 fbEventLoop;
static int64 fbEndSessionLoop; static int64 fbEndSessionLoop;
static Ctrl& Desktop();
static void TimerAndPaint();
static bool ProcessEvent(const String& event);
static bool quit;
static int main_pid;
static Vector<int> pid;
static TcpSocket socket;
static WebSocket websocket;
static int64 update_serial;
static int64 recieved_update_serial;
static void CursorSync(); static Vector<Rect> invalid;
static BiVector<String> event_queue;
static Size DesktopSize;
static void AddInvalid(const Rect& r);
void AddInvalid() { AddInvalid(GetScreenRect()); }
static void InvalidateDesktop();
int FindTopCtrl() const; int FindTopCtrl() const;
static Rect GetClipBound(const Vector<Rect>& inv, const Rect& r); static Rect GetClipBound(const Vector<Rect>& inv, const Rect& r);
@ -49,21 +68,17 @@ private:
void SetOpen(bool b) { isopen = b; } void SetOpen(bool b) { isopen = b; }
protected:
static Ctrl& Desktop();
static void TimerAndPaint();
static bool ProcessEvent(const String& event);
static bool quit;
static int main_pid;
static Vector<int> pid;
static TcpSocket socket;
static WebSocket websocket;
static void Signal(int signal); static void Signal(int signal);
static void Broadcast(int signal); static void Broadcast(int signal);
static void Put8(int x) { turtle_stream.Put(x); }
static void Put16(int x);
static void Put32(int x);
static void Put(Point p);
static void Put(Size sz);
static void Put(const Rect& r);
static void Put(const String& s);
public: public:
static bool DoKeyFB(dword key, int cnt); static bool DoKeyFB(dword key, int cnt);
@ -71,6 +86,9 @@ public:
static int port; static int port;
static bool debugmode; static bool debugmode;
static String ip; static String ip;
static Time stat_started;
static int64 stat_data_send;
static bool StartSession(); static bool StartSession();
static Callback WhenDisconnect; static Callback WhenDisconnect;
@ -80,21 +98,12 @@ public:
static Ctrl *GetDesktop() { return desktop; } static Ctrl *GetDesktop() { return desktop; }
static void SetDesktopSize(Size sz); static void SetDesktopSize(Size sz);
static void Invalidate() { invalid = true; }
void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n, void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation); Color color, int type, int animation);
static Ctrl *FindMouseTopCtrl(); static Ctrl *FindMouseTopCtrl();
static void PaintScene(SystemDraw& draw); static void PaintScene(SystemDraw& draw);
static void PaintCaretCursor(SystemDraw& draw);
static bool SystemCursor;
enum { DRAWDRAGRECT_SCREEN = 0x8000 }; enum { DRAWDRAGRECT_SCREEN = 0x8000 };
_TODO_
static bool ProcessEventQueue(const String& event_queue);
//$ }; //$ };

View file

@ -2,43 +2,10 @@
#ifdef GUI_TURTLE #ifdef GUI_TURTLE
#define LLOG(x) // LOG(x)
NAMESPACE_UPP NAMESPACE_UPP
void SystemDraw::Put16(int x)
{
Put8(LOBYTE(x));
Put8(HIBYTE(x));
}
void SystemDraw::Put32(int x)
{
Put16(LOWORD(x));
Put16(HIWORD(x));
}
void SystemDraw::Put(Point p)
{// TODO: Clamp?
Put16(p.x);
Put16(p.y);
}
void SystemDraw::Put(Size sz)
{
Put((Point)sz);
}
void SystemDraw::Put(const Rect& r)
{
Put(r.TopLeft());
Put(r.GetSize());
}
void SystemDraw::Put(const String& s)
{
Put32(s.GetLength());
turtle_stream.Put(s);
}
Index<int64> SystemDraw::img_index[3]; Index<int64> SystemDraw::img_index[3];
int SystemDraw::GetImageI(int from, Index<int64>& img_index, int maxcount, const Image& img) int SystemDraw::GetImageI(int from, Index<int64>& img_index, int maxcount, const Image& img)
@ -54,15 +21,16 @@ int SystemDraw::GetImageI(int from, Index<int64>& img_index, int maxcount, const
q = Random(maxcount); q = Random(maxcount);
img_index.Set(q, id); img_index.Set(q, id);
} }
Put8(SETIMAGE); LLOG("SetImage " << q + from << ", size: " << img.GetLength());
Put16(q + from); Ctrl::Put8(SETIMAGE);
Put(img.GetSize()); Ctrl::Put16(q + from);
Ctrl::Put(img.GetSize());
const RGBA *end = ~img + img.GetLength(); const RGBA *end = ~img + img.GetLength();
for(const RGBA *s = ~img; s < end; s++) { for(const RGBA *s = ~img; s < end; s++) {
Put8(s->r); Ctrl::Put8(s->r);
Put8(s->g); Ctrl::Put8(s->g);
Put8(s->b); Ctrl::Put8(s->b);
Put8(s->a); Ctrl::Put8(s->a);
} }
} }
return q + from; return q + from;
@ -78,28 +46,55 @@ int SystemDraw::GetImageI(const Image& img)
void SystemDraw::PutImage(Point p, const Image& img, const Rect& src) void SystemDraw::PutImage(Point p, const Image& img, const Rect& src)
{ {
LLOG("Ctrl::PutImage " << p << ", size: " << img.GetSize() << ", src: " << src << ", id: " << img.GetSerialId());
int i = GetImageI(img); int i = GetImageI(img);
Put8(IMAGE); if(Rect(img.GetSize()) == src) {
Put16(i); Point dp = p - pos;
Put(p); if(abs(dp.x) < 256 && abs(dp.y) < 256) {
Put(src); Ctrl::Put8(dp.x < 0 ? dp.y < 0 ? IMAGENN : IMAGENP : dp.y < 0 ? IMAGEPN : IMAGEPP);
Ctrl::Put8(abs(dp.x));
Ctrl::Put8(abs(dp.y));
Ctrl::Put16(i);
pos = p;
return;
}
}
Ctrl::Put8(IMAGE);
Ctrl::Put16(i);
Ctrl::Put(p);
Ctrl::Put(src);
pos = p;
} }
void SystemDraw::PutRect(const Rect& r, Color color) void SystemDraw::PutRect(const Rect& r, Color color)
{ // TODO: Support InvertColor {
LLOG("Ctrl::PutRect " << r << ", color " << color);
Point p = r.TopLeft();
if(color == InvertColor()) { if(color == InvertColor()) {
Put8(INVERTRECT); Ctrl::Put8(INVERTRECT);
Put(r); Ctrl::Put(r);
} }
else { else {
Put8(RECT); Size sz = r.GetSize();
Put(r); Point dp = p - pos;
Put8(color.GetR()); if(abs(dp.x) < 256 && abs(dp.y) < 256 && sz.cx < 256 && sz.cy < 256 && 0) {
Put8(color.GetG()); Ctrl::Put8(dp.x < 0 ? dp.y < 0 ? RECTNN : RECTNP : dp.y < 0 ? RECTPN : RECTPP);
Put8(color.GetB()); Ctrl::Put8(abs(dp.x));
Ctrl::Put8(abs(dp.y));
Ctrl::Put8(sz.cx);
Ctrl::Put8(sz.cy);
}
else {
Ctrl::Put8(RECT);
Ctrl::Put(r);
}
Ctrl::Put8(color.GetR());
Ctrl::Put8(color.GetG());
Ctrl::Put8(color.GetB());
} }
pos = p;
} }
END_UPP_NAMESPACE END_UPP_NAMESPACE
#endif #endif

View file

@ -63,7 +63,7 @@ void DrawDragRect(Ctrl& q, const DrawDragRectInfo& f)
DrawDragFrame(w, f.rect1, f.n, dash, f.animation); DrawDragFrame(w, f.rect1, f.n, dash, f.animation);
DrawDragFrame(w, f.rect2, f.n, dash, f.animation); DrawDragFrame(w, f.rect2, f.n, dash, f.animation);
// w.End(); // w.End();
Ctrl::PaintCaretCursor(w); // Ctrl::PaintCaretCursor(w);
// SDL_GL_SwapWindow(screen.win); // SDL_GL_SwapWindow(screen.win);
} }
@ -88,7 +88,7 @@ void FinishDragRect(Ctrl& q)
{ {
SystemDraw w; SystemDraw w;
Ctrl::PaintScene(w); Ctrl::PaintScene(w);
Ctrl::PaintCaretCursor(w); // Ctrl::PaintCaretCursor(w);
_TODO_ _TODO_
//SDL_GL_SwapWindow(screen.win); //SDL_GL_SwapWindow(screen.win);
} }

View file

@ -8,9 +8,12 @@ NAMESPACE_UPP
#define LDUMP(x) // RDUMP(x) #define LDUMP(x) // RDUMP(x)
#define LTIMING(x) #define LTIMING(x)
Time Ctrl::stat_started;
int64 Ctrl::stat_data_send;
static Point MousePos; static Point MousePos;
Size DesktopSize = Size(1000, 1000); Size Ctrl::DesktopSize = Size(1000, 1000);
StaticRect& DesktopRect() StaticRect& DesktopRect()
{ {
@ -23,24 +26,7 @@ Ctrl& Ctrl::Desktop()
return DesktopRect(); return DesktopRect();
} }
BiVector<String> event_queue; BiVector<String> Ctrl::event_queue;
void Ctrl::TimerAndPaint()
{
LLOG("TimerAndPaint " << msecs());
TimerProc(GetTickCount());
DefferedFocusSync();
SyncCaret();
SyncTopWindows();
SweepMkImageCache();
DoPaint();
socket.Timeout(20000);
websocket.SendBinary(ZCompress(String(SystemDraw::DISABLESENDING, 1))); // Do not send events until data transfered and processed
String s = turtle_stream.FlushStream();
if(s.GetCount() > 10)
LLOG("Sending " << s.GetLength());
websocket.SendBinary(s);
}
void Ctrl::EndSession() void Ctrl::EndSession()
{ {
@ -66,8 +52,20 @@ bool Ctrl::IsWaitingEvent()
} }
LLOG("Recieved data " << s); LLOG("Recieved data " << s);
StringStream ss(s); StringStream ss(s);
while(!ss.IsEof()) while(!ss.IsEof()) {
event_queue.AddTail(ss.GetLine()); String s = ss.GetLine();
CParser p(s);
try {
if(p.Id("S")) {
uint32 l = p.ReadNumber();
uint32 h = p.ReadNumber();
recieved_update_serial = MAKEQWORD(l, h);
}
else
event_queue.AddTail(s);
}
catch(CParser::Error) {}
}
} }
socket.Timeout(20000); socket.Timeout(20000);
if(socket.IsError()) if(socket.IsError())
@ -148,86 +146,6 @@ void Ctrl::SetCaret(int x, int y, int cx, int cy)
SyncCaret(); SyncCaret();
} }
void Ctrl::SyncCaret()
{
CursorSync();
}
void Ctrl::CursorSync()
{
// LLOG("@ CursorSync");
Point p = GetMousePos() - fbCursorImage.GetHotSpot();
Rect cr = Null;
if(focusCtrl && (((GetTickCount() - fbCaretTm) / 500) & 1) == 0)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
if(fbCursorPos != p && !SystemCursor || cr != fbCaretRect) {
fbCaretRect = cr;
fbCursorPos = p;
Invalidate();
}
}
void Ctrl::PaintScene(SystemDraw& draw)
{
if(!desktop)
return;
LLOG("@ DoPaint");
LTIMING("DoPaint paint");
draw.Init(DesktopSize);
draw.Begin();
Vector<Rect> invalid;
invalid.Add(DesktopSize); _TODO_
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Rect r = topctrl[i]->GetRect();
Rect ri = GetClipBound(invalid, r);
if(!IsNull(ri)) {
draw.Clipoff(r);
topctrl[i]->UpdateArea(draw, ri - r.TopLeft());
draw.End();
Subtract(invalid, r);
draw.ExcludeClip(r);
}
}
Rect ri = GetClipBound(invalid, desktop->GetRect().GetSize());
if(!IsNull(ri))
desktop->UpdateArea(draw, ri);
draw.End();
}
void Ctrl::PaintCaretCursor(SystemDraw& draw)
{
if(!IsNull(fbCaretRect))
draw.DrawRect(fbCaretRect, InvertColor);
int64 q = fbCursorImage.GetAuxData();
if(q) {
draw.Put8(SystemDraw::STD_CURSORIMAGE);
draw.Put8(clamp((int)q, 1, 16));
}
else {
String h;
Point p = fbCursorImage.GetHotSpot();
h << "url('data:image/png;base64,"
<< Base64Encode(PNGEncoder().SaveString(fbCursorImage))
<< "') " << p.x << ' ' << p.y << ", default";
draw.Put8(SystemDraw::SETCURSORIMAGE);
draw.Put16(0); // _TODO_ Cursor cache
draw.Put(h);
draw.Put8(SystemDraw::CURSORIMAGE);
draw.Put16(0); // _TODO_ Cursor cache
}
}
void Ctrl::DoPaint()
{
if(invalid && desktop) {
invalid = false;
SystemDraw draw;
PaintScene(draw);
PaintCaretCursor(draw);
}
}
bool keyShift; bool keyShift;
bool keyCtrl; bool keyCtrl;
bool keyAlt; bool keyAlt;
@ -238,7 +156,8 @@ bool GetAlt() { return keyAlt; }
bool GetCapsLock() { return false; } // Impossible to implement bool GetCapsLock() { return false; } // Impossible to implement
dword fbKEYtoK(dword chr) { dword fbKEYtoK(dword chr) {
chr = chr + K_DELTA; if(findarg(chr, 9, 0xd) < 0)
chr = chr + K_DELTA;
if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY) if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY)
return chr; return chr;
if(GetCtrl()) chr |= K_CTRL; if(GetCtrl()) chr |= K_CTRL;
@ -409,7 +328,7 @@ bool Ctrl::ProcessEvent(const String& event)
int code = p.ReadInt(); int code = p.ReadInt();
int which = p.ReadInt(); int which = p.ReadInt();
ReadKeyMods(p); ReadKeyMods(p);
if(which && !keyAlt && !keyCtrl) if(which && !keyAlt && !keyCtrl && findarg(which, 9, 0xd) < 0)
DoKeyFB(which, 1); DoKeyFB(which, 1);
} }
} }

146
rainbow/Turtle/Output.cpp Normal file
View file

@ -0,0 +1,146 @@
#include "Local.h"
#ifdef GUI_TURTLE
NAMESPACE_UPP
#define LLOG(x) // LLOG(x)
#define LDUMP(x) // RDUMP(x)
#define LTIMING(x)
void Ctrl::Put16(int x)
{
Put8(LOBYTE(x));
Put8(HIBYTE(x));
}
void Ctrl::Put32(int x)
{
Put16(LOWORD(x));
Put16(HIWORD(x));
}
void Ctrl::Put(Point p)
{// TODO: Clamp?
Put16(p.x);
Put16(p.y);
}
void Ctrl::Put(Size sz)
{
Put((Point)sz);
}
void Ctrl::Put(const Rect& r)
{
Put(r.TopLeft());
Put(r.GetSize());
}
void Ctrl::Put(const String& s)
{
Put32(s.GetLength());
turtle_stream.Put(s);
}
void Ctrl::TimerAndPaint()
{
LLOG("TimerAndPaint " << msecs());
TimerProc(GetTickCount());
DefferedFocusSync();
SyncCaret();
SyncTopWindows();
SweepMkImageCache();
DoPaint();
socket.Timeout(20000);
if(turtle_stream.HasData()) {
websocket.SendBinary(ZCompress(String(SystemDraw::DISABLESENDING, 1))); // Do not send events until data transfered and processed
int64 x = ++update_serial;
Put8(SystemDraw::UPDATESERIAL);
Put32(LODWORD(x));
Put32(HIDWORD(x));
String s = turtle_stream.FlushStream();
stat_data_send += s.GetCount();
LLOG("Sending " << s.GetLength());
websocket.SendBinary(s);
}
}
void Ctrl::SyncCaret()
{
Rect cr = Null;
if(focusCtrl)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
if(cr != fbCaretRect) { // TODO: SetCaret should perhaps be called on Ctrl::SetCaret
Put8(SystemDraw::SETCARET);
Put(cr);
fbCaretRect = cr;
}
}
void Ctrl::PaintScene(SystemDraw& draw)
{
if(!desktop)
return;
LLOG("@ DoPaint");
LTIMING("DoPaint paint");
draw.Init(invalid, DesktopSize.cy);
// draw.Init(DesktopSize);
draw.Begin();
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Rect r = topctrl[i]->GetRect();
Rect ri = GetClipBound(invalid, r);
LLOG(i << " Window " << r << ", bound " << ri);
if(!IsNull(ri)) {
draw.Clipoff(r);
topctrl[i]->UpdateArea(draw, ri - r.TopLeft());
draw.End();
draw.ExcludeClip(r);
Subtract(invalid, r);
}
}
Rect ri = GetClipBound(invalid, DesktopSize);
if(!IsNull(ri))
desktop->UpdateArea(draw, ri);
invalid.Clear();
draw.End();
// DDUMP(turtle_stream.FlushStream().GetCount()); abort();
}
void Ctrl::DoPaint()
{
if(recieved_update_serial >= update_serial - 1) { // Prevent overloading of transfer
if(invalid.GetCount() && desktop) {
SystemDraw draw;
PaintScene(draw);
}
static int64 prev_cursor_id = Null;
int64 id = fbCursorImage.GetSerialId();
if(id != prev_cursor_id) {
prev_cursor_id = id;
int64 q = fbCursorImage.GetAuxData();
if(q) {
Put8(SystemDraw::STD_CURSORIMAGE);
Put8(clamp((int)q, 1, 16));
}
else {
String h;
Point p = fbCursorImage.GetHotSpot();
h << "url('data:image/png;base64,"
<< Base64Encode(PNGEncoder().SaveString(fbCursorImage))
<< "') " << p.x << ' ' << p.y << ", default";
Put8(SystemDraw::SETCURSORIMAGE);
Put16(0); // _TODO_ Cursor cache
Put(h);
Put8(SystemDraw::CURSORIMAGE);
Put16(0); // _TODO_ Cursor cache
}
}
}
}
END_UPP_NAMESPACE
#endif

View file

@ -25,35 +25,6 @@ void Ctrl::Broadcast(int signal) {
kill(pid[i], signal); kill(pid[i], signal);
#endif #endif
} }
void Ctrl::Signal(int signal)
{
#ifdef PLATFORM_POSIX
int i = 0;
while(i < pid.GetCount())
if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0)
pid.Remove(i);
else
i++;
switch(signal) {
case SIGTERM:
case SIGHUP:
quit = true;
Broadcast(signal);
break;
case SIGINT:
Broadcast(signal);
exit(0);
break;
case SIGALRM:
if(getpid() != main_pid) {
// "Timeout - session stoped"
exit(0);
}
break;
}
#endif
}
String Ctrl::host = "localhost"; String Ctrl::host = "localhost";
int Ctrl::port = 8088; int Ctrl::port = 8088;
@ -61,21 +32,14 @@ bool Ctrl::debugmode;
String Ctrl::ip = "0.0.0.0"; String Ctrl::ip = "0.0.0.0";
TcpSocket Ctrl::socket; TcpSocket Ctrl::socket;
WebSocket Ctrl::websocket; WebSocket Ctrl::websocket;
int64 Ctrl::update_serial;
int64 Ctrl::recieved_update_serial;
bool Ctrl::StartSession() bool Ctrl::StartSession()
{ {
LLOG("Connect"); LLOG("Connect");
#ifdef PLATFORM_POSIX #ifdef PLATFORM_POSIX
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = Signal;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGALRM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
main_pid = getpid(); main_pid = getpid();
#endif #endif
@ -99,11 +63,19 @@ bool Ctrl::StartSession()
} }
#endif #endif
RLOG("Starting to listen on 8088"); RLOG("Starting to listen on 8088, pid: " << getpid());
socket.Timeout(2000); // TODO: Not quite ideal way to make quit work.. socket.Timeout(2000); // TODO: Not quite ideal way to make quit work..
for(;;) { for(;;) {
if(quit) if(quit)
return false; return false;
#ifdef PLATFORM_POSIX
int i = 0;
while(i < pid.GetCount())
if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0)
pid.Remove(i);
else
i++;
#endif
if(server.IsError()) if(server.IsError())
server.ClearError(); server.ClearError();
if(socket.Accept(server)) { if(socket.Accept(server)) {
@ -112,8 +84,10 @@ bool Ctrl::StartSession()
RLOG("Accepted, header read"); RLOG("Accepted, header read");
if(websocket.WebAccept(socket, http)) { // TODO: Connection limit, info if(websocket.WebAccept(socket, http)) { // TODO: Connection limit, info
#ifdef PLATFORM_POSIX #ifdef PLATFORM_POSIX
if(debugmode)
break;
int newpid = fork(); int newpid = fork();
if(debugmode || newpid == 0) if(newpid == 0)
break; break;
else { else {
pid.Add(newpid); pid.Add(newpid);
@ -132,7 +106,7 @@ bool Ctrl::StartSession()
socket.Close(); socket.Close();
} }
} }
RLOG("Connection established with " << socket.GetPeerAddr()); RLOG("Connection established with " << socket.GetPeerAddr() << ", pid: " << getpid());
server.Close(); server.Close();
if(socket.IsError()) if(socket.IsError())
RLOG("CONNECT ERROR: " << socket.GetErrorDesc()); RLOG("CONNECT ERROR: " << socket.GetErrorDesc());
@ -145,12 +119,18 @@ bool Ctrl::StartSession()
#endif #endif
ChStdSkin(); ChStdSkin();
extern Size DesktopSize;
extern StaticRect& DesktopRect(); extern StaticRect& DesktopRect();
DesktopRect().Color(Cyan()); DesktopRect().Color(Cyan());
DesktopRect().SetRect(0, 0, DesktopSize.cx, DesktopSize.cy); DesktopRect().SetRect(0, 0, DesktopSize.cx, DesktopSize.cy);
SetDesktop(Desktop()); SetDesktop(Desktop());
stat_started = GetSysTime();
while(!IsWaitingEvent())
GuiSleep(10);
ProcessEvents();
return true; return true;
} }

View file

@ -14,11 +14,13 @@ void TurtleStream::Reset()
{ {
zlib.Clear(); zlib.Clear();
zlib.Compress(); zlib.Compress();
hasdata = false;
} }
void TurtleStream::Out(const void *data, dword size) void TurtleStream::Out(const void *data, dword size)
{ {
zlib.Put(data, (int)size); zlib.Put(data, (int)size);
hasdata = true;
} }
String TurtleStream::FlushStream() String TurtleStream::FlushStream()

View file

@ -20,11 +20,13 @@ public:
private: private:
Zlib zlib; Zlib zlib;
bool hasdata;
void Reset(); void Reset();
public: public:
String FlushStream(); String FlushStream();
bool HasData() const { return hasdata; }
TurtleStream() { Reset(); } TurtleStream() { Reset(); }
}; };
@ -46,24 +48,33 @@ public:
SETCURSORIMAGE = 5, SETCURSORIMAGE = 5,
CURSORIMAGE = 6, CURSORIMAGE = 6,
DISABLESENDING = 7, DISABLESENDING = 7,
UPDATESERIAL = 8,
IMAGEPP = 9,
IMAGENP = 10,
IMAGEPN = 11,
IMAGENN = 12,
RECTPP = 13,
RECTNP = 14,
RECTPN = 15,
RECTNN = 16,
SETCARET = 17,
}; };
static Index<int64> img_index[3]; static Index<int64> img_index[3];
Point pos;
int GetImageI(int from, Index<int64>& img_index, int maxcount, const Image& img); int GetImageI(int from, Index<int64>& img_index, int maxcount, const Image& img);
int GetImageI(const Image& img); int GetImageI(const Image& img);
static void ResetI() { for(int i = 0; i < 3; i++) img_index[i].Clear(); } static void ResetI() { for(int i = 0; i < 3; i++) img_index[i].Clear(); }
void Put8(int x) { turtle_stream.Put(x); }
void Put16(int x);
void Put32(int x);
void Put(Point p);
void Put(Size sz);
void Put(const Rect& r);
void Put(const String& s);
bool CanSetSurface() { return false; } bool CanSetSurface() { return false; }
static void Flush() {} static void Flush() {}
SystemDraw() { pos = Point(0, 0); }
}; };
struct BackDraw__ : public SystemDraw { struct BackDraw__ : public SystemDraw {
@ -114,7 +125,7 @@ class TopWindowFrame;
#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <Turtle/Top.h> #define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <Turtle/Top.h>
class PrinterJob { // Dummy only... class PrinterJob { // _TODO_
NilDraw nil; NilDraw nil;
Vector<int> pages; Vector<int> pages;
@ -137,11 +148,6 @@ public:
~PrinterJob() {} ~PrinterJob() {}
}; };
void USDLSetup(dword flags);
void InitTelpp();
END_UPP_NAMESPACE END_UPP_NAMESPACE
#define GUIPLATFORM_INCLUDE_AFTER <Turtle/After.h> #define GUIPLATFORM_INCLUDE_AFTER <Turtle/After.h>

View file

@ -40,8 +40,8 @@ U.prototype.k=function(){var b=this.input,d,a;d=this.q.k();this.a=this.q.a;if(th
function Log(msg) function Log(msg)
{ {
// if (window.console && console.log) if (window.console && console.log)
// console.log(msg); //for firebug console.log(msg); //for firebug
} }
function Char(p, ch) function Char(p, ch)
@ -83,19 +83,94 @@ function GetString(p)
var SendingEnabled = true; var SendingEnabled = true;
var posx, posy;
var ctx;
var caretx = 0, carety = 0, caretcx = 0, caretcy = 0, caretshown = false;
var caretTimerID;
function InvertRect(x, y, cx, cy)
{
if(cx <= 0 || cy <= 0)
return;
var imageData = ctx.getImageData(x, y, cx, cy);
var data = imageData.data;
for(var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i];
data[i + 1] = 255 - data[i + 1];
data[i + 2] = 255 - data[i + 2];
}
ctx.putImageData(imageData, x, y);
}
function InvertCaret()
{
// Log("InvertCaret " + caretx + " " + carety + " " + caretcx + " " + caretcy);
if(caretcx >= 0 || caretcy >= 0)
InvertRect(caretx, carety, caretcx, caretcy);
}
function ClearCaretTimer()
{
if(caretTimerID != undefined)
clearTimeout(caretTimerID);
}
function CaretTimer()
{
ClearCaretTimer();
caretTimerID = setTimeout(DoCaret, 500);
}
function DoCaret()
{
if(caretcx || caretcy) {
InvertCaret();
caretshown = !caretshown;
CaretTimer();
}
}
function InvertShownCaret()
{
if(caretshown)
InvertCaret();
}
function HideCaret(x, y, cx, cy)
{
return;
if(caretHidden)
return;
if(Math.max(x, caretx) < Math.min(x + cx, caretx + caretcx) &&
Math.max(y, carety) < Math.min(y + cy, carety + caretcy)) {
Log("Hiding caret");
InvertShownCaret();
caretHidden = true;
}
}
function ProcessDraw(s) function ProcessDraw(s)
{ {
// console.clear(); // console.clear();
// window.document.title = "Processing draw";
var p = new Object; var p = new Object;
p.data = s; p.data = s;
p.pos = 0; p.pos = 0;
var canvas = document.getElementById("myCanvas"); var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx = canvas.getContext("2d");
SendingEnabled = true; SendingEnabled = true;
posx = 0;
posy = 0;
InvertShownCaret();
while(p.pos < p.data.length) { while(p.pos < p.data.length) {
// Log(p.pos + ": " + p.data[p.pos]); // Log(p.pos + ": " + p.data[p.pos]);
if(Char(p, 0)) { // RECT if(Char(p, 0)) { // RECT
@ -110,7 +185,10 @@ function ProcessDraw(s)
var c = "rgb(" + r + "," + g + "," + b + ")"; var c = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillStyle = c; ctx.fillStyle = c;
// Log("color: " + c); // Log("color: " + c);
HideCaret(x, y, cx, cy);
ctx.fillRect(x, y, cx, cy); ctx.fillRect(x, y, cx, cy);
posx = x;
posy = y;
} }
else else
if(Char(p, 3)) { // INVERTRECT if(Char(p, 3)) { // INVERTRECT
@ -119,14 +197,8 @@ function ProcessDraw(s)
var cx = Get16(p); var cx = Get16(p);
var cy = Get16(p); var cy = Get16(p);
// Log("irect: " + x + ", " + y + ", " + cx + ", " + cy); // Log("irect: " + x + ", " + y + ", " + cx + ", " + cy);
var imageData = ctx.getImageData(x, y, cx, cy); HideCaret(x, y, cx, cy);
var data = imageData.data; InvertRect(x, y, cx, cy);
for(var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i];
data[i + 1] = 255 - data[i + 1];
data[i + 2] = 255 - data[i + 2];
}
ctx.putImageData(imageData, x, y);
} }
else else
if(Char(p, 2)) { // SETIMAGE if(Char(p, 2)) { // SETIMAGE
@ -161,8 +233,12 @@ function ProcessDraw(s)
// Log("Draw image: " + n); // Log("Draw image: " + n);
if(window.img_cache[n] == undefined) if(window.img_cache[n] == undefined)
alert("Undefined: " + n); alert("Undefined image: " + n);
HideCaret(x, y, cx, cy);
ctx.drawImage(window.img_cache[n], x, y, cx, cy, px, py, cx, cy); ctx.drawImage(window.img_cache[n], x, y, cx, cy, px, py, cx, cy);
posx = px;
posy = py;
} }
else else
if(Char(p, 4)) { // STD_CURSORIMAGE if(Char(p, 4)) { // STD_CURSORIMAGE
@ -201,14 +277,93 @@ function ProcessDraw(s)
if(Char(p, 7)) { // DISABLESENDING if(Char(p, 7)) { // DISABLESENDING
SendingEnabled = true; SendingEnabled = true;
} }
else
if(Char(p, 8)) { // UPDATESERIAL
update_serial_l = Get32(p);
update_serial_h = Get32(p);
ws.send("S " + update_serial_l + " " + update_serial_h + "\n");
}
else
if(Char(p, 9)) // IMAGEPP
SImage(p, 1, 1);
else
if(Char(p, 10)) // IMAGENP
SImage(p, -1, 1);
else
if(Char(p, 11)) // IMAGEPN
SImage(p, 1, -1);
else
if(Char(p, 12)) // IMAGENN
SImage(p, -1, -1);
else
if(Char(p, 13)) // RECTPP
SRect(p, 1, 1);
else
if(Char(p, 14)) // RECTNP
SRect(p, -1, 1);
else
if(Char(p, 15)) // RECTPN
SRect(p, 1, -1);
else
if(Char(p, 16)) // RECTNN
SRect(p, -1, -1);
else
if(Char(p, 17)) { // SETCARET
caretx = Get16(p);
carety = Get16(p);
caretcx = Get16(p);
caretcy = Get16(p);
caretshown = true;
CaretTimer();
// Log("SET CARET " + caretx + " " + carety + " " + caretcx + " " + caretcy);
}
} }
InvertShownCaret();
// window.document.title = "OK";
if(SendingEnabled && event_queue.length) if(SendingEnabled && event_queue.length)
ScheduleSend(); ScheduleSend();
} }
function SImage(p, sx, sy)
{
var px = posx + sx * Get8(p);
var py = posy + sy * Get8(p);
var n = Get16(p);
// Log("Draw opt image: " + px + " " + py + " " + n);
var img = window.img_cache[n];
if(img == undefined)
alert("Undefined image: " + n);
HideCaret(px, py, img.width, img.height);
ctx.drawImage(window.img_cache[n], px, py);
posx = px;
posy = py;
}
function SRect(p, sx, sy)
{
var px = posx + sx * Get8(p);
var py = posy + sy * Get8(p);
var cx = Get8(p);
var cy = Get8(p);
var r = Get8(p);
var g = Get8(p);
var b = Get8(p);
// Log("rect: " + x + ", " + y + ", " + cx + ", " + cy);
var c = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillStyle = c;
// Log("color: " + c);
HideCaret(x, y, cx, cy);
ctx.fillRect(x, y, cx, cy);
posx = px;
posy = py;
}
window.img_cache = {}; window.img_cache = {};
window.event_queue = "I\n"; window.event_queue = "I\n";
window.cursor_cache = {}; window.cursor_cache = {};
window.update_serial_l = 0;
window.update_serial_h = 0;
var canvas = document.getElementById("myCanvas"); var canvas = document.getElementById("myCanvas");
@ -302,9 +457,10 @@ function ScheduleSend()
function SendEvents() function SendEvents()
{ {
if(SendingEnabled) { if(SendingEnabled) {
if(event_queue.length) if(event_queue.length) {
Log("Sending " + event_queue); Log(event_queue);
ws.send(event_queue); ws.send(event_queue);
}
event_queue = ""; event_queue = "";
if(timerID != undefined) if(timerID != undefined)
clearTimeout(timerID); clearTimeout(timerID);
@ -320,7 +476,7 @@ ws.onopen = function()
ws.onmessage = function(event) ws.onmessage = function(event)
{ {
Log("onmessage"); // Log("onmessage");
if(event.data instanceof ArrayBuffer) { if(event.data instanceof ArrayBuffer) {
var inflate = new Zlib.Inflate(new Uint8Array(event.data)); var inflate = new Zlib.Inflate(new Uint8Array(event.data));
ProcessDraw(inflate.decompress()); ProcessDraw(inflate.decompress());
@ -329,6 +485,7 @@ ws.onmessage = function(event)
ws.onclose = function(ev) ws.onclose = function(ev)
{ {
ClearCaretTimer();
alert("Connection closed."); alert("Connection closed.");
}; };

View file

@ -19,6 +19,7 @@ file
Cursor.cpp, Cursor.cpp,
Stream.cpp, Stream.cpp,
Server.cpp, Server.cpp,
Output.cpp,
Event.cpp, Event.cpp,
Top.h, Top.h,
TopFrame.cpp, TopFrame.cpp,

View file

@ -12,31 +12,32 @@ NAMESPACE_UPP
Ptr<Ctrl> Ctrl::desktop; Ptr<Ctrl> Ctrl::desktop;
Vector<Ctrl *> Ctrl::topctrl; Vector<Ctrl *> Ctrl::topctrl;
bool Ctrl::invalid;
bool Ctrl::sdlMouseIsIn;
Point Ctrl::fbCursorPos = Null; Point Ctrl::fbCursorPos = Null;
Image Ctrl::fbCursorImage; Image Ctrl::fbCursorImage;
Rect Ctrl::fbCaretRect; Rect Ctrl::fbCaretRect;
int Ctrl::fbCaretTm; int Ctrl::fbCaretTm;
bool Ctrl::fbEndSession; bool Ctrl::fbEndSession;
bool Ctrl::SystemCursor; Vector<Rect> Ctrl::invalid;
void Ctrl::InvalidateDesktop()
{
AddInvalid(desktop->GetSize());
}
void Ctrl::SetDesktop(Ctrl& q) void Ctrl::SetDesktop(Ctrl& q)
{ {
desktop = &q; desktop = &q;
desktop->SetOpen(true); desktop->SetOpen(true);
desktop->NewTop(); desktop->NewTop();
invalid = true; InvalidateDesktop();
} }
void Ctrl::SetDesktopSize(Size sz) void Ctrl::SetDesktopSize(Size sz)
{ {
if(desktop) if(desktop)
desktop->SetRect(sz); desktop->SetRect(sz);
invalid = true; InvalidateDesktop();
SyncTopWindows(); SyncTopWindows();
} }
@ -164,11 +165,11 @@ Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r)
return ri; return ri;
} }
void Ctrl::WndUpdate(const Rect&) void Ctrl::WndUpdate(const Rect& r)
{ {
GuiLock __; GuiLock __;
Invalidate(); // WndInvalidateRect(r);
DoPaint(); // DoPaint(); // TODO
} }
Rect Ctrl::GetWndScreenRect() const Rect Ctrl::GetWndScreenRect() const
@ -255,7 +256,7 @@ void Ctrl::DestroyWnd()
topctrl[i]->WndDestroy(); topctrl[i]->WndDestroy();
int q = FindTopCtrl(); int q = FindTopCtrl();
if(q >= 0) { if(q >= 0) {
Invalidate(); AddInvalid();
topctrl.Remove(q); topctrl.Remove(q);
} }
if(top) { if(top) {
@ -279,7 +280,7 @@ void Ctrl::PutForeground()
{ {
int q = FindTopCtrl(); int q = FindTopCtrl();
if(q >= 0) { if(q >= 0) {
Invalidate(); AddInvalid();
topctrl.Remove(q); topctrl.Remove(q);
topctrl.Add(this); topctrl.Add(this);
} }
@ -355,10 +356,21 @@ bool Ctrl::HasWndCapture() const
return captureCtrl && captureCtrl->GetTopCtrl() == this; return captureCtrl && captureCtrl->GetTopCtrl() == this;
} }
void Ctrl::WndInvalidateRect(const Rect&) void Ctrl::AddInvalid(const Rect& r_)
{
Rect r = r_ & Rect(DesktopSize);
if(!IsNull(r))
AddRefreshRect(invalid, r);
}
void Ctrl::WndInvalidateRect(const Rect& r)
{ {
GuiLock __; GuiLock __;
Invalidate(); int q = FindTopCtrl();
if(q >= 0)
AddInvalid(r + topctrl[q]->GetRect().TopLeft());
else
AddInvalid(r);
} }
void Ctrl::WndSetPos(const Rect& rect) void Ctrl::WndSetPos(const Rect& rect)
@ -367,14 +379,15 @@ void Ctrl::WndSetPos(const Rect& rect)
TopWindow *w = dynamic_cast<TopWindow *>(this); TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w) if(w)
w->SyncFrameRect(rect); w->SyncFrameRect(rect);
Invalidate(); AddInvalid();
SetWndRect(rect); SetWndRect(rect);
AddInvalid(rect);
} }
void Ctrl::WndScrollView(const Rect& r, int dx, int dy) void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{ {
GuiLock __; GuiLock __;
LLOG("ScrollView " << rect); LLOG("ScrollView " << r << ", size " << GetSize());
WndInvalidateRect(r); WndInvalidateRect(r);
} }
@ -396,7 +409,7 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, boo
popup = isopen = true; popup = isopen = true;
RefreshLayoutDeep(); RefreshLayoutDeep();
if(activate) SetFocusWnd(); if(activate) SetFocusWnd();
Invalidate(); AddInvalid();
} }
Rect Ctrl::GetDefaultWindowRect() { Rect Ctrl::GetDefaultWindowRect() {

View file

@ -1,7 +1,4 @@
#include <RichEdit/RichEdit.h> #include "WebWord.h"
#include <PdfDraw/PdfDraw.h>
using namespace Upp;
#define IMAGECLASS UWordImg #define IMAGECLASS UWordImg
#define IMAGEFILE <UWord/UWord.iml> #define IMAGEFILE <UWord/UWord.iml>
@ -19,46 +16,6 @@ FileSel& PdfFs()
return fs; return fs;
} }
struct UWord : public TopWindow {
public:
virtual void DragAndDrop(Point, PasteClip& d);
virtual void FrameDragAndDrop(Point, PasteClip& d);
virtual void ShutdownWindow();
RichEdit editor;
MenuBar menubar;
ToolBar toolbar;
StatusBar statusbar;
String filename;
static LRUList& lrufile() { static LRUList l; return l; }
void Load(const String& filename);
void OpenFile(const String& fn);
void New();
void Open();
void Save0();
void Save();
void SaveAs();
void Print();
void Pdf();
void About();
void Destroy(bool shutdown);
void SetBar();
void FileBar(Bar& bar);
void AboutMenu(Bar& bar);
void MainMenu(Bar& bar);
void MainBar(Bar& bar);
public:
typedef UWord CLASSNAME;
static void SerializeApp(Stream& s);
UWord();
};
void UWord::FileBar(Bar& bar) void UWord::FileBar(Bar& bar)
{ {
/* /*
@ -94,6 +51,36 @@ void UWord::AboutMenu(Bar& bar)
bar.Add("About..", THISBACK(About)); bar.Add("About..", THISBACK(About));
} }
String FormatSize(int64 n)
{
if(n < 10000)
return Format("%d B", n);
else
if(n < 10000 * 1024)
return Format("%d.%d KB", n >> 10, (n & 1023) / 103);
else
if(n < I64(10000000) * 1024)
return Format("%d.%d MB", n >> 20, (n & 1023) / 103);
else
return Format("%d.%d GB", n >> 30, (n & 1023) / 103);
}
void UWord::ShowInfo()
{
String s;
s << "Mem " << MemoryUsedKb() << " KB";
int secs = GetSysTime() - Ctrl::stat_started;
Time tm = Time(1, 1, 1, 0, 0, 0) + secs;
s << ", uptime " << Format("%d:%0d:%02d:%02d", tm - Date(1, 1, 1), tm.hour, tm.minute, tm.second);
s << ", data sent " << FormatSize(Ctrl::stat_data_send);
if(secs)
s << ", average bandwidth " << FormatSize(Ctrl::stat_data_send / secs) << "/s";
s << ", actual bandwidth " << FormatSize(Ctrl::stat_data_send - sent_prev);
sent_prev = Ctrl::stat_data_send;
statusbar.Set(s);
}
void UWord::MainMenu(Bar& bar) void UWord::MainMenu(Bar& bar)
{ {
// bar.Add("File", THISBACK(FileBar)); // bar.Add("File", THISBACK(FileBar));
@ -248,6 +235,9 @@ UWord::UWord()
editor.WhenRefreshBar = THISBACK(SetBar); editor.WhenRefreshBar = THISBACK(SetBar);
OpenMain(); OpenMain();
ActiveFocus(editor); ActiveFocus(editor);
SetTimeCallback(-1000, THISBACK(ShowInfo));
sent_prev = 0;
} }
void UWord::SerializeApp(Stream& s) void UWord::SerializeApp(Stream& s)
@ -294,7 +284,7 @@ struct EventsWnd : TopWindow {
EventsWnd() { EventsWnd() {
Add(l.SizePos()); Add(l.SizePos());
SetTimeCallback(-100, THISBACK(Do)); SetTimeCallback(-1000, THISBACK(Do));
} }
}; };
@ -311,7 +301,8 @@ CONSOLE_APP_MAIN
LOG("Session Started"); LOG("Session Started");
#ifdef _DEBUG #ifdef _DEBUG
MemoryLimitKb(10000); MemoryLimitKb(5000000);
Ctrl::debugmode = true;
#endif #endif
Ctrl::WhenDisconnect = callback(FinishApp); Ctrl::WhenDisconnect = callback(FinishApp);
@ -324,6 +315,8 @@ CONSOLE_APP_MAIN
{ {
SetLanguage(LNG_ENGLISH); SetLanguage(LNG_ENGLISH);
SetDefaultCharset(CHARSET_UTF8); SetDefaultCharset(CHARSET_UTF8);
PromptOK("Session started");
UWordFs().Type("QTF files", "*.qtf") UWordFs().Type("QTF files", "*.qtf")
.AllFilesType() .AllFilesType()

53
rainbow/WebWord/WebWord.h Normal file
View file

@ -0,0 +1,53 @@
#ifndef _WebWord_WebWord_h_
#define _WebWord_WebWord_h_
#include <RichEdit/RichEdit.h>
#include <PdfDraw/PdfDraw.h>
using namespace Upp;
struct UWord : public TopWindow {
public:
virtual void DragAndDrop(Point, PasteClip& d);
virtual void FrameDragAndDrop(Point, PasteClip& d);
virtual void ShutdownWindow();
RichEdit editor;
MenuBar menubar;
ToolBar toolbar;
StatusBar statusbar;
String filename;
int64 sent_prev;
static LRUList& lrufile() { static LRUList l; return l; }
void Load(const String& filename);
void OpenFile(const String& fn);
void New();
void Open();
void Save0();
void Save();
void SaveAs();
void Print();
void Pdf();
void About();
void Destroy(bool shutdown);
void SetBar();
void FileBar(Bar& bar);
void AboutMenu(Bar& bar);
void MainMenu(Bar& bar);
void MainBar(Bar& bar);
void ShowInfo();
public:
typedef UWord CLASSNAME;
static void SerializeApp(Stream& s);
UWord();
};
#endif

View file

@ -7,6 +7,7 @@ uses
file file
test.qtf, test.qtf,
WebWord.h,
WebWord.cpp; WebWord.cpp;
mainconfig mainconfig

View file

@ -57,4 +57,5 @@
#define GUIPLATFORM_KEYCODES_INCLUDE <Turtle/Keys.h> #define GUIPLATFORM_KEYCODES_INCLUDE <Turtle/Keys.h>
//need to make SDL_keysym.h known before K_ enum //need to make SDL_keysym.h known before K_ enum
#define GUIPLATFORM_INCLUDE <Turtle/Turtle.h> #define GUIPLATFORM_INCLUDE <Turtle/Turtle.h>
#define GUIPLATFORM_NOSCROLL
#endif #endif