docs: function(text, start, end) {
  			if (text === undefined) { text = ""; }
  			if (start === undefined) { start = 0; }
  			if (end === undefined) { end = this.getCharCount(); }
  			if (start === end && text === "") { return; }
  			var startLine = this.getLineAtOffset(start);
  			var endLine = this.getLineAtOffset(end);
  			var eventStart = start;
  			var removedCharCount = end - start;
  			var removedLineCount = endLine - startLine;
  			var addedCharCount = text.length;
  			var addedLineCount = 0;
  			var lineCount = this.getLineCount();
  			
  			var cr = 0, lf = 0, index = 0;
  			var newLineOffsets = [];
  			while (true) {
  				if (cr !== -1 && cr <= index) { cr = text.indexOf("\r", index); } //$NON-NLS-0$
  				if (lf !== -1 && lf <= index) { lf = text.indexOf("\n", index); } //$NON-NLS-0$
  				if (lf === -1 && cr === -1) { break; }
  				if (cr !== -1 && lf !== -1) {
  					if (cr + 1 === lf) {
  						index = lf + 1;
  					} else {
  						index = (cr < lf ? cr : lf) + 1;
  					}
  				} else if (cr !== -1) {
  					index = cr + 1;
  				} else {
  					index = lf + 1;
  				}
  				newLineOffsets.push(start + index);
  				addedLineCount++;
  			}
  		
  			var modelChangingEvent = {
  				type: "Changing", //$NON-NLS-0$
  				text: text,
  				start: eventStart,
  				removedCharCount: removedCharCount,
  				addedCharCount: addedCharCount,
  				removedLineCount: removedLineCount,
  				addedLineCount: addedLineCount
  			};
  			this.onChanging(modelChangingEvent);
  			
  			var changedText = text;
  
  			//TODO this should be done the loops below to avoid getText()
  			if (newLineOffsets.length === 0) {
  				var startLineOffset = this.getLineStart(startLine), endLineOffset;
  				if (endLine + 1 < lineCount) {
  					endLineOffset = this.getLineStart(endLine + 1);
  				} else {
  					endLineOffset = this.getCharCount();
  				}
  				if (start !== startLineOffset) {
  					text = this.getText(startLineOffset, start) + text;
  					start = startLineOffset;
  				}
  				if (end !== endLineOffset) {
  					text = text + this.getText(end, endLineOffset);
  					end = endLineOffset;
  				}
  			}
  			
  			var changeCount = addedCharCount - removedCharCount;
  			for (var j = startLine + removedLineCount + 1; j < lineCount; j++) {
  				this._lineOffsets[j] += changeCount;
  			}
  			
  			/*
  			* Feature in Chrome.  Chrome exceeds the maximum call stack when calling splice
  			* around 62k arguments. The limit seems to be higher on IE (250K) and Firefox (450k).
  			* The fix is to break the splice in junks of 50k.
  			*/
  			var SPLICE_LIMIT = 50000;
  			var limit = SPLICE_LIMIT, args;
  			if (newLineOffsets.length < limit) {
  				args = [startLine + 1, removedLineCount].concat(newLineOffsets);
  				Array.prototype.splice.apply(this._lineOffsets, args);
  			} else {
  				index = startLine + 1;
  				this._lineOffsets.splice(index, removedLineCount);
  				for (var k = 0; k < newLineOffsets.length; k += limit) {
  					args = [index, 0].concat(newLineOffsets.slice(k, Math.min(newLineOffsets.length, k + limit)));
  					Array.prototype.splice.apply(this._lineOffsets, args);
  					index += limit;
  				}
  			}
  			
  			var offset = 0, chunk = 0, length;
  			while (chunk<this._text.length) {
  				length = this._text[chunk].length; 
  				if (start <= offset + length) { break; }
  				offset += length;
  				chunk++;
  			}
  			var firstOffset = offset;
  			var firstChunk = chunk;
  			while (chunk<this._text.length) {
  				length = this._text[chunk].length; 
  				if (end <= offset + length) { break; }
  				offset += length;
  				chunk++;
  			}
  			var lastOffset = offset;
  			var lastChunk = chunk;
  			var firstText = this._text[firstChunk];
  			var lastText = this._text[lastChunk];
  			var beforeText = firstText.substring(0, start - firstOffset);
  			var afterText = lastText.substring(end - lastOffset);
  			var params = [firstChunk, lastChunk - firstChunk + 1];
  			if (beforeText) { params.push(beforeText); }
  			if (text) { params.push(text); }
  			if (afterText) { params.push(afterText); }
  			Array.prototype.splice.apply(this._text, params);
  			if (this._text.length === 0) { this._text = [""]; }
  			
  			var modelChangedEvent = {
  				type: "Changed", //$NON-NLS-0$
  				start: eventStart,
  				text: changedText,
  				removedCharCount: removedCharCount,
  				addedCharCount: addedCharCount,
  				removedLineCount: removedLineCount,
  				addedLineCount: addedLineCount
  			};
  			this.onChanged(modelChangedEvent);
  		}