[Phpmyadmin-git] [SCM] phpMyAdmin branch, master, updated. RELEASE_3_4_3_1-12037-g9525cac

Michal Čihař nijel at users.sourceforge.net
Tue Jul 26 07:21:54 CEST 2011


The branch, master has been updated
       via  9525cac85cb206f6ab6da2f56f85e613f17b601b (commit)
      from  c50d21541bd80f8870ebb5f4ceedbb81a1d4aabe (commit)


- Log -----------------------------------------------------------------
commit 9525cac85cb206f6ab6da2f56f85e613f17b601b
Author: Michal Čihař <michal at cihar.com>
Date:   Tue Jul 26 07:21:27 2011 +0200

    Update CodeMirror to 2.12

-----------------------------------------------------------------------

Summary of changes:
 js/codemirror/lib/codemirror.js |  421 ++++++++++++++++++++++++---------------
 1 files changed, 265 insertions(+), 156 deletions(-)

diff --git a/js/codemirror/lib/codemirror.js b/js/codemirror/lib/codemirror.js
index 844c54a..27bec72 100644
--- a/js/codemirror/lib/codemirror.js
+++ b/js/codemirror/lib/codemirror.js
@@ -21,7 +21,7 @@ var CodeMirror = (function() {
     wrapper.innerHTML =
       '<div style="overflow: hidden; position: relative; width: 1px; height: 0px;">' + // Wraps and hides input textarea
         '<textarea style="position: absolute; width: 2px;" wrap="off"></textarea></div>' +
-      '<div class="CodeMirror-scroll">' +
+      '<div class="CodeMirror-scroll cm-s-' + options.theme + '">' +
         '<div style="position: relative">' + // Set to the height of the text, causes scrolling
           '<div style="position: absolute; height: 0; width: 0; overflow: hidden;"></div>' +
           '<div style="position: relative">' + // Moved around its parent to cover visible view
@@ -72,19 +72,17 @@ var CodeMirror = (function() {
     var editing, bracketHighlighted;
     // Tracks the maximum line length so that the horizontal scrollbar
     // can be kept static when scrolling.
-    var maxLine = "";
+    var maxLine = "", maxWidth;
 
-    // Initialize the content. Somewhat hacky (delayed prepareInput)
-    // to work around browser issues.
+    // Initialize the content.
     operation(function(){setValue(options.value || ""); updateInput = false;})();
-    setTimeout(prepareInput, 20);
 
     // Register our event handlers.
     connect(scroller, "mousedown", operation(onMouseDown));
     // Gecko browsers fire contextmenu *after* opening the menu, at
     // which point we can't mess with it anymore. Context menu is
     // handled in onMouseDown for Gecko.
-    if (!gecko) connect(scroller, "contextmenu", operation(onContextMenu));
+    if (!gecko) connect(scroller, "contextmenu", onContextMenu);
     connect(code, "dblclick", operation(onDblClick));
     connect(scroller, "scroll", function() {updateDisplay([]); if (options.onScroll) options.onScroll(instance);});
     connect(window, "resize", function() {updateDisplay(true);});
@@ -94,8 +92,8 @@ var CodeMirror = (function() {
     connect(input, "focus", onFocus);
     connect(input, "blur", onBlur);
 
-    connect(scroller, "dragenter", function(e){e.stop();});
-    connect(scroller, "dragover", function(e){e.stop();});
+    connect(scroller, "dragenter", e_stop);
+    connect(scroller, "dragover", e_stop);
     connect(scroller, "drop", operation(onDrop));
     connect(scroller, "paste", function(){focusInput(); fastPoll();});
     connect(input, "paste", function(){fastPoll();});
@@ -104,7 +102,7 @@ var CodeMirror = (function() {
     // IE throws unspecified error in certain cases, when 
     // trying to access activeElement before onload
     var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
-    if (hasFocus) onFocus();
+    if (hasFocus) setTimeout(onFocus, 20);
     else onBlur();
 
     function isLine(l) {return l >= 0 && l < lines.length;}
@@ -124,6 +122,7 @@ var CodeMirror = (function() {
         if (option == "lineNumbers" || option == "gutter") gutterChanged();
         else if (option == "mode" || option == "indentUnit") loadMode();
         else if (option == "readOnly" && value == "nocursor") input.blur();
+        else if (option == "theme") scroller.className = scroller.className.replace(/cm-s-\w+/, "cm-s-" + value);
       },
       getOption: function(option) {return options[option];},
       undo: operation(undo),
@@ -135,6 +134,10 @@ var CodeMirror = (function() {
         pos = clipPos(pos);
         return lines[pos.line].getTokenAt(mode, getStateBefore(pos.line), pos.ch);
       },
+      getStateAfter: function(line) {
+        line = clipLine(line == null ? lines.length - 1: line);
+        return getStateBefore(line + 1);
+      },
       cursorCoords: function(start){
         if (start == null) start = sel.inverted;
         return pageCoords(start ? sel.from : sel.to);
@@ -151,13 +154,25 @@ var CodeMirror = (function() {
       clearMarker: removeGutterMarker,
       setLineClass: operation(setLineClass),
       lineInfo: lineInfo,
-      addWidget: function(pos, node, scroll) {
-        var pos = localCoords(clipPos(pos), true);
-        node.style.top = (showingFrom * lineHeight() + pos.yBot + paddingTop()) + "px";
-        node.style.left = (pos.x + paddingLeft()) + "px";
+      addWidget: function(pos, node, scroll, where) {
+        pos = localCoords(clipPos(pos));
+        var top = pos.yBot, left = pos.x;
+        node.style.position = "absolute";
         code.appendChild(node);
+        node.style.left = left + "px";
+        if (where == "over") top = pos.y;
+        else if (where == "near") {
+          var vspace = Math.max(scroller.offsetHeight, lines.length * lineHeight()),
+              hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
+          if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
+            top = pos.y - node.offsetHeight;
+          if (left + node.offsetWidth > hspace)
+            left = hspace - node.offsetWidth;
+        }
+        node.style.top = (top + paddingTop()) + "px";
+        node.style.left = (left + paddingLeft()) + "px";
         if (scroll)
-          scrollIntoView(pos.x, pos.yBot, pos.x + node.offsetWidth, pos.yBot + node.offsetHeight);
+          scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
       },
 
       lineCount: function() {return lines.length;},
@@ -184,7 +199,8 @@ var CodeMirror = (function() {
       operation: function(f){return operation(f)();},
       refresh: function(){updateDisplay(true);},
       getInputField: function(){return input;},
-      getWrapperElement: function(){return wrapper;}
+      getWrapperElement: function(){return wrapper;},
+      getScrollerElement: function(){return scroller;}
     };
 
     function setValue(code) {
@@ -202,28 +218,39 @@ var CodeMirror = (function() {
     }
 
     function onMouseDown(e) {
+      // Check whether this is a click in a widget
+      for (var n = e_target(e); n != wrapper; n = n.parentNode)
+        if (n.parentNode == code && n != mover) return;
       var ld = lastDoubleClick; lastDoubleClick = null;
       // First, see if this is a click in the gutter
-      for (var n = e.target(); n != wrapper; n = n.parentNode)
+      for (var n = e_target(e); n != wrapper; n = n.parentNode)
         if (n.parentNode == gutterText) {
           if (options.onGutterClick)
             options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom);
-          return e.stop();
+          return e_preventDefault(e);
         }
 
-      if (gecko && e.button() == 3) onContextMenu(e);
-      if (e.button() != 1) return;
+      var start = posFromMouse(e);
+      
+      switch (e_button(e)) {
+      case 3:
+        if (gecko && !mac) onContextMenu(e);
+        return;
+      case 2:
+        if (start) setCursor(start.line, start.ch, true);
+        return;
+      }
       // For button 1, if it was clicked inside the editor
       // (posFromMouse returning non-null), we have to adjust the
       // selection.
-      var start = posFromMouse(e), last = start, going;
-      if (!start) {if (e.target() == scroller) e.stop(); return;}
+      if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
 
       if (!focused) onFocus();
-      e.stop();
+      e_preventDefault(e);
       if (ld && +new Date - ld < 400) return selectLine(start.line);
 
       setCursor(start.line, start.ch, true);
+      var last = start, going;
       // And then we have to see if it's a drag event, in which case
       // the dragged-over text must be selected.
       function end() {
@@ -246,14 +273,14 @@ var CodeMirror = (function() {
 
       var move = connect(targetDocument, "mousemove", operation(function(e) {
         clearTimeout(going);
-        e.stop();
+        e_preventDefault(e);
         extend(e);
       }), true);
       var up = connect(targetDocument, "mouseup", operation(function(e) {
         clearTimeout(going);
         var cur = posFromMouse(e);
         if (cur) setSelectionUser(start, cur);
-        e.stop();
+        e_preventDefault(e);
         end();
       }), true);
     }
@@ -261,15 +288,14 @@ var CodeMirror = (function() {
       var pos = posFromMouse(e);
       if (!pos) return;
       selectWordAt(pos);
-      e.stop();
+      e_preventDefault(e);
       lastDoubleClick = +new Date;
     }
     function onDrop(e) {
-      var pos = posFromMouse(e, true), files = e.e.dataTransfer.files;
+      e.preventDefault();
+      var pos = posFromMouse(e, true), files = e.dataTransfer.files;
       if (!pos || options.readOnly) return;
       if (files && files.length && window.FileReader && window.File) {
-        var n = files.length, text = Array(n), read = 0;
-        for (var i = 0; i < n; ++i) loadFile(files[i], i);
         function loadFile(file, i) {
           var reader = new FileReader;
           reader.onload = function() {
@@ -278,10 +304,12 @@ var CodeMirror = (function() {
           };
           reader.readAsText(file);
         }
+        var n = files.length, text = Array(n), read = 0;
+        for (var i = 0; i < n; ++i) loadFile(files[i], i);
       }
       else {
         try {
-          var text = e.e.dataTransfer.getData("Text");
+          var text = e.dataTransfer.getData("Text");
           if (text) replaceRange(text, pos, pos);
         }
         catch(e){}
@@ -290,25 +318,27 @@ var CodeMirror = (function() {
     function onKeyDown(e) {
       if (!focused) onFocus();
 
-      var code = e.e.keyCode;
+      var code = e.keyCode;
+      // IE does strange things with escape.
+      if (ie && code == 27) { e.returnValue = false; }
       // Tries to detect ctrl on non-mac, cmd on mac.
-      var mod = (mac ? e.e.metaKey : e.e.ctrlKey) && !e.e.altKey, anyMod = e.e.ctrlKey || e.e.altKey || e.e.metaKey;
-      if (code == 16 || e.e.shiftKey) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
+      var mod = (mac ? e.metaKey : e.ctrlKey) && !e.altKey, anyMod = e.ctrlKey || e.altKey || e.metaKey;
+      if (code == 16 || e.shiftKey) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
       else shiftSelecting = null;
       // First give onKeyEvent option a chance to handle this.
-      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
 
-      if (code == 33 || code == 34) {scrollPage(code == 34); return e.stop();} // page up/down
+      if (code == 33 || code == 34) {scrollPage(code == 34); return e_preventDefault(e);} // page up/down
       if (mod && ((code == 36 || code == 35) || // ctrl-home/end
                   mac && (code == 38 || code == 40))) { // cmd-up/down
-        scrollEnd(code == 36 || code == 38); return e.stop();
+        scrollEnd(code == 36 || code == 38); return e_preventDefault(e);
       }
-      if (mod && code == 65) {selectAll(); return e.stop();} // ctrl-a
+      if (mod && code == 65) {selectAll(); return e_preventDefault(e);} // ctrl-a
       if (!options.readOnly) {
         if (!anyMod && code == 13) {return;} // enter
-        if (!anyMod && code == 9 && handleTab(e.e.shiftKey)) return e.stop(); // tab
-        if (mod && code == 90) {undo(); return e.stop();} // ctrl-z
-        if (mod && ((e.e.shiftKey && code == 90) || code == 89)) {redo(); return e.stop();} // ctrl-shift-z, ctrl-y
+        if (!anyMod && code == 9 && handleTab(e.shiftKey)) return e_preventDefault(e); // tab
+        if (mod && code == 90) {undo(); return e_preventDefault(e);} // ctrl-z
+        if (mod && ((e.shiftKey && code == 90) || code == 89)) {redo(); return e_preventDefault(e);} // ctrl-shift-z, ctrl-y
       }
 
       // Key id to use in the movementKeys map. We also pass it to
@@ -328,42 +358,47 @@ var CodeMirror = (function() {
       fastPoll(curKeyId);
     }
     function onKeyUp(e) {
-      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
       if (reducedSelection) {
         reducedSelection = null;
         updateInput = true;
       }
-      if (e.e.keyCode == 16) shiftSelecting = null;
+      if (e.keyCode == 16) shiftSelecting = null;
     }
     function onKeyPress(e) {
-      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e.e))) return;
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
       if (options.electricChars && mode.electricChars) {
-        var ch = String.fromCharCode(e.e.charCode == null ? e.e.keyCode : e.e.charCode);
+        var ch = String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode);
         if (mode.electricChars.indexOf(ch) > -1)
           setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 50);
       }
-      var code = e.e.keyCode;
+      var code = e.keyCode;
       // Re-stop tab and enter. Necessary on some browsers.
-      if (code == 13) {if (!options.readOnly) handleEnter(); e.stop();}
-      else if (!e.e.ctrlKey && !e.e.altKey && !e.e.metaKey && code == 9 && options.tabMode != "default") e.stop();
+      if (code == 13) {if (!options.readOnly) handleEnter(); e_preventDefault(e);}
+      else if (!e.ctrlKey && !e.altKey && !e.metaKey && code == 9 && options.tabMode != "default") e_preventDefault(e);
       else fastPoll(curKeyId);
     }
 
     function onFocus() {
       if (options.readOnly == "nocursor") return;
-      if (!focused && options.onFocus) options.onFocus(instance);
-      focused = true;
+      if (!focused) {
+        if (options.onFocus) options.onFocus(instance);
+        focused = true;
+        if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
+          wrapper.className += " CodeMirror-focused";
+        if (!leaveInputAlone) prepareInput();
+      }
       slowPoll();
-      if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
-        wrapper.className += " CodeMirror-focused";
       restartBlink();
     }
     function onBlur() {
-      if (focused && options.onBlur) options.onBlur(instance);
+      if (focused) {
+        if (options.onBlur) options.onBlur(instance);
+        focused = false;
+        wrapper.className = wrapper.className.replace(" CodeMirror-focused", "");
+      }
       clearInterval(blinker);
-      shiftSelecting = null;
-      focused = false;
-      wrapper.className = wrapper.className.replace(" CodeMirror-focused", "");
+      setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
     }
 
     // Replace the range from from to to by the strings in newText.
@@ -386,6 +421,7 @@ var CodeMirror = (function() {
         var pos = clipPos({line: change.start + change.old.length - 1,
                            ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
         updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: lines[end-1].text.length}, change.old, pos, pos);
+        updateInput = true;
       }
     }
     function undo() {unredoHelper(history.done, history.undone);}
@@ -393,7 +429,7 @@ var CodeMirror = (function() {
 
     function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
       var recomputeMaxLength = false, maxLineLength = maxLine.length;
-      for (var i = from.line; i < to.line; ++i) {
+      for (var i = from.line; i <= to.line; ++i) {
         if (lines[i].text.length == maxLineLength) {recomputeMaxLength = true; break;}
       }
 
@@ -427,12 +463,12 @@ var CodeMirror = (function() {
       for (var i = from.line, e = i + newText.length; i < e; ++i) {
         var l = lines[i].text;
         if (l.length > maxLineLength) {
-          maxLine = l; maxLineLength = l.length;
+          maxLine = l; maxLineLength = l.length; maxWidth = null;
           recomputeMaxLength = false;
         }
       }
       if (recomputeMaxLength) {
-        maxLineLength = 0;
+        maxLineLength = 0; maxLine = ""; maxWidth = null;
         for (var i = 0, e = lines.length; i < e; ++i) {
           var l = lines[i].text;
           if (l.length > maxLineLength) {
@@ -449,7 +485,12 @@ var CodeMirror = (function() {
         if (task < from.line) newWork.push(task);
         else if (task > to.line) newWork.push(task + lendiff);
       }
-      if (newText.length) newWork.push(from.line);
+      if (newText.length < 5) {
+        highlightLines(from.line, from.line + newText.length);
+        newWork.push(from.line + newText.length);
+      } else {
+        newWork.push(from.line);
+      }
       work = newWork;
       startWorker(100);
       // Remember that these lines changed, for updating the display
@@ -537,7 +578,7 @@ var CodeMirror = (function() {
     // to the data in the editing variable, and updates the editor
     // content or cursor if something changed.
     function readInput() {
-      if (leaveInputAlone) return;
+      if (leaveInputAlone || !focused) return;
       var changed = false, text = input.value, sr = selRange(input);
       if (!sr) return false;
       var changed = editing.text != text, rs = reducedSelection;
@@ -565,13 +606,10 @@ var CodeMirror = (function() {
       // so that you can, for example, press shift-up at the start of
       // your selection and have the right thing happen.
       if (rs) {
-        from = sr.start == rs.anchor ? to : from;
-        to = shiftSelecting ? sel.to : sr.start == rs.anchor ? from : to;
-        if (!posLess(from, to)) {
-          reducedSelection = null;
-          sel.inverted = false;
-          var tmp = from; from = to; to = tmp;
-        }
+        var head = sr.start == rs.anchor ? to : from;
+        var tail = shiftSelecting ? sel.to : sr.start == rs.anchor ? from : to;
+        if (sel.inverted = posLess(head, tail)) { from = head; to = tail; }
+        else { reducedSelection = null; from = tail; to = head; }
       }
 
       // In some cases (cursor on same line as before), we don't have
@@ -591,8 +629,8 @@ var CodeMirror = (function() {
         var ch = nl > -1 ? start - nl : start, endline = editing.to - 1, edend = editing.text.length;
         for (;;) {
           c = editing.text.charAt(edend);
-          if (c == "\n") endline--;
           if (text.charAt(end) != c) {++end; ++edend; break;}
+          if (c == "\n") endline--;
           if (edend <= start || end <= start) break;
           --end; --edend;
         }
@@ -731,8 +769,15 @@ var CodeMirror = (function() {
         updateGutter();
       }
 
-      var textWidth = stringWidth(maxLine);
-      lineSpace.style.width = textWidth > scroller.clientWidth ? textWidth + "px" : "";
+      if (maxWidth == null) maxWidth = stringWidth(maxLine);
+      if (maxWidth > scroller.clientWidth) {
+        lineSpace.style.width = maxWidth + "px";
+        // Needed to prevent odd wrapping/hiding of widgets placed in here.
+        code.style.width = "";
+        code.style.width = scroller.scrollWidth + "px";
+      } else {
+        lineSpace.style.width = code.style.width = "";
+      }
 
       // Since this is all rather error prone, it is honoured with the
       // only assertion in the whole file.
@@ -807,7 +852,7 @@ var CodeMirror = (function() {
       var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
       gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
       var html = [];
-      for (var i = showingFrom; i < showingTo; ++i) {
+      for (var i = showingFrom; i < Math.max(showingTo, showingFrom + 1); ++i) {
         var marker = lines[i].gutterMarker;
         var text = options.lineNumbers ? i + options.firstLineNumber : null;
         if (marker && marker.text)
@@ -850,10 +895,9 @@ var CodeMirror = (function() {
       if (posEq(sel.from, from) && posEq(sel.to, to)) return;
       if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
 
-      var startEq = posEq(sel.to, to), endEq = posEq(sel.from, from);
       if (posEq(from, to)) sel.inverted = false;
-      else if (startEq && !endEq) sel.inverted = true;
-      else if (endEq && !startEq) sel.inverted = false;
+      else if (posEq(from, sel.to)) sel.inverted = false;
+      else if (posEq(to, sel.from)) sel.inverted = true;
 
       // Some ugly logic used to only mark the lines that actually did
       // see a change in selection as changed, rather than the whole
@@ -926,12 +970,17 @@ var CodeMirror = (function() {
         indentLine(sel.from.line, options.enterMode == "keep" ? "prev" : "smart");
     }
     function handleTab(shift) {
+      function indentSelected(mode) {
+        if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
+        var e = sel.to.line - (sel.to.ch ? 0 : 1);
+        for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
+      }
       shiftSelecting = null;
       switch (options.tabMode) {
       case "default":
         return false;
       case "indent":
-        for (var i = sel.from.line, e = sel.to.line; i <= e; ++i) indentLine(i, "smart");
+        indentSelected("smart");
         break;
       case "classic":
         if (posEq(sel.from, sel.to)) {
@@ -940,7 +989,7 @@ var CodeMirror = (function() {
           break;
         }
       case "shift":
-        for (var i = sel.from.line, e = sel.to.line; i <= e; ++i) indentLine(i, shift ? "subtract" : "add");
+        indentSelected(shift ? "subtract" : "add");
         break;
       }
       return true;
@@ -1121,7 +1170,9 @@ var CodeMirror = (function() {
     function paddingLeft() {return lineSpace.offsetLeft;}
 
     function posFromMouse(e, liberal) {
-      var offW = eltOffset(scroller, true), x = e.e.clientX, y = e.e.clientY;
+      var offW = eltOffset(scroller, true), x, y;
+      // Fails unpredictably on IE[67] when mouse is dragged around quickly.
+      try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
       // This is a mess of a heuristic to try and determine whether a
       // scroll-bar was clicked or not, and to return null if one was
       // (and !liberal).
@@ -1135,18 +1186,21 @@ var CodeMirror = (function() {
       var pos = posFromMouse(e);
       if (!pos || window.opera) return; // Opera is difficult.
       if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
-        setCursor(pos.line, pos.ch);
+        operation(setCursor)(pos.line, pos.ch);
 
       var oldCSS = input.style.cssText;
-      input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.pageY() - 1) +
-        "px; left: " + (e.pageX() - 1) + "px; z-index: 1000; background: white; " +
-        "border-width: 0; outline: none; overflow: hidden;";
+      inputDiv.style.position = "absolute";
+      input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e_pageY(e) - 1) +
+        "px; left: " + (e_pageX(e) - 1) + "px; z-index: 1000; background: white; " +
+        "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
+      leaveInputAlone = true;
       var val = input.value = getSelection();
       focusInput();
       setSelRange(input, 0, input.value.length);
-      leaveInputAlone = true;
       function rehide() {
-        if (input.value != val) operation(replaceSelection)(input.value, "end");
+        var newVal = splitLines(input.value).join("\n");
+        if (newVal != val) operation(replaceSelection)(newVal, "end");
+        inputDiv.style.position = "relative";
         input.style.cssText = oldCSS;
         leaveInputAlone = false;
         prepareInput();
@@ -1154,7 +1208,7 @@ var CodeMirror = (function() {
       }
       
       if (gecko) {
-        e.stop()
+        e_stop(e);
         var mouseup = connect(window, "mouseup", function() {
           mouseup();
           setTimeout(rehide, 20);
@@ -1201,19 +1255,20 @@ var CodeMirror = (function() {
           }
         }
       }
-      for (var i = head.line, e = forward ? Math.min(i + 50, lines.length) : Math.max(-1, i - 50); i != e; i+=d) {
+      for (var i = head.line, e = forward ? Math.min(i + 100, lines.length) : Math.max(-1, i - 100); i != e; i+=d) {
         var line = lines[i], first = i == head.line;
         var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
-        if (found) {
-          var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
-          var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
-              two = markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
-          var clear = operation(function(){one(); two();});
-          if (autoclear) setTimeout(clear, 800);
-          else bracketHighlighted = clear;
-          break;
-        }
+        if (found) break;
       }
+      if (!found) found = {pos: null, match: false};
+      var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
+      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
+          two = found.pos != null
+            ? markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style)
+            : function() {};
+      var clear = operation(function(){one(); two();});
+      if (autoclear) setTimeout(clear, 800);
+      else bracketHighlighted = clear;
     }
 
     // Finds the line to start with when starting a parse. Tries to
@@ -1244,38 +1299,49 @@ var CodeMirror = (function() {
         line.highlight(mode, state);
         line.stateAfter = copyState(mode, state);
       }
-      if (!lines[n].stateAfter) work.push(n);
+      if (n < lines.length && !lines[n].stateAfter) work.push(n);
       return state;
     }
+    function highlightLines(start, end) {
+      var state = getStateBefore(start);
+      for (var i = start; i < end; ++i) {
+        var line = lines[i];
+        line.highlight(mode, state);
+        line.stateAfter = copyState(mode, state);
+      }
+    }
     function highlightWorker() {
       var end = +new Date + options.workTime;
-      var didSomething = false;
+      var foundWork = work.length;
       while (work.length) {
         if (!lines[showingFrom].stateAfter) var task = showingFrom;
         else var task = work.pop();
         if (task >= lines.length) continue;
-        didSomething = true;
         var start = findStartLine(task), state = start && lines[start-1].stateAfter;
         if (state) state = copyState(mode, state);
         else state = startState(mode);
 
-        var unchanged = 0;
+        var unchanged = 0, compare = mode.compareStates;
         for (var i = start, l = lines.length; i < l; ++i) {
           var line = lines[i], hadState = line.stateAfter;
           if (+new Date > end) {
             work.push(i);
             startWorker(options.workDelay);
-            changes.push({from: task, to: i});
+            changes.push({from: task, to: i + 1});
             return;
           }
           var changed = line.highlight(mode, state);
           line.stateAfter = copyState(mode, state);
-          if (changed || !hadState) unchanged = 0;
-          else if (++unchanged > 3) break;
+          if (compare) {
+            if (hadState && compare(hadState, state)) break;
+          } else {
+            if (changed || !hadState) unchanged = 0;
+            else if (++unchanged > 3) break;
+          }
         }
-        changes.push({from: task, to: i});
+        changes.push({from: task, to: i + 1});
       }
-      if (didSomething && options.onHighlightComplete)
+      if (foundWork && options.onHighlightComplete)
         options.onHighlightComplete(instance);
     }
     function startWorker(time) {
@@ -1300,7 +1366,8 @@ var CodeMirror = (function() {
 
       // updateInput can be set to a boolean value to force/prevent an
       // update.
-      if (!leaveInputAlone && (updateInput === true || (updateInput !== false && selectionChanged)))
+      if (focused && !leaveInputAlone &&
+          (updateInput === true || (updateInput !== false && selectionChanged)))
         prepareInput();
 
       if (selectionChanged && options.matchBrackets)
@@ -1427,9 +1494,21 @@ var CodeMirror = (function() {
       },
 
       from: function() {if (this.atOccurrence) return copyPos(this.pos.from);},
-      to: function() {if (this.atOccurrence) return copyPos(this.pos.to);}
+      to: function() {if (this.atOccurrence) return copyPos(this.pos.to);},
+
+      replace: function(newText) {
+        var self = this;
+        if (this.atOccurrence)
+          operation(function() {
+            self.pos.to = replaceRange(newText, self.pos.from, self.pos.to);
+          })();
+      }
     };
 
+    for (var ext in extensions)
+      if (extensions.propertyIsEnumerable(ext) &&
+          !instance.propertyIsEnumerable(ext))
+        instance[ext] = extensions[ext];
     return instance;
   } // (end of function CodeMirror)
 
@@ -1437,6 +1516,7 @@ var CodeMirror = (function() {
   CodeMirror.defaults = {
     value: "",
     mode: null,
+    theme: "default",
     indentUnit: 2,
     indentWithTabs: false,
     tabMode: "classic",
@@ -1482,7 +1562,7 @@ var CodeMirror = (function() {
       return CodeMirror.getMode(options, "text/plain");
     }
     return mfactory(options, config || {});
-  }
+  };
   CodeMirror.listModes = function() {
     var list = [];
     for (var m in modes)
@@ -1496,6 +1576,11 @@ var CodeMirror = (function() {
     return list;
   };
 
+  var extensions = {};
+  CodeMirror.defineExtension = function(name, func) {
+    extensions[name] = func;
+  };
+
   CodeMirror.fromTextArea = function(textarea, options) {
     if (!options) options = {};
     options.value = textarea.value;
@@ -1727,7 +1812,7 @@ var CodeMirror = (function() {
           var str = st[i], l = str.length;
           if (ch + l > len) str = str.slice(0, len - ch);
           ch += l;
-          span(str, st[i+1]);
+          span(str, "cm-" + st[i+1]);
         }
       else {
         var pos = 0, i = 0, text = "", style, sg = 0;
@@ -1759,12 +1844,12 @@ var CodeMirror = (function() {
           }
           for (;;) {
             var end = pos + text.length;
-            var apliedStyle = style;
-            if (extraStyle) apliedStyle = style ? style + extraStyle : extraStyle;
-            span(end > upto ? text.slice(0, upto - pos) : text, apliedStyle);
+            var appliedStyle = style;
+            if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;
+            span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
             if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
             pos = end;
-            text = st[i++]; style = st[i++];
+            text = st[i++]; style = "cm-" + st[i++];
           }
         }
         if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
@@ -1822,44 +1907,44 @@ var CodeMirror = (function() {
     }
   };
 
-  // Event stopping compatibility wrapper.
-  function stopEvent() {
-    if (this.preventDefault) {this.preventDefault(); this.stopPropagation();}
-    else {this.returnValue = false; this.cancelBubble = true;}
-  }
+  function stopMethod() {e_stop(this);}
   // Ensure an event has a stop method.
   function addStop(event) {
-    if (!event.stop) event.stop = stopEvent;
+    if (!event.stop) event.stop = stopMethod;
     return event;
   }
 
-  // Event wrapper, exposing the few operations we need.
-  function Event(orig) {this.e = orig;}
-  Event.prototype = {
-    stop: function() {stopEvent.call(this.e);},
-    target: function() {return this.e.target || this.e.srcElement;},
-    button: function() {
-      if (this.e.which) return this.e.which;
-      else if (this.e.button & 1) return 1;
-      else if (this.e.button & 2) return 3;
-      else if (this.e.button & 4) return 2;
-    },
-    pageX: function() {
-      if (this.e.pageX != null) return this.e.pageX;
-      var doc = this.target().ownerDocument;
-      return this.e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft;
-    },
-    pageY: function() {
-      if (this.e.pageY != null) return this.e.pageY;
-      var doc = this.target().ownerDocument;
-      return this.e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop;
-    }
-  };
+  function e_preventDefault(e) {
+    if (e.preventDefault) e.preventDefault();
+    else e.returnValue = false;
+  }
+  function e_stopPropagation(e) {
+    if (e.stopPropagation) e.stopPropagation();
+    else e.cancelBubble = true;
+  }
+  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
+  function e_target(e) {return e.target || e.srcElement;}
+  function e_button(e) {
+    if (e.which) return e.which;
+    else if (e.button & 1) return 1;
+    else if (e.button & 2) return 3;
+    else if (e.button & 4) return 2;
+  }
+  function e_pageX(e) {
+    if (e.pageX != null) return e.pageX;
+    var doc = e_target(e).ownerDocument;
+    return e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft;
+  }
+  function e_pageY(e) {
+    if (e.pageY != null) return e.pageY;
+    var doc = e_target(e).ownerDocument;
+    return e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop;
+  }
 
   // Event handler registration. If disconnect is true, it'll return a
   // function that unregisters the handler.
   function connect(node, type, handler, disconnect) {
-    function wrapHandler(event) {handler(new Event(event || window.event));}
+    function wrapHandler(event) {handler(event || window.event);}
     if (typeof node.addEventListener == "function") {
       node.addEventListener(type, wrapHandler, false);
       if (disconnect) return function() {node.removeEventListener(type, wrapHandler, false);};
@@ -1881,6 +1966,8 @@ var CodeMirror = (function() {
   })();
 
   var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
+  var ie = /MSIE \d/.test(navigator.userAgent);
+  var safari = /Apple Computer/.test(navigator.vendor);
 
   var lineSep = "\n";
   // Feature-detect whether newlines in textareas are converted to \r\n
@@ -1910,17 +1997,21 @@ var CodeMirror = (function() {
     return n;
   }
 
+  function computedStyle(elt) {
+    if (elt.currentStyle) return elt.currentStyle;
+    return window.getComputedStyle(elt, null);
+  }
   // Find the position of an element by following the offsetParent chain.
   // If screen==true, it returns screen (rather than page) coordinates.
   function eltOffset(node, screen) {
     var doc = node.ownerDocument.body;
-    var x = 0, y = 0, hitDoc = false;
+    var x = 0, y = 0, skipDoc = false;
     for (var n = node; n; n = n.offsetParent) {
       x += n.offsetLeft; y += n.offsetTop;
-      // Fixed-position elements don't have the document in their offset chain
-      if (n == doc) hitDoc = true;
+      if (screen && computedStyle(n).position == "fixed")
+        skipDoc = true;
     }
-    var e = screen && hitDoc ? null : doc;
+    var e = screen && !skipDoc ? null : doc;
     for (var n = node.parentNode; n != e; n = n.parentNode)
       if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}
     return {left: x, top: y};
@@ -1935,10 +2026,10 @@ var CodeMirror = (function() {
   function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
   function copyPos(x) {return {line: x.line, ch: x.ch};}
 
+  var escapeElement = document.createElement("div");
   function htmlEscape(str) {
-    return str.replace(/[<>&]/g, function(str) {
-      return str == "&" ? "&" : str == "<" ? "<" : ">";
-    });
+    escapeElement.innerText = escapeElement.textContent = str;
+    return escapeElement.innerHTML;
   }
   CodeMirror.htmlEscape = htmlEscape;
 
@@ -1961,8 +2052,9 @@ var CodeMirror = (function() {
 
   // See if "".split is the broken IE version, if so, provide an
   // alternative way to split lines.
+  var splitLines, selRange, setSelRange;
   if ("\n\nb".split(/\n/).length != 3)
-    var splitLines = function(string) {
+    splitLines = function(string) {
       var pos = 0, nl, result = [];
       while ((nl = string.indexOf("\n", pos)) > -1) {
         result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl));
@@ -1972,23 +2064,39 @@ var CodeMirror = (function() {
       return result;
     };
   else
-    var splitLines = function(string){return string.split(/\r?\n/);};
+    splitLines = function(string){return string.split(/\r?\n/);};
   CodeMirror.splitLines = splitLines;
 
   // Sane model of finding and setting the selection in a textarea
   if (window.getSelection) {
-    var selRange = function(te) {
+    selRange = function(te) {
       try {return {start: te.selectionStart, end: te.selectionEnd};}
       catch(e) {return null;}
     };
-    var setSelRange = function(te, start, end) {
-      try {te.setSelectionRange(start, end);}
-      catch(e) {} // Fails on Firefox when textarea isn't part of the document
-    };
+    if (safari)
+      // On Safari, selection set with setSelectionRange are in a sort
+      // of limbo wrt their anchor. If you press shift-left in them,
+      // the anchor is put at the end, and the selection expanded to
+      // the left. If you press shift-right, the anchor ends up at the
+      // front. This is not what CodeMirror wants, so it does a
+      // spurious modify() call to get out of limbo.
+      setSelRange = function(te, start, end) {
+        if (start == end)
+          te.setSelectionRange(start, end);
+        else {
+          te.setSelectionRange(start, end - 1);
+          window.getSelection().modify("extend", "forward", "character");
+        }
+      };
+    else
+      setSelRange = function(te, start, end) {
+        try {te.setSelectionRange(start, end);}
+        catch(e) {} // Fails on Firefox when textarea isn't part of the document
+      };
   }
   // IE model. Don't ask.
   else {
-    var selRange = function(te) {
+    selRange = function(te) {
       try {var range = te.ownerDocument.selection.createRange();}
       catch(e) {return null;}
       if (!range || range.parentElement() != te) return null;
@@ -2010,7 +2118,7 @@ var CodeMirror = (function() {
       for (var i = val.indexOf("\r"); i > -1 && i < end; i = val.indexOf("\r", i+1), end++) {}
       return {start: start, end: end};
     };
-    var setSelRange = function(te, start, end) {
+    setSelRange = function(te, start, end) {
       var range = te.createTextRange();
       range.collapse(true);
       var endrange = range.duplicate();
@@ -2032,4 +2140,5 @@ var CodeMirror = (function() {
   CodeMirror.defineMIME("text/plain", "null");
 
   return CodeMirror;
-})();
+})()
+;
\ No newline at end of file


hooks/post-receive
-- 
phpMyAdmin




More information about the Git mailing list