Project

General

Profile

web_worker_1.txt

Sergey Ivanovskiy, 02/10/2016 01:18 PM

Download (93.5 KB)

 
1
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java'
2
--- src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java	2015-05-18 20:48:28 +0000
3
+++ src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java	2016-02-09 18:52:59 +0000
4
@@ -11,6 +11,8 @@
5
 ** -#- -I- --Date-- ----------------------Description--------------------------
6
 ** 001 MAG 20140220 Created initial version.
7
 ** 002 GES 20150308 Moved to a more generic package location.
8
+** 003 SBI 20160209 Implemented sending messages that can exceed the limit message size defined
9
+**                  for the current web socket session. 
10
 */
11
 
12
 package com.goldencode.p2j.ui.client.driver.web;
13
@@ -147,6 +149,43 @@
14
    }
15
    
16
    /**
17
+    * Sends a binary message in packets that don't exceed the maximum binary message size for
18
+    * the current web socket session.
19
+    * 
20
+    * @param    message
21
+    *           The binary message that should be send in packets.
22
+    * @throws   IOException
23
+    *           The exception that can be thrown during the web socket write operation.
24
+    */
25
+   private void sendBytesByPackets(ByteBuffer message) throws IOException
26
+   {
27
+      int messageLimit = session.getPolicy().getMaxBinaryMessageSize();
28
+      boolean isLast;
29
+      message.position(0);
30
+      message.limit(message.capacity());
31
+      while(message.hasRemaining())
32
+      {
33
+         System.err.println("message.remaining()=" + message.remaining());
34
+         if (message.remaining() > messageLimit)
35
+         {
36
+            isLast = false;
37
+            message.limit(messageLimit + message.position());
38
+         }
39
+         else
40
+         {
41
+            isLast = true;
42
+         }
43
+         remote.sendPartialBytes(message, isLast);
44
+         message.position(message.limit());
45
+         message.limit(message.capacity());
46
+         System.err.println("message.position()=" + message.position());
47
+         System.err.println("message.limit()=" + message.limit());
48
+         System.err.println("message.remaining()=" + message.remaining());
49
+         System.err.println("message.hasRemaining()=" + message.hasRemaining());
50
+      }
51
+   }
52
+   
53
+   /**
54
     * Send a message.
55
     */
56
    private void sendMessage()
57
@@ -166,6 +205,7 @@
58
                // test message type
59
                if (message instanceof ByteBuffer)
60
                {
61
+                  //sendBytesByPackets((ByteBuffer) message);
62
                   remote.sendBytes((ByteBuffer) message);
63
                }
64
                else if (message instanceof String)
65

    
66
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/index.html'
67
--- src/com/goldencode/p2j/ui/client/driver/web/index.html	2015-12-17 20:00:50 +0000
68
+++ src/com/goldencode/p2j/ui/client/driver/web/index.html	2016-02-07 17:47:14 +0000
69
@@ -18,6 +18,7 @@
70
       <script type="text/javascript" src="/client/p2j.virtual_desktop.js"></script>
71
       <script type="text/javascript" src="/client/p2j.mouse.js"></script>
72
       <script type="text/javascript" src="/client/p2j.screen.js"></script>
73
+      <script type="text/javascript" src="/common/p2j.io.js"></script>
74
       <script type="text/javascript" src="/common/p2j.socket.js"></script>
75
       <script type="text/javascript" src="/common/p2j.keymap.js"></script>
76
       <script type="text/javascript" src="/common/p2j.keyboard.js"></script>
77

    
78
=== added file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.connector.js'
79
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.connector.js	1970-01-01 00:00:00 +0000
80
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.connector.js	2016-02-09 19:52:55 +0000
81
@@ -0,0 +1,665 @@
82
+/*
83
+** Module   : p2j.connector.js
84
+** Abstract : Defines the connection module that is responsible for the web socket management.
85
+**
86
+** Copyright (c) 2015-2016, Golden Code Development Corporation.
87
+** ALL RIGHTS RESERVED. Use is subject to license terms.
88
+**
89
+**         Golden Code Development Corporation
90
+**                 CONFIDENTIAL
91
+**
92
+** -#- -I- --Date-- ----------------------Description--------------------------
93
+** 001 SBI 20160209 Implemented the module that manages web socket connection and is executed by
94
+**                  the dedicated web worker thread.
95
+*/
96
+"use strict";
97
+
98
+importScripts("/common/p2j.io.js");
99
+
100
+/** The low level web socket */
101
+var ws;
102
+
103
+/** The connection status */
104
+var connected = false;
105
+
106
+/** Input and output channel that is the helper class for read and write web socket operations */
107
+var io = InputOutputChannel(
108
+      function(data)
109
+      {
110
+         if (connected)
111
+         {
112
+            ws.send(data);
113
+         }
114
+      });
115
+
116
+/**
117
+ * The web worker message handler that listens messages from the UI thread.
118
+ * 
119
+ * @param    {MessageEvent} msg
120
+ *           The message from the UI thread.
121
+ */
122
+self.onmessage = function(msg)
123
+{
124
+   var data = msg.data;
125
+   switch(data.type)
126
+   {
127
+      case MSG.MSG_WEB_SOCKET_OPEN:
128
+         var url = data.url;
129
+         try
130
+         {
131
+            createWebsocket(url);
132
+         }
133
+         catch(ex)
134
+         {
135
+            self.postMessage({type : MSG.MSG_WEB_SOCKET_ERROR});
136
+         }
137
+         break;
138
+      case MSG.MSG_WEB_SOCKET_CLOSE:
139
+         if (connected)
140
+         {
141
+            connected = false;
142
+            ws.close();
143
+         }
144
+         break;
145
+      case MSG.MSG_PAGE_LOADED:
146
+         // notify the web socket has opened and the page is loaded
147
+         io.sendNotification(MSG.MSG_PAGE_LOADED);
148
+         break;
149
+      case MSG.MSG_WEB_SOCKET_SEND:
150
+         io.send(data.message);
151
+         break;
152
+   }
153
+};
154
+
155
+/** Web socket message handler */
156
+function messageHandler(message)
157
+{
158
+   var type = message[0];
159
+   switch (type)
160
+   {
161
+      case MSG.MSG_CLEAR:
162
+      case MSG.MSG_BEEP:
163
+      case MSG.MSG_QUIT:
164
+         self.postMessage({type : type});
165
+         break;
166
+      case MSG.MSG_DRAW:
167
+         // remove the MD5 code and save it here
168
+         var md5a = new message.constructor(16);
169
+         message = io.splice(message, 1, 16, md5a);
170
+         var md5 = io.createHexString(md5a);
171
+         console.debug("draw buffer length=" + message.buffer.byteLength);
172
+         self.postMessage({type : type, md5 : md5, drawBuffer : message.buffer}, [message.buffer]);
173
+         break;
174
+      case MSG.MSG_CURSOR_POS:
175
+         self.postMessage({type : type, col : message[1], row : message[2]});
176
+         break;
177
+      case MSG.MSG_CURSOR_STATUS:
178
+         self.postMessage({type : type, status : message[1]});
179
+         break;
180
+      case MSG.MSG_VT100:
181
+         self.postMessage({type : type, vt100 : (message[1] == 0) ? false : true});
182
+         break;
183
+      case MSG.MSG_READ_CLIPBOARD:
184
+         self.postMessage({type : type});
185
+         break;
186
+      case MSG.MSG_WRITE_CLIPBOARD:
187
+         // The clipboard is changed.
188
+         var text = io.readStringBinaryMessage(message, 1);
189
+         self.postMessage({type : type, clipboardText : text});
190
+         break;
191
+      case MSG.MSG_CREATE_WINDOW:
192
+         // create a top-level window with the given id
193
+         var id = io.readInt32BinaryMessage(message, 1);
194
+         self.postMessage({type : type, id : id});
195
+         break;
196
+      case MSG.MSG_CREATE_CHILD_WINDOW:
197
+         // create a child window with the given id, owner and title
198
+         var id    = io.readInt32BinaryMessage(message, 1);
199
+         var owner = io.readInt32BinaryMessage(message, 5);
200
+         var title = io.readStringBinaryMessage(message, 9);
201
+         self.postMessage({type : type, id : id, owner : owner, title : title});
202
+         break;
203
+      case MSG.MSG_DESTROY_WINDOW:
204
+         // destroy top-level or child window
205
+         var id = io.readInt32BinaryMessage(message, 1);
206
+         var numberImages = io.readInt32BinaryMessage(message, 5);
207
+         var images = new ArrayBuffer(numberImages * 4);
208
+         var imagesView = new Int32Array(images);
209
+         
210
+         for (var i = 0; i < numberImages; i++)
211
+         {
212
+            imagesView[i] = io.readInt32BinaryMessage(message, 9 + (i * 4));
213
+         }
214
+         self.postMessage({type : type, id : id, numberImages : numberImages, images : images},
215
+               [images]);
216
+         break;
217
+      case MSG.MSG_WINDOW_VISIBILITY:
218
+         // change visibility for top-level or child window
219
+         var id = io.readInt32BinaryMessage(message, 1);
220
+         var visible = message[5] === 0 ? false : true;
221
+         self.postMessage({type : type, id : id, visible : visible});
222
+         break;
223
+      // font and metrics related requests
224
+      case MSG.MSG_GET_PAR_HEIGHT:
225
+         // paragraph height
226
+         
227
+         var offset = 1;
228
+         
229
+         var msgId = io.readInt32BinaryMessage(message, offset);
230
+         offset = offset + 4;
231
+         
232
+         var textLength = io.readInt32BinaryMessage(message, offset);
233
+         offset = offset + 4;
234
+
235
+         var text  = io.readStringBinaryMessageByLength(message, offset, textLength);
236
+         offset = offset + textLength * 2;
237
+         
238
+         var font = io.readInt32BinaryMessage(message, offset);
239
+         offset = offset + 4;
240
+
241
+         var maxWidth = io.readInt16BinaryMessage(message, offset);
242
+         offset = offset + 2;
243
+
244
+         self.postMessage(
245
+               {
246
+                  type : type, msgId : msgId, textLength : textLength,
247
+                  text : text, font : font, maxWidth : maxWidth
248
+               });
249
+         break;
250
+      case MSG.MSG_GET_TEXT_HEIGHT:
251
+         // text height
252
+         
253
+         var offset = 1;
254
+
255
+         var msgId = io.readInt32BinaryMessage(message, offset);
256
+         offset = offset + 4;
257
+         
258
+         var textLength = io.readInt32BinaryMessage(message, offset);
259
+         offset = offset + 4;
260
+
261
+         var text  = io.readStringBinaryMessageByLength(message, offset, textLength);
262
+         offset = offset + textLength * 2;
263
+
264
+         var font = io.readInt32BinaryMessage(message, offset);
265
+         
266
+         self.postMessage(
267
+               {
268
+                  type : type, msgId : msgId, textLength : textLength,
269
+                  text : text, font : font
270
+               });
271
+         break;
272
+      case MSG.MSG_GET_TEXT_WIDTH:
273
+         // text width
274
+         var offset = 1;
275
+         
276
+         var msgId = io.readInt32BinaryMessage(message, offset);
277
+         offset = offset + 4;
278
+         
279
+         var textLength = io.readInt32BinaryMessage(message, offset);
280
+         offset = offset + 4;
281
+
282
+         var text  = io.readStringBinaryMessageByLength(message, offset, textLength);
283
+         offset = offset + textLength * 2;
284
+
285
+         var font = io.readInt32BinaryMessage(message, offset);
286
+         offset = offset + 4;
287
+         
288
+         self.postMessage(
289
+               {
290
+                  type : type, msgId : msgId, textLength : textLength,
291
+                  text : text, font : font
292
+               });
293
+         break;
294
+      case MSG.MSG_GET_FONT_HEIGHT:
295
+         // font height
296
+
297
+         var offset = 1;
298
+
299
+         var msgId = io.readInt32BinaryMessage(message, offset);
300
+         offset = offset + 4;
301
+
302
+         var font = io.readInt32BinaryMessage(message, offset);
303
+         offset = offset + 4;
304
+         
305
+         self.postMessage(
306
+               {
307
+                  type : type, msgId : msgId, font : font
308
+               });
309
+         break;
310
+      case MSG.MSG_GET_FONT_WIDTHS:
311
+         // font widths
312
+         var offset = 1;
313
+         
314
+         var msgId = io.readInt32BinaryMessage(message, offset);
315
+         offset = offset + 4;
316
+         
317
+         var font = io.readInt32BinaryMessage(message, offset);
318
+         offset = offset + 4;
319
+         self.postMessage(
320
+               {
321
+                  type : type, msgId : msgId, font : font
322
+               });
323
+         break;
324
+      case MSG.MSG_CREATE_FONT:
325
+         // create font
326
+         var offset = 1;
327
+         
328
+         var msgId = io.readInt32BinaryMessage(message, offset);
329
+         offset = offset + 4;
330
+         
331
+         var font = io.readInt32BinaryMessage(message, offset);
332
+         offset = offset + 4;
333
+         
334
+         var nameLength = io.readInt16BinaryMessage(message, offset);
335
+         offset = offset + 2;
336
+
337
+         var name  = io.readStringBinaryMessageByLength(message, offset, nameLength);
338
+         offset = offset + nameLength * 2;
339
+         
340
+         var size = message[offset];
341
+         offset = offset + 1;
342
+         
343
+         var style = message[offset];
344
+         offset = offset + 1;
345
+         
346
+         var defLength = io.readInt32BinaryMessage(message, offset);
347
+         offset = offset + 4;
348
+         
349
+         var b64font = "";
350
+         if (defLength > 0)
351
+         {
352
+            var binFont = '';
353
+            for (var i = 0; i < defLength; i++)
354
+            {
355
+               binFont += String.fromCharCode(message[offset]);
356
+               offset = offset + 1;
357
+            }
358
+            b64font = self.btoa(binFont);
359
+         }
360
+         
361
+         self.postMessage(
362
+               {
363
+                  type : type, msgId : msgId, font : font, nameLength : nameLength,
364
+                  name : name, size : size, style : style, b64font : b64font
365
+               });
366
+         break;
367
+      case MSG.MSG_DERIVE_FONT:
368
+         // derive font
369
+         var offset = 1;
370
+         
371
+         var msgId = io.readInt32BinaryMessage(message, offset);
372
+         offset = offset + 4;
373
+         
374
+         var font = io.readInt32BinaryMessage(message, offset);
375
+         offset = offset + 4;
376
+         self.postMessage(
377
+               {
378
+                  type : type, msgId : msgId, font : font
379
+               });
380
+         break;
381
+      case MSG.MSG_SET_CURSOR_STYLE:
382
+         // set cursor style
383
+         var styleId = io.readInt32BinaryMessage(message, 1);
384
+         var wid = io.readInt32BinaryMessage(message, 5);
385
+         self.postMessage(
386
+               {
387
+                  type : type, styleId : styleId, wid : wid
388
+               });
389
+         break;
390
+      case MSG.MSG_RESTACK_WINDOWS:
391
+         // restack windows
392
+         var num = io.readInt32BinaryMessage(message, 1);
393
+         var winids = new ArrayBuffer(num * 4);
394
+         var winidsView = new Int32Array(winids);
395
+         for (var i = 0; i < num; i++)
396
+         {
397
+            winidsView[i] = io.readInt32BinaryMessage(message, 5 + (i * 4));
398
+         }
399
+         self.postMessage({type : type, winids : winids}, [winids]);
400
+         break;
401
+      case MSG.PROCESS_MOUSE_WIDGETS:
402
+          // register/deregister widgets for mouse actions
403
+          var offset = 1;
404
+          
405
+          // the number of windows with new widgets
406
+          var windowNo = io.readInt16BinaryMessage(message, offset);
407
+          offset = offset + 2;
408
+          
409
+          for (var j = 0; j < windowNo; j++)
410
+          {
411
+             // the window ID
412
+             var windowID = io.readInt32BinaryMessage(message, offset);
413
+             offset = offset + 4;
414
+             
415
+             // the number of new widgets in this window
416
+             var widgetNo = io.readInt16BinaryMessage(message, offset);
417
+             offset = offset + 2;
418
+
419
+             var widgets = new ArrayBuffer(widgetNo * 4);
420
+             var widgetsView = new Int32Array(widgets);
421
+             
422
+             var xCoords = new ArrayBuffer(widgetNo * 2);
423
+             var xCoordsView = new Int16Array(xCoords);
424
+
425
+             var yCoords = new ArrayBuffer(widgetNo * 2);
426
+             var yCoordsView = new Int16Array(yCoords);
427
+
428
+             var widths = new ArrayBuffer(widgetNo * 2);
429
+             var widthsView = new Int16Array(widths);
430
+
431
+             var heights = new ArrayBuffer(widgetNo * 2);
432
+             var heightsView = new Int16Array(heights);
433
+
434
+             var actions = new ArrayBuffer(widgetNo * 4);
435
+             var actionsView = new Int32Array(actions);
436
+
437
+             for (var k = 0; k < widgetNo; k++)
438
+             {
439
+                // the widget ID
440
+                widgetsView[k] = io.readInt32BinaryMessage(message, offset);
441
+                offset = offset + 4;
442
+
443
+                // the coordinates
444
+                xCoordsView[k] = io.readInt16BinaryMessage(message, offset);
445
+                offset = offset + 2;
446
+                
447
+                yCoordsView[k] = io.readInt16BinaryMessage(message, offset);
448
+                offset = offset + 2;
449
+
450
+                // the size
451
+                widthsView[k] = io.readInt16BinaryMessage(message, offset);
452
+                offset = offset + 2;
453
+
454
+                heightsView[k] = io.readInt16BinaryMessage(message, offset);
455
+                offset = offset + 2;
456
+
457
+                // bit-encoded mouse ops: each bit from 1 to 11, if set, represents a mouse
458
+                // operation as defined in p2j.screen.mouseOps
459
+                actionsView[k] = io.readInt32BinaryMessage(message, offset);
460
+                offset = offset + 4;
461
+             }
462
+             var allWNo = io.readInt16BinaryMessage(message, offset);
463
+             offset = offset + 2;
464
+             var zOrder     = new ArrayBuffer(allWNo * 4);
465
+             var zOrderView = new Int32Array(zOrder);
466
+             
467
+             for (var k = 0; k < allWNo; k++)
468
+             {
469
+               zOrderView[k] = io.readInt32BinaryMessage(message, offset);
470
+               offset = offset + 4;
471
+             }
472
+             self.postMessage(
473
+                   {
474
+                      type : type, label : "registerWidgets", windowID : windowID, widgetNo : widgetNo,
475
+                      widgets : widgets,
476
+                      xCoords : xCoords, yCoords : yCoords,
477
+                      widths: widths, heights : heights,
478
+                      actions : actions,
479
+                      zOrder  : zOrder
480
+                   }, [widgets, xCoords, yCoords, widths, heights, actions, zOrder]);
481
+          }
482
+
483
+          // the number of windows with dead widgets
484
+          windowNo = io.readInt16BinaryMessage(message, offset);
485
+          offset = offset + 2;
486
+          
487
+          for (var j = 0; j < windowNo; j++)
488
+          {
489
+             // the window ID
490
+             var windowID = io.readInt32BinaryMessage(message, offset);
491
+             offset = offset + 4;
492
+             
493
+             // the number of dead widgets in this window
494
+             var widgetNo = io.readInt16BinaryMessage(message, offset);
495
+             
496
+             var widgets = new ArrayBuffer(widgetNo * 4);
497
+             var widgetsView = new Int32Array(widgets);
498
+
499
+             offset = offset + 2;
500
+             
501
+             for (var k = 0; k < widgetNo; k++)
502
+             {
503
+                // the widget ID
504
+                widgetsView[k] = io.readInt32BinaryMessage(message, offset);
505
+                offset = offset + 4;
506
+             }
507
+             self.postMessage(
508
+                   {
509
+                      type : type, label : "deregisterWidgets",
510
+                      windowID : windowID, widgetNo : widgetNo,
511
+                      widgets : widgets
512
+                   }, [widgets]);
513
+          }
514
+
515
+          // the number of windows with new "any widgets"
516
+          windowNo = io.readInt16BinaryMessage(message, offset);
517
+          offset = offset + 2;
518
+          
519
+          for (var j = 0; j < windowNo; j++)
520
+          {
521
+             // the window ID
522
+             var windowID = io.readInt32BinaryMessage(message, offset);
523
+             offset = offset + 4;
524
+             
525
+             // the number of new "any widgets" in this window
526
+             var widgetNo = io.readInt16BinaryMessage(message, offset);
527
+             
528
+             var widgets = new ArrayBuffer(widgetNo * 4);
529
+             var widgetsView = new Int32Array(widgets);
530
+             
531
+             offset = offset + 2;
532
+             
533
+             for (var k = 0; k < widgetNo; k++)
534
+             {
535
+                // the widget ID
536
+                widgetsView[k] = io.readInt32BinaryMessage(message, offset);
537
+                offset = offset + 4;
538
+             }
539
+             self.postMessage(
540
+                   {
541
+                      type : type, label : "registerAnyWidgets",
542
+                      windowID : windowID, widgetNo : widgetNo,
543
+                      widgets : widgets
544
+                   }, [widgets]);
545
+          }
546
+
547
+          // the number of windows with dead "any widgets"
548
+          windowNo = io.readInt16BinaryMessage(message, offset);
549
+          offset = offset + 2;
550
+          
551
+          for (var j = 0; j < windowNo; j++)
552
+          {
553
+             // the window ID
554
+             var windowID = io.readInt32BinaryMessage(message, offset);
555
+             offset = offset + 4;
556
+             
557
+             // the number of dead "any widgets" in this window
558
+             var widgetNo = io.readInt16BinaryMessage(message, offset);
559
+             
560
+             var widgets = new ArrayBuffer(widgetNo * 4);
561
+             var widgetsView = new Int32Array(widgets);
562
+             
563
+             offset = offset + 2;
564
+             
565
+             for (var k = 0; k < widgetNo; k++)
566
+             {
567
+                // the widget ID
568
+                widgetsView[k] = io.readInt32BinaryMessage(message, offset);
569
+                offset = offset + 4;
570
+             }
571
+             self.postMessage(
572
+                   {
573
+                      type : type, label : "deregisterAnyWidgets",
574
+                      windowID : windowID, widgetNo : widgetNo,
575
+                      widgets : widgets,
576
+                      
577
+                   }, [widgets]);
578
+          }
579
+          break;
580
+      case MSG.CAPTURE_MOUSE:
581
+         self.postMessage({type : type, capture : (message[1] == 1)});
582
+         break;
583
+      case MSG.ENABLE_OS_EVENTS:
584
+         // enable/disable OS events
585
+         var wid = io.readInt32BinaryMessage(message, 1);
586
+         self.postMessage(
587
+               {
588
+                  type : type,
589
+                  windowID : wid,
590
+                  enable : message[5] == 1
591
+               });
592
+         break;
593
+      case MSG.SET_ICONIFICATION_STATE:
594
+         // set window iconification state
595
+         var offset = 1;
596
+
597
+         var windowID = io.readInt32BinaryMessage(message, offset);
598
+         self.postMessage(
599
+               {
600
+                  type : type,
601
+                  windowID : windowID,
602
+                  iconified : message[5] == 1
603
+               });
604
+         break;
605
+      case MSG.SET_RESIZEABLE_WINDOW:
606
+         // resizeable window
607
+         var offset = 1;
608
+         
609
+         var windowID = io.readInt32BinaryMessage(message, offset);
610
+         offset = offset + 4;
611
+         
612
+         var resizeable = (message[offset] == 1);
613
+         offset = offset + 1;
614
+         
615
+         var msg = {type : type, windowID : windowID, resizeable : resizeable};
616
+         
617
+         if (resizeable)
618
+         {
619
+            msg.minWidth = io.readInt16BinaryMessage(message, offset);
620
+            offset = offset + 2;
621
+            msg.minHeight = io.readInt16BinaryMessage(message, offset);
622
+            offset = offset + 2;
623
+            msg.maxWidth = io.readInt16BinaryMessage(message, offset);
624
+            offset = offset + 2;
625
+            msg.maxHeight = io.readInt16BinaryMessage(message, offset);
626
+            offset = offset + 2;
627
+         }
628
+         self.postMessage(msg);
629
+         break;
630
+      case MSG.MSG_CURRENT_SELECTION:
631
+         // current editors selection is changed
632
+         var text = io.readStringBinaryMessage(message, 1);
633
+         self.postMessage({type : type, clipboardText : text});
634
+         break;
635
+      case MSG.MSG_MOVE_TO_TOP:
636
+      case MSG.MSG_MOVE_TO_BOTTOM:
637
+         var id = io.readInt32BinaryMessage(message, 1);
638
+         self.postMessage({type : type, windowID : id});
639
+         break;
640
+      case MSG.MSG_WINDOW_SENSITIVITY:
641
+         // change sensitivity for top-level or child window
642
+         var id = io.readInt32BinaryMessage(message, 1);
643
+         var enabled  = message[5] === 0 ? false : true;
644
+         self.postMessage({type : type, windowID : id, enabled : enabled});
645
+         break;
646
+      case MSG.MSG_IS_FONT_INSTALLED:
647
+         // font is installed
648
+         var offset = 1;
649
+         
650
+         var msgId = io.readInt32BinaryMessage(message, offset);
651
+         offset = offset + 4;
652
+         
653
+         var fontNameLength = io.readInt32BinaryMessage(message, offset);
654
+         offset = offset + 4;
655
+         
656
+         var fontName  = io.readStringBinaryMessageByLength(message, offset, fontNameLength);
657
+         
658
+         self.postMessage({type : type, msgId : msgId, fontName : fontName});
659
+         break;
660
+      case MSG.MSG_REMOVE_EXPIRED_HASH:
661
+         // remove hashes
662
+         var offset = 1;
663
+         
664
+         var msgId = io.readInt32BinaryMessage(message, offset);
665
+         offset = offset + 4;
666
+         
667
+         // window ID
668
+         var windowID = io.readInt32BinaryMessage(message, offset);
669
+         offset = offset + 4;
670
+
671
+         // number of hashes
672
+         var hashNo = io.readInt32BinaryMessage(message, offset);
673
+         offset = offset + 4;
674
+         var hashes = message.slice(offset);
675
+         console.debug("hashes buffer length=" + hashes.buffer.byteLength);
676
+         self.postMessage(
677
+               {
678
+                  type : type, msgId : msgId, windowID : windowID, hashNo : hashNo,
679
+                  hashes : hashes.buffer
680
+               }, [hashes.buffer]);
681
+         break;
682
+   };
683
+}
684
+
685
+/**
686
+ * Creates a web socket connection and attaches the error, message and close listeners for it.
687
+ * 
688
+ * @param    {String} url
689
+ *           The web socket connection url
690
+ */
691
+function createWebsocket(url)
692
+{
693
+   ws = new WebSocket(url);
694
+
695
+   /**
696
+    * Handles the web socket open message.
697
+    */
698
+   ws.onopen = function()
699
+   {
700
+      connected = true;
701
+      ws.binaryType = 'arraybuffer';
702
+      
703
+      self.postMessage({type : MSG.MSG_WEB_SOCKET_OPEN});
704
+      
705
+   };
706
+
707
+   /**
708
+    * Handles the web socket data messages.
709
+    */
710
+   ws.onmessage = function(evt)
711
+   {
712
+      var data = evt.data;
713
+      console.debug("evt=" + JSON.stringify(evt));
714
+      console.debug("data=" + JSON.stringify(data));
715
+      if (data instanceof ArrayBuffer)
716
+      {
717
+         // binary messages
718
+         var message = new Uint8Array(data);
719
+         messageHandler(message);
720
+      }
721
+      else
722
+      {
723
+         // text messages
724
+         var msg = JSON.parse(data);
725
+         self.postMessage({type : MSG.MSG_COLOR_PALETTE, msg : msg});
726
+      }
727
+   };
728
+
729
+   /**
730
+    * Handles the web socket close message.
731
+    */
732
+   ws.onclose = function()
733
+   { 
734
+      connected = false;
735
+      self.postMessage({type : MSG.MSG_WEB_SOCKET_CLOSE});
736
+   };
737
+   
738
+   /**
739
+    * Handles the web socket errors.
740
+    */
741
+   ws.onerror = function(ex)
742
+   {
743
+      console.debug("exception=" + ex);
744
+      //self.postMessage({type : MSG.MSG_WEB_SOCKET_ERROR});
745
+   };
746
+}
747
\ No newline at end of file
748

    
749
=== added file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.io.js'
750
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.io.js	1970-01-01 00:00:00 +0000
751
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.io.js	2016-02-09 17:40:29 +0000
752
@@ -0,0 +1,667 @@
753
+/*
754
+** Module   : p2j.io.js
755
+** Abstract : Defines the common message's types and the helper input and output channel.
756
+**
757
+** Copyright (c) 2015-2016, Golden Code Development Corporation.
758
+** ALL RIGHTS RESERVED. Use is subject to license terms.
759
+**
760
+**         Golden Code Development Corporation
761
+**                 CONFIDENTIAL
762
+**
763
+** -#- -I- --Date-- ----------------------Description--------------------------
764
+** 001 SBI 20160209 Reused the common input and output functions under the input and output
765
+**                  channel object.
766
+*/
767
+"use strict";
768
+
769
+/**
770
+ * Defines the common message's types.
771
+ */
772
+var MSG = {
773
+      /** Message that the web page has finished loading/initializing. */
774
+      MSG_PAGE_LOADED : 0xFF,
775
+
776
+      /** Progress compatible keyboard message. */
777
+      MSG_KEY : 0x01,
778
+
779
+      /** Virtual VT100 terminal keyboard message. */
780
+      MSG_KEY_VT100 : 0x02,
781
+
782
+      /** Paste message. */
783
+      MSG_PASTE : 0x03,
784
+
785
+      /** Contents from the clipboard. */
786
+      MSG_CLIPBOARD_CONTENTS : 0x04,
787
+
788
+      /** Web client is requesting the current selection text. */
789
+      MSG_CLIPBOARD_PREPARE : 0x05,
790
+
791
+      /** Web client is sending computed paragraph height. */
792
+      MSG_SENT_PAR_HEIGHT : 0x06,
793
+
794
+      /** Web client is sending computed text height. */
795
+      MSG_SENT_TEXT_HEIGHT : 0x07,
796
+
797
+      /** Web client is sending computed text width. */
798
+      MSG_SENT_TEXT_WIDTH : 0x08,
799
+
800
+      /** Web client is sending computed font height. */
801
+      MSG_SENT_FONT_HEIGHT : 0x09,
802
+
803
+      /** Web client is sending computed font widths. */
804
+      MSG_SENT_FONT_WIDTHS : 0x0A,
805
+
806
+      /** Web client is informing the font has been created. */
807
+      MSG_DONE_CREATE_FONT : 0x0B,
808
+
809
+      /** Web client is informing the font has been derived. */
810
+      MSG_DONE_DERIVE_FONT : 0x0C,
811
+
812
+      /** Web client is informing of a mouse event. */
813
+      MSG_MOUSE_EVENT : 0x0D,
814
+
815
+      /** Web client is informing of new window location. */
816
+      MSG_SET_WINDOW_LOC : 0x0E,
817
+
818
+      /** Web client is informing of new top window. */
819
+      MSG_WINDOW_ACTIVATED : 0x0F,
820
+
821
+      /** Web client is informing of new window iconification state. */
822
+      MSG_WINDOW_ICONIFY : 0x10,
823
+
824
+      /** Web client is informing of new window location/dimension after resize. */
825
+      MSG_WINDOW_RESIZED : 0x11,
826
+
827
+      /** Web client is informing it finished removing the hashes. */
828
+      MSG_DRAW_HASH_REMOVED : 0x12,
829
+
830
+      /** Clear screen message. */
831
+      MSG_CLEAR : 0x80,
832
+
833
+      /** Draw text on screen. */
834
+      MSG_DRAW : 0x81,
835
+
836
+      /** Set cursor position. */
837
+      MSG_CURSOR_POS : 0x82,
838
+
839
+      /** Set cursor status. */
840
+      MSG_CURSOR_STATUS : 0x83,
841
+
842
+      /** Beep message. */
843
+      MSG_BEEP : 0x84,
844
+
845
+      /** Quit message. */
846
+      MSG_QUIT : 0x85,
847
+
848
+      /** Switch input processing to virtual VT100 terminal mode. */
849
+      MSG_VT100 : 0x86,
850
+
851
+      /** Request clipboard contents from web client. */
852
+      MSG_READ_CLIPBOARD : 0x87,
853
+
854
+      /** Copy the given text to the web client's clipboard. */
855
+      MSG_WRITE_CLIPBOARD : 0x88,
856
+
857
+      /** Create a new top-level window. */
858
+      MSG_CREATE_WINDOW : 0x89,
859
+
860
+      /** Create a new child window. */
861
+      MSG_CREATE_CHILD_WINDOW : 0x8A,
862
+
863
+      /** Destroy the specified window or child window. */
864
+      MSG_DESTROY_WINDOW : 0x8B,
865
+
866
+      /** Change the visibility for the specified window or child window. */
867
+      MSG_WINDOW_VISIBILITY : 0x8C,
868
+
869
+      /** Ask the client for the paragraph height. */
870
+      MSG_GET_PAR_HEIGHT : 0x8D,
871
+
872
+      /** Ask the client for the text height. */
873
+      MSG_GET_TEXT_HEIGHT : 0x8E,
874
+
875
+      /** Ask the client for the text width. */
876
+      MSG_GET_TEXT_WIDTH : 0x8F,
877
+
878
+      /** Ask the client for the font height. */
879
+      MSG_GET_FONT_HEIGHT : 0x90,
880
+
881
+      /** Ask the client for the font widths. */
882
+      MSG_GET_FONT_WIDTHS : 0x91,
883
+
884
+      /** Ask the client to create a font. */
885
+      MSG_CREATE_FONT : 0x92,
886
+
887
+      /** Ask the client to derive a font. */
888
+      MSG_DERIVE_FONT : 0x93,
889
+
890
+      /** Set the cursor style. */
891
+      MSG_SET_CURSOR_STYLE : 0x94,
892
+
893
+      /** Restack the z-order of all windows. */
894
+      MSG_RESTACK_WINDOWS : 0x95,
895
+
896
+      /** Send the mouse-aware widget details. */
897
+      PROCESS_MOUSE_WIDGETS : 0x96,
898
+
899
+      /** Disable/enable mouse event processing. */
900
+      CAPTURE_MOUSE : 0x97,
901
+
902
+      /** Disable/enable OS event processing. */
903
+      ENABLE_OS_EVENTS : 0x98,
904
+
905
+      /** Window state changed event. */
906
+      SET_ICONIFICATION_STATE : 0x99,
907
+
908
+      /** Resizeable widget. */
909
+      SET_RESIZEABLE_WINDOW : 0x9A,
910
+
911
+      /** Notifies the client about the current selection. */
912
+      MSG_CURRENT_SELECTION : 0x9B,
913
+
914
+      /** Requests the client to move a window to the top of the z-order. */
915
+      MSG_MOVE_TO_TOP : 0x9C,
916
+
917
+      /** Requests the client to move a window to the bottom of the z-order. */
918
+      MSG_MOVE_TO_BOTTOM : 0x9D,
919
+
920
+      /** Change the sensitivity for the specified window or child window. */
921
+      MSG_WINDOW_SENSITIVITY : 0x9E,
922
+
923
+      /** Requests the client if the target font is installed. */
924
+      MSG_IS_FONT_INSTALLED : 0x9F,
925
+
926
+      /** Inform the javascript side to remove the list of expired hashes. */
927
+      MSG_REMOVE_EXPIRED_HASH : 0xA0,
928
+      
929
+      /** Color palette message. */
930
+      MSG_COLOR_PALETTE : 0xA5,
931
+      
932
+      /** WEB SOCKET CLOSE */
933
+      MSG_WEB_SOCKET_OPEN : 0xA1,
934
+      
935
+      /** WEB SOCKET CLOSE */
936
+      MSG_WEB_SOCKET_CLOSE : 0xA2,
937
+      
938
+      /** WEB SOCKET ERROR */
939
+      MSG_WEB_SOCKET_ERROR : 0xA3,
940
+      
941
+      /** WEB SOCKET SEND */
942
+      MSG_WEB_SOCKET_SEND : 0xA4,
943
+      
944
+    };
945
+
946
+/**
947
+ * Input and output channel.
948
+ * 
949
+ * @param    {Function} callback
950
+ *           The callback function to which all output operations are deligated.
951
+ * 
952
+ * @return   {Object}
953
+ *           The helper input and output channel.
954
+ */
955
+function InputOutputChannel(callback)
956
+{
957
+   
958
+   var me = {};
959
+   
960
+   /**
961
+    * Send data.
962
+    * 
963
+    * @param {array}
964
+    *           data
965
+    */
966
+   me.send = function(data)
967
+   {
968
+      callback(data);
969
+   };
970
+
971
+   /**
972
+    * Send a binary message with the given message type as the first and only
973
+    * byte.
974
+    * 
975
+    * @param {byte}
976
+    *           type Message type code.
977
+    */
978
+   me.sendNotification = function(type)
979
+   {
980
+      var msg = new Uint8Array(1);
981
+      msg[0] = type;
982
+      
983
+      me.send(msg);
984
+   };
985
+   
986
+   /**
987
+    * Sends the window active event to the server.
988
+    * 
989
+    * @param {Number}
990
+    *           wid The target window id
991
+    * @param {Boolean}
992
+    *           active The flag indicating that the target window should be
993
+    *           active or not.
994
+    * @param {Boolean}
995
+    *           focusOut The true value indicates that the current focus is
996
+    *           moved from a non P2J window to a P2J window for an activation
997
+    *           event or from a P2j window to a non P2j window for a
998
+    *           deactivation event.
999
+    */
1000
+   me.sendWindowActive = function(wid, active, focusOut)
1001
+   {
1002
+      // send the window activation/deactivation to the java side
1003
+      var msg = new Uint8Array(7);
1004
+      
1005
+      // message type
1006
+      msg[0] = 0x0f;
1007
+      
1008
+      // 1. the window ID
1009
+      me.writeInt32BinaryMessage(msg, 1, wid);
1010
+      
1011
+      msg[5] = active   ? 1 : 0;
1012
+      msg[6] = focusOut ? 1 : 0;
1013
+      
1014
+      // send the window active event
1015
+      me.send(msg);
1016
+   }
1017
+   
1018
+   /**
1019
+    * Sends the window icon state event to the server.
1020
+    * 
1021
+    * @param {Number}
1022
+    *           wid The target window id.
1023
+    * @param {Boolean}
1024
+    *           minimized The target window has been minimized.
1025
+    */
1026
+   me.sendWindowIconState = function(wid, minimized)
1027
+   {
1028
+      var msg = new Uint8Array(6);
1029
+      
1030
+      // message type
1031
+      msg[0] = 0x10;
1032
+      
1033
+      // 0. the window ID
1034
+      me.writeInt32BinaryMessage(msg, 1, wid);
1035
+      
1036
+      // 1. the iconification state
1037
+      msg[5] = minimized ? 1 : 0;
1038
+      
1039
+      // send the mouse event
1040
+      me.send(msg);
1041
+   }
1042
+   
1043
+   /**
1044
+    * Send a binary message with the given message type and the specified byte array serialized.
1045
+    *
1046
+    * @param    {byte} type
1047
+    *           Message type code.
1048
+    * @param    {int} msgId
1049
+    *           The message ID.
1050
+    * @param    {c} c
1051
+    *           The array to send.
1052
+    */
1053
+   me.sendByteArrayBinaryMessage = function(type, msgId, c)
1054
+   {
1055
+      var msg = new Uint8Array(1 + 4 + 2 + c.length);
1056
+
1057
+      var offset = 0;
1058
+      msg[offset] = type;
1059
+      offset = offset + 1;
1060
+
1061
+      me.writeInt32BinaryMessage(msg, offset, msgId);
1062
+      offset = offset + 4;
1063
+      
1064
+      msg[offset] = c.length & 0xff;
1065
+      offset = offset + 1;
1066
+      msg[offset] = (c.length >> 8) & 0xff
1067
+      offset = offset + 1;
1068
+      
1069
+      for (var i = 0; i < c.length; i++)
1070
+      {
1071
+         msg[offset] = c[i] & 0xff;
1072
+         offset = offset + 1;
1073
+      }
1074
+      
1075
+      me.send(msg);
1076
+   };
1077
+   
1078
+   /**
1079
+    * Send a binary message with the given message type and the specified byte as the second byte.
1080
+    *
1081
+    * @param    {byte} type
1082
+    *           Message type code.
1083
+    * @param    {int} msgId
1084
+    *           The message ID.
1085
+    * @param    {c} c
1086
+    *           The byte to send.
1087
+    */
1088
+   me.sendInt8BinaryMessage = function(type, msgId, c)
1089
+   {
1090
+      var msg = new Uint8Array(1 + 4 + 1);
1091
+
1092
+      msg[0] = type;
1093
+      me.writeInt32BinaryMessage(msg, 1, msgId);
1094
+      msg[5] = c;
1095
+      
1096
+      me.send(msg);
1097
+   };
1098
+
1099
+   /**
1100
+    * Send a binary message with the given message type and the specified 16bit integer as the 
1101
+    * second and third bytes.
1102
+    *
1103
+    * @param    {byte} type
1104
+    *           Message type code.
1105
+    * @param    {int} msgId
1106
+    *           The message ID.
1107
+    * @param    {c} c
1108
+    *           The 16bit integer to send.
1109
+    */
1110
+   me.sendInt16BinaryMessage = function(type, msgId, c)
1111
+   {
1112
+      var msg = new Uint8Array(1 + 4 + 2);
1113
+
1114
+      msg[0] = type;
1115
+      me.writeInt32BinaryMessage(msg, 1, msgId);
1116
+      me.writeInt16BinaryMessage(msg, 5, c);
1117
+      
1118
+      me.send(msg);
1119
+   };
1120
+
1121
+   /**
1122
+    * Send a binary message with the given message type and the specified 32bit integer as the 
1123
+    * second, third, forth and fifth bytes.
1124
+    *
1125
+    * @param    {byte} type
1126
+    *           Message type code.
1127
+    * @param    {int} msgId
1128
+    *           The message ID.
1129
+    * @param    {c} c
1130
+    *           The 32bit integer to send.
1131
+    */
1132
+   me.sendInt32BinaryMessage = function(type, msgId, c)
1133
+   {
1134
+      var msg = new Uint8Array(1 + 4 + 4);
1135
+
1136
+      msg[0] = type;
1137
+      me.writeInt32BinaryMessage(msg, 1, msgId);
1138
+      me.writeInt32BinaryMessage(msg, 5, c);
1139
+      
1140
+      me.send(msg);
1141
+   };
1142
+
1143
+   /**
1144
+    * Send text as a binary message with the given message type as the first byte.
1145
+    *
1146
+    * @param    {byte} type
1147
+    *           Message type code.
1148
+    * @param    {String} text
1149
+    *           The text to send.
1150
+    */
1151
+   me.sendStringBinaryMessage = function(type, text)
1152
+   {
1153
+      var msg = new Uint8Array(text.length * 2 + 1);
1154
+      msg[0] = type;
1155
+
1156
+      for (var i = 0, j = 1; i < text.length; i++, j += 2)
1157
+      {
1158
+         var c = text.charCodeAt(i);
1159
+         msg[j + 1] = c & 0xff;
1160
+         c = c >> 8;
1161
+         msg[j] = c & 0xff;
1162
+      }
1163
+      
1164
+      me.send(msg);
1165
+   };
1166
+   
1167
+   /**
1168
+    * Read text from a binary message with characters interpreted as 16-bit values.
1169
+    *
1170
+    * @param    {byte[]} message
1171
+    *           Message bytes.
1172
+    * @param    {int} offset
1173
+    *           The location in the message at which the characters start.
1174
+    */
1175
+   me.readStringBinaryMessage = function(message, offset)
1176
+   {
1177
+      var text = "";
1178
+
1179
+      for (var i = offset; i < message.length; i += 2)
1180
+      {
1181
+         var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
1182
+         
1183
+         text = text + c;
1184
+      }
1185
+      
1186
+      return text;
1187
+   };
1188
+   
1189
+   /**
1190
+    * Read text from a binary message with characters interpreted as 16-bit values, with the
1191
+    * specified length
1192
+    *
1193
+    * @param    {byte[]} message
1194
+    *           Message bytes.
1195
+    * @param    {int} offset
1196
+    *           The location in the message at which the characters start.
1197
+    * @param    {len} length
1198
+    *           The length of the string.
1199
+    */
1200
+   me.readStringBinaryMessageByLength = function(message, offset, len)
1201
+   {
1202
+      var text = "";
1203
+
1204
+      for (var i = offset; i < offset + len * 2; i += 2)
1205
+      {
1206
+         var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
1207
+         
1208
+         text = text + c;
1209
+      }
1210
+      
1211
+      return text;
1212
+   };
1213
+   
1214
+   /**
1215
+    * Read a 32-bit integer from a binary message at a specific offset.
1216
+    *
1217
+    * @param    {byte[]} message
1218
+    *           Message bytes.
1219
+    * @param    {int} offset
1220
+    *           The location in the message at which the characters start.
1221
+    *
1222
+    * @return   The number that was read.
1223
+    */
1224
+   me.readInt32BinaryMessage = function(message, offset)
1225
+   {
1226
+      var num = 0;
1227
+
1228
+      for (var i = 0; i < 4; i++)
1229
+      {
1230
+         num |= message[offset + i] << (8 * (3 - i));
1231
+      }
1232
+      
1233
+      return num;
1234
+   };
1235
+
1236
+   /**
1237
+    * Write a 64-bit integer to a binary message at a specific offset.
1238
+    * 
1239
+    * @param    {byte[]} message
1240
+    *           Message bytes.
1241
+    * @param    {int} offset
1242
+    *           The location in the message at which the characters start.
1243
+    * @param    {int} value
1244
+    *           The value to write.
1245
+    */
1246
+   me.writeInt64BinaryMessage = function(message, offset, value)
1247
+   {
1248
+      // javascript keeps all numbers as decimal, with:
1249
+      // - the fraction in bits from 0 to 51
1250
+      // - the exponent in bits from 52 to 62
1251
+      // - the sign in bit 63
1252
+      
1253
+      // for this reason, use the hex representation to transform it into 2 32bit integer values
1254
+      // and send the high and low bits separately.
1255
+      var hex = value.toString(16);
1256
+
1257
+      // left-pad with zeros
1258
+      while (hex.length < 16)
1259
+      {
1260
+         hex = "0" + hex;
1261
+      }
1262
+
1263
+      var hexHigh = hex.substring(0, 8);
1264
+      var hexLow = hex.substring(8, 16);
1265
+
1266
+      var ihigh = parseInt(hexHigh, 16);
1267
+      var ilow = parseInt(hexLow, 16);
1268
+
1269
+      // clear high bits 20 to 30 (52 to 62, the exponent) 
1270
+      for (var i = 20; i <= 30; i++)
1271
+      {
1272
+         ihigh = ihigh & ~(1 << i);
1273
+      }
1274
+
1275
+      me.writeInt32BinaryMessage(message, offset, ihigh);
1276
+      offset = offset + 4;
1277
+      me.writeInt32BinaryMessage(message, offset, ilow);
1278
+      offset = offset + 4;
1279
+   }
1280
+
1281
+   /**
1282
+    * Write a 32-bit integer to a binary message at a specific offset.
1283
+    *
1284
+    * @param    {byte[]} message
1285
+    *           Message bytes.
1286
+    * @param    {int} offset
1287
+    *           The location in the message at which the characters start.
1288
+    * @param    {int} value
1289
+    *           The value to write.
1290
+    */
1291
+   me.writeInt32BinaryMessage = function(message, offset, value)
1292
+   {
1293
+      message[offset]     = ((value >> 24) & 0xFF);
1294
+      message[offset + 1] = ((value >> 16) & 0xFF);
1295
+      message[offset + 2] = ((value >>  8) & 0xFF);
1296
+      message[offset + 3] = ( value        & 0xFF);
1297
+   }
1298
+
1299
+   /**
1300
+    * Write a 16-bit integer to a binary message at a specific offset.
1301
+    *
1302
+    * @param    {byte[]} message
1303
+    *           Message bytes.
1304
+    * @param    {int} offset
1305
+    *           The location in the message at which the characters start.
1306
+    * @param    {int} value
1307
+    *           The value to write.
1308
+    */
1309
+   me.writeInt16BinaryMessage = function(message, offset, value)
1310
+   {
1311
+      message[offset]     = ((value >> 8)  & 0xFF);
1312
+      message[offset + 1] = ( value        & 0xFF);
1313
+   }
1314
+   
1315
+   /**
1316
+    * Read a 16-bit integer from a binary message at a specific offset.
1317
+    *
1318
+    * @param    {byte[]} message
1319
+    *           Message bytes.
1320
+    * @param    {int} offset
1321
+    *           The location in the message at which the characters start.
1322
+    *
1323
+    * @return   The number that was read.
1324
+    */
1325
+   me.readInt16BinaryMessage = function(message, offset)
1326
+   {
1327
+      var num = 0;
1328
+
1329
+      for (var i = 0; i < 2; i++)
1330
+      {
1331
+         num |= message[offset + i] << (8 * (1 - i));
1332
+      }
1333
+      
1334
+      return num;
1335
+   };
1336
+
1337
+   /**
1338
+    * Parse a hex string and return its byte array.
1339
+    *
1340
+    * @param    {String} str
1341
+    *           The hex-encoded string.
1342
+    *
1343
+    * @return   {Uint8Array} byte-array for the given string.
1344
+    */
1345
+   me.hexStringToBytes = function(str)
1346
+   {
1347
+      var bytes = new Uint8Array(str.length / 2);
1348
+
1349
+      var idx = 0;
1350
+      for (var c = 0, idx = 0; c < str.length; c += 2, idx++)
1351
+      { 
1352
+         bytes[idx] = parseInt(str.substr(c, 2), 16);
1353
+      }
1354
+      
1355
+      return bytes;
1356
+    }
1357
+   
1358
+   /**
1359
+    * Create a hex string from the given byte array.
1360
+    *
1361
+    * @param    {Uint8Array}  arr
1362
+    *           The byte array.
1363
+    *
1364
+    * @return   Hex representation of the given byte array.
1365
+    */
1366
+   me.createHexString = function(arr)
1367
+   {
1368
+      var result = "";
1369
+      for (var i in arr)
1370
+      {
1371
+         var str = arr[i].toString(16);
1372
+         str = str.length == 0 ? "00" :
1373
+               str.length == 1 ? "0" + str : 
1374
+               str.length == 2 ? str :
1375
+               str.substring(str.length-2, str.length);
1376
+               
1377
+         result += str;
1378
+      }
1379
+      
1380
+      return result;
1381
+   }
1382
+   
1383
+   /**
1384
+    * Remove the sub-array from the given array and save it in the splice parameter.
1385
+    *
1386
+    * @param    {array}  arr
1387
+    *           The byte array from where elements are removed.
1388
+    * @param    {int} starting
1389
+    *           The starting position (inclusive).
1390
+    * @param    {int} deleteCount
1391
+    *           The number of elements to delete.
1392
+    * @param    {array} splice
1393
+    *           The array where to save the elements (must have enough space).
1394
+    *
1395
+    * @return   The original array with the elements removed.
1396
+    */
1397
+   me.splice = function(arr, starting, deleteCount, splice)
1398
+   {
1399
+      if (arguments.length === 1)
1400
+      {
1401
+         return arr;
1402
+      }
1403
+      
1404
+      starting = Math.max(starting, 0);
1405
+      deleteCount = Math.max(deleteCount, 0);
1406
+
1407
+      const newSize = arr.length - deleteCount;
1408
+      const splicedArray = new arr.constructor(newSize);
1409
+
1410
+      splicedArray.set(arr.subarray(0, starting));
1411
+      splicedArray.set(arr.subarray(starting + deleteCount), starting);
1412
+      
1413
+      splice.set(arr.subarray(starting, starting + deleteCount));
1414
+      
1415
+      return splicedArray;
1416
+   };
1417
+
1418
+   return me;
1419
+}
1420
\ No newline at end of file
1421

    
1422
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js'
1423
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js	2016-02-03 21:22:52 +0000
1424
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js	2016-02-09 20:05:13 +0000
1425
@@ -41,7 +41,9 @@
1426
 **     SBI 20160107 Supported new message with 0x9F id to test if the target font family is
1427
 **                  available for the browser.
1428
 **     CA  20160629 Added a drawing cache (and cache management, when the hash was expired by the
1429
-*                   client-side).
1430
+**                   client-side).
1431
+**     SBi 20160209 Changed to put the web socket processing in the dedicated web worker thread
1432
+**                  in order to send the large binary messages in packets.
1433
 */
1434
 
1435
 "use strict";
1436
@@ -66,6 +68,24 @@
1437
    /** The count of the drawing operations. */
1438
    var drawNo = 0;
1439
 
1440
+   /** Web worker */
1441
+   var webWorker;
1442
+   
1443
+   /** Input and output channel */
1444
+   var io = InputOutputChannel(
1445
+         function(data)
1446
+         {
1447
+            if (connected) 
1448
+            {
1449
+               webWorker.postMessage({type : MSG.MSG_WEB_SOCKET_SEND, message: data}, [data.buffer]);
1450
+            }
1451
+            else
1452
+            {
1453
+               p2j.sound.beep();
1454
+            }
1455
+         });
1456
+   
1457
+   
1458
    /**
1459
     * Send data.
1460
     * 
1461
@@ -73,14 +93,7 @@
1462
     */
1463
    me.send = function(data)
1464
    {
1465
-      if (connected) 
1466
-      {
1467
-         ws.send(data);
1468
-      }
1469
-      else
1470
-      {
1471
-         p2j.sound.beep();
1472
-      }
1473
+      io.send(data);
1474
    };
1475
 
1476
    /**
1477
@@ -91,10 +104,7 @@
1478
     */
1479
    me.sendNotification = function(type)
1480
    {
1481
-      var msg = new Uint8Array(1);
1482
-      msg[0] = type;
1483
-      
1484
-      me.send(msg);
1485
+      io.sendNotification(type);
1486
    };
1487
    
1488
    /**
1489
@@ -111,20 +121,7 @@
1490
     */
1491
    me.sendWindowActive = function(wid, active, focusOut)
1492
    {
1493
-      // send the window activation/deactivation to the java side
1494
-      var msg = new Uint8Array(7);
1495
-      
1496
-      // message type
1497
-      msg[0] = 0x0f;
1498
-      
1499
-      // 1. the window ID
1500
-      me.writeInt32BinaryMessage(msg, 1, wid);
1501
-      
1502
-      msg[5] = active   ? 1 : 0;
1503
-      msg[6] = focusOut ? 1 : 0;
1504
-      
1505
-      // send the window active event
1506
-      me.send(msg);
1507
+      io.sendWindowActive(wid, active, focusOut);
1508
    }
1509
    
1510
    /**
1511
@@ -137,19 +134,7 @@
1512
     */
1513
    me.sendWindowIconState = function(wid, minimized)
1514
    {
1515
-      var msg = new Uint8Array(6);
1516
-      
1517
-      // message type
1518
-      msg[0] = 0x10;
1519
-      
1520
-      // 0. the window ID
1521
-      me.writeInt32BinaryMessage(msg, 1, wid);
1522
-      
1523
-      // 1. the iconification state
1524
-      msg[5] = minimized ? 1 : 0;
1525
-      
1526
-      // send the mouse event
1527
-      me.send(msg);
1528
+      io.sendWindowIconState(wid, minimized);
1529
    }
1530
    
1531
    /**
1532
@@ -164,27 +149,7 @@
1533
     */
1534
    me.sendByteArrayBinaryMessage = function(type, msgId, c)
1535
    {
1536
-      var msg = new Uint8Array(1 + 4 + 2 + c.length);
1537
-
1538
-      var offset = 0;
1539
-      msg[offset] = type;
1540
-      offset = offset + 1;
1541
-
1542
-      me.writeInt32BinaryMessage(msg, offset, msgId);
1543
-      offset = offset + 4;
1544
-      
1545
-      msg[offset] = c.length & 0xff;
1546
-      offset = offset + 1;
1547
-      msg[offset] = (c.length >> 8) & 0xff
1548
-      offset = offset + 1;
1549
-      
1550
-      for (var i = 0; i < c.length; i++)
1551
-      {
1552
-         msg[offset] = c[i] & 0xff;
1553
-         offset = offset + 1;
1554
-      }
1555
-      
1556
-      me.send(msg);
1557
+      io.sendByteArrayBinaryMessage(type, msgId, c);
1558
    };
1559
    
1560
    /**
1561
@@ -199,13 +164,7 @@
1562
     */
1563
    me.sendInt8BinaryMessage = function(type, msgId, c)
1564
    {
1565
-      var msg = new Uint8Array(1 + 4 + 1);
1566
-
1567
-      msg[0] = type;
1568
-      me.writeInt32BinaryMessage(msg, 1, msgId);
1569
-      msg[5] = c;
1570
-      
1571
-      me.send(msg);
1572
+      io.sendInt8BinaryMessage(type, msgId, c);
1573
    };
1574
 
1575
    /**
1576
@@ -221,13 +180,7 @@
1577
     */
1578
    me.sendInt16BinaryMessage = function(type, msgId, c)
1579
    {
1580
-      var msg = new Uint8Array(1 + 4 + 2);
1581
-
1582
-      msg[0] = type;
1583
-      me.writeInt32BinaryMessage(msg, 1, msgId);
1584
-      me.writeInt16BinaryMessage(msg, 5, c);
1585
-      
1586
-      me.send(msg);
1587
+      io.sendInt16BinaryMessage(type, msgId, c);
1588
    };
1589
 
1590
    /**
1591
@@ -243,13 +196,7 @@
1592
     */
1593
    me.sendInt32BinaryMessage = function(type, msgId, c)
1594
    {
1595
-      var msg = new Uint8Array(1 + 4 + 4);
1596
-
1597
-      msg[0] = type;
1598
-      me.writeInt32BinaryMessage(msg, 1, msgId);
1599
-      me.writeInt32BinaryMessage(msg, 5, c);
1600
-      
1601
-      me.send(msg);
1602
+      io.sendInt32BinaryMessage(type, msgId, c);
1603
    };
1604
 
1605
    /**
1606
@@ -262,18 +209,7 @@
1607
     */
1608
    me.sendStringBinaryMessage = function(type, text)
1609
    {
1610
-      var msg = new Uint8Array(text.length * 2 + 1);
1611
-      msg[0] = type;
1612
-
1613
-      for (var i = 0, j = 1; i < text.length; i++, j += 2)
1614
-      {
1615
-         var c = text.charCodeAt(i);
1616
-         msg[j + 1] = c & 0xff;
1617
-         c = c >> 8;
1618
-         msg[j] = c & 0xff;
1619
-      }
1620
-      
1621
-      me.send(msg);
1622
+      io.sendStringBinaryMessage(type, text);
1623
    };
1624
    
1625
    /**
1626
@@ -286,16 +222,7 @@
1627
     */
1628
    me.readStringBinaryMessage = function(message, offset)
1629
    {
1630
-      var text = "";
1631
-
1632
-      for (var i = offset; i < message.length; i += 2)
1633
-      {
1634
-         var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
1635
-         
1636
-         text = text + c;
1637
-      }
1638
-      
1639
-      return text;
1640
+      return io.readStringBinaryMessage(message, offset);
1641
    };
1642
    
1643
    /**
1644
@@ -311,16 +238,7 @@
1645
     */
1646
    me.readStringBinaryMessageByLength = function(message, offset, len)
1647
    {
1648
-      var text = "";
1649
-
1650
-      for (var i = offset; i < offset + len * 2; i += 2)
1651
-      {
1652
-         var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
1653
-         
1654
-         text = text + c;
1655
-      }
1656
-      
1657
-      return text;
1658
+      return io.readStringBinaryMessageByLength(message, offset, len);
1659
    };
1660
    
1661
    /**
1662
@@ -335,14 +253,7 @@
1663
     */
1664
    me.readInt32BinaryMessage = function(message, offset)
1665
    {
1666
-      var num = 0;
1667
-
1668
-      for (var i = 0; i < 4; i++)
1669
-      {
1670
-         num |= message[offset + i] << (8 * (3 - i));
1671
-      }
1672
-      
1673
-      return num;
1674
+      return io.readInt32BinaryMessage(message, offset)
1675
    };
1676
 
1677
    /**
1678
@@ -357,37 +268,7 @@
1679
     */
1680
    me.writeInt64BinaryMessage = function(message, offset, value)
1681
    {
1682
-      // javascript keeps all numbers as decimal, with:
1683
-      // - the fraction in bits from 0 to 51
1684
-      // - the exponent in bits from 52 to 62
1685
-      // - the sign in bit 63
1686
-      
1687
-      // for this reason, use the hex representation to transform it into 2 32bit integer values
1688
-      // and send the high and low bits separately.
1689
-      var hex = value.toString(16);
1690
-
1691
-      // left-pad with zeros
1692
-      while (hex.length < 16)
1693
-      {
1694
-         hex = "0" + hex;
1695
-      }
1696
-
1697
-      var hexHigh = hex.substring(0, 8);
1698
-      var hexLow = hex.substring(8, 16);
1699
-
1700
-      var ihigh = parseInt(hexHigh, 16);
1701
-      var ilow = parseInt(hexLow, 16);
1702
-
1703
-      // clear high bits 20 to 30 (52 to 62, the exponent) 
1704
-      for (var i = 20; i <= 30; i++)
1705
-      {
1706
-         ihigh = ihigh & ~(1 << i);
1707
-      }
1708
-
1709
-      me.writeInt32BinaryMessage(message, offset, ihigh);
1710
-      offset = offset + 4;
1711
-      me.writeInt32BinaryMessage(message, offset, ilow);
1712
-      offset = offset + 4;
1713
+      io.writeInt64BinaryMessage(message, offset, value);
1714
    }
1715
 
1716
    /**
1717
@@ -402,10 +283,7 @@
1718
     */
1719
    me.writeInt32BinaryMessage = function(message, offset, value)
1720
    {
1721
-      message[offset]     = ((value >> 24) & 0xFF);
1722
-      message[offset + 1] = ((value >> 16) & 0xFF);
1723
-      message[offset + 2] = ((value >>  8) & 0xFF);
1724
-      message[offset + 3] = ( value        & 0xFF);
1725
+      io.writeInt32BinaryMessage(message, offset, value);
1726
    }
1727
 
1728
    /**
1729
@@ -420,8 +298,7 @@
1730
     */
1731
    me.writeInt16BinaryMessage = function(message, offset, value)
1732
    {
1733
-      message[offset]     = ((value >> 8)  & 0xFF);
1734
-      message[offset + 1] = ( value        & 0xFF);
1735
+      io.writeInt16BinaryMessage(message, offset, value);
1736
    }
1737
    
1738
    /**
1739
@@ -436,15 +313,271 @@
1740
     */
1741
    me.readInt16BinaryMessage = function(message, offset)
1742
    {
1743
-      var num = 0;
1744
+      return io.readInt16BinaryMessage(message, offset);
1745
+   };
1746
+   
1747
+   /** Web worker message handler */
1748
+   var messageHandler = function(message)
1749
+   {
1750
+      callNo = callNo + 1;
1751
+      console.log(callNo + ": " + message.type.toString(16));
1752
 
1753
-      for (var i = 0; i < 2; i++)
1754
+      switch (message.type)
1755
       {
1756
-         num |= message[offset + i] << (8 * (1 - i));
1757
-      }
1758
-      
1759
-      return num;
1760
-   };
1761
+         case MSG.MSG_CLEAR:
1762
+            // clear screen 
1763
+            p2j.screen.clear();
1764
+            break;
1765
+         case MSG.MSG_DRAW:
1766
+            drawNo = drawNo + 1;
1767
+            // draw screen
1768
+            var t1 = (new Date()).getTime();
1769
+            console.debug("drawBuffer.length=" + message.drawBuffer.byteLength);
1770
+            var binaries = new Uint8Array(message.drawBuffer); 
1771
+            p2j.screen.drawRectangles(binaries, message.md5);
1772
+            var t2 = (new Date()).getTime();
1773
+            console.log(callNo + ":" + drawNo + " draw: " + message.drawBuffer.byteLength
1774
+                  + " done in " + (t2 - t1) + " with md5: " + message.md5);
1775
+            break;
1776
+         case MSG.MSG_CURSOR_POS:
1777
+            // set cursor position
1778
+            p2j.screen.setCursorPosition(message.col, message.row);
1779
+            break;
1780
+         case MSG.MSG_CURSOR_STATUS:
1781
+            // show cursor
1782
+            p2j.screen.setCursorStatus(message.status);
1783
+            break;
1784
+         case MSG.MSG_BEEP:
1785
+            // message beep
1786
+            p2j.sound.beep();
1787
+            break;
1788
+         case MSG.MSG_QUIT:
1789
+            // quit
1790
+            window.location.replace(referrer);
1791
+            break;
1792
+         case MSG.MSG_VT100:
1793
+            // switch mode p2j/vt100
1794
+            p2j.keyboard.vt100 = (message[1] == 0) ? false : true;
1795
+            break;
1796
+         case MSG.MSG_READ_CLIPBOARD:
1797
+            // server-driven request for clipboard contents
1798
+            p2j.clipboard.sendClipboardContents();
1799
+            break;
1800
+         case MSG.MSG_WRITE_CLIPBOARD:
1801
+            // The clipboard is changed.
1802
+            p2j.clipboard.writeClipboard(message.clipboardText);
1803
+            break;
1804
+         case MSG.MSG_CREATE_WINDOW:
1805
+            // create a top-level window with the given id
1806
+            p2j.screen.createWindow(message.id);
1807
+            break;
1808
+         case MSG.MSG_CREATE_CHILD_WINDOW:
1809
+            // create a child window with the given id, owner and title
1810
+            p2j.screen.createChildWindow(message.id, message.owner);
1811
+            break;
1812
+         case MSG.MSG_DESTROY_WINDOW:
1813
+            // destroy top-level or child window
1814
+            var imagesView = new Int32Array(message.images);
1815
+            p2j.screen.destroyWindow(message.id, imagesView);
1816
+            break;
1817
+         case MSG.MSG_WINDOW_VISIBILITY:
1818
+            // change visibility for top-level or child window
1819
+            p2j.screen.setWindowVisible(message.id, message.visible);
1820
+            break;
1821
+         // font and metrics related requests
1822
+         case MSG.MSG_GET_PAR_HEIGHT:
1823
+            // paragraph height
1824
+            var pheight = p2j.screen.layoutParagraphWorker(null,
1825
+                                                           message.text,
1826
+                                                           message.font, 
1827
+                                                           0,
1828
+                                                           0, 
1829
+                                                           message.maxWidth);
1830
+
1831
+            me.sendInt16BinaryMessage(MSG.MSG_SENT_PAR_HEIGHT, message.msgId, pheight);
1832
+            break;
1833
+         case MSG.MSG_GET_TEXT_HEIGHT:
1834
+            // text height
1835
+            var theight = p2j.fonts.getTextHeight(message.font, message.text);
1836
+            
1837
+            me.sendInt8BinaryMessage(MSG.MSG_SENT_TEXT_HEIGHT, message.msgId, theight);
1838
+            break;
1839
+         case MSG.MSG_GET_TEXT_WIDTH:
1840
+            // text width
1841
+            var twidth = p2j.fonts.getTextWidth(message.font, message.text);
1842
+            
1843
+            me.sendInt16BinaryMessage(MSG.MSG_SENT_TEXT_WIDTH, message.msgId, twidth);
1844
+            break;
1845
+         case MSG.MSG_GET_FONT_HEIGHT:
1846
+            // font height
1847
+            var fheight = p2j.fonts.getFontHeight(message.font);
1848
+            
1849
+            me.sendInt8BinaryMessage(MSG.MSG_SENT_FONT_HEIGHT, message.msgId, fheight);
1850
+            break;
1851
+         case MSG.MSG_GET_FONT_WIDTHS:
1852
+            // font widths
1853
+            var fwidths = p2j.fonts.getFontWidths(message.font);
1854
+            
1855
+            me.sendByteArrayBinaryMessage(MSG.MSG_SENT_FONT_WIDTHS, message.msgId, fwidths);
1856
+            break;
1857
+         case MSG.MSG_CREATE_FONT:
1858
+            // create font
1859
+            var fontId = p2j.fonts.createFont(message.font, message.name, message.size,
1860
+                  message.style, message.b64font);
1861
+            
1862
+            me.sendInt32BinaryMessage(MSG.MSG_DONE_CREATE_FONT, message.msgId, fontId);
1863
+            break;
1864
+         case MSG.MSG_DERIVE_FONT:
1865
+            // derive font
1866
+            p2j.fonts.deriveFont(message.font);
1867
+            
1868
+            me.sendInt8BinaryMessage(MSG.MSG_DONE_DERIVE_FONT, message.msgId, 1);
1869
+            break;
1870
+         case MSG.MSG_SET_CURSOR_STYLE:
1871
+            // set cursor style
1872
+            p2j.screen.setCursorStyle(message.styleId, message.wid);
1873
+            break;
1874
+         case MSG.MSG_RESTACK_WINDOWS:
1875
+            // restack windows
1876
+            var winidsView = new Int32Array(message.winids);
1877
+            p2j.screen.restackZOrderEntries(winidsView);
1878
+            break;
1879
+         case MSG.PROCESS_MOUSE_WIDGETS:
1880
+             // register/deregister widgets for mouse actions
1881
+            if (!p2j.screen.isExistingWindowId(message.windowID))
1882
+            {
1883
+               console.log("undefined window " + message.windowID);
1884
+               break;
1885
+            }
1886
+            var theWindow = p2j.screen.getWindow(message.windowID);
1887
+            var widgetsView = new Int32Array(message.widgets);
1888
+
1889
+            switch(message.label)
1890
+            {
1891
+               case "registerWidgets":
1892
+                  var actionsView = new Int32Array(message.actions);
1893
+                  var xCoordsView = new Int16Array(message.xCoords);
1894
+                  var yCoordsView = new Int16Array(message.yCoords);
1895
+                  var widthsView  = new Int16Array(message.widths);
1896
+                  var heightsView = new Int16Array(message.heights);
1897
+                  for (var k = 0; k < message.widgetNo; k++)
1898
+                  {
1899
+                     theWindow.deregisterMouseWidget(widgetsView[k]);
1900
+                     theWindow.registerMouseWidget(
1901
+                            widgetsView[k], xCoordsView[k], yCoordsView[k],
1902
+                            widthsView[k], heightsView[k], actionsView[k]);
1903
+                  }
1904
+                  var zOrderView = new Int32Array(message.zOrder);
1905
+                  theWindow.setWidgetZOrder(Array.prototype.slice.call(zOrderView));
1906
+                  break;
1907
+               case "registerAnyWidgets":
1908
+                  for (var k = 0; k < message.widgetNo; k++)
1909
+                  {
1910
+                     theWindow.deregisterAnyMouseWidget(widgetsView[k]);
1911
+                     theWindow.registerAnyMouseWidget(widgetsView[k]);
1912
+                  }
1913
+                  break;
1914
+               case "derigisterWidgets":
1915
+                  for (var k = 0; k < message.widgetNo; k++)
1916
+                  {
1917
+                     theWindow.deregisterMouseWidget(widgetsView[k]);
1918
+                  }
1919
+                  break;
1920
+               case "derigisterAnyWidgets":
1921
+                  for (var k = 0; k < message.widgetNo; k++)
1922
+                  {
1923
+                     theWindow.deregisterAnyMouseWidget(widgetsView[k]);
1924
+                  }
1925
+                  break;
1926
+            }
1927
+            break;
1928
+         case MSG.CAPTURE_MOUSE:
1929
+            // enable/disable mouse events
1930
+            p2j.screen.captureMouseEvents(message.capture);
1931
+            break;
1932
+         case MSG.ENABLE_OS_EVENTS:
1933
+            // enable/disable OS events
1934
+            p2j.screen.enableOsEvents(message.windowID, message.enable);
1935
+            break;
1936
+         case MSG.SET_ICONIFICATION_STATE:
1937
+            var theWindow = p2j.screen.getWindow(message.windowID);
1938
+            //p2j.logger.log("recieved 0x99: iconified = " + message.iconified + " windowId=" + message.windowID);
1939
+            if (message.iconified)
1940
+            {
1941
+               theWindow.iconify();
1942
+            }
1943
+            else
1944
+            {
1945
+               theWindow.deiconify();
1946
+            }
1947
+            break;
1948
+         case MSG.SET_RESIZEABLE_WINDOW:
1949
+            // resizeable window
1950
+            var theWindow = p2j.screen.getWindow(message.windowID);
1951
+
1952
+            theWindow.resizeable = message.resizeable;
1953
+            
1954
+            if (message.resizeable)
1955
+            {
1956
+               theWindow.minWidth  = message.minWidth;
1957
+               theWindow.minHeight = message.minHeight;
1958
+               theWindow.maxWidth  = message.maxWidth;
1959
+               theWindow.maxHeight = message.maxHeight;
1960
+            }
1961
+            else
1962
+            {
1963
+               var rect = theWindow.canvas.getBoundingClientRect();
1964
+
1965
+               var rwidth  = rect.right - rect.left + 1;
1966
+               var rheight = rect.bottom - rect.top + 1;
1967
+               
1968
+               theWindow.minWidth = rwidth;
1969
+               theWindow.minHeight = rheight;
1970
+
1971
+               theWindow.maxWidth = rwidth;
1972
+               theWindow.maxHeight = rheight;
1973
+            }
1974
+            
1975
+            break;
1976
+         case MSG.MSG_CURRENT_SELECTION:
1977
+            // current editors selection is changed
1978
+            p2j.clipboard.setSelection(message.clipboardText);
1979
+            break;
1980
+         case MSG.MSG_MOVE_TO_TOP:
1981
+            p2j.screen.moveToTop(message.windowID);
1982
+            break;
1983
+         case MSG.MSG_MOVE_TO_BOTTOM:
1984
+            p2j.screen.moveToBottom(message.windowID);
1985
+            break;
1986
+         case MSG.MSG_WINDOW_SENSITIVITY:
1987
+            // change sensitivity for top-level or child window
1988
+            p2j.screen.setWindowEnabled(message.windowID, message.enabled);
1989
+            break;
1990
+         case MSG.MSG_IS_FONT_INSTALLED:
1991
+            // font is installed
1992
+            var result = p2j.fonts.isFontInstalled(message.fontName);
1993
+            
1994
+            me.sendInt8BinaryMessage(MSG.MSG_IS_FONT_INSTALLED, message.msgId, result ? 1 : 0);
1995
+            break;
1996
+         case MSG.MSG_REMOVE_EXPIRED_HASH:
1997
+            // remove hashes
1998
+            var theWindow = p2j.screen.getWindow(message.windowID);
1999
+            var hashes = new Uint8Array(message.hashes);
2000
+            var offset = 0;
2001
+            for (var i = 0; i < message.hashNo; i++)
2002
+            {
2003
+               // read each hash and remove it
2004
+               var hashBytes = hashes.slice(offset, offset + 16);
2005
+               var hash = io.createHexString(hashBytes);
2006
+               delete theWindow.removeCachedDraw(hash);
2007
+               
2008
+               offset += 16;
2009
+            }
2010
+            
2011
+            me.sendInt8BinaryMessage(MSG.MSG_DRAW_HASH_REMOVED, message.msgId, 1);
2012
+            break;
2013
+      };
2014
+   }
2015
    
2016
    /**
2017
     * Initialize module.
2018
@@ -454,639 +587,77 @@
2019
    me.init = function(cfg)
2020
    {      
2021
       referrer = cfg.referrer;
2022
+
2023
+      webWorker = new Worker("/common/p2j.connector.js");
2024
       
2025
-      if ('WebSocket' in window)
2026
+      /** 
2027
+       * Handles messages from the dedicated web worker.
2028
+       * 
2029
+       * @param    {MessageEvent} evt
2030
+       *           The message from the web worker.
2031
+       */
2032
+      var webWorkerHandler = function(evt)
2033
       {
2034
-         ws = new WebSocket(cfg.socket.url);
2035
-
2036
-         // on web socket open
2037
-         ws.onopen = function()
2038
-         {
2039
-            connected = true;
2040
-            ws.binaryType = 'arraybuffer';
2041
-
2042
-            // notify the web socket has opened and the page is loaded
2043
-            me.sendNotification(0xff);
2044
-         };
2045
-
2046
-         /** Web socket message handler */
2047
-         var messageHandler = function(message)
2048
-         {
2049
-            callNo = callNo + 1;
2050
-            console.log(callNo + ": " + message[0].toString(16));
2051
-
2052
-            switch (message[0])
2053
-            {
2054
-               case 0x80:
2055
-                  // clear screen 
2056
-                  p2j.screen.clear();                        
2057
-                  break;
2058
-               case 0x81:
2059
-                  // remove the MD5 code and save it here
2060
-                  var md5a = new message.constructor(16);
2061
-                  message = splice(message, 1, 16, md5a);
2062
-                  var md5 = me.createHexString(md5a);
2063
-                  
2064
-                  drawNo = drawNo + 1;
2065
-                  // draw screen
2066
-                  var t1 = (new Date()).getTime();
2067
-                  p2j.screen.drawRectangles(message, md5);
2068
-                  var t2 = (new Date()).getTime();
2069
-                  console.log(callNo + ":" + drawNo + " draw: " + message.length + " done in " + (t2 - t1) + " with md5: " + md5);
2070
-                  break;
2071
-               case 0x82:
2072
-                  // set cursor position
2073
-                  p2j.screen.setCursorPosition(message[1], message[2]);                        
2074
-                  break;
2075
-               case 0x83:
2076
-                  // show cursor
2077
-                  p2j.screen.setCursorStatus(message[1]);                        
2078
-                  break;
2079
-               case 0x84:
2080
-                  // message beep
2081
-                  p2j.sound.beep();                        
2082
-                  break;
2083
-               case 0x85:
2084
-                  // quit
2085
-                  window.location.replace(referrer);                        
2086
-                  break;
2087
-               case 0x86:
2088
-                  // switch mode p2j/vt100
2089
-                  p2j.keyboard.vt100 = (message[1] == 0) ? false : true;          
2090
-                  break;
2091
-               case 0x87:
2092
-                  // server-driven request for clipboard contents
2093
-                  p2j.clipboard.sendClipboardContents();          
2094
-                  break;
2095
-               case 0x88:
2096
-                  // The clipboard is changed.
2097
-                  var text = me.readStringBinaryMessage(message, 1);
2098
-                  p2j.clipboard.writeClipboard(text);
2099
-                  break;
2100
-               case 0x89:
2101
-                  // create a top-level window with the given id
2102
-                  var id = me.readInt32BinaryMessage(message, 1);
2103
-                  p2j.screen.createWindow(id);
2104
-                  break;
2105
-               case 0x8A:
2106
-                  // create a child window with the given id, owner and title
2107
-                  var id    = me.readInt32BinaryMessage(message, 1);
2108
-                  var owner = me.readInt32BinaryMessage(message, 5);
2109
-                  var title = me.readStringBinaryMessage(message, 9);
2110
-                  p2j.screen.createChildWindow(id, owner);
2111
-                  break;
2112
-               case 0x8B:
2113
-                  // destroy top-level or child window
2114
-                  var id = me.readInt32BinaryMessage(message, 1);
2115
-                  var numberImages = me.readInt32BinaryMessage(message, 5);
2116
-                  var images = [];
2117
-                  for (var i = 0; i < numberImages; i++)
2118
-                  {
2119
-                     images[i] = me.readInt32BinaryMessage(message, 9 + (i * 4));
2120
-                  }
2121
-                  p2j.screen.destroyWindow(id, images);
2122
-                  break;
2123
-               case 0x8C:
2124
-                  // change visibility for top-level or child window
2125
-                  var id = me.readInt32BinaryMessage(message, 1);
2126
-                  var visible = message[5] === 0 ? false : true;
2127
-                  p2j.screen.setWindowVisible(id, visible);
2128
-                  break;
2129
-                  
2130
-               // font and metrics related requests
2131
-               case 0x8D:
2132
-                  // paragraph height
2133
-                  
2134
-                  var offset = 1;
2135
-                  
2136
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2137
-                  offset = offset + 4;
2138
-                  
2139
-                  var textLength = me.readInt32BinaryMessage(message, offset);
2140
-                  offset = offset + 4;
2141
-
2142
-                  var text  = me.readStringBinaryMessageByLength(message, offset, textLength);
2143
-                  offset = offset + textLength * 2;
2144
-                  
2145
-                  var font = me.readInt32BinaryMessage(message, offset);
2146
-                  offset = offset + 4;
2147
-
2148
-                  var maxWidth = me.readInt16BinaryMessage(message, offset);
2149
-                  offset = offset + 2;
2150
-
2151
-                  var pheight = p2j.screen.layoutParagraphWorker(null,
2152
-                                                                 text,
2153
-                                                                 font, 
2154
-                                                                 0,
2155
-                                                                 0, 
2156
-                                                                 maxWidth);
2157
-
2158
-                  me.sendInt16BinaryMessage(0x06, msgId, pheight);
2159
-                  break;
2160
-               case 0x8E:
2161
-                  // text height
2162
-                  
2163
-                  var offset = 1;
2164
-
2165
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2166
-                  offset = offset + 4;
2167
-                  
2168
-                  var textLength = me.readInt32BinaryMessage(message, offset);
2169
-                  offset = offset + 4;
2170
-
2171
-                  var text  = me.readStringBinaryMessageByLength(message, offset, textLength);
2172
-                  offset = offset + textLength * 2;
2173
-
2174
-                  var font = me.readInt32BinaryMessage(message, offset);
2175
-                  
2176
-                  var theight = p2j.fonts.getTextHeight(font, text);
2177
-
2178
-                  me.sendInt8BinaryMessage(0x07, msgId, theight);
2179
-                  break;
2180
-               case 0x8F:
2181
-                  // text width
2182
-
2183
-                  var offset = 1;
2184
-                  
2185
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2186
-                  offset = offset + 4;
2187
-                  
2188
-                  var textLength = me.readInt32BinaryMessage(message, offset);
2189
-                  offset = offset + 4;
2190
-
2191
-                  var text  = me.readStringBinaryMessageByLength(message, offset, textLength);
2192
-                  offset = offset + textLength * 2;
2193
-
2194
-                  var font = me.readInt32BinaryMessage(message, offset);
2195
-                  offset = offset + 4;
2196
-                  
2197
-                  var twidth = p2j.fonts.getTextWidth(font, text);
2198
-                  
2199
-                  me.sendInt16BinaryMessage(0x08, msgId, twidth);
2200
-                  break;
2201
-               case 0x90:
2202
-                  // font height
2203
-
2204
-                  var offset = 1;
2205
-
2206
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2207
-                  offset = offset + 4;
2208
-
2209
-                  var font = me.readInt32BinaryMessage(message, offset);
2210
-                  offset = offset + 4;
2211
-                  
2212
-                  var fheight = p2j.fonts.getFontHeight(font);
2213
-                  
2214
-                  me.sendInt8BinaryMessage(0x09, msgId, fheight);
2215
-                  break;
2216
-               case 0x91:
2217
-                  // font widths
2218
-
2219
-                  var offset = 1;
2220
-                  
2221
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2222
-                  offset = offset + 4;
2223
-                  
2224
-                  var font = me.readInt32BinaryMessage(message, offset);
2225
-                  offset = offset + 4;
2226
-                  
2227
-                  var fwidths = p2j.fonts.getFontWidths(font);
2228
-                  
2229
-                  me.sendByteArrayBinaryMessage(0x0A, msgId, fwidths);
2230
-                  break;
2231
-               case 0x92:
2232
-                  // create font
2233
-
2234
-                  var offset = 1;
2235
-                  
2236
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2237
-                  offset = offset + 4;
2238
-                  
2239
-                  var font = me.readInt32BinaryMessage(message, offset);
2240
-                  offset = offset + 4;
2241
-                  
2242
-                  var nameLength = me.readInt16BinaryMessage(message, offset);
2243
-                  offset = offset + 2;
2244
-
2245
-                  var name  = me.readStringBinaryMessageByLength(message, offset, nameLength);
2246
-                  offset = offset + nameLength * 2;
2247
-                  
2248
-                  var size = message[offset];
2249
-                  offset = offset + 1;
2250
-                  
2251
-                  var style = message[offset];
2252
-                  offset = offset + 1;
2253
-                  
2254
-                  var defLength = me.readInt32BinaryMessage(message, offset);
2255
-                  offset = offset + 4;
2256
-                  
2257
-                  var b64font = "";
2258
-                  if (defLength > 0)
2259
-                  {
2260
-                     var binFont = '';
2261
-                     for (var i = 0; i < defLength; i++)
2262
-                     {
2263
-                        binFont += String.fromCharCode(message[offset]);
2264
-                        offset = offset + 1;
2265
-                     }
2266
-                     b64font = window.btoa(binFont);
2267
-                  }
2268
-
2269
-                  var fontId = p2j.fonts.createFont(font, name, size, style, b64font);
2270
-                  
2271
-                  me.sendInt32BinaryMessage(0x0B, msgId, fontId);
2272
-                  break;
2273
-               case 0x93:
2274
-                  // derive font
2275
-
2276
-                  var offset = 1;
2277
-                  
2278
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2279
-                  offset = offset + 4;
2280
-                  
2281
-                  var font = me.readInt32BinaryMessage(message, offset);
2282
-                  offset = offset + 4;
2283
-
2284
-                  p2j.fonts.deriveFont(font);
2285
-                   
2286
-                  me.sendInt8BinaryMessage(0x0C, msgId, 1);
2287
-                  break;
2288
-               case 0x94:
2289
-                  // set cursor style
2290
-                  var styleId = me.readInt32BinaryMessage(message, 1);
2291
-                  var wid = me.readInt32BinaryMessage(message, 5);
2292
-                  p2j.screen.setCursorStyle(styleId, wid);
2293
-                  break;
2294
-               case 0x95:
2295
-                  // restack windows
2296
-                  var num = me.readInt32BinaryMessage(message, 1);
2297
-                  var winids = [];
2298
-                  for (var i = 0; i < num; i++)
2299
-                  {
2300
-                     winids.push(me.readInt32BinaryMessage(message, 5 + (i * 4)));
2301
-                  }
2302
-                  p2j.screen.restackZOrderEntries(winids);
2303
-                  break;
2304
-               case 0x96:
2305
-                   // register/deregister widgets for mouse actions
2306
-                   
2307
-                   var offset = 1;
2308
-                   
2309
-                   // the number of windows with new widgets
2310
-                   var windowNo = me.readInt16BinaryMessage(message, offset);
2311
-                   offset = offset + 2;
2312
-                   
2313
-                   for (var j = 0; j < windowNo; j++)
2314
-                   {
2315
-                      // the window ID
2316
-                      var windowID = me.readInt32BinaryMessage(message, offset);
2317
-                      offset = offset + 4;
2318
-                      
2319
-                      if (!p2j.screen.isExistingWindowId(windowID))
2320
-                      {
2321
-                         console.log("undefined window " + windowID);
2322
-                         continue;
2323
-                      }
2324
-                      
2325
-                      var theWindow = p2j.screen.getWindow(windowID);
2326
-                      
2327
-                      // the number of new widgets in this window
2328
-                      var widgetNo = me.readInt16BinaryMessage(message, offset);
2329
-                      offset = offset + 2;
2330
-                      
2331
-                      for (var k = 0; k < widgetNo; k++)
2332
-                      {
2333
-                         // the widget ID
2334
-                         var wid = me.readInt32BinaryMessage(message, offset);
2335
-                         offset = offset + 4;
2336
-
2337
-                         // the coordinates
2338
-                         var x = me.readInt16BinaryMessage(message, offset);
2339
-                         offset = offset + 2;
2340
-                         
2341
-                         var y = me.readInt16BinaryMessage(message, offset);
2342
-                         offset = offset + 2;
2343
-         
2344
-                         // the size
2345
-                         var width = me.readInt16BinaryMessage(message, offset);
2346
-                         offset = offset + 2;
2347
-         
2348
-                         var height = me.readInt16BinaryMessage(message, offset);
2349
-                         offset = offset + 2;
2350
-         
2351
-                         // bit-encoded mouse ops: each bit from 1 to 11, if set, represents a mouse
2352
-                         // operation as defined in p2j.screen.mouseOps
2353
-                         var actions = me.readInt32BinaryMessage(message, offset);
2354
-                         offset = offset + 4;
2355
-                         theWindow.deregisterMouseWidget(wid);
2356
-                         theWindow.registerMouseWidget(wid, x, y, width, height, actions);
2357
-                      }
2358
-                      
2359
-                      var allWNo = me.readInt16BinaryMessage(message, offset);
2360
-                      offset = offset + 2;
2361
-                      var zOrder = [];
2362
-                      
2363
-                      for (var k = 0; k < allWNo; k++)
2364
-                      {
2365
-                        zOrder[k] = me.readInt32BinaryMessage(message, offset);
2366
-                        offset = offset + 4;
2367
-                      }
2368
-                      
2369
-                      theWindow.setWidgetZOrder(zOrder);
2370
-                   }
2371
-   
2372
-                   // the number of windows with dead widgets
2373
-                   windowNo = me.readInt16BinaryMessage(message, offset);
2374
-                   offset = offset + 2;
2375
-                   
2376
-                   for (var j = 0; j < windowNo; j++)
2377
-                   {
2378
-                      // the window ID
2379
-                      var windowID = me.readInt32BinaryMessage(message, offset);
2380
-                      offset = offset + 4;
2381
-                      
2382
-                      var theWindow = p2j.screen.getWindow(windowID);
2383
-                      
2384
-                      if (theWindow == undefined)
2385
-                      {
2386
-                         console.log("undefined window" + windowID);
2387
-                         continue;
2388
-                      }
2389
-                      
2390
-                      // the number of dead widgets in this window
2391
-                      var widgetNo = me.readInt16BinaryMessage(message, offset);
2392
-                      offset = offset + 2;
2393
-                      
2394
-                      for (var k = 0; k < widgetNo; k++)
2395
-                      {
2396
-                         // the widget ID
2397
-                         var wid = me.readInt32BinaryMessage(message, offset);
2398
-                         offset = offset + 4;
2399
-
2400
-                         theWindow.deregisterMouseWidget(wid);
2401
-                      }
2402
-                   }
2403
-
2404
-                   // the number of windows with new "any widgets"
2405
-                   windowNo = me.readInt16BinaryMessage(message, offset);
2406
-                   offset = offset + 2;
2407
-                   
2408
-                   for (var j = 0; j < windowNo; j++)
2409
-                   {
2410
-                      // the window ID
2411
-                      var windowID = me.readInt32BinaryMessage(message, offset);
2412
-                      offset = offset + 4;
2413
-                      
2414
-                      if (!p2j.screen.isExistingWindowId(windowID))
2415
-                      {
2416
-                         console.log("undefined window " + windowID);
2417
-                         continue;
2418
-                      }
2419
-                      
2420
-                      var theWindow = p2j.screen.getWindow(windowID);
2421
-                      
2422
-                      // the number of new "any widgets" in this window
2423
-                      var widgetNo = me.readInt16BinaryMessage(message, offset);
2424
-                      offset = offset + 2;
2425
-                      
2426
-                      for (var k = 0; k < widgetNo; k++)
2427
-                      {
2428
-                         // the widget ID
2429
-                         var wid = me.readInt32BinaryMessage(message, offset);
2430
-                         offset = offset + 4;
2431
-                         theWindow.deregisterAnyMouseWidget(wid);
2432
-                         theWindow.registerAnyMouseWidget(wid);
2433
-                      }
2434
-                   }
2435
-   
2436
-                   // the number of windows with dead "any widgets"
2437
-                   windowNo = me.readInt16BinaryMessage(message, offset);
2438
-                   offset = offset + 2;
2439
-                   
2440
-                   for (var j = 0; j < windowNo; j++)
2441
-                   {
2442
-                      // the window ID
2443
-                      var windowID = me.readInt32BinaryMessage(message, offset);
2444
-                      offset = offset + 4;
2445
-                      
2446
-                      var theWindow = p2j.screen.getWindow(windowID);
2447
-                      
2448
-                      if (theWindow == undefined)
2449
-                      {
2450
-                         console.log("undefined window" + windowID);
2451
-                         continue;
2452
-                      }
2453
-                      
2454
-                      // the number of dead "any widgets" in this window
2455
-                      var widgetNo = me.readInt16BinaryMessage(message, offset);
2456
-                      offset = offset + 2;
2457
-                      
2458
-                      for (var k = 0; k < widgetNo; k++)
2459
-                      {
2460
-                         // the widget ID
2461
-                         var wid = me.readInt32BinaryMessage(message, offset);
2462
-                         offset = offset + 4;
2463
-
2464
-                         theWindow.deregisterAnyMouseWidget(wid);
2465
-                      }
2466
-                   }
2467
-
2468
-                   break;
2469
-               case 0x97:
2470
-                  // enable/disable mouse events
2471
-                  p2j.screen.captureMouseEvents(message[1] == 1);
2472
-                  break;
2473
-               case 0x98:
2474
-                  // enable/disable OS events
2475
-                  var wid = me.readInt32BinaryMessage(message, 1);
2476
-                  p2j.screen.enableOsEvents(wid, message[5] == 1);
2477
-                  break;
2478
-               case 0x99:
2479
-                  // set window iconification state
2480
-                  var offset = 1;
2481
-
2482
-                  var windowID = me.readInt32BinaryMessage(message, offset);
2483
-                  offset = offset + 4;
2484
-                  
2485
-                  var iconified = (message[offset] == 1);
2486
-                  offset = offset + 1;
2487
-                  
2488
-                  var theWindow = p2j.screen.getWindow(windowID);
2489
-                  //p2j.logger.log("recieved 0x99: iconified = " + iconified + " windowId=" + windowID);
2490
-                  if (iconified)
2491
-                  {
2492
-                     theWindow.iconify();
2493
-                  }
2494
-                  else
2495
-                  {
2496
-                     theWindow.deiconify();
2497
-                  }
2498
-
2499
-                  break;
2500
-               case 0x9A:
2501
-                  // resizeable window
2502
-                  var offset = 1;
2503
-                  
2504
-                  var windowID = me.readInt32BinaryMessage(message, offset);
2505
-                  offset = offset + 4;
2506
-                  
2507
-                  var theWindow = p2j.screen.getWindow(windowID);
2508
-
2509
-                  theWindow.resizeable = (message[offset] == 1);
2510
-                  offset = offset + 1;
2511
-                  
2512
-                  if (theWindow.resizeable)
2513
-                  {
2514
-                     theWindow.minWidth = me.readInt16BinaryMessage(message, offset);
2515
-                     offset = offset + 2;
2516
-                     theWindow.minHeight = me.readInt16BinaryMessage(message, offset);
2517
-                     offset = offset + 2;
2518
-                     
2519
-                     theWindow.maxWidth = me.readInt16BinaryMessage(message, offset);
2520
-                     offset = offset + 2;
2521
-                     theWindow.maxHeight = me.readInt16BinaryMessage(message, offset);
2522
-                     offset = offset + 2;
2523
-                  }
2524
-                  else
2525
-                  {
2526
-                     var rect = theWindow.canvas.getBoundingClientRect();
2527
-
2528
-                     var rwidth  = rect.right - rect.left + 1;
2529
-                     var rheight = rect.bottom - rect.top + 1;
2530
-                     
2531
-                     theWindow.minWidth = rwidth;
2532
-                     theWindow.minHeight = rheight;
2533
-
2534
-                     theWindow.maxWidth = rwidth;
2535
-                     theWindow.maxHeight = rheight;
2536
-                  }
2537
-                  
2538
-                  break;
2539
-               case 0x9B:
2540
-                  // current editors selection is changed
2541
-                  var text = me.readStringBinaryMessage(message, 1);
2542
-                  p2j.clipboard.setSelection(text);
2543
-                  break;
2544
-               case 0x9C:
2545
-                  var id = me.readInt32BinaryMessage(message, 1);
2546
-                  p2j.screen.moveToTop(id);
2547
-                  break;
2548
-               case 0x9D:
2549
-                  var id = me.readInt32BinaryMessage(message, 1);
2550
-                  p2j.screen.moveToBottom(id);
2551
-                  break;
2552
-               case 0x9E:
2553
-                  // change sensitivity for top-level or child window
2554
-                  var id = me.readInt32BinaryMessage(message, 1);
2555
-                  var enabled  = message[5] === 0 ? false : true;
2556
-                  p2j.screen.setWindowEnabled(id, enabled);
2557
-                  break;
2558
-               case 0x9F:
2559
-                  // font is installed
2560
-                  var offset = 1;
2561
-                  
2562
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2563
-                  offset = offset + 4;
2564
-                  
2565
-                  var fontNameLength = me.readInt32BinaryMessage(message, offset);
2566
-                  offset = offset + 4;
2567
-
2568
-                  var fontName  = me.readStringBinaryMessageByLength(message, offset, fontNameLength);
2569
-                  
2570
-                  var result = p2j.fonts.isFontInstalled(fontName);
2571
-                  
2572
-                  me.sendInt8BinaryMessage(0x9F, msgId, result ? 1 : 0);
2573
-                  break;
2574
-               case 0xA0:
2575
-                  // remove hashes
2576
-                  var offset = 1;
2577
-                  
2578
-                  var msgId = me.readInt32BinaryMessage(message, offset);
2579
-                  offset = offset + 4;
2580
-                  
2581
-                  // window ID
2582
-                  var windowID = me.readInt32BinaryMessage(message, offset);
2583
-                  offset = offset + 4;
2584
-
2585
-                  // number of hashes
2586
-                  var hashNo = me.readInt32BinaryMessage(message, offset);
2587
-                  offset = offset + 4;
2588
-                  
2589
-                  var theWindow = p2j.screen.getWindow(windowID);
2590
-                  
2591
-                  for (var i = 0; i < hashNo; i++)
2592
-                  {
2593
-                     // read each hash and remove it
2594
-                     var hashBytes = message.slice(offset, offset + 16);
2595
-                     var hash = me.createHexString(hashBytes);
2596
-                     delete theWindow.removeCachedDraw(hash);
2597
-                     
2598
-                     offset += 16;
2599
-                  }
2600
-                  
2601
-                  me.sendInt8BinaryMessage(0x12, msgId, 1);
2602
-                  break;
2603
-            };
2604
-         };
2605
-         // on web socket message
2606
-         ws.onmessage = function(evt)
2607
-         {
2608
-            var data = evt.data;
2609
-            
2610
-            if (data instanceof ArrayBuffer)
2611
-            {
2612
-               // binary messages
2613
-               var message = new Uint8Array(data);
2614
-               var isDrawing = message[0] === 0x81;
2615
-               if (isDrawing)
2616
-               {
2617
-                  p2j.displayWaitCursor();
2618
-               }
2619
-               setTimeout(function() { messageHandler(message); }, 1);
2620
-               if (isDrawing)
2621
-               {
2622
-                  setTimeout(function() { p2j.restoreCursor(); }, 1);
2623
-               }
2624
-            }
2625
-            else
2626
-            {
2627
-               // text messages
2628
-               var pay = JSON.parse(data);
2629
+         var data = evt.data;
2630
+         switch(data.type)
2631
+         {
2632
+            case MSG.MSG_WEB_SOCKET_ERROR:
2633
+               p2j.screen.error('WebSockets are NOT supported by your Browser.');
2634
+               webWorker.terminate();
2635
+               break;
2636
+            case MSG.MSG_COLOR_PALETTE:
2637
                setTimeout(
2638
                      function()
2639
                      {
2640
-                        switch (pay.c)
2641
+                        switch (data.msg.c)
2642
                         {
2643
                            case 0:
2644
                               // color palette
2645
-                              p2j.screen.palette = pay.p;
2646
+                              p2j.screen.palette = data.msg.p;
2647
                               break;
2648
                         };
2649
                      }, 1);
2650
-            }
2651
+               break;
2652
+            case MSG.MSG_WEB_SOCKET_OPEN:
2653
+               // on web socket open
2654
+               connected = true;
2655
+               webWorker.postMessage({type: MSG.MSG_PAGE_LOADED});
2656
+               break;
2657
+            case MSG.MSG_WEB_SOCKET_CLOSE:
2658
+               // on web socket close
2659
+               connected = false;
2660
+               p2j.screen.error('Connection closed by remote host.'); 
2661
+               window.setInterval(function() { window.location.replace(referrer); }, 5000);
2662
+               break;
2663
+            case MSG.MSG_DRAW:
2664
+               p2j.displayWaitCursor();
2665
+               setTimeout(
2666
+                     function()
2667
+                     {
2668
+                        messageHandler(data);
2669
+                     }, 1);
2670
+               setTimeout(function() { p2j.restoreCursor(); }, 1);
2671
+               break;
2672
+            default:
2673
+               setTimeout(
2674
+                     function()
2675
+                     {
2676
+                        messageHandler(data);
2677
+                     }, 1);
2678
          }
2679
-
2680
-         // on web socket close
2681
-         ws.onclose = function()
2682
-         { 
2683
-            connected = false;
2684
-            p2j.screen.error('Connection closed by remote host.'); 
2685
-            window.setInterval(function() { window.location.replace(referrer); }, 5000);
2686
-         };
2687
-         
2688
-         // refresh
2689
-         window.onpagehide = function() 
2690
-         {
2691
-            if (connected)
2692
-            {
2693
-               ws.close();
2694
-            }
2695
-         };                  
2696
-      } 
2697
-      else 
2698
+      };
2699
+      
2700
+      /** Added the web worker message listener */
2701
+      webWorker.addEventListener("message", webWorkerHandler);
2702
+      
2703
+      // Directs the web worker to open a web socket connection
2704
+      webWorker.postMessage({type: MSG.MSG_WEB_SOCKET_OPEN, url : cfg.socket.url});
2705
+      
2706
+      // refresh
2707
+      window.onpagehide = function() 
2708
       {
2709
-         p2j.screen.error('WebSockets are NOT supported by your Browser.');
2710
-      }      
2711
+         webWorker.postMessage({type: MSG.MSG_WEB_SOCKET_CLOSE});
2712
+      };
2713
    };
2714
 
2715
    /**
2716
@@ -1099,15 +670,7 @@
2717
     */
2718
    me.hexStringToBytes = function(str)
2719
    {
2720
-      var bytes = new Uint8Array(str.length / 2);
2721
-
2722
-      var idx = 0;
2723
-      for (var c = 0, idx = 0; c < str.length; c += 2, idx++)
2724
-      { 
2725
-         bytes[idx] = parseInt(str.substr(c, 2), 16);
2726
-      }
2727
-      
2728
-      return bytes;
2729
+      return io.hexStringToBytes(str);
2730
     }
2731
    
2732
    /**
2733
@@ -1120,55 +683,8 @@
2734
     */
2735
    me.createHexString = function(arr)
2736
    {
2737
-      var result = "";
2738
-      for (var i in arr)
2739
-      {
2740
-         var str = arr[i].toString(16);
2741
-         str = str.length == 0 ? "00" :
2742
-               str.length == 1 ? "0" + str : 
2743
-               str.length == 2 ? str :
2744
-               str.substring(str.length-2, str.length);
2745
-               
2746
-         result += str;
2747
-      }
2748
-      
2749
-      return result;
2750
+      return io.createHexString(arr);
2751
    }
2752
    
2753
-   /**
2754
-    * Remove the sub-array from the given array and save it in the splice parameter.
2755
-    *
2756
-    * @param    {array}  arr
2757
-    *           The byte array from where elements are removed.
2758
-    * @param    {int} starting
2759
-    *           The starting position (inclusive).
2760
-    * @param    {int} deleteCount
2761
-    *           The number of elements to delete.
2762
-    * @param    {array} splice
2763
-    *           The array where to save the elements (must have enough space).
2764
-    *
2765
-    * @return   The original array with the elements removed.
2766
-    */
2767
-   function splice(arr, starting, deleteCount, splice)
2768
-   {
2769
-      if (arguments.length === 1)
2770
-      {
2771
-         return arr;
2772
-      }
2773
-      
2774
-      starting = Math.max(starting, 0);
2775
-      deleteCount = Math.max(deleteCount, 0);
2776
-
2777
-      const newSize = arr.length - deleteCount;
2778
-      const splicedArray = new arr.constructor(newSize);
2779
-
2780
-      splicedArray.set(arr.subarray(0, starting));
2781
-      splicedArray.set(arr.subarray(starting + deleteCount), starting);
2782
-      
2783
-      splice.set(arr.subarray(starting, starting + deleteCount));
2784
-      
2785
-      return splicedArray;
2786
-   };
2787
-
2788
    return me;
2789
 }());
2790