1
|
=== added file 'src/com/goldencode/p2j/ui/client/chui/driver/web/res/p2j.mouse.js'
|
2
|
--- src/com/goldencode/p2j/ui/client/chui/driver/web/res/p2j.mouse.js 1970-01-01 00:00:00 +0000
|
3
|
+++ src/com/goldencode/p2j/ui/client/chui/driver/web/res/p2j.mouse.js 2016-06-06 06:02:53 +0000
|
4
|
@@ -0,0 +1,15 @@
|
5
|
+/*
|
6
|
+** Module : p2j.mouse.js
|
7
|
+** Abstract : CHUI mouse support module
|
8
|
+**
|
9
|
+** Copyright (c) 2016, Golden Code Development Corporation.
|
10
|
+** ALL RIGHTS RESERVED. Use is subject to license terms.
|
11
|
+**
|
12
|
+** Golden Code Development Corporation
|
13
|
+** CONFIDENTIAL
|
14
|
+**
|
15
|
+** -#- -I- --Date-- ------------------------------Description----------------------------------
|
16
|
+** 001 SBI 20160605 The first version defines the empty sub module.
|
17
|
+*/
|
18
|
+
|
19
|
+"use strict";
|
20
|
|
21
|
=== modified file 'src/com/goldencode/p2j/ui/client/chui/driver/web/res/p2j.screen.js'
|
22
|
--- src/com/goldencode/p2j/ui/client/chui/driver/web/res/p2j.screen.js 2015-08-11 12:06:47 +0000
|
23
|
+++ src/com/goldencode/p2j/ui/client/chui/driver/web/res/p2j.screen.js 2016-06-08 00:09:05 +0000
|
24
|
@@ -22,6 +22,7 @@
|
25
|
** 009 SBI 20150731 Applied "use strict" directive, fixed undeclared variables,
|
26
|
** added end-lines on copy.
|
27
|
** 010 GES 20150716 Dynamically create the canvas that is the "default window".
|
28
|
+** 011 SBI 20160607 Fixed the font height detection.
|
29
|
*/
|
30
|
|
31
|
"use strict";
|
32
|
@@ -401,15 +402,35 @@
|
33
|
|
34
|
font = cfg.font.size + 'px ' + cfg.font.name;
|
35
|
bold = 'bold ' + font;
|
36
|
-
|
37
|
+ console.debug("Font name: " + font);
|
38
|
ctx.font = font;
|
39
|
|
40
|
dx = ctx.measureText('\u2500').width;
|
41
|
+ // closest integer
|
42
|
+ dx = (dx + 0.5) | 0;
|
43
|
+
|
44
|
dy = fontMetrics.cellHeight(font);
|
45
|
|
46
|
- canvas.width = cols * dx;
|
47
|
+ console.debug("dx: " + dx + " dy:" + dy);
|
48
|
+
|
49
|
+ var vertical = fontMetrics.calculatePureTextHeight(font, '\u2502');
|
50
|
+ var offset = 0;
|
51
|
+ if (dy > vertical)
|
52
|
+ {
|
53
|
+ offset = dy - vertical;
|
54
|
+ }
|
55
|
+ // to cover dy with vertical lines it is required to draw two '\u2502' chars
|
56
|
+ me.verticalOffset = offset;
|
57
|
+
|
58
|
+ console.debug("verticalOffset=" + me.verticalOffset);
|
59
|
+
|
60
|
+ canvas.width = cols * dx;
|
61
|
canvas.height = rows * dy;
|
62
|
|
63
|
+// console.debug("cols: " + cols + " rows:" + rows);
|
64
|
+//
|
65
|
+// console.debug("width: " + canvas.width + " height: " + canvas.height);
|
66
|
+
|
67
|
ctx.fillStyle = cfg.font.color.b;
|
68
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
69
|
|
70
|
@@ -433,13 +454,14 @@
|
71
|
}
|
72
|
|
73
|
// export some values
|
74
|
- me.canvasWidth = canvas.width;
|
75
|
+ me.canvasWidth = canvas.width;
|
76
|
me.canvasHeight = canvas.height;
|
77
|
- me.charWidth = dx;
|
78
|
+ me.charWidth = dx;
|
79
|
me.charHeight = dy;
|
80
|
|
81
|
// container center aligned
|
82
|
- document.getElementById(cfg.container).style.width = me.canvasWidth + 'px';
|
83
|
+ document.getElementById(cfg.container).style.width = me.canvasWidth + 'px';
|
84
|
+ //document.getElementById(cfg.container).style.height = me.canvasHeight + 'px';
|
85
|
|
86
|
canvas.focus();
|
87
|
};
|
88
|
@@ -619,12 +641,19 @@
|
89
|
|
90
|
ctx.save();
|
91
|
ctx.beginPath();
|
92
|
- ctx.rect(x, y, dx, dy);
|
93
|
+ ctx.rect(x, y - me.verticalOffset, dx, dy + me.verticalOffset);
|
94
|
ctx.clip();
|
95
|
-
|
96
|
- ctx.fillText(text, x, y, dx);
|
97
|
+ // TODO to separate border drawings
|
98
|
+ // to fix vertical border drawings
|
99
|
+ if (me.verticalOffset > 0 && text.indexOf('\u2502') >= 0)
|
100
|
+ {
|
101
|
+ ctx.fillText('\u2502', x, y - me.verticalOffset);
|
102
|
+ ctx.fillText('\u2502', x, y + me.verticalOffset);
|
103
|
+ //console.debug(text + " x=" + x + " y=" + y + " f=" + ctx.font + " dx=" + dx + " dy=" + dy);
|
104
|
+ }
|
105
|
+ ctx.fillText(text, x, y, dx);
|
106
|
|
107
|
- ctx.restore();
|
108
|
+ ctx.restore();
|
109
|
};
|
110
|
|
111
|
/**
|
112
|
@@ -643,10 +672,13 @@
|
113
|
var width = 128;
|
114
|
|
115
|
/** Canvas use to measure metrics. */
|
116
|
- var fontCanvas;
|
117
|
+ var fontCanvas = document.createElement('canvas');
|
118
|
|
119
|
+ fontCanvas.height = height;
|
120
|
+ fontCanvas.width = width;
|
121
|
+
|
122
|
/** 2D graphical context. */
|
123
|
- var fontCtx;
|
124
|
+ var fontCtx = fontCanvas.getContext('2d');
|
125
|
|
126
|
/**
|
127
|
* Get font height.
|
128
|
@@ -657,66 +689,171 @@
|
129
|
*/
|
130
|
me.cellHeight = function(font)
|
131
|
{
|
132
|
- fontCanvas = document.createElement('canvas');
|
133
|
- fontCanvas.setAttribute('height', height);
|
134
|
- fontCanvas.setAttribute('width', width);
|
135
|
- fontCtx = fontCanvas.getContext('2d');
|
136
|
- fontCtx.fillStyle = 'black';
|
137
|
- fontCtx.fillRect(0, 0, width, height);
|
138
|
+ // character height
|
139
|
+ me.charHeight = calculatePureTextHeight(font, '\u2503Eghy');
|
140
|
+
|
141
|
+ return me.charHeight;
|
142
|
+ };
|
143
|
+
|
144
|
+ /**
|
145
|
+ * Calculates the pure text height for the given font without antialiasing.
|
146
|
+ *
|
147
|
+ * @param {String}
|
148
|
+ * The string font representation
|
149
|
+ * @param {String}
|
150
|
+ * The text to measure its height.
|
151
|
+ *
|
152
|
+ * @return The height in pixels that is occupied by the given text for the provided font
|
153
|
+ * without antialiasing.
|
154
|
+ */
|
155
|
+ function calculatePureTextHeight(font, text)
|
156
|
+ {
|
157
|
+ fontCtx.clearRect(0, 0, width, height);
|
158
|
fontCtx.textBaseline = 'top';
|
159
|
fontCtx.fillStyle = 'white';
|
160
|
fontCtx.font = font;
|
161
|
- fontCtx.fillText('\u2503Eghy', 0, 0);
|
162
|
-
|
163
|
- var pixels = fontCtx.getImageData(0, 0, width, height).data;
|
164
|
-
|
165
|
- // row numbers where we first find letter end where it ends
|
166
|
+ fontCtx.fillText(text, 0, 0);
|
167
|
+
|
168
|
+ var image = fontCtx.getImageData(0, 0, width, height);
|
169
|
+ var d = calculatePixelsDistribution(image);
|
170
|
+ //console.debug(d);
|
171
|
+ var s = calculateMeanAndVariance(d, 0, height, 0);
|
172
|
+ //console.debug(s);
|
173
|
+ return findValuableDomain(d, 0, height, s[0], s[1], 0);
|
174
|
+ };
|
175
|
+
|
176
|
+ /**
|
177
|
+ * Calculate pixels horizontal distribution for the given image
|
178
|
+ *
|
179
|
+ * @param {ImageData} img
|
180
|
+ * The provided image to test.
|
181
|
+ * @return The array built from the average of sqrt(R*R + G*G + B*B) along horizontals.
|
182
|
+ */
|
183
|
+ function calculatePixelsDistribution(img)
|
184
|
+ {
|
185
|
+ var awidth = img.width;
|
186
|
+ var aheight = img.height;
|
187
|
+ var data = img.data;
|
188
|
+ var x = 0;
|
189
|
+ var y = 0;
|
190
|
+ var w = 0;
|
191
|
+ var distribution = [];
|
192
|
+ var count = 0;
|
193
|
+ var pixelsInBytes = awidth * aheight * 4;
|
194
|
+ for (var p = 0; p < pixelsInBytes;)
|
195
|
+ {
|
196
|
+ if (distribution[y] === undefined)
|
197
|
+ {
|
198
|
+ distribution[y] = 0;
|
199
|
+ }
|
200
|
+ w = Math.sqrt(data[p] * data[p] + data[p + 1] * data[p + 1] + data[p + 2] * data[p + 2] /*+ data[p + 3] * data[p + 3]*/);
|
201
|
+ if (w > 0)
|
202
|
+ {
|
203
|
+ // console.debug(p + ":" + data[p] + ":" + data[p + 1] + ":" + data[p + 2])
|
204
|
+ count++;
|
205
|
+ distribution[y] += w;
|
206
|
+ }
|
207
|
+ x++;
|
208
|
+ if (x === width)
|
209
|
+ {
|
210
|
+ distribution[y] = distribution[y] / (count > 0 ? count : 1);
|
211
|
+// distribution[y] = (distribution[y] / count + 0.5) | 0;
|
212
|
+ y++;
|
213
|
+ x = 0;
|
214
|
+ count = 0;
|
215
|
+ }
|
216
|
+ p += 4;
|
217
|
+ };
|
218
|
+ return distribution;
|
219
|
+ }
|
220
|
+
|
221
|
+ /**
|
222
|
+ * Calculate the mean and the variance for the target distribution along the provided
|
223
|
+ * segment and the given threshold.
|
224
|
+ *
|
225
|
+ * @param {Array} d
|
226
|
+ * The target distribution.
|
227
|
+ * @param {Integer} i1
|
228
|
+ * The point that defines the distribution domain.
|
229
|
+ * @param {Integer} i2
|
230
|
+ * The point that defines the distribution domain.
|
231
|
+ * @param {Number} threshold
|
232
|
+ * Defines the low bound for the distribution values.
|
233
|
+ *
|
234
|
+ * @return The 2-elements array filled with the mean and the variance.
|
235
|
+ */
|
236
|
+ function calculateMeanAndVariance(d, i1, i2, threshold)
|
237
|
+ {
|
238
|
+ var n = 0;
|
239
|
+ var mean = 0;
|
240
|
+ var M2 = 0;
|
241
|
+ var delta = 0;
|
242
|
+ for (var i = i1; i < i2; i++)
|
243
|
+ {
|
244
|
+ if (d[i] > threshold)
|
245
|
+ {
|
246
|
+ n++;
|
247
|
+ delta = d[i] - mean;
|
248
|
+ mean += delta / n;
|
249
|
+ M2 += delta * (d[i] - mean);
|
250
|
+ }
|
251
|
+ }
|
252
|
+ var v;
|
253
|
+ if (n < 2)
|
254
|
+ {
|
255
|
+ v = undefined;
|
256
|
+ }
|
257
|
+ else
|
258
|
+ {
|
259
|
+ v = M2 / (n - 1);
|
260
|
+ }
|
261
|
+
|
262
|
+ return [mean, v];
|
263
|
+ }
|
264
|
+
|
265
|
+ /**
|
266
|
+ * Defines the valuable domain for this distribution taken into account its mean and
|
267
|
+ * its variance throwing out values that are less or equal than the provided threshold.
|
268
|
+ *
|
269
|
+ * @param {Array} d
|
270
|
+ * The target distribution.
|
271
|
+ * @param {Integer} i1
|
272
|
+ * The point that defines the distribution domain.
|
273
|
+ * @param {Integer} i2
|
274
|
+ * The point that defines the distribution domain.
|
275
|
+ * @param {Number} mean
|
276
|
+ * The mean of the given distribution d.
|
277
|
+ * @param {Number} variance
|
278
|
+ * The variance of the given distribution d.
|
279
|
+ * @param {Number} threshold
|
280
|
+ * Defines the low bound for the distribution values.
|
281
|
+ *
|
282
|
+ * @return The valuable domain width for the target distribution.
|
283
|
+ */
|
284
|
+ function findValuableDomain(d, i1, i2, mean, variance, threshold)
|
285
|
+ {
|
286
|
var beg = -1;
|
287
|
+ for (var i = i1; i < i2; i++)
|
288
|
+ {
|
289
|
+ if (d[i] > threshold && ((d[i] - mean) * (d[i] - mean)) <= 9 * variance)
|
290
|
+ {
|
291
|
+ beg = i;
|
292
|
+ break;
|
293
|
+ }
|
294
|
+ }
|
295
|
var end = -1;
|
296
|
-
|
297
|
- for (var row = 0; row < height; row++)
|
298
|
+ for (var i = i2 - 1; i >= i1; i--)
|
299
|
{
|
300
|
- for (var col = 0; col < width; col++)
|
301
|
+ if (d[i] > threshold && ((d[i] - mean) * (d[i] - mean)) <= 9 * variance)
|
302
|
{
|
303
|
- var index = (row * width + col) * 4;
|
304
|
-
|
305
|
- // if pixel is not white (background color)
|
306
|
- if (pixels[index] === 0)
|
307
|
- {
|
308
|
- // we havent met white (font color) pixel
|
309
|
- // on the row and the letters was detected
|
310
|
- if (col === (width - 1) && beg !== -1)
|
311
|
- {
|
312
|
- end = row;
|
313
|
- row = height;
|
314
|
- break;
|
315
|
- }
|
316
|
- }
|
317
|
- else
|
318
|
- {
|
319
|
- // we find top of letter
|
320
|
- if (beg === -1)
|
321
|
- {
|
322
|
- beg = row;
|
323
|
- }
|
324
|
- // ..letters body
|
325
|
- break;
|
326
|
- }
|
327
|
+ end = i;
|
328
|
+ break;
|
329
|
}
|
330
|
}
|
331
|
-
|
332
|
- // space at top
|
333
|
- me.top = beg;
|
334
|
-
|
335
|
- // character height
|
336
|
- me.charHeight = end - beg;
|
337
|
-
|
338
|
- // cell height top + charHeight
|
339
|
- me.cellHeight = end;
|
340
|
-
|
341
|
- // cell height
|
342
|
- return p2j.isWindows ? end : end - 1;
|
343
|
- };
|
344
|
+ return end - beg + 1;
|
345
|
+ }
|
346
|
+
|
347
|
+ me.calculatePureTextHeight = calculatePureTextHeight;
|
348
|
|
349
|
return me;
|
350
|
})();
|
351
|
|
352
|
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/index.html'
|
353
|
--- src/com/goldencode/p2j/ui/client/driver/web/index.html 2016-06-03 10:10:16 +0000
|
354
|
+++ src/com/goldencode/p2j/ui/client/driver/web/index.html 2016-06-06 08:10:15 +0000
|
355
|
@@ -131,6 +131,6 @@
|
356
|
</audio>
|
357
|
|
358
|
</div>
|
359
|
- <textarea name="copy" id="copy" value="" class="hidden"/>
|
360
|
+ <textarea name="copy" id="copy" value="" class="hidden"></textarea>
|
361
|
</body>
|
362
|
</html>
|
363
|
|
364
|
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.keyboard.js'
|
365
|
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.keyboard.js 2016-06-03 18:08:16 +0000
|
366
|
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.keyboard.js 2016-06-05 21:05:05 +0000
|
367
|
@@ -103,7 +103,10 @@
|
368
|
*/
|
369
|
var doVT100 = function(key, evt)
|
370
|
{
|
371
|
- if (evt.ctrlKey)
|
372
|
+ // process COMMAND key for Safari as CTRL key
|
373
|
+ var metaToCtrl = p2j.isSafari && evt.metaKey;
|
374
|
+
|
375
|
+ if (evt.ctrlKey || metaToCtrl)
|
376
|
{
|
377
|
// CTRL keys
|
378
|
var charCode = p2j.keymap.mapKey(evt);
|
379
|
@@ -268,11 +271,15 @@
|
380
|
function onkeypress(evt)
|
381
|
{
|
382
|
var key = evt.charCode;
|
383
|
+
|
384
|
+ // process COMMAND key for Safari as CTRL key
|
385
|
+ var metaToCtrl = p2j.isSafari && evt.metaKey;
|
386
|
|
387
|
- // prevent Firefox keypress on CTRL-C and CTRL-V
|
388
|
- if (p2j.clipboard.enabled && p2j.isFirefox && evt.ctrlKey)
|
389
|
+ // prevent Firefox keypress on CTRL-C and CTRL-V
|
390
|
+ // Chrome doesn't generate keypress event for CTRL-C and CTRL-V
|
391
|
+ if (p2j.clipboard.enabled && (p2j.isFirefox && evt.ctrlKey || metaToCtrl))
|
392
|
{
|
393
|
- if (key === 99 || key === 118)
|
394
|
+ if (key === 99 || key === 118 || (p2j.isSafari && (key === 3 || key === 22)))
|
395
|
{
|
396
|
return;
|
397
|
}
|
398
|
@@ -318,7 +325,8 @@
|
399
|
{
|
400
|
var key = evt.keyCode;
|
401
|
|
402
|
- if (altChar || key === keys.CTRL || key === keys.SHIFT)
|
403
|
+ if (altChar || key === keys.CTRL || key === keys.SHIFT || key === keys.LEFT_WINDOW ||
|
404
|
+ key === keys.RIGHT_WINDOW)
|
405
|
{
|
406
|
return;
|
407
|
}
|
408
|
@@ -327,7 +335,7 @@
|
409
|
{
|
410
|
if (evt.location === evt.DOM_KEY_LOCATION_RIGHT)
|
411
|
{
|
412
|
- altChar = evt.ctrlKey;
|
413
|
+ altChar = evt.ctrlKey;
|
414
|
}
|
415
|
return;
|
416
|
}
|
417
|
@@ -353,9 +361,12 @@
|
418
|
escape = !escape;
|
419
|
}
|
420
|
|
421
|
- return;
|
422
|
+ return;
|
423
|
};
|
424
|
-
|
425
|
+
|
426
|
+ // process COMMAND key for Safari as CTRL key
|
427
|
+ var metaToCtrl = p2j.isSafari && evt.metaKey;
|
428
|
+
|
429
|
var p4code = -1;
|
430
|
var charCode = p2j.keymap.mapKey(evt);
|
431
|
|
432
|
@@ -413,7 +424,7 @@
|
433
|
else
|
434
|
{
|
435
|
p4code = -1;
|
436
|
- if (evt.ctrlKey)
|
437
|
+ if (evt.ctrlKey || metaToCtrl)
|
438
|
{
|
439
|
switch(key)
|
440
|
{
|
441
|
@@ -860,7 +871,10 @@
|
442
|
// then we can rely on the lastKey that is merged with keys modifiers
|
443
|
var charCode = evt.charCode > 0 ? evt.charCode : printedCode;
|
444
|
var code = -1;
|
445
|
+
|
446
|
+ // process COMMAND key for Safari as CTRL key
|
447
|
var metaToCtrl = p2j.isSafari && meta;
|
448
|
+
|
449
|
if (ctrl || metaToCtrl)
|
450
|
{
|
451
|
if (isAlphabeticCharacter(lastKey))
|
452
|
@@ -950,6 +964,8 @@
|
453
|
// In general (lastKey.keyCode === evt.keyCode) is true but if the keys are permuted,
|
454
|
// then we can rely on the lastKey that is merged with keys modifiers
|
455
|
var code = mappedCode === undefined ? lastKey.keyCode : mappedCode;
|
456
|
+
|
457
|
+ // process COMMAND key for Safari as CTRL key
|
458
|
var metaToCtrl = p2j.isSafari && meta;
|
459
|
|
460
|
if (ctrl || metaToCtrl)
|
461
|
|
462
|
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.keymap.js'
|
463
|
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.keymap.js 2016-06-03 18:08:16 +0000
|
464
|
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.keymap.js 2016-06-05 20:49:39 +0000
|
465
|
@@ -798,7 +798,10 @@
|
466
|
{
|
467
|
var ctrlCode = -1;
|
468
|
|
469
|
- if (evt.ctrlKey || (p2j.isSafari && evt.metaKey))
|
470
|
+ // process COMMAND key for Safari as CTRL key
|
471
|
+ var metaToCtrl = p2j.isSafari && evt.metaKey;
|
472
|
+
|
473
|
+ if (evt.ctrlKey || metaToCtrl)
|
474
|
{
|
475
|
if (code === 50 || code === 64) //'2'
|
476
|
{
|
477
|
|