Author: dgoette
Date: Wed Jan 7 08:43:03 2009
New Revision: 38631
URL:
http://svn.reactos.org/svn/reactos?rev=38631&view=rev
Log:
* readd & update diff function
* fix css
* fix problem, while requesting translations
Added:
branches/danny-web/reactos.org/htdocs/roscms/js/diff.js
Modified:
branches/danny-web/reactos.org/htdocs/roscms/css/cms_website.css
branches/danny-web/reactos.org/htdocs/roscms/js/cms_website.js
branches/danny-web/reactos.org/htdocs/roscms/lib/Export_XML.class.php
Modified:
branches/danny-web/reactos.org/htdocs/roscms/css/cms_website.css
URL:
http://svn.reactos.org/svn/reactos/branches/danny-web/reactos.org/htdocs/ro…
==============================================================================
---
branches/danny-web/reactos.org/htdocs/roscms/css/cms_website.css [iso-8859-1]
(original)
+++
branches/danny-web/reactos.org/htdocs/roscms/css/cms_website.css [iso-8859-1] Wed Jan
7 08:43:03 2009
@@ -115,3 +115,8 @@
.detailmenu { color: #006090; text-decoration: underline; cursor: pointer; }
.frmeditbutton { cursor:pointer; color:#006090; }
+
+#legend { display: block; width: 500px; border: solid 1px black; }
+
+#legend .lbox { border: solid 1px black; width: 17px;}
+
Modified:
branches/danny-web/reactos.org/htdocs/roscms/js/cms_website.js
URL:
http://svn.reactos.org/svn/reactos/branches/danny-web/reactos.org/htdocs/ro…
==============================================================================
---
branches/danny-web/reactos.org/htdocs/roscms/js/cms_website.js [iso-8859-1]
(original)
+++
branches/danny-web/reactos.org/htdocs/roscms/js/cms_website.js [iso-8859-1] Wed Jan 7
08:43:03 2009
@@ -1961,15 +1961,10 @@
break;
case 'diff':
+ case 'diff2':
document.getElementById('editzone').innerHTML = '<div
id="frmdiff">'+ http_request.responseText + '</div>';
loadEditor('diffentry');
- document.getElementById('frmeditdiff').innerHTML =
CDiffString(document.getElementById('frmeditdiff1').innerHTML,
document.getElementById('frmeditdiff2').innerHTML);
- break;
-
- // update diff-area with new entries start diff-process; called from within
diff-area
- case 'diff2':
- document.getElementById('frmdiff').innerHTML = http_request.responseText;
- document.getElementById('frmeditdiff').innerHTML =
CDiffString(document.getElementById('frmeditdiff1').innerHTML,
document.getElementById('frmeditdiff2').innerHTML);
+ document.getElementById('frmeditdiff').innerHTML =
WDiffShortenOutput(WDiffString(document.getElementById('frmeditdiff1').innerHTML,
document.getElementById('frmeditdiff2').innerHTML));
break;
case 'changetags':
Added:
branches/danny-web/reactos.org/htdocs/roscms/js/diff.js
URL:
http://svn.reactos.org/svn/reactos/branches/danny-web/reactos.org/htdocs/ro…
==============================================================================
---
branches/danny-web/reactos.org/htdocs/roscms/js/diff.js (added)
+++
branches/danny-web/reactos.org/htdocs/roscms/js/diff.js [iso-8859-1] Wed Jan 7
08:43:03 2009
@@ -1,0 +1,1108 @@
+/*
+
+Name: diff.js
+Version: 0.9.5a (April 6, 2008)
+Info:
http://en.wikipedia.org/wiki/User:Cacycle/diff
+Code:
http://en.wikipedia.org/wiki/User:Cacycle/diff.js
+
+JavaScript diff algorithm by [[en:User:Cacycle]]
(
http://en.wikipedia.org/wiki/User_talk:Cacycle).
+Outputs html/css-formatted new text with highlighted deletions, inserts, and block
moves.
+
+The program uses cross-browser code and should work with all modern browsers. It has been
tested with:
+* Mozilla Firefox 1.5.0.1
+* Mozilla SeaMonkey 1.0
+* Opera 8.53
+* Internet Explorer 6.0.2900.2180
+* Internet Explorer 7.0.5730.11
+This program is also compatibel with Greasemonkey
+
+An implementation of the word-based algorithm from:
+
+Communications of the ACM 21(4):264 (1978)
+http://doi.acm.org/10.1145/359460.359467
+
+With the following additional feature:
+
+* Word types have been optimized for MediaWiki source texts
+* Additional post-pass 5 code for resolving islands caused by adding
+ two common words at the end of sequences of common words
+* Additional detection of block borders and color coding of moved blocks and their
original position
+* Optional "intelligent" omission of unchanged parts from the output
+
+This code is used by the MediaWiki in-browser text editors [[en:User:Cacycle/editor]] and
[[en:User:Cacycle/wikEd]]
+and the enhanced diff view tool wikEdDiff [[en:User:Cacycle/wikEd]].
+
+Usage: var htmlText = WDiffString(oldText, newText);
+
+This code has been released into the public domain.
+
+Datastructures:
+
+text: an object that holds all text related datastructures
+ .newWords: consecutive words of the new text (N)
+ .oldWords: consecutive words of the old text (O)
+ .newToOld: array of corresponding word number in old text (NA)
+ .oldToNew: array of corresponding word number in new text (OA)
+ .message: output message for testing purposes
+
+symbol['word']: symbol table for passes 1 - 3, holds words as a hash
+ .newCtr: new word occurences counter (NC)
+ .oldCtr: old word occurences counter (OC)
+ .toNew: table last old word number
+ .toOld: last new word number (OLNA)
+
+block: an object that holds block move information
+ blocks indexed after new text:
+ .newStart: new text word number of start of this block
+ .newLength: element number of this block including non-words
+ .newWords: true word number of this block
+ .newNumber: corresponding block index in old text
+ .newBlock: moved-block-number of a block that has been moved here
+ .newLeft: moved-block-number of a block that has been moved from this border
leftwards
+ .newRight: moved-block-number of a block that has been moved from this border
rightwards
+ .newLeftIndex: index number of a block that has been moved from this border leftwards
+ .newRightIndex: index number of a block that has been moved from this border rightwards
+ blocks indexed after old text:
+ .oldStart: word number of start of this block
+ .oldToNew: corresponding new text word number of start
+ .oldLength: element number of this block including non-words
+ .oldWords: true word number of this block
+
+*/
+
+
+// css for change indicators
+if (typeof(wDiffStyleDelete) == 'undefined') { window.wDiffStyleDelete =
'font-weight: normal; text-decoration: none; color: #fff; background-color:
#990033;'; }
+if (typeof(wDiffStyleInsert) == 'undefined') { window.wDiffStyleInsert =
'font-weight: normal; text-decoration: none; color: #fff; background-color:
#009933;'; }
+if (typeof(wDiffStyleMoved) == 'undefined') { window.wDiffStyleMoved =
'font-weight: bold; color: #000; vertical-align: text-bottom; font-size: xx-small;
padding: 0; border: solid 1px;'; }
+if (typeof(wDiffStyleBlock) == 'undefined') { window.wDiffStyleBlock = [
+ 'color: #000; background-color: #ffff80;',
+ 'color: #000; background-color: #c0ffff;',
+ 'color: #000; background-color: #ffd0f0;',
+ 'color: #000; background-color: #ffe080;',
+ 'color: #000; background-color: #aaddff;',
+ 'color: #000; background-color: #ddaaff;',
+ 'color: #000; background-color: #ffbbbb;',
+ 'color: #000; background-color: #d8ffa0;',
+ 'color: #000; background-color: #d0d0d0;'
+]; }
+
+// html for change indicators, {number} is replaced by the block number
+// {block} is replaced by the block style, class and html comments are important for
shortening the output
+if (typeof(wDiffHtmlMovedRight) == 'undefined') { window.wDiffHtmlMovedRight =
'<input class="wDiffHtmlMovedRight" type="button"
value=">" style="' + wDiffStyleMoved + '
{block}"><!--wDiffHtmlMovedRight-->'; }
+if (typeof(wDiffHtmlMovedLeft) == 'undefined') { window.wDiffHtmlMovedLeft =
'<input class="wDiffHtmlMovedLeft" type="button"
value="<" style="' + wDiffStyleMoved + '
{block}"><!--wDiffHtmlMovedLeft-->'; }
+
+if (typeof(wDiffHtmlBlockStart) == 'undefined') { window.wDiffHtmlBlockStart =
'<span class="wDiffHtmlBlock" style="{block}">'; }
+if (typeof(wDiffHtmlBlockEnd) == 'undefined') { window.wDiffHtmlBlockEnd =
'</span><!--wDiffHtmlBlock-->'; }
+
+if (typeof(wDiffHtmlDeleteStart) == 'undefined') { window.wDiffHtmlDeleteStart =
'<span class="wDiffHtmlDelete" style="' + wDiffStyleDelete +
'">'; }
+if (typeof(wDiffHtmlDeleteEnd) == 'undefined') { window.wDiffHtmlDeleteEnd =
'</span><!--wDiffHtmlDelete-->'; }
+
+if (typeof(wDiffHtmlInsertStart) == 'undefined') { window.wDiffHtmlInsertStart =
'<span class="wDiffHtmlInsert" style="' + wDiffStyleInsert +
'">'; }
+if (typeof(wDiffHtmlInsertEnd) == 'undefined') { window.wDiffHtmlInsertEnd =
'</span><!--wDiffHtmlInsert-->'; }
+
+// minimal number of real words for a moved block (0 for always displaying block move
indicators)
+if (typeof(wDiffBlockMinLength) == 'undefined') { window.wDiffBlockMinLength = 3;
}
+
+// exclude identical sequence starts and endings from change marking
+if (typeof(wDiffWordDiff) == 'undefined') { window.wDiffWordDiff = true; }
+
+// enable recursive diff to resolve problematic sequences
+if (typeof(wDiffRecursiveDiff) == 'undefined') { window.wDiffRecursiveDiff =
true; }
+
+// enable block move display
+if (typeof(wDiffShowBlockMoves) == 'undefined') { window.wDiffShowBlockMoves =
true; }
+
+// remove unchanged parts from final output
+
+// characters before diff tag to search for previous heading, paragraph, line break, cut
characters
+if (typeof(wDiffHeadingBefore) == 'undefined') { window.wDiffHeadingBefore =
1500; }
+if (typeof(wDiffParagraphBefore) == 'undefined') { window.wDiffParagraphBefore =
1500; }
+if (typeof(wDiffLineBeforeMax) == 'undefined') { window.wDiffLineBeforeMax =
1000; }
+if (typeof(wDiffLineBeforeMin) == 'undefined') { window.wDiffLineBeforeMin =
500; }
+if (typeof(wDiffBlankBeforeMax) == 'undefined') { window.wDiffBlankBeforeMax =
1000; }
+if (typeof(wDiffBlankBeforeMin) == 'undefined') { window.wDiffBlankBeforeMin =
500; }
+if (typeof(wDiffCharsBefore) == 'undefined') { window.wDiffCharsBefore =
500; }
+
+// characters after diff tag to search for next heading, paragraph, line break, or
characters
+if (typeof(wDiffHeadingAfter) == 'undefined') { window.wDiffHeadingAfter =
1500; }
+if (typeof(wDiffParagraphAfter) == 'undefined') { window.wDiffParagraphAfter =
1500; }
+if (typeof(wDiffLineAfterMax) == 'undefined') { window.wDiffLineAfterMax =
1000; }
+if (typeof(wDiffLineAfterMin) == 'undefined') { window.wDiffLineAfterMin =
500; }
+if (typeof(wDiffBlankAfterMax) == 'undefined') { window.wDiffBlankAfterMax =
1000; }
+if (typeof(wDiffBlankAfterMin) == 'undefined') { window.wDiffBlankAfterMin =
500; }
+if (typeof(wDiffCharsAfter) == 'undefined') { window.wDiffCharsAfter =
500; }
+
+// maximal fragment distance to join close fragments
+if (typeof(wDiffFragmentJoin) == 'undefined') { window.wDiffFragmentJoin = 1000;
}
+if (typeof(wDiffOmittedChars) == 'undefined') { window.wDiffOmittedChars =
'
'; }
+if (typeof(wDiffOmittedLines) == 'undefined') { window.wDiffOmittedLines =
'<hr style="height: 2px; margin: 1em 10%;">'; }
+if (typeof(wDiffNoChange) == 'undefined') { window.wDiffNoChange =
'<hr style="height: 2px; margin: 1em 20%;">'; }
+
+// compatibility fix for old name of main function
+window.StringDiff = window.WDiffString;
+
+
+// WDiffString: main program
+// input: oldText, newText, strings containing the texts
+// returns: html diff
+
+window.WDiffString = function(oldText, newText) {
+
+// IE / Mac fix
+ oldText = oldText.replace(/(\r\n)/g, '\n');
+ newText = newText.replace(/(\r\n)/g, '\n');
+
+ var text = {};
+ text.newWords = [];
+ text.oldWords = [];
+ text.newToOld = [];
+ text.oldToNew = [];
+ text.message = '';
+ var block = {};
+ var outText = '';
+
+// trap trivial changes: no change
+ if (oldText == newText) {
+ outText = newText;
+ outText = WDiffEscape(outText);
+ outText = WDiffHtmlFormat(outText);
+ return(outText);
+ }
+
+// trap trivial changes: old text deleted
+ if ( (oldText == null) || (oldText.length == 0) ) {
+ outText = newText;
+ outText = WDiffEscape(outText);
+ outText = WDiffHtmlFormat(outText);
+ outText = wDiffHtmlInsertStart + outText + wDiffHtmlInsertEnd;
+ return(outText);
+ }
+
+// trap trivial changes: new text deleted
+ if ( (newText == null) || (newText.length == 0) ) {
+ outText = oldText;
+ outText = WDiffEscape(outText);
+ outText = WDiffHtmlFormat(outText);
+ outText = wDiffHtmlDeleteStart + outText + wDiffHtmlDeleteEnd;
+ return(outText);
+ }
+
+// split new and old text into words
+ WDiffSplitText(oldText, newText, text);
+
+// calculate diff information
+ WDiffText(text);
+
+//detect block borders and moved blocks
+ WDiffDetectBlocks(text, block);
+
+// process diff data into formatted html text
+ outText = WDiffToHtml(text, block);
+
+// IE fix
+ outText = outText.replace(/> ( *)</g, '> $1<');
+
+ return(outText);
+}
+
+
+// WDiffSplitText: split new and old text into words
+// input: oldText, newText, strings containing the texts
+// changes: text.newWords and text.oldWords, arrays containing the texts in arrays of
words
+
+window.WDiffSplitText = function(oldText, newText, text) {
+
+// convert strange spaces
+ oldText = oldText.replace(/[\t\u000b\u00a0\u2028\u2029]+/g, ' ');
+ newText = newText.replace(/[\t\u000b\u00a0\u2028\u2029]+/g, ' ');
+
+// split old text into words
+
+// / | | | | | | | | | | | | | | /
+ var pattern = /[\w]+|\[\[|\]\]|\{\{|\}\}|\n+|
+|&\w+;|'''|''|=+|\{\||\|\}|\|\-|./g;
+ var result;
+ do {
+ result = pattern.exec(oldText);
+ if (result != null) {
+ text.oldWords.push(result[0]);
+ }
+ } while (result != null);
+
+// split new text into words
+ do {
+ result = pattern.exec(newText);
+ if (result != null) {
+ text.newWords.push(result[0]);
+ }
+ } while (result != null);
+
+ return;
+}
+
+
+// WDiffText: calculate diff information
+// input: text.newWords and text.oldWords, arrays containing the texts in arrays of
words
+// optionally for recursive calls: newStart, newEnd, oldStart, oldEnd, recursionLevel
+// changes: text.newToOld and text.oldToNew, containing the line numbers in the other
version
+
+window.WDiffText = function(text, newStart, newEnd, oldStart, oldEnd, recursionLevel) {
+
+ symbol = new Object();
+ symbol.newCtr = [];
+ symbol.oldCtr = [];
+ symbol.toNew = [];
+ symbol.toOld = [];
+
+// set defaults
+ newStart = newStart || 0;
+ newEnd = newEnd || text.newWords.length;
+ oldStart = oldStart || 0;
+ oldEnd = oldEnd || text.oldWords.length;
+ recursionLevel = recursionLevel || 0;
+
+// limit recursion depth
+ if (recursionLevel > 10) {
+ return;
+ }
+
+// pass 1: parse new text into symbol table s
+
+ var word;
+ for (var i = newStart; i < newEnd; i ++) {
+ word = text.newWords[i];
+
+// add new entry to symbol table
+ if ( symbol[word] == null) {
+ symbol[word] = { newCtr: 0, oldCtr: 0, toNew: null, toOld: null };
+ }
+
+// increment symbol table word counter for new text
+ symbol[word].newCtr ++;
+
+// add last word number in new text
+ symbol[word].toNew = i;
+ }
+
+// pass 2: parse old text into symbol table
+
+ for (var j = oldStart; j < oldEnd; j ++) {
+ word = text.oldWords[j];
+
+// add new entry to symbol table
+ if ( symbol[word] == null) {
+ symbol[word] = { newCtr: 0, oldCtr: 0, toNew: null, toOld: null };
+ }
+
+// increment symbol table word counter for old text
+ symbol[word].oldCtr ++;
+
+// add last word number in old text
+ symbol[word].toOld = j;
+ }
+
+// pass 3: connect unique words
+
+ for (var i in symbol) {
+
+// find words in the symbol table that occur only once in both versions
+ if ( (symbol[i].newCtr == 1) && (symbol[i].oldCtr == 1) ) {
+ var toNew = symbol[i].toNew;
+ var toOld = symbol[i].toOld;
+
+// do not use spaces as unique markers
+ if ( ! /\s/.test( text.newWords[toNew] ) ) {
+
+// connect from new to old and from old to new
+ text.newToOld[toNew] = toOld;
+ text.oldToNew[toOld] = toNew;
+ }
+ }
+ }
+
+// pass 4: connect adjacent identical words downwards
+
+ for (var i = newStart; i < newEnd - 1; i ++) {
+
+// find already connected pairs
+ if (text.newToOld[i] != null) {
+ j = text.newToOld[i];
+
+// check if the following words are not yet connected
+ if ( (text.newToOld[i + 1] == null) && (text.oldToNew[j + 1] == null) ) {
+
+// if the following words are the same connect them
+ if ( text.newWords[i + 1] == text.oldWords[j + 1] ) {
+ text.newToOld[i + 1] = j + 1;
+ text.oldToNew[j + 1] = i + 1;
+ }
+ }
+ }
+ }
+
+// pass 5: connect adjacent identical words upwards
+
+ for (var i = newEnd - 1; i > newStart; i --) {
+
+// find already connected pairs
+ if (text.newToOld[i] != null) {
+ j = text.newToOld[i];
+
+// check if the preceeding words are not yet connected
+ if ( (text.newToOld[i - 1] == null) && (text.oldToNew[j - 1] == null) ) {
+
+// if the preceeding words are the same connect them
+ if ( text.newWords[i - 1] == text.oldWords[j - 1] ) {
+ text.newToOld[i - 1] = j - 1;
+ text.oldToNew[j - 1] = i - 1;
+ }
+ }
+ }
+ }
+
+// recursively diff still unresolved regions downwards
+
+ if (wDiffRecursiveDiff) {
+ i = newStart;
+ j = oldStart;
+ while (i < newEnd) {
+ if (text.newToOld[i - 1] != null) {
+ j = text.newToOld[i - 1] + 1;
+ }
+
+// check for the start of an unresolved sequence
+ if ( (text.newToOld[i] == null) && (text.oldToNew[j] == null) ) {
+
+// determine the ends of the sequences
+ var iStart = i;
+ var iEnd = i;
+ while ( (text.newToOld[iEnd] == null) && (iEnd < newEnd) ) {
+ iEnd ++;
+ }
+ var iLength = iEnd - iStart;
+
+ var jStart = j;
+ var jEnd = j;
+ while ( (text.oldToNew[jEnd] == null) && (jEnd < oldEnd) ) {
+ jEnd ++;
+ }
+ var jLength = jEnd - jStart;
+
+// recursively diff the unresolved sequence
+ if ( (iLength > 0) && (jLength > 0) ) {
+ if ( (iLength > 1) || (jLength > 1) ) {
+ if ( (iStart != newStart) || (iEnd != newEnd) || (jStart != oldStart) || (jEnd !=
oldEnd) ) {
+ WDiffText(text, iStart, iEnd, jStart, jEnd, recursionLevel + 1);
+ }
+ }
+ }
+ i = iEnd;
+ }
+ else {
+ i ++;
+ }
+ }
+ }
+
+// recursively diff still unresolved regions upwards
+
+ if (wDiffRecursiveDiff) {
+ i = newEnd - 1;
+ j = oldEnd - 1;
+ while (i >= newStart) {
+ if (text.newToOld[i + 1] != null) {
+ j = text.newToOld[i + 1] - 1;
+ }
+
+// check for the start of an unresolved sequence
+ if ( (text.newToOld[i] == null) && (text.oldToNew[j] == null) ) {
+
+// determine the ends of the sequences
+ var iStart = i;
+ var iEnd = i + 1;
+ while ( (text.newToOld[iStart - 1] == null) && (iStart >= newStart) ) {
+ iStart --;
+ }
+ var iLength = iEnd - iStart;
+
+ var jStart = j;
+ var jEnd = j + 1;
+ while ( (text.oldToNew[jStart - 1] == null) && (jStart >= oldStart) ) {
+ jStart --;
+ }
+ var jLength = jEnd - jStart;
+
+// recursively diff the unresolved sequence
+ if ( (iLength > 0) && (jLength > 0) ) {
+ if ( (iLength > 1) || (jLength > 1) ) {
+ if ( (iStart != newStart) || (iEnd != newEnd) || (jStart != oldStart) || (jEnd !=
oldEnd) ) {
+ WDiffText(text, iStart, iEnd, jStart, jEnd, recursionLevel + 1);
+ }
+ }
+ }
+ i = iStart - 1;
+ }
+ else {
+ i --;
+ }
+ }
+ }
+ return;
+}
+
+
+// WDiffToHtml: process diff data into formatted html text
+// input: text.newWords and text.oldWords, arrays containing the texts in arrays of
words
+// text.newToOld and text.oldToNew, containing the line numbers in the other version
+// block data structure
+// returns: outText, a html string
+
+window.WDiffToHtml = function(text, block) {
+
+ var outText = text.message;
+
+ var blockNumber = 0;
+ var i = 0;
+ var j = 0;
+ var movedAsInsertion;
+
+// cycle through the new text
+ do {
+ var movedIndex = [];
+ var movedBlock = [];
+ var movedLeft = [];
+ var blockText = '';
+ var identText = '';
+ var delText = '';
+ var insText = '';
+ var identStart = '';
+
+// check if a block ends here and finish previous block
+ if (movedAsInsertion != null) {
+ if (movedAsInsertion == false) {
+ identStart += wDiffHtmlBlockEnd;
+ }
+ else {
+ identStart += wDiffHtmlInsertEnd;
+ }
+ movedAsInsertion = null;
+ }
+
+// detect block boundary
+ if ( (text.newToOld[i] != j) || (blockNumber == 0 ) ) {
+ if ( ( (text.newToOld[i] != null) || (i >= text.newWords.length) ) && (
(text.oldToNew[j] != null) || (j >= text.oldWords.length) ) ) {
+
+// block moved right
+ var moved = block.newRight[blockNumber];
+ if (moved > 0) {
+ var index = block.newRightIndex[blockNumber];
+ movedIndex.push(index);
+ movedBlock.push(moved);
+ movedLeft.push(false);
+ }
+
+// block moved left
+ moved = block.newLeft[blockNumber];
+ if (moved > 0) {
+ var index = block.newLeftIndex[blockNumber];
+ movedIndex.push(index);
+ movedBlock.push(moved);
+ movedLeft.push(true);
+ }
+
+// check if a block starts here
+ moved = block.newBlock[blockNumber];
+ if (moved > 0) {
+
+// mark block as inserted text
+ if (block.newWords[blockNumber] < wDiffBlockMinLength) {
+ identStart += wDiffHtmlInsertStart;
+ movedAsInsertion = true;
+ }
+
+// mark block by color
+ else {
+ if (moved > wDiffStyleBlock.length) {
+ moved = wDiffStyleBlock.length;
+ }
+ identStart += WDiffHtmlCustomize(wDiffHtmlBlockStart, moved - 1);
+ movedAsInsertion = false;
+ }
+ }
+
+ if (i >= text.newWords.length) {
+ i ++;
+ }
+ else {
+ j = text.newToOld[i];
+ blockNumber ++;
+ }
+ }
+ }
+
+// get the correct order if moved to the left as well as to the right from here
+ if (movedIndex.length == 2) {
+ if (movedIndex[0] > movedIndex[1]) {
+ movedIndex.reverse();
+ movedBlock.reverse();
+ movedLeft.reverse();
+ }
+ }
+
+// handle left and right block moves from this position
+ for (var m = 0; m < movedIndex.length; m ++) {
+
+// insert the block as deleted text
+ if (block.newWords[ movedIndex[m] ] < wDiffBlockMinLength) {
+ var movedStart = block.newStart[ movedIndex[m] ];
+ var movedLength = block.newLength[ movedIndex[m] ];
+ var str = '';
+ for (var n = movedStart; n < movedStart + movedLength; n ++) {
+ str += text.newWords[n];
+ }
+ str = WDiffEscape(str);
+ str = str.replace(/\n/g, '¶<br>');
+ blockText += wDiffHtmlDeleteStart + str + wDiffHtmlDeleteEnd;
+ }
+
+// add a placeholder / move direction indicator
+ else {
+ if (movedBlock[m] > wDiffStyleBlock.length) {
+ movedBlock[m] = wDiffStyleBlock.length;
+ }
+ if (movedLeft[m]) {
+ blockText += WDiffHtmlCustomize(wDiffHtmlMovedLeft, movedBlock[m] - 1);
+ }
+ else {
+ blockText += WDiffHtmlCustomize(wDiffHtmlMovedRight, movedBlock[m] - 1);
+ }
+ }
+ }
+
+// collect consecutive identical text
+ while ( (i < text.newWords.length) && (j < text.oldWords.length) ) {
+ if ( (text.newToOld[i] == null) || (text.oldToNew[j] == null) ) {
+ break;
+ }
+ if (text.newToOld[i] != j) {
+ break;
+ }
+ identText += text.newWords[i];
+ i ++;
+ j ++;
+ }
+
+// collect consecutive deletions
+ while ( (text.oldToNew[j] == null) && (j < text.oldWords.length) ) {
+ delText += text.oldWords[j];
+ j ++;
+ }
+
+// collect consecutive inserts
+ while ( (text.newToOld[i] == null) && (i < text.newWords.length) ) {
+ insText += text.newWords[i];
+ i ++;
+ }
+
+// remove leading and trailing similarities betweein delText and ins from highlighting
+ var preText = '';
+ var postText = '';
+ if (wDiffWordDiff) {
+ if ( (delText != '') && (insText != '') ) {
+
+// remove leading similarities
+ while ( delText.charAt(0) == insText.charAt(0) && (delText != '')
&& (insText != '') ) {
+ preText = preText + delText.charAt(0);
+ delText = delText.substr(1);
+ insText = insText.substr(1);
+ }
+
+// remove trailing similarities
+ while ( delText.charAt(delText.length - 1) == insText.charAt(insText.length - 1)
&& (delText != '') && (insText != '') ) {
+ postText = delText.charAt(delText.length - 1) + postText;
+ delText = delText.substr(0, delText.length - 1);
+ insText = insText.substr(0, insText.length - 1);
+ }
+ }
+ }
+
+// output the identical text, deletions and inserts
+
+// moved from here indicator
+ if (blockText != '') {
+ outText += blockText;
+ }
+
+// identical text
+ if (identText != '') {
+ outText += identStart + WDiffEscape(identText);
+ }
+ outText += preText;
+
+// deleted text
+ if (delText != '') {
+ delText = wDiffHtmlDeleteStart + WDiffEscape(delText) + wDiffHtmlDeleteEnd;
+ delText = delText.replace(/\n/g, '¶<br>');
+ outText += delText;
+ }
+
+// inserted text
+ if (insText != '') {
+ insText = wDiffHtmlInsertStart + WDiffEscape(insText) + wDiffHtmlInsertEnd;
+ insText = insText.replace(/\n/g, '¶<br>');
+ outText += insText;
+ }
+ outText += postText;
+ } while (i <= text.newWords.length);
+
+ outText += '\n';
+ outText = WDiffHtmlFormat(outText);
+
+ return(outText);
+}
+
+
+// WDiffEscape: replaces html-sensitive characters in output text with character
entities
+
+window.WDiffEscape = function(text) {
+
+ text = text.replace(/&/g, '&');
+ text = text.replace(/</g, '<');
+ text = text.replace(/>/g, '>');
+ text = text.replace(/\"/g, '"');
+
+ return(text);
+}
+
+
+// HtmlCustomize: customize indicator html: replace {number} with the block number,
{block} with the block style
+
+window.WDiffHtmlCustomize = function(text, block) {
+
+ text = text.replace(/\{number\}/, block);
+ text = text.replace(/\{block\}/, wDiffStyleBlock[block]);
+
+ return(text);
+}
+
+
+// HtmlFormat: replaces newlines and multiple spaces in text with html code
+
+window.WDiffHtmlFormat = function(text) {
+
+ text = text.replace(/ /g, ' ');
+ text = text.replace(/\n/g, '<br>');
+
+ return(text);
+}
+
+
+// WDiffDetectBlocks: detect block borders and moved blocks
+// input: text object, block object
+
+window.WDiffDetectBlocks = function(text, block) {
+
+ block.oldStart = [];
+ block.oldToNew = [];
+ block.oldLength = [];
+ block.oldWords = [];
+ block.newStart = [];
+ block.newLength = [];
+ block.newWords = [];
+ block.newNumber = [];
+ block.newBlock = [];
+ block.newLeft = [];
+ block.newRight = [];
+ block.newLeftIndex = [];
+ block.newRightIndex = [];
+
+ var blockNumber = 0;
+ var wordCounter = 0;
+ var realWordCounter = 0;
+
+// get old text block order
+ if (wDiffShowBlockMoves) {
+ var j = 0;
+ var i = 0;
+ do {
+
+// detect block boundaries on old text
+ if ( (text.oldToNew[j] != i) || (blockNumber == 0 ) ) {
+ if ( ( (text.oldToNew[j] != null) || (j >= text.oldWords.length) ) && (
(text.newToOld[i] != null) || (i >= text.newWords.length) ) ) {
+ if (blockNumber > 0) {
+ block.oldLength[blockNumber - 1] = wordCounter;
+ block.oldWords[blockNumber - 1] = realWordCounter;
+ wordCounter = 0;
+ realWordCounter = 0;
+ }
+
+ if (j >= text.oldWords.length) {
+ j ++;
+ }
+ else {
+ i = text.oldToNew[j];
+ block.oldStart[blockNumber] = j;
+ block.oldToNew[blockNumber] = text.oldToNew[j];
+ blockNumber ++;
+ }
+ }
+ }
+
+// jump over identical pairs
+ while ( (i < text.newWords.length) && (j < text.oldWords.length) ) {
+ if ( (text.newToOld[i] == null) || (text.oldToNew[j] == null) ) {
+ break;
+ }
+ if (text.oldToNew[j] != i) {
+ break;
+ }
+ i ++;
+ j ++;
+ wordCounter ++;
+ if ( /\w/.test( text.newWords[i] ) ) {
+ realWordCounter ++;
+ }
+ }
+
+// jump over consecutive deletions
+ while ( (text.oldToNew[j] == null) && (j < text.oldWords.length) ) {
+ j ++;
+ }
+
+// jump over consecutive inserts
+ while ( (text.newToOld[i] == null) && (i < text.newWords.length) ) {
+ i ++;
+ }
+ } while (j <= text.oldWords.length);
+
+// get the block order in the new text
+ var lastMin;
+ var currMinIndex;
+ lastMin = null;
+
+// sort the data by increasing start numbers into new text block info
+ for (var i = 0; i < blockNumber; i ++) {
+ currMin = null;
+ for (var j = 0; j < blockNumber; j ++) {
+ curr = block.oldToNew[j];
+ if ( (curr > lastMin) || (lastMin == null) ) {
+ if ( (curr < currMin) || (currMin == null) ) {
+ currMin = curr;
+ currMinIndex = j;
+ }
+ }
+ }
+ block.newStart[i] = block.oldToNew[currMinIndex];
+ block.newLength[i] = block.oldLength[currMinIndex];
+ block.newWords[i] = block.oldWords[currMinIndex];
+ block.newNumber[i] = currMinIndex;
+ lastMin = currMin;
+ }
+
+// detect not moved blocks
+ for (var i = 0; i < blockNumber; i ++) {
+ if (block.newBlock[i] == null) {
+ if (block.newNumber[i] == i) {
+ block.newBlock[i] = 0;
+ }
+ }
+ }
+
+// detect switches of neighbouring blocks
+ for (var i = 0; i < blockNumber - 1; i ++) {
+ if ( (block.newBlock[i] == null) && (block.newBlock[i + 1] == null) ) {
+ if (block.newNumber[i] - block.newNumber[i + 1] == 1) {
+ if ( (block.newNumber[i + 1] - block.newNumber[i + 2] != 1) || (i + 2 >=
blockNumber) ) {
+
+// the shorter one is declared the moved one
+ if (block.newLength[i] < block.newLength[i + 1]) {
+ block.newBlock[i] = 1;
+ block.newBlock[i + 1] = 0;
+ }
+ else {
+ block.newBlock[i] = 0;
+ block.newBlock[i + 1] = 1;
+ }
+ }
+ }
+ }
+ }
+
+// mark all others as moved and number the moved blocks
+ j = 1;
+ for (var i = 0; i < blockNumber; i ++) {
+ if ( (block.newBlock[i] == null) || (block.newBlock[i] == 1) ) {
+ block.newBlock[i] = j++;
+ }
+ }
+
+// check if a block has been moved from this block border
+ for (var i = 0; i < blockNumber; i ++) {
+ for (var j = 0; j < blockNumber; j ++) {
+
+ if (block.newNumber[j] == i) {
+ if (block.newBlock[j] > 0) {
+
+// block moved right
+ if (block.newNumber[j] < j) {
+ block.newRight[i] = block.newBlock[j];
+ block.newRightIndex[i] = j;
+ }
+
+// block moved left
+ else {
+ block.newLeft[i + 1] = block.newBlock[j];
+ block.newLeftIndex[i + 1] = j;
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+
+// WDiffShortenOutput: remove unchanged parts from final output
+// input: the output of WDiffString
+// returns: the text with removed unchanged passages indicated by (...)
+
+window.WDiffShortenOutput = function(diffText) {
+
+// html <br/> to newlines
+ diffText = diffText.replace(/<br[^>]*>/g, '\n');
+
+// scan for diff html tags
+ var regExpDiff = new RegExp('<\\w+
class=\\"(\\w+)\\"[^>]*>(.|\\n)*?<!--\\1-->', 'g');
+ var tagStart = [];
+ var tagEnd = [];
+ var i = 0;
+ var found;
+ while ( (found = regExpDiff.exec(diffText)) != null ) {
+
+// combine consecutive diff tags
+ if ( (i > 0) && (tagEnd[i - 1] == found.index) ) {
+ tagEnd[i - 1] = found.index + found[0].length;
+ }
+ else {
+ tagStart[i] = found.index;
+ tagEnd[i] = found.index + found[0].length;
+ i ++;
+ }
+ }
+
+// no diff tags detected
+ if (tagStart.length == 0) {
+ return(wDiffNoChange);
+ }
+
+// define regexps
+ var regExpHeading = new RegExp('\\n=+.+?=+ *\\n|\\n\\{\\||\\n\\|\\}',
'g');
+ var regExpParagraph = new RegExp('\\n\\n+', 'g');
+ var regExpLine = new RegExp('\\n+', 'g');
+ var regExpBlank = new RegExp('(<[^>]+>)*\\s+', 'g');
+
+// determine fragment border positions around diff tags
+ var rangeStart = [];
+ var rangeEnd = [];
+ var rangeStartType = [];
+ var rangeEndType = [];
+ for (var i = 0; i < tagStart.length; i ++) {
+ var found;
+
+// find last heading before diff tag
+ var lastPos = tagStart[i] - wDiffHeadingBefore;
+ if (lastPos < 0) {
+ lastPos = 0;
+ }
+ regExpHeading.lastIndex = lastPos;
+ while ( (found = regExpHeading.exec(diffText)) != null ) {
+ if (found.index > tagStart[i]) {
+ break;
+ }
+ rangeStart[i] = found.index;
+ rangeStartType[i] = 'heading';
+ }
+
+// find last paragraph before diff tag
+ if (rangeStart[i] == null) {
+ lastPos = tagStart[i] - wDiffParagraphBefore;
+ if (lastPos < 0) {
+ lastPos = 0;
+ }
+ regExpParagraph.lastIndex = lastPos;
+ while ( (found = regExpParagraph.exec(diffText)) != null ) {
+ if (found.index > tagStart[i]) {
+ break;
+ }
+ rangeStart[i] = found.index;
+ rangeStartType[i] = 'paragraph';
+ }
+ }
+
+// find line break before diff tag
+ if (rangeStart[i] == null) {
+ lastPos = tagStart[i] - wDiffLineBeforeMax;
+ if (lastPos < 0) {
+ lastPos = 0;
+ }
+ regExpLine.lastIndex = lastPos;
+ while ( (found = regExpLine.exec(diffText)) != null ) {
+ if (found.index > tagStart[i] - wDiffLineBeforeMin) {
+ break;
+ }
+ rangeStart[i] = found.index;
+ rangeStartType[i] = 'line';
+ }
+ }
+
+// find blank before diff tag
+ if (rangeStart[i] == null) {
+ lastPos = tagStart[i] - wDiffBlankBeforeMax;
+ if (lastPos < 0) {
+ lastPos = 0;
+ }
+ regExpBlank.lastIndex = lastPos;
+ while ( (found = regExpBlank.exec(diffText)) != null ) {
+ if (found.index > tagStart[i] - wDiffBlankBeforeMin) {
+ break;
+ }
+ rangeStart[i] = found.index;
+ rangeStartType[i] = 'blank';
+ }
+ }
+
+// fixed number of chars before diff tag
+ if (rangeStart[i] == null) {
+ rangeStart[i] = tagStart[i] - wDiffCharsBefore;
+ rangeStartType[i] = 'chars';
+ if (rangeStart[i] < 0) {
+ rangeStart[i] = 0;
+ }
+ }
+
+// find first heading after diff tag
+ regExpHeading.lastIndex = tagEnd[i];
+ if ( (found = regExpHeading.exec(diffText)) != null ) {
+ if (found.index < tagEnd[i] + wDiffHeadingAfter) {
+ rangeEnd[i] = found.index + found[0].length;
+ rangeEndType[i] = 'heading';
+ }
+ }
+
+// find first paragraph after diff tag
+ if (rangeEnd[i] == null) {
+ regExpParagraph.lastIndex = tagEnd[i];
+ if ( (found = regExpParagraph.exec(diffText)) != null ) {
+ if (found.index < tagEnd[i] + wDiffParagraphAfter) {
+ rangeEnd[i] = found.index;
+ rangeEndType[i] = 'paragraph';
+ }
+ }
+ }
+
+// find first line break after diff tag
+ if (rangeEnd[i] == null) {
+ regExpLine.lastIndex = tagEnd[i] + wDiffLineAfterMin;
+ if ( (found = regExpLine.exec(diffText)) != null ) {
+ if (found.index < tagEnd[i] + wDiffLineAfterMax) {
+ rangeEnd[i] = found.index;
+ rangeEndType[i] = 'break';
+ }
+ }
+ }
+
+// find blank after diff tag
+ if (rangeEnd[i] == null) {
+ regExpBlank.lastIndex = tagEnd[i] + wDiffBlankAfterMin;
+ if ( (found = regExpBlank.exec(diffText)) != null ) {
+ if (found.index < tagEnd[i] + wDiffBlankAfterMax) {
+ rangeEnd[i] = found.index;
+ rangeEndType[i] = 'blank';
+ }
+ }
+ }
+
+// fixed number of chars after diff tag
+ if (rangeEnd[i] == null) {
+ rangeEnd[i] = tagEnd[i] + wDiffCharsAfter;
+ if (rangeEnd[i] > diffText.length) {
+ rangeEnd[i] = diffText.length;
+ rangeEndType[i] = 'chars';
+ }
+ }
+ }
+
+// remove overlaps, join close fragments
+ var fragmentStart = [];
+ var fragmentEnd = [];
+ var fragmentStartType = [];
+ var fragmentEndType = [];
+ fragmentStart[0] = rangeStart[0];
+ fragmentEnd[0] = rangeEnd[0];
+ fragmentStartType[0] = rangeStartType[0];
+ fragmentEndType[0] = rangeEndType[0];
+ var j = 1;
+ for (var i = 1; i < rangeStart.length; i ++) {
+ if (rangeStart[i] > fragmentEnd[j - 1] + wDiffFragmentJoin) {
+ fragmentStart[j] = rangeStart[i];
+ fragmentEnd[j] = rangeEnd[i];
+ fragmentStartType[j] = rangeStartType[i];
+ fragmentEndType[j] = rangeEndType[i];
+ j ++;
+ }
+ else {
+ fragmentEnd[j - 1] = rangeEnd[i];
+ fragmentEndType[j - 1] = rangeEndType[i];
+ }
+ }
+
+// assemble the fragments
+ var outText = '';
+ for (var i = 0; i < fragmentStart.length; i ++) {
+
+// get text fragment
+ var fragment = diffText.substring(fragmentStart[i], fragmentEnd[i]);
+ var fragment = fragment.replace(/^\n+|\n+$/g, '');
+
+// add inline marks for omitted chars and words
+ if (fragmentStart[i] > 0) {
+ if (fragmentStartType[i] == 'chars') {
+ fragment = wDiffOmittedChars + fragment;
+ }
+ else if (fragmentStartType[i] == 'blank') {
+ fragment = wDiffOmittedChars + ' ' + fragment;
+ }
+ }
+ if (fragmentEnd[i] < diffText.length) {
+ if (fragmentStartType[i] == 'chars') {
+ fragment = fragment + wDiffOmittedChars;
+ }
+ else if (fragmentStartType[i] == 'blank') {
+ fragment = fragment + ' ' + wDiffOmittedChars;
+ }
+ }
+
+// add omitted line separator
+ if (fragmentStart[i] > 0) {
+ outText += wDiffOmittedLines;
+ }
+
+// encapsulate span errors
+ outText += '<div>' + fragment + '</div>';
+ }
+
+// add trailing omitted line separator
+ if (fragmentEnd[i - 1] < diffText.length) {
+ outText = outText + wDiffOmittedLines;
+ }
+
+// remove leading and trailing empty lines
+ outText = outText.replace(/^(<div>)\n+|\n+(<\/div>)$/g, '$1$2');
+
+// convert to html linebreaks
+ outText = outText.replace(/\n/g, '<br />');
+
+ return(outText);
+}
+
Modified:
branches/danny-web/reactos.org/htdocs/roscms/lib/Export_XML.class.php
URL:
http://svn.reactos.org/svn/reactos/branches/danny-web/reactos.org/htdocs/ro…
==============================================================================
---
branches/danny-web/reactos.org/htdocs/roscms/lib/Export_XML.class.php [iso-8859-1]
(original)
+++
branches/danny-web/reactos.org/htdocs/roscms/lib/Export_XML.class.php [iso-8859-1] Wed
Jan 7 08:43:03 2009
@@ -149,7 +149,7 @@
$tdata .= '<view curpos="'.$page_offset.'"
pagelimit="'.$this->page_limit.'"
pagemax="'.$ptm_entries.'"
tblcols="|'.$this->column_list.'|" />';
// prepare for usage in loop
- $stmt_trans=&DBConnection::getInstance()->prepare("SELECT r.data_id,
d.name, d.type, r.id, r.version, r.lang_id, r.datetime, r.user_id FROM
".ROSCMST_ENTRIES." d JOIN ".ROSCMST_REVISIONS." r ON r.data_id=d.id
WHERE d.id = :data_id AND r.version > 0 AND r.lang_id = :lang WHERE r.archive =
:archive LIMIT 1");
+ $stmt_trans=&DBConnection::getInstance()->prepare("SELECT r.data_id,
d.name, d.type, r.id, r.version, r.lang_id, r.datetime, r.user_id FROM
".ROSCMST_ENTRIES." d JOIN ".ROSCMST_REVISIONS." r ON r.data_id=d.id
WHERE d.id = :data_id AND r.version > 0 AND r.lang_id = :lang AND r.archive = :archive
LIMIT 1");
$stmt_trans->bindParam('archive',$this->archive_mode,PDO::PARAM_BOOL);
$stmt_trans->bindParam('lang',$this->translation_lang,PDO::PARAM_INT);
$stmt_stext=&DBConnection::getInstance()->prepare("SELECT content FROM
".ROSCMST_STEXT." WHERE rev_id = :rev_id AND name = 'title' LIMIT
1");