+ function createFillingChar( doc )\r
+ {\r
+ removeFillingChar( doc );\r
+\r
+ var fillingChar = doc.createText( '\u200B' );\r
+ doc.setCustomData( 'cke-fillingChar', fillingChar );\r
+\r
+ return fillingChar;\r
+ }\r
+\r
+ function getFillingChar( doc )\r
+ {\r
+ return doc && doc.getCustomData( 'cke-fillingChar' );\r
+ }\r
+\r
+ // Checks if a filling char has been used, eventualy removing it (#1272).\r
+ function checkFillingChar( doc )\r
+ {\r
+ var fillingChar = doc && getFillingChar( doc );\r
+ if ( fillingChar )\r
+ {\r
+ // Use this flag to avoid removing the filling char right after\r
+ // creating it.\r
+ if ( fillingChar.getCustomData( 'ready' ) )\r
+ removeFillingChar( doc );\r
+ else\r
+ fillingChar.setCustomData( 'ready', 1 );\r
+ }\r
+ }\r
+\r
+ function removeFillingChar( doc )\r
+ {\r
+ var fillingChar = doc && doc.removeCustomData( 'cke-fillingChar' );\r
+ if ( fillingChar )\r
+ {\r
+ var bm,\r
+ sel = doc.getSelection().getNative(),\r
+ // Be error proof.\r
+ range = sel && sel.type != 'None' && sel.getRangeAt( 0 );\r
+\r
+ // Text selection position might get mangled by\r
+ // subsequent dom modification, save it now for restoring. (#8617)\r
+ if ( fillingChar.getLength() > 1\r
+ && range && range.intersectsNode( fillingChar.$ ) )\r
+ {\r
+ bm = [ sel.anchorOffset, sel.focusOffset ];\r
+\r
+ // Anticipate the offset change brought by the removed char.\r
+ var startAffected = sel.anchorNode == fillingChar.$ && sel.anchorOffset > 0,\r
+ endAffected = sel.focusNode == fillingChar.$ && sel.focusOffset > 0;\r
+ startAffected && bm[ 0 ]--;\r
+ endAffected && bm[ 1 ]--;\r
+\r
+ // Revert the bookmark order on reverse selection.\r
+ isReversedSelection( sel ) && bm.unshift( bm.pop() );\r
+ }\r
+\r
+ // We can't simply remove the filling node because the user\r
+ // will actually enlarge it when typing, so we just remove the\r
+ // invisible char from it.\r
+ fillingChar.setText( fillingChar.getText().replace( /\u200B/g, '' ) );\r
+\r
+ // Restore the bookmark.\r
+ if ( bm )\r
+ {\r
+ var rng = sel.getRangeAt( 0 );\r
+ rng.setStart( rng.startContainer, bm[ 0 ] );\r
+ rng.setEnd( rng.startContainer, bm[ 1 ] );\r
+ sel.removeAllRanges();\r
+ sel.addRange( rng );\r
+ }\r
+ }\r
+ }\r
+\r
+ function isReversedSelection( sel )\r
+ {\r
+ if ( !sel.isCollapsed )\r
+ {\r
+ var range = sel.getRangeAt( 0 );\r
+ // Potentially alter an reversed selection range.\r
+ range.setStart( sel.anchorNode, sel.anchorOffset );\r
+ range.setEnd( sel.focusNode, sel.focusOffset );\r
+ return range.collapsed;\r
+ }\r
+ }\r
+\r