|
|
|
|
@@ -12,6 +12,38 @@ Mgly.Timer = function(){
|
|
|
|
|
self.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mgly.ChangeExpression = new RegExp(/(\d+(?:,\d+)?)([acd])(\d+(?:,\d+)?)/);
|
|
|
|
|
|
|
|
|
|
Mgly.DiffParser = function(diff) {
|
|
|
|
|
var changes = [];
|
|
|
|
|
var change_id = 0;
|
|
|
|
|
// parse diff
|
|
|
|
|
var diff_lines = diff.split(/\n/);
|
|
|
|
|
for (var i = 0; i < diff_lines.length; ++i) {
|
|
|
|
|
if (diff_lines[i].length == 0) continue;
|
|
|
|
|
var change = {};
|
|
|
|
|
var test = Mgly.ChangeExpression.exec(diff_lines[i]);
|
|
|
|
|
if (test == null) continue;
|
|
|
|
|
// lines are zero-based
|
|
|
|
|
var fr = test[1].split(',');
|
|
|
|
|
change['lhs-line-from'] = fr[0] - 1;
|
|
|
|
|
if (fr.length == 1) change['lhs-line-to'] = fr[0] - 1;
|
|
|
|
|
else change['lhs-line-to'] = fr[1] - 1;
|
|
|
|
|
var to = test[3].split(',');
|
|
|
|
|
change['rhs-line-from'] = to[0] - 1;
|
|
|
|
|
if (to.length == 1) change['rhs-line-to'] = to[0] - 1;
|
|
|
|
|
else change['rhs-line-to'] = to[1] - 1;
|
|
|
|
|
// TODO: optimize for changes that are adds/removes
|
|
|
|
|
if (change['lhs-line-from'] < 0) change['lhs-line-from'] = 0;
|
|
|
|
|
if (change['lhs-line-to'] < 0) change['lhs-line-to'] = 0;
|
|
|
|
|
if (change['rhs-line-from'] < 0) change['rhs-line-from'] = 0;
|
|
|
|
|
if (change['rhs-line-to'] < 0) change['rhs-line-to'] = 0;
|
|
|
|
|
change['op'] = test[2];
|
|
|
|
|
changes[change_id++] = change;
|
|
|
|
|
}
|
|
|
|
|
return changes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mgly.sizeOf = function(obj) {
|
|
|
|
|
var size = 0, key;
|
|
|
|
|
for (key in obj) {
|
|
|
|
|
@@ -21,87 +53,50 @@ Mgly.sizeOf = function(obj) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mgly.LCS = function(x, y) {
|
|
|
|
|
//http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
|
|
|
|
|
this.length = this._lcs(x, y);
|
|
|
|
|
var C = [];
|
|
|
|
|
x = x.split('');
|
|
|
|
|
y = y.split('');
|
|
|
|
|
x.unshift('');//add an empty element to the start [1..m]
|
|
|
|
|
y.unshift('');//add an empty element to the start [1..n]
|
|
|
|
|
this.C = C;
|
|
|
|
|
this.x = x;
|
|
|
|
|
this.y = y;
|
|
|
|
|
var i = 0;
|
|
|
|
|
var j = 0;
|
|
|
|
|
for (i = 0; i < x.length + 1; ++i) {
|
|
|
|
|
C[i] = [];
|
|
|
|
|
for (j = 0; j < y.length + 1; ++j) C[i][j] = 0;
|
|
|
|
|
}
|
|
|
|
|
for (i = 1; i < x.length + 1; ++i) {
|
|
|
|
|
for (j = 1; j < y.length + 1; ++j) {
|
|
|
|
|
if (x[i - 1] == y[j - 1]) C[i][j] = C[i - 1][j - 1] + 1;
|
|
|
|
|
else C[i][j] = Math.max( C[i][j - 1], C[i - 1][j] );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.ready = 1;
|
|
|
|
|
this.x = x.replace(/ /g, '\n');
|
|
|
|
|
this.y = y.replace(/ /g, '\n');
|
|
|
|
|
}
|
|
|
|
|
jQuery.extend(Mgly.LCS.prototype, {
|
|
|
|
|
clear: function() { this.ready = 0; },
|
|
|
|
|
diff: function(added, removed) {
|
|
|
|
|
this._diff(this.x.length - 1, this.y.length - 1, added, removed);
|
|
|
|
|
},
|
|
|
|
|
_diff: function(i, j, added, removed){
|
|
|
|
|
var x = this.x;
|
|
|
|
|
var y = this.y;
|
|
|
|
|
var C = this.C;
|
|
|
|
|
if (this.ready && i > 0 && j > 0 && (x[i] == y[j])) {
|
|
|
|
|
this._diff(i - 1, j - 1, added, removed);
|
|
|
|
|
var d = new Mgly.diff(this.x, this.y, retain_lines = true, ignore_ws = false);
|
|
|
|
|
var changes = Mgly.DiffParser(d.normal_form());
|
|
|
|
|
var li = 0, ri = 0, lj = 0, rj = 0, r0 = 0, l0 = 0;
|
|
|
|
|
for (var i = 0; i < changes.length; ++i) {
|
|
|
|
|
var change = changes[i];
|
|
|
|
|
|
|
|
|
|
// find the starting index of the line
|
|
|
|
|
li += d.lhs_lines.slice(lj, change['lhs-line-from']).join(' ').length;
|
|
|
|
|
// if the starting index is more than last time, add 1 (space)
|
|
|
|
|
if (li > l0) li += 1;
|
|
|
|
|
// get the index of the the span of the change
|
|
|
|
|
lj = change['lhs-line-to'] + 1;
|
|
|
|
|
// get the changed text
|
|
|
|
|
var lchange = d.lhs_lines.slice(change['lhs-line-from'], lj).join(' ');
|
|
|
|
|
// output the changed index and text
|
|
|
|
|
removed(li, li + lchange.length);
|
|
|
|
|
// increment the starting index beyond the last change
|
|
|
|
|
li += lchange.length + 1;
|
|
|
|
|
// remember last index
|
|
|
|
|
l0 = li;
|
|
|
|
|
|
|
|
|
|
// find the starting index of the line
|
|
|
|
|
ri += d.rhs_lines.slice(rj, change['rhs-line-from']).join(' ').length;
|
|
|
|
|
// if the starting index is more than last time, add 1 (space)
|
|
|
|
|
if (ri > r0) ri += 1;
|
|
|
|
|
// get the index of the the span of the change
|
|
|
|
|
rj = change['rhs-line-to'] + 1;
|
|
|
|
|
// get the changed text
|
|
|
|
|
var rchange = d.rhs_lines.slice(change['rhs-line-from'], rj).join(' ');
|
|
|
|
|
// output the changed index and text
|
|
|
|
|
added(ri, ri + rchange.length);
|
|
|
|
|
// increment the starting index beyond the last change
|
|
|
|
|
ri += rchange.length + 1;
|
|
|
|
|
// remember last index
|
|
|
|
|
r0 = ri;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (j > 0 && (i == 0 || (C[i][j - 1] >= C[i-1][j]))) {
|
|
|
|
|
this._diff(i, j - 1, added, removed);
|
|
|
|
|
if (added) added(j - 1, y[j]);
|
|
|
|
|
}
|
|
|
|
|
else if (i > 0 && (j == 0 || (C[i][j - 1] < C[i - 1][j]))) {
|
|
|
|
|
this._diff(i - 1, j, added, removed);
|
|
|
|
|
if (removed) removed(i - 1, x[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_lcs: function(string1, string2) {
|
|
|
|
|
// init max value
|
|
|
|
|
var longest = 0;
|
|
|
|
|
// init 2D array with 0
|
|
|
|
|
var table = Array(string1.length);
|
|
|
|
|
for(a = 0; a <= string1.length; a++){
|
|
|
|
|
table[a] = Array(string2.length);
|
|
|
|
|
for(b = 0; b <= string2.length; b++){
|
|
|
|
|
table[a][b] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// fill table
|
|
|
|
|
for(var i = 0; i < string1.length; i++) {
|
|
|
|
|
for(var j = 0; j < string2.length; j++) {
|
|
|
|
|
if(string1[i]==string2[j]) {
|
|
|
|
|
if(table[i][j] == 0){
|
|
|
|
|
table[i+1][j+1] = 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
table[i+1][j+1] = table[i][j] + 1;
|
|
|
|
|
}
|
|
|
|
|
if(table[i+1][j+1] > longest){
|
|
|
|
|
longest = table[i+1][j+1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
table[i+1][j+1] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return longest;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Mgly.diff = function(lhs, rhs, retain_lines, ignore_ws) {
|
|
|
|
|
this.diff_codes = {};
|
|
|
|
|
this.max_code = 0;
|
|
|
|
|
@@ -365,11 +360,12 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
resize_timeout: 500,
|
|
|
|
|
change_timeout: 150,
|
|
|
|
|
fgcolor: {a:'#4ba3fa',c:'#a3a3a3',d:'#ff7f7f'},
|
|
|
|
|
_bgcolor: '#eee',
|
|
|
|
|
bgcolor: '#eee',
|
|
|
|
|
vpcolor: 'rgba(0, 0, 200, 0.5)',
|
|
|
|
|
lhs: function(setValue) { },
|
|
|
|
|
rhs: function(setValue) { },
|
|
|
|
|
loaded: function() { },
|
|
|
|
|
_auto_height: function(h) { return h - 20; },
|
|
|
|
|
//_auto_height: function(h) { return h - 20; },
|
|
|
|
|
_auto_width: function(w) { return w; },
|
|
|
|
|
resize: function() {
|
|
|
|
|
var w = jQuery(el).parent().width();
|
|
|
|
|
@@ -382,7 +378,8 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
this.editor_width = w;
|
|
|
|
|
}
|
|
|
|
|
if (this.height == 'auto') {
|
|
|
|
|
h = this._auto_height(h);
|
|
|
|
|
//h = this._auto_height(h);
|
|
|
|
|
h = jQuery(el).parent().height();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
h = this.height;
|
|
|
|
|
@@ -403,7 +400,7 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
}
|
|
|
|
|
if (this.resized) this.resized();
|
|
|
|
|
},
|
|
|
|
|
_debug: '', //scroll,draw,calc,diff,markup,change
|
|
|
|
|
_debug: 'change', //scroll,draw,calc,diff,markup,change
|
|
|
|
|
resized: function() { }
|
|
|
|
|
};
|
|
|
|
|
var cmsettings = {
|
|
|
|
|
@@ -455,6 +452,7 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
this.editor[this.id + '-rhs'].on('scroll', function(){ self._scrolling(self.id + '-rhs'); });
|
|
|
|
|
|
|
|
|
|
// resize
|
|
|
|
|
if (this.settings.autoresize) {
|
|
|
|
|
var sz_timeout1 = null;
|
|
|
|
|
var sz = function() {
|
|
|
|
|
//self.em_height = null; //recalculate
|
|
|
|
|
@@ -470,6 +468,7 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
sz();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
unbind: function() {
|
|
|
|
|
if (this.changed_timeout != null) clearTimeout(this.changed_timeout);
|
|
|
|
|
@@ -492,6 +491,10 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
update: function() {
|
|
|
|
|
this._changing(this.id + '-lhs', this.id + '-rhs');
|
|
|
|
|
},
|
|
|
|
|
unmarkup: function() {
|
|
|
|
|
console.log('UNMARKUP');
|
|
|
|
|
this._clear();
|
|
|
|
|
},
|
|
|
|
|
scrollTo: function(side, num) {
|
|
|
|
|
var le = this.editor[this.id + '-lhs'];
|
|
|
|
|
var re = this.editor[this.id + '-rhs'];
|
|
|
|
|
@@ -507,8 +510,10 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
options: function(opts) {
|
|
|
|
|
if (opts) {
|
|
|
|
|
jQuery.extend(this.settings, opts);
|
|
|
|
|
if (this.settings.autoresize) {
|
|
|
|
|
this.resize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return this.settings;
|
|
|
|
|
}
|
|
|
|
|
@@ -575,7 +580,9 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
var height = this.settings.editor_height;
|
|
|
|
|
var width = this.settings.editor_width;
|
|
|
|
|
this.changed_timeout = null;
|
|
|
|
|
this.change_funcs = [];
|
|
|
|
|
this.chfns = {};
|
|
|
|
|
this.chfns[this.id + '-lhs'] = [];
|
|
|
|
|
this.chfns[this.id + '-rhs'] = [];
|
|
|
|
|
this.prev_query = [];
|
|
|
|
|
this.cursor = [];
|
|
|
|
|
this._skipscroll = {};
|
|
|
|
|
@@ -720,22 +727,27 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
}, this.settings.change_timeout);
|
|
|
|
|
},
|
|
|
|
|
_changed: function(editor_name1, editor_name2) {
|
|
|
|
|
this._clear();
|
|
|
|
|
this._diff(editor_name1, editor_name2);
|
|
|
|
|
},
|
|
|
|
|
_clear: function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
for (var name in this.editor) {
|
|
|
|
|
if (!this.editor.hasOwnProperty(name)) continue;
|
|
|
|
|
var editor = this.editor[name];
|
|
|
|
|
var fns = self.chfns[name];
|
|
|
|
|
// clear editor changes
|
|
|
|
|
editor.operation(function() {
|
|
|
|
|
var timer = new Mgly.Timer();
|
|
|
|
|
for (var i = 0, l = editor.lineCount(); i < l; ++i) {
|
|
|
|
|
editor.removeLineClass(i, 'background');
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < self.change_funcs.length; ++i) {
|
|
|
|
|
var edid = editor.getDoc().id;
|
|
|
|
|
var change = self.change_funcs[i];
|
|
|
|
|
if (change.doc.id != edid) continue;
|
|
|
|
|
for (var i = 0; i < fns.length; ++i) {
|
|
|
|
|
//var edid = editor.getDoc().id;
|
|
|
|
|
var change = fns[i];
|
|
|
|
|
//if (change.doc.id != edid) continue;
|
|
|
|
|
if (change.lines.length) {
|
|
|
|
|
self.trace('change', 'clear text', edid, change.lines[0].text);
|
|
|
|
|
self.trace('change', 'clear text', change.lines[0].text);
|
|
|
|
|
}
|
|
|
|
|
change.clear();
|
|
|
|
|
}
|
|
|
|
|
@@ -743,8 +755,28 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
self.trace('change', 'clear time', timer.stop());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
self.change_funcs = [];
|
|
|
|
|
this._diff(editor_name1, editor_name2);
|
|
|
|
|
self.chfns[name] = [];
|
|
|
|
|
|
|
|
|
|
var ex = this._draw_info(this.id + '-lhs', this.id + '-rhs');
|
|
|
|
|
var ctx_lhs = ex.clhs.get(0).getContext('2d');
|
|
|
|
|
var ctx_rhs = ex.crhs.get(0).getContext('2d');
|
|
|
|
|
var ctx = ex.dcanvas.getContext('2d');
|
|
|
|
|
|
|
|
|
|
ctx_lhs.beginPath();
|
|
|
|
|
ctx_lhs.fillStyle = this.settings.bgcolor;
|
|
|
|
|
ctx_lhs.strokeStyle = '#888';
|
|
|
|
|
ctx_lhs.fillRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
ctx_lhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
|
|
|
|
|
ctx_rhs.beginPath();
|
|
|
|
|
ctx_rhs.fillStyle = this.settings.bgcolor;
|
|
|
|
|
ctx_rhs.strokeStyle = '#888';
|
|
|
|
|
ctx_rhs.fillRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
ctx_rhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.fillStyle = '#fff';
|
|
|
|
|
ctx.fillRect(0, 0, this.draw_mid_width, ex.visible_page_height);
|
|
|
|
|
},
|
|
|
|
|
_diff: function(editor_name1, editor_name2) {
|
|
|
|
|
var lhs = this.editor[editor_name1].getValue();
|
|
|
|
|
@@ -752,7 +784,7 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
var timer = new Mgly.Timer();
|
|
|
|
|
var d = new Mgly.diff(lhs, rhs, false, this.settings.ignorews);
|
|
|
|
|
this.trace('change', 'diff time', timer.stop());
|
|
|
|
|
this.changes = this._parse_diff(editor_name1, editor_name2, d.normal_form());
|
|
|
|
|
this.changes = Mgly.DiffParser(d.normal_form());
|
|
|
|
|
this.trace('change', 'parse time', timer.stop());
|
|
|
|
|
this._calculate_offsets(editor_name1, editor_name2, this.changes);
|
|
|
|
|
this.trace('change', 'offsets time', timer.stop());
|
|
|
|
|
@@ -828,7 +860,8 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
console.error('canvas width is 0');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.draw_rhs_max = jQuery('#' + editor_name1 + '-' + editor_name2 + '-canvas').width() - 0.5; //24.5;
|
|
|
|
|
this.draw_mid_width = jQuery('#' + editor_name1 + '-' + editor_name2 + '-canvas').width();
|
|
|
|
|
this.draw_rhs_max = this.draw_mid_width - 0.5; //24.5;
|
|
|
|
|
this.draw_lhs_width = 5;
|
|
|
|
|
this.draw_rhs_width = 5;
|
|
|
|
|
this.trace('calc', 'change offsets calculated', {top_offset: top_offset, lhs_min: this.draw_lhs_min, rhs_max: this.draw_rhs_max, lhs_width: this.draw_lhs_width, rhs_width: this.draw_rhs_width});
|
|
|
|
|
@@ -1052,62 +1085,14 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
var rhs_stop = { line: -1, ch: -1 };
|
|
|
|
|
|
|
|
|
|
var lcs = new Mgly.LCS(lhs_line, rhs_line);
|
|
|
|
|
var max = Math.max(lhs_line.length, rhs_line.length);
|
|
|
|
|
if (max == 0) max = 1;
|
|
|
|
|
var percent = ((1.0)*lcs.length / max) * 100;
|
|
|
|
|
if (percent < 10) lcs.clear();
|
|
|
|
|
lcs.diff(
|
|
|
|
|
added = function (index, c) {
|
|
|
|
|
if (rhs_start.ch < 0) {
|
|
|
|
|
rhs_start.line = k;
|
|
|
|
|
rhs_start.ch = index;
|
|
|
|
|
rhs_stop.line = k;
|
|
|
|
|
rhs_stop.ch = index;
|
|
|
|
|
}
|
|
|
|
|
else if (index == rhs_stop.ch + 1) {
|
|
|
|
|
rhs_stop.ch = index;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if ((rhs_start.ch >= 0) && (rhs_stop.ch >= rhs_start.ch)) {
|
|
|
|
|
rhs_stop.ch += 1;
|
|
|
|
|
marktext.push([red, {line:rhs_start.line, ch:rhs_start.ch}, {line:rhs_stop.line, ch:rhs_stop.ch}, {className: 'mergely ch a rhs'}]);
|
|
|
|
|
}
|
|
|
|
|
//reset
|
|
|
|
|
rhs_start.ch = -1;
|
|
|
|
|
rhs_stop.ch = -1;
|
|
|
|
|
if (c != '\n') this.added(index, c);//call again
|
|
|
|
|
}
|
|
|
|
|
function (from, to) {//added
|
|
|
|
|
marktext.push([red, {line:k, ch:from}, {line:k, ch:to}, {className: 'mergely ch a rhs'}]);
|
|
|
|
|
},
|
|
|
|
|
removed = function (index, c) {
|
|
|
|
|
if (lhs_start.ch < 0) {
|
|
|
|
|
lhs_start.line = j;
|
|
|
|
|
lhs_start.ch = index;
|
|
|
|
|
lhs_stop.line = j;
|
|
|
|
|
lhs_stop.ch = index;
|
|
|
|
|
}
|
|
|
|
|
else if (index == lhs_stop.ch + 1) {
|
|
|
|
|
lhs_stop.ch = index;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if ((lhs_start.ch >= 0) && (lhs_stop.ch >= lhs_start.ch)) {
|
|
|
|
|
lhs_stop.ch += 1;
|
|
|
|
|
marktext.push([led, {line:lhs_start.line, ch:lhs_start.ch}, {line:lhs_stop.line, ch:lhs_stop.ch}, {className: 'mergely ch d lhs'}]);
|
|
|
|
|
}
|
|
|
|
|
//reset
|
|
|
|
|
lhs_start.ch = -1;
|
|
|
|
|
lhs_stop.ch = -1;
|
|
|
|
|
if (c != '\n') this.removed(index, c);//call again
|
|
|
|
|
}
|
|
|
|
|
removed = function (from, to) {//removed
|
|
|
|
|
marktext.push([led, {line:j, ch:from}, {line:j, ch:to}, {className: 'mergely ch d lhs'}]);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
if ((rhs_start.ch >= 0) && (rhs_stop.ch >= rhs_start.ch)) {
|
|
|
|
|
rhs_stop.ch += 1;
|
|
|
|
|
marktext.push([red, {line:rhs_start.line, ch:rhs_start.ch}, {line:rhs_stop.line, ch:rhs_stop.ch}, {className: 'mergely ch a rhs'}]);
|
|
|
|
|
}
|
|
|
|
|
if ((lhs_start.ch >= 0) && (lhs_stop.ch >= lhs_start.ch)) {
|
|
|
|
|
lhs_stop.ch += 1;
|
|
|
|
|
marktext.push([led, {line:lhs_start.line, ch:lhs_start.ch}, {line:lhs_stop.line, ch:lhs_stop.ch}, {className: 'mergely ch d lhs'}]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1119,7 +1104,7 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
for (var i = 0; i < marktext.length; ++i) {
|
|
|
|
|
var m = marktext[i];
|
|
|
|
|
if (m[0].doc.id != led.getDoc().id) continue;
|
|
|
|
|
self.change_funcs.push(m[0].markText(m[1], m[2], m[3]));
|
|
|
|
|
self.chfns[self.id + '-lhs'].push(m[0].markText(m[1], m[2], m[3]));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
red.operation(function() {
|
|
|
|
|
@@ -1127,8 +1112,7 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
for (var i = 0; i < marktext.length; ++i) {
|
|
|
|
|
var m = marktext[i];
|
|
|
|
|
if (m[0].doc.id != red.getDoc().id) continue;
|
|
|
|
|
var mark = m[0].markText(m[1], m[2], m[3]);
|
|
|
|
|
self.change_funcs.push(m[0].markText(m[1], m[2], m[3]));
|
|
|
|
|
self.chfns[self.id + '-rhs'].push(m[0].markText(m[1], m[2], m[3]));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.trace('change', 'LCS markup time', timer.stop());
|
|
|
|
|
@@ -1165,18 +1149,46 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
{ line: change[side + '-line-from'], ch: 0 },
|
|
|
|
|
{ line: change[side + '-line-to'], ch: line[side].text.length });
|
|
|
|
|
|
|
|
|
|
if (side == 'rhs') {
|
|
|
|
|
if (change['op'] == 'c') {
|
|
|
|
|
ed[oside].replaceRange( text,
|
|
|
|
|
{ line: change[oside + '-line-from'], ch: 0 },
|
|
|
|
|
{ line: change[oside + '-line-to'], ch: line[oside].text.length });
|
|
|
|
|
}
|
|
|
|
|
else {// 'a' or 'd'
|
|
|
|
|
else if (change['op'] == 'a') {
|
|
|
|
|
ed[oside].replaceRange( text + '\n',
|
|
|
|
|
{ line: change[oside + '-line-from'], ch: 0 },
|
|
|
|
|
{ line: change[oside + '-line-to'], ch: 0 });
|
|
|
|
|
}
|
|
|
|
|
else {// 'd'
|
|
|
|
|
var from = parseInt(change[oside + '-line-from']);
|
|
|
|
|
var to = parseInt(change[oside + '-line-to']);
|
|
|
|
|
for (var i = to; i >= from; --i) {
|
|
|
|
|
ed[oside].removeLine(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { // lhs
|
|
|
|
|
if (change['op'] == 'c') {
|
|
|
|
|
ed[oside].replaceRange( text,
|
|
|
|
|
{ line: change[oside + '-line-from'], ch: 0 },
|
|
|
|
|
{ line: change[oside + '-line-to'], ch: line[oside].text.length });
|
|
|
|
|
}
|
|
|
|
|
else if (change['op'] == 'a') {
|
|
|
|
|
var from = parseInt(change[oside + '-line-from']);
|
|
|
|
|
var to = parseInt(change[oside + '-line-to']);
|
|
|
|
|
for (var i = to; i >= from; --i) {
|
|
|
|
|
ed[oside].removeLine(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {// 'd'
|
|
|
|
|
var from = parseInt(change[oside + '-line-from']);
|
|
|
|
|
var to = parseInt(change[oside + '-line-to']);
|
|
|
|
|
ed[oside].replaceRange( '\n' + text,
|
|
|
|
|
{ line: change[oside + '-line-from'], ch: line[oside].text.length },
|
|
|
|
|
{ line: change[oside + '-line-to'], ch: line[oside].text.length });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//reset
|
|
|
|
|
ed['lhs'].setValue(ed['lhs'].getValue());
|
|
|
|
|
ed['rhs'].setValue(ed['rhs'].getValue());
|
|
|
|
|
@@ -1184,51 +1196,61 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
});
|
|
|
|
|
this.trace('change', 'markup buttons time', timer.stop());
|
|
|
|
|
},
|
|
|
|
|
_draw_diff: function(editor_name1, editor_name2, changes) {
|
|
|
|
|
_draw_info: function(editor_name1, editor_name2) {
|
|
|
|
|
var visible_page_height = jQuery(this.editor[editor_name1].getScrollerElement()).height();
|
|
|
|
|
var gutter_height = jQuery(this.editor[editor_name1].getScrollerElement()).children(':first-child').height();
|
|
|
|
|
var visible_page_ratio = (visible_page_height / gutter_height);
|
|
|
|
|
var margin_ratio = (visible_page_height / gutter_height);
|
|
|
|
|
var lhs_scroller = jQuery(this.editor[editor_name1].getScrollerElement());
|
|
|
|
|
var rhs_scroller = jQuery(this.editor[editor_name2].getScrollerElement());
|
|
|
|
|
var lhs_lines = this.editor[editor_name1].lineCount();
|
|
|
|
|
var rhs_lines = this.editor[editor_name2].lineCount();
|
|
|
|
|
|
|
|
|
|
this.trace('draw', 'visible_page_height', visible_page_height);
|
|
|
|
|
this.trace('draw', 'gutter_height', gutter_height);
|
|
|
|
|
this.trace('draw', 'visible_page_ratio', visible_page_ratio);
|
|
|
|
|
this.trace('draw', 'lhs-scroller-top', lhs_scroller.scrollTop());
|
|
|
|
|
this.trace('draw', 'rhs-scroller-top', rhs_scroller.scrollTop());
|
|
|
|
|
|
|
|
|
|
var dcanvas = document.getElementById(editor_name1 + '-' + editor_name2 + '-canvas');
|
|
|
|
|
if (dcanvas == undefined) throw 'Failed to find: ' + editor_name1 + '-' + editor_name2 + '-canvas';
|
|
|
|
|
jQuery.each(jQuery.find('#' + this.id + ' canvas'), function () {
|
|
|
|
|
jQuery(this).get(0).height = visible_page_height;
|
|
|
|
|
});
|
|
|
|
|
var clhs = jQuery('#' + this.id + '-lhs-margin');
|
|
|
|
|
var crhs = jQuery('#' + this.id + '-rhs-margin');
|
|
|
|
|
clhs.unbind('click');
|
|
|
|
|
crhs.unbind('click');
|
|
|
|
|
var mcanvas_lhs = clhs.get(0);
|
|
|
|
|
var mcanvas_rhs = crhs.get(0);
|
|
|
|
|
var lhs_xyoffset = jQuery(clhs).offset();
|
|
|
|
|
var rhs_xyoffset = jQuery(crhs).offset();
|
|
|
|
|
|
|
|
|
|
var ctx = dcanvas.getContext('2d');
|
|
|
|
|
return {
|
|
|
|
|
visible_page_height: visible_page_height,
|
|
|
|
|
gutter_height: gutter_height,
|
|
|
|
|
visible_page_ratio: (visible_page_height / gutter_height),
|
|
|
|
|
margin_ratio: (visible_page_height / gutter_height),
|
|
|
|
|
lhs_scroller: jQuery(this.editor[editor_name1].getScrollerElement()),
|
|
|
|
|
rhs_scroller: jQuery(this.editor[editor_name2].getScrollerElement()),
|
|
|
|
|
lhs_lines: this.editor[editor_name1].lineCount(),
|
|
|
|
|
rhs_lines: this.editor[editor_name2].lineCount(),
|
|
|
|
|
dcanvas: dcanvas,
|
|
|
|
|
clhs: clhs,
|
|
|
|
|
crhs: crhs,
|
|
|
|
|
lhs_xyoffset: jQuery(clhs).offset(),
|
|
|
|
|
rhs_xyoffset: jQuery(crhs).offset()
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
_draw_diff: function(editor_name1, editor_name2, changes) {
|
|
|
|
|
var ex = this._draw_info(editor_name1, editor_name2);
|
|
|
|
|
var mcanvas_lhs = ex.clhs.get(0);
|
|
|
|
|
var mcanvas_rhs = ex.crhs.get(0);
|
|
|
|
|
var ctx = ex.dcanvas.getContext('2d');
|
|
|
|
|
var ctx_lhs = mcanvas_lhs.getContext('2d');
|
|
|
|
|
var ctx_rhs = mcanvas_rhs.getContext('2d');
|
|
|
|
|
|
|
|
|
|
this.trace('draw', 'visible_page_height', ex.visible_page_height);
|
|
|
|
|
this.trace('draw', 'gutter_height', ex.gutter_height);
|
|
|
|
|
this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
|
|
|
|
|
this.trace('draw', 'lhs-scroller-top', ex.lhs_scroller.scrollTop());
|
|
|
|
|
this.trace('draw', 'rhs-scroller-top', ex.rhs_scroller.scrollTop());
|
|
|
|
|
|
|
|
|
|
jQuery.each(jQuery.find('#' + this.id + ' canvas'), function () {
|
|
|
|
|
jQuery(this).get(0).height = ex.visible_page_height;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ex.clhs.unbind('click');
|
|
|
|
|
ex.crhs.unbind('click');
|
|
|
|
|
|
|
|
|
|
ctx_lhs.beginPath();
|
|
|
|
|
ctx_lhs.fillStyle = this.settings._bgcolor;
|
|
|
|
|
ctx_lhs.fillStyle = this.settings.bgcolor;
|
|
|
|
|
ctx_lhs.strokeStyle = '#888';
|
|
|
|
|
ctx_lhs.fillRect(0, 0, 6.5, visible_page_height);
|
|
|
|
|
ctx_lhs.strokeRect(0, 0, 6.5, visible_page_height);
|
|
|
|
|
ctx_lhs.fillRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
ctx_lhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
|
|
|
|
|
ctx_rhs.beginPath();
|
|
|
|
|
ctx_rhs.fillStyle = this.settings._bgcolor;
|
|
|
|
|
ctx_rhs.fillStyle = this.settings.bgcolor;
|
|
|
|
|
ctx_rhs.strokeStyle = '#888';
|
|
|
|
|
ctx_rhs.fillRect(0, 0, 6.5, visible_page_height);
|
|
|
|
|
ctx_rhs.strokeRect(0, 0, 6.5, visible_page_height);
|
|
|
|
|
ctx_rhs.fillRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
ctx_rhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
|
|
|
|
|
|
|
|
|
|
var vp = this._get_viewport(editor_name1, editor_name2);
|
|
|
|
|
for (var i = 0; i < changes.length; ++i) {
|
|
|
|
|
@@ -1236,10 +1258,10 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
|
|
|
|
|
this.trace('draw', change);
|
|
|
|
|
// margin indicators
|
|
|
|
|
lhs_y_start = ((change['lhs-y-start'] + lhs_scroller.scrollTop()) * visible_page_ratio);
|
|
|
|
|
lhs_y_end = ((change['lhs-y-end'] + lhs_scroller.scrollTop()) * visible_page_ratio) + 1;
|
|
|
|
|
rhs_y_start = ((change['rhs-y-start'] + rhs_scroller.scrollTop()) * visible_page_ratio);
|
|
|
|
|
rhs_y_end = ((change['rhs-y-end'] + rhs_scroller.scrollTop()) * visible_page_ratio) + 1;
|
|
|
|
|
var lhs_y_start = ((change['lhs-y-start'] + ex.lhs_scroller.scrollTop()) * ex.visible_page_ratio);
|
|
|
|
|
var lhs_y_end = ((change['lhs-y-end'] + ex.lhs_scroller.scrollTop()) * ex.visible_page_ratio) + 1;
|
|
|
|
|
var rhs_y_start = ((change['rhs-y-start'] + ex.rhs_scroller.scrollTop()) * ex.visible_page_ratio);
|
|
|
|
|
var rhs_y_end = ((change['rhs-y-end'] + ex.rhs_scroller.scrollTop()) * ex.visible_page_ratio) + 1;
|
|
|
|
|
this.trace('draw', 'marker calculated', lhs_y_start, lhs_y_end, rhs_y_start, rhs_y_end);
|
|
|
|
|
|
|
|
|
|
ctx_lhs.beginPath();
|
|
|
|
|
@@ -1260,10 +1282,10 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lhs_y_start = change['lhs-y-start'];
|
|
|
|
|
var lhs_y_end = change['lhs-y-end'];
|
|
|
|
|
var rhs_y_start = change['rhs-y-start'];
|
|
|
|
|
var rhs_y_end = change['rhs-y-end'];
|
|
|
|
|
lhs_y_start = change['lhs-y-start'];
|
|
|
|
|
lhs_y_end = change['lhs-y-end'];
|
|
|
|
|
rhs_y_start = change['rhs-y-start'];
|
|
|
|
|
rhs_y_end = change['rhs-y-end'];
|
|
|
|
|
|
|
|
|
|
var radius = 3;
|
|
|
|
|
|
|
|
|
|
@@ -1343,29 +1365,29 @@ jQuery.extend(Mgly.mergely.prototype, {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// visible window feedback
|
|
|
|
|
ctx_lhs.fillStyle = 'rgba(0, 0, 200, 0.5)';
|
|
|
|
|
ctx_rhs.fillStyle = 'rgba(0, 0, 200, 0.5)';
|
|
|
|
|
ctx_lhs.fillStyle = this.settings.vpcolor;
|
|
|
|
|
ctx_rhs.fillStyle = this.settings.vpcolor;
|
|
|
|
|
|
|
|
|
|
var to = clhs.height() * visible_page_ratio;
|
|
|
|
|
var from = (lhs_scroller.scrollTop() / gutter_height) * clhs.height();
|
|
|
|
|
this.trace('draw', 'cls.height', clhs.height());
|
|
|
|
|
this.trace('draw', 'lhs_scroller.scrollTop()', lhs_scroller.scrollTop());
|
|
|
|
|
this.trace('draw', 'gutter_height', gutter_height);
|
|
|
|
|
this.trace('draw', 'visible_page_ratio', visible_page_ratio);
|
|
|
|
|
var to = ex.clhs.height() * ex.visible_page_ratio;
|
|
|
|
|
var from = (ex.lhs_scroller.scrollTop() / ex.gutter_height) * ex.clhs.height();
|
|
|
|
|
this.trace('draw', 'cls.height', ex.clhs.height());
|
|
|
|
|
this.trace('draw', 'lhs_scroller.scrollTop()', ex.lhs_scroller.scrollTop());
|
|
|
|
|
this.trace('draw', 'gutter_height', ex.gutter_height);
|
|
|
|
|
this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
|
|
|
|
|
this.trace('draw', 'from', from, 'to', to);
|
|
|
|
|
|
|
|
|
|
ctx_lhs.fillRect(1.5, from, 4.5, to);
|
|
|
|
|
ctx_rhs.fillRect(1.5, from, 4.5, to);
|
|
|
|
|
|
|
|
|
|
clhs.click(function (ev) {
|
|
|
|
|
ex.clhs.click(function (ev) {
|
|
|
|
|
var y = ev.pageY - lhs_xyoffset.top - (to / 2);
|
|
|
|
|
var sto = Math.max(0, (y / mcanvas_lhs.height) * lhs_scroller.get(0).scrollHeight);
|
|
|
|
|
lhs_scroller.scrollTop(sto);
|
|
|
|
|
var sto = Math.max(0, (y / ex.mcanvas_lhs.height) * ex.lhs_scroller.get(0).scrollHeight);
|
|
|
|
|
ex.lhs_scroller.scrollTop(sto);
|
|
|
|
|
});
|
|
|
|
|
crhs.click(function (ev) {
|
|
|
|
|
ex.crhs.click(function (ev) {
|
|
|
|
|
var y = ev.pageY - rhs_xyoffset.top - (to / 2);
|
|
|
|
|
var sto = Math.max(0, (y / mcanvas_rhs.height) * rhs_scroller.get(0).scrollHeight);
|
|
|
|
|
rhs_scroller.scrollTop(sto);
|
|
|
|
|
var sto = Math.max(0, (y / ex.mcanvas_rhs.height) * ex.rhs_scroller.get(0).scrollHeight);
|
|
|
|
|
ex.rhs_scroller.scrollTop(sto);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
trace: function(name) {
|
|
|
|
|
|