34 #include "config_auto.h"    45 #include "allheaders.h"    54 static std::map<int, ScrollView*> svmap;
    57 static std::map<std::pair<ScrollView*, SVEventType>,
    58                 std::pair<SVSemaphore*, SVEvent*> > waiting_for_events;
    59 static SVMutex* waiting_for_events_mu;
    81 #ifndef GRAPHICS_DISABLED    82 void* ScrollView::MessageReceiver(
void* a) {
    87   int counter_event_id = 0;  
    88   char* message = 
nullptr;
    91     message = ScrollView::GetStream()->
Receive();
    92   } 
while (message == 
nullptr);
   107     sscanf(message, 
"%d,%d,%d,%d,%d,%d,%d,%n", &window_id, &ev_type, &cur->
x,
   109     char* p = (message + n);
   112     cur->
window = svmap[window_id];
   114     if (cur->
window != 
nullptr) {
   115       cur->
parameter = 
new char[strlen(p) + 1];
   131       if (cur->
window->y_axis_is_reversed_)
   133       cur->
counter = counter_event_id;
   137       counter_event_id += 2;
   143       cur->
window->SetEvent(cur);
   146       std::pair<ScrollView*, SVEventType> awaiting_list(cur->
window,
   148       std::pair<ScrollView*, SVEventType> awaiting_list_any(cur->
window,
   150       std::pair<ScrollView*, SVEventType> awaiting_list_any_window((
ScrollView*)
nullptr,
   152       waiting_for_events_mu->
Lock();
   153       if (waiting_for_events.count(awaiting_list) > 0) {
   154         waiting_for_events[awaiting_list].second = cur;
   155         waiting_for_events[awaiting_list].first->Signal();
   156       } 
else if (waiting_for_events.count(awaiting_list_any) > 0) {
   157         waiting_for_events[awaiting_list_any].second = cur;
   158         waiting_for_events[awaiting_list_any].first->Signal();
   159       } 
else if (waiting_for_events.count(awaiting_list_any_window) > 0) {
   160         waiting_for_events[awaiting_list_any_window].second = cur;
   161         waiting_for_events[awaiting_list_any_window].first->Signal();
   166       waiting_for_events_mu->
Unlock();
   180       message = ScrollView::GetStream()->
Receive();
   181     } 
while (message == 
nullptr);
   190   {255, 255, 255, 255},  
   199   {128, 128, 255, 255},  
   203   {192, 192, 255, 255},  
   206   {255, 128, 128, 255},  
   210   {192, 192, 128, 255},  
   215   {192, 255, 192, 255},  
   217   {192, 192, 192, 255},  
   220   {128, 128, 128, 255},  
   225   {255, 192, 192, 255},  
   230   {255, 192, 128, 255},  
   244 SVNetwork* ScrollView::stream_ = 
nullptr;
   245 int ScrollView::nr_created_windows_ = 0;
   246 int ScrollView::image_index_ = 0;
   250                        int y_size, 
int x_canvas_size, 
int y_canvas_size,
   251                        bool y_axis_reversed, 
const char* server_name) {
   252   Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
   253              y_axis_reversed, server_name);}
   257                        int y_size, 
int x_canvas_size, 
int y_canvas_size,
   258                        bool y_axis_reversed) {
   259   Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
   260              y_axis_reversed, 
"localhost");
   265                        int y_size, 
int x_canvas_size, 
int y_canvas_size) {
   266   Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
   271 void ScrollView::Initialize(
const char* name, 
int x_pos, 
int y_pos, 
int x_size,
   272                             int y_size, 
int x_canvas_size, 
int y_canvas_size,
   273                             bool y_axis_reversed, 
const char* server_name) {
   276   if (stream_ == 
nullptr) {
   277     nr_created_windows_ = 0;
   279     waiting_for_events_mu = 
new SVMutex();
   282         "svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
   287   nr_created_windows_++;
   288   event_handler_ = 
nullptr;
   289   event_handler_ended_ = 
false;
   290   y_axis_is_reversed_ = y_axis_reversed;
   291   y_size_ = y_canvas_size;
   293   window_id_ = nr_created_windows_;
   296   points_->
empty = 
true;
   299   svmap[window_id_] = 
this;
   303     event_table_[i] = 
nullptr;
   311   snprintf(message, 
sizeof(message),
   312            "w%u = luajava.newInstance('com.google.scrollview.ui"   313            ".SVWindow','%s',%u,%u,%u,%u,%u,%u,%u)\n",
   314            window_id_, window_name_, window_id_,
   315            x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size);
   322 void* ScrollView::StartEventHandler(
void* a) {
   328     sv->semaphore_->
Wait();
   336       if (sv->event_table_[i] != 
nullptr &&
   337           (serial < 0 || sv->event_table_[i]->counter < serial)) {
   338         new_event = sv->event_table_[i];
   339         serial = sv->event_table_[i]->
counter;
   344     if (new_event != 
nullptr) {
   345       sv->event_table_[k] = 
nullptr;
   347       if (sv->event_handler_ != 
nullptr) { sv->event_handler_->
Notify(new_event); }
   350         sv->event_handler_ended_ = 
true;
   354     } 
else { sv->mutex_->
Unlock(); }
   356   } 
while (sv != 
nullptr);
   359 #endif  // GRAPHICS_DISABLED   362   #ifndef GRAPHICS_DISABLED   364   if (svmap[window_id_] != 
nullptr) {
   372     svmap[window_id_] = 
nullptr;
   377     while (!event_handler_ended_)
   386     delete event_table_[i];
   388   #endif  // GRAPHICS_DISABLED   391 #ifndef GRAPHICS_DISABLED   399   va_start(args, format);  
   404   snprintf(form, 
kMaxMsgSize, 
"w%u:%s\n", window_id_, message);
   417   event_handler_ = listener;
   420 void ScrollView::Signal() {
   424 void ScrollView::SetEvent(
SVEvent* svevent) {
   433   delete event_table_[specific->
type];
   436   event_table_[specific->
type] = specific;
   448   std::pair<ScrollView*, SVEventType> ea(
this, type);
   449   waiting_for_events_mu->
Lock();
   450   waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
   451   waiting_for_events_mu->
Unlock();
   456   waiting_for_events_mu->
Lock();
   457   SVEvent* ret = waiting_for_events[ea].second;
   458   waiting_for_events.erase(ea);
   460   waiting_for_events_mu->
Unlock();
   470   waiting_for_events_mu->
Lock();
   471   waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, (
SVEvent*)
nullptr);
   472   waiting_for_events_mu->
Unlock();
   477   waiting_for_events_mu->
Lock();
   478   SVEvent* ret = waiting_for_events[ea].second;
   479   waiting_for_events.erase(ea);
   480   waiting_for_events_mu->
Unlock();
   485 void ScrollView::SendPolygon() {
   486   if (!points_->
empty) {
   487     points_->
empty = 
true;  
   488     int length = points_->
xcoords.size();
   493       SendMsg(
"drawLine(%d,%d,%d,%d)",
   496     } 
else if (length > 2) {
   498       SendMsg(
"createPolyline(%d)", length);
   500       std::string decimal_coords;
   501       for (
int i = 0; i < length; ++i) {
   504         decimal_coords += coordpair;
   506       decimal_coords += 
'\n';
   530   points_->
empty = 
false;
   539   } 
else if (!points_->
xcoords.empty() && x2 == points_->
xcoords.back() &&
   552   if (visible) { 
SendMsg(
"setVisible(true)");
   553   } 
else { 
SendMsg(
"setVisible(false)"); }
   558   if (b) { 
SendMsg(
"setAlwaysOnTop(true)");
   559   } 
else { 
SendMsg(
"setAlwaysOnTop(false)"); }
   568   va_start(args, format);  
   572   snprintf(form, 
kMaxMsgSize, 
"w%u:%s", window_id_, message);
   574   char* esc = AddEscapeChars(form);
   575   SendMsg(
"addMessage(\"%s\")", esc);
   597   SendMsg(
"setStrokeWidth(%f)", width);
   603   if (x1 == x2 && y1 == y2)
   605   SendMsg(
"drawRectangle(%d,%d,%d,%d)",
   612   SendMsg(
"drawEllipse(%d,%d,%u,%u)",
   618   SendMsg(
"pen(%d,%d,%d)", red, green, blue);
   623   SendMsg(
"pen(%d,%d,%d,%d)", red, green, blue, alpha);
   628   SendMsg(
"brush(%d,%d,%d)", red, green, blue);
   633   SendMsg(
"brush(%d,%d,%d,%d)", red, green, blue, alpha);
   638                                 bool bold, 
bool italic, 
bool underlined) {
   643   if (bold) { b = 
"true";
   644   } 
else { b = 
"false"; }
   645   if (italic) { i = 
"true";
   646   } 
else { i = 
"false"; }
   647   if (underlined) { u = 
"true";
   648   } 
else { u = 
"false"; }
   649   SendMsg(
"textAttributes('%s',%u,%s,%s,%s)", font, pixel_size,
   660   SendMsg(
"openImage('%s')", image);
   661   SendMsg(
"drawImage('%s',%d,%d)",
   667                           int cmdEvent, 
bool flag) {
   668   if (parent == 
nullptr) { parent = 
""; }
   669   if (flag) { 
SendMsg(
"addMenuBarItem('%s','%s',%d,true)",
   670                       parent, name, cmdEvent);
   671   } 
else { 
SendMsg(
"addMenuBarItem('%s','%s',%d,false)",
   672                    parent, name, cmdEvent); }
   677   if (parent == 
nullptr) { parent = 
""; }
   678   SendMsg(
"addMenuBarItem('%s','%s',%d)", parent, name, cmdEvent);
   683   if (parent == 
nullptr) { parent = 
""; }
   684   SendMsg(
"addMenuBarItem('%s','%s')", parent, name);
   689   if (parent == 
nullptr) { parent = 
""; }
   690   SendMsg(
"addPopupMenuItem('%s','%s')", parent, name);
   695                            int cmdEvent, 
const char* value, 
const char* desc) {
   696   if (parent == 
nullptr) { parent = 
""; }
   697   char* esc = AddEscapeChars(value);
   698   char* esc2 = AddEscapeChars(desc);
   699   SendMsg(
"addPopupMenuItem('%s','%s',%d,'%s','%s')", parent, name,
   700           cmdEvent, esc, esc2);
   713   for (std::map<int, ScrollView*>::iterator iter = svmap.begin();
   714       iter != svmap.end(); ++iter) {
   715     if (iter->second != 
nullptr)
   716       iter->second->UpdateWindow();
   723   Pen(table_colors[color][0], table_colors[color][1],
   724       table_colors[color][2], table_colors[color][3]);
   729   Brush(table_colors[color][0],
   730         table_colors[color][1],
   731         table_colors[color][2],
   732         table_colors[color][3]);
   737   SendMsg(
"showInputDialog(\"%s\")", msg);
   741   char* p = 
new char[strlen(ev->
parameter) + 1];
   749   SendMsg(
"showYesNoDialog(\"%s\")", msg);
   763   SendMsg(
"zoomRectangle(%d,%d,%d,%d)",
   764           std::min(x1, x2), std::min(y1, y2), std::max(x1, x2), std::max(y1, y2));
   771   pixWriteMem(&data, &size, image, IFF_PNG);
   772   int base64_len = (size + 2) / 3 * 4;
   774   SendMsg(
"readImage(%d,%d,%d)", x_pos, y_pos, base64_len);
   776   const char kBase64Table[64] = {
   777     'A', 
'B', 
'C', 
'D', 
'E', 
'F', 
'G', 
'H',
   778     'I', 
'J', 
'K', 
'L', 
'M', 
'N', 
'O', 
'P',
   779     'Q', 
'R', 
'S', 
'T', 
'U', 
'V', 
'W', 
'X',
   780     'Y', 
'Z', 
'a', 
'b', 
'c', 
'd', 
'e', 
'f',
   781     'g', 
'h', 
'i', 
'j', 
'k', 
'l', 
'm', 
'n',
   782     'o', 
'p', 
'q', 
'r', 
's', 
't', 
'u', 
'v',
   783     'w', 
'x', 
'y', 
'z', 
'0', 
'1', 
'2', 
'3',
   784     '4', 
'5', 
'6', 
'7', 
'8', 
'9', 
'+', 
'/',
   786   char* base64 = 
new char[base64_len + 1];
   787   memset(base64, 
'=', base64_len);
   788   base64[base64_len] = 
'\0';
   792   for (
size_t i = 0; i < size; ++i) {
   793     int code = (data[i] >> (bits_left + 2)) | remainder;
   794     base64[code_len++] = kBase64Table[code & 63];
   796     remainder = data[i] << (6 - bits_left);
   797     if (bits_left == 6) {
   798       base64[code_len++] = kBase64Table[remainder & 63];
   804     base64[code_len++] = kBase64Table[remainder & 63];
   812 char* ScrollView::AddEscapeChars(
const char* input) {
   813   const char* nextptr = strchr(input, 
'\'');
   814   const char* lastptr = input;
   817   while (nextptr != 
nullptr) {
   818     strncpy(message+pos, lastptr, nextptr-lastptr);
   819     pos += nextptr - lastptr;
   823     nextptr = strchr(nextptr+1, 
'\'');
   825   strcpy(message+pos, lastptr);
   831   if (!y_axis_is_reversed_) { 
return y;
   832   } 
else { 
return y_size_ - y; }
   835 #endif  // GRAPHICS_DISABLED virtual void Notify(const SVEvent *sve)
virtual ~SVEventHandler()
void DrawTo(int x, int y)
void Unlock()
Unlocks on a mutex. 
int ShowYesNoDialog(const char *msg)
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
void Send(const char *msg)
Put a message in the messagebuffer to the server and try to send it. 
SVEvent * AwaitEventAnyWindow()
static void StartThread(void *(*func)(void *), void *arg)
Create new thread. 
void SetVisible(bool visible)
void Lock()
Locks on a mutex. 
void ZoomToRectangle(int x1, int y1, int x2, int y2)
void Wait()
Wait on a semaphore. 
void MenuItem(const char *parent, const char *name)
int TranslateYCoordinate(int y)
void Signal()
Signal a semaphore. 
static void SendRawMessage(const char *msg)
void SetCursor(int x, int y)
void SendMsg(const char *msg,...)
Send a message to the server, attaching the window id. 
const int kMaxIntPairSize
void Ellipse(int x, int y, int width, int height)
void PopupItem(const char *parent, const char *name)
SVEvent * AwaitEvent(SVEventType type)
char * ShowInputDialog(const char *msg)
void Text(int x, int y, const char *mystring)
ScrollView(const char *name, int x_pos, int y_pos, int x_size, int y_size, int x_canvas_size, int y_canvas_size)
Calls Initialize with default argument for server_name_ & y_axis_reversed. 
void AddEventHandler(SVEventHandler *listener)
Add an Event Listener to this ScrollView Window. 
void Image(struct Pix *image, int x_pos, int y_pos)
std::vector< int > ycoords
std::vector< int > xcoords
void Rectangle(int x1, int y1, int x2, int y2)
void Flush()
Flush the buffer. 
void Line(int x1, int y1, int x2, int y2)
void AddMessage(const char *format,...)