@breakside/jskit 2022.24.0 → 2022.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSFileManager+Node.js +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSURL.js +3 -0
- package/Frameworks/Foundation.jsframework/JS/JSZip.js +97 -76
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Info.json +2 -2
- package/Node/io.breakside.jskit-bundle.js +2 -2
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSFileManager+Node.js +2 -2
- package/Root/Frameworks/Foundation/JSURL.js +3 -0
- package/Root/Frameworks/Foundation/JSZip.js +97 -76
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIBasicAnimation.js +1 -1
- package/Root/Frameworks/UIKit/UICursor.js +19 -4
- package/Root/Frameworks/UIKit/UIHTMLApplication.js +53 -15
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +2 -48
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerContext.js +0 -6
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerSVGContext.js +6 -77
- package/Root/Frameworks/UIKit/UIHTMLTextField.js +9 -3
- package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +2 -29
- package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +6 -79
- package/Root/Frameworks/UIKit/UIImageLayer.js +14 -7
- package/Root/Frameworks/UIKit/UILabel.js +74 -1
- package/Root/Frameworks/UIKit/UIMouseTrackingArea.js +55 -0
- package/Root/Frameworks/UIKit/UIState.js +23 -0
- package/Root/Frameworks/UIKit/UITextEditor.js +277 -76
- package/Root/Frameworks/UIKit/UITextEditorDelegate.js +3 -1
- package/Root/Frameworks/UIKit/UITextLayer.js +1 -1
- package/Root/Frameworks/UIKit/UIView.js +118 -46
- package/Root/Frameworks/UIKit/UIViewController.js +6 -0
- package/Root/Frameworks/UIKit/UIWindow.js +89 -0
- package/Root/Frameworks/UIKit/UIWindowServer.js +20 -79
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -145,17 +145,22 @@ JSClass("UITextEditor", JSObject, {
|
|
|
145
145
|
}else{
|
|
146
146
|
this._handledSelectOnMouseDown = true;
|
|
147
147
|
var range = null;
|
|
148
|
+
var atomicRange;
|
|
148
149
|
var affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
149
150
|
var selection = this._createSelectionAtLocation(location);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
151
|
+
if (selection.range.length === 0){
|
|
152
|
+
var index = selection.range.location - (selection.affinity == UITextInput.SelectionAffinity.afterPreviousCharacter ? 1 : 0);
|
|
153
|
+
if (event.clickCount === 2){
|
|
154
|
+
range = this.textLayoutManager.textStorage.string.rangeForWordAtIndex(index);
|
|
155
|
+
affinity = selection.affinity;
|
|
156
|
+
}else if (event.clickCount === 3){
|
|
157
|
+
range = this.textLayoutManager.textStorage.string.rangeForLineAtIndex(index);
|
|
158
|
+
}
|
|
159
|
+
if (range !== null){
|
|
160
|
+
selection = this._createSelection(range, UITextInput.SelectionInsertionPoint.end, affinity);
|
|
161
|
+
this._insertSelection(selection);
|
|
162
|
+
}
|
|
163
|
+
}else{
|
|
159
164
|
this._insertSelection(selection);
|
|
160
165
|
}
|
|
161
166
|
this._cursorOn();
|
|
@@ -172,12 +177,12 @@ JSClass("UITextEditor", JSObject, {
|
|
|
172
177
|
if (newSelection.range.location < draggingSelection.range.end){
|
|
173
178
|
draggingSelection.range = JSRange(newSelection.range.location, draggingSelection.range.end - newSelection.range.location);
|
|
174
179
|
}else{
|
|
175
|
-
draggingSelection.range = JSRange(draggingSelection.range.end, newSelection.range.
|
|
180
|
+
draggingSelection.range = JSRange(draggingSelection.range.end, newSelection.range.end - draggingSelection.range.end);
|
|
176
181
|
draggingSelection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
177
182
|
}
|
|
178
183
|
}else{
|
|
179
|
-
if (newSelection.range.
|
|
180
|
-
draggingSelection.range = JSRange(draggingSelection.range.location, newSelection.range.
|
|
184
|
+
if (newSelection.range.end >= draggingSelection.range.location){
|
|
185
|
+
draggingSelection.range = JSRange(draggingSelection.range.location, newSelection.range.end - draggingSelection.range.location);
|
|
181
186
|
}else{
|
|
182
187
|
draggingSelection.range = JSRange(newSelection.range.location, draggingSelection.range.location - newSelection.range.location);
|
|
183
188
|
draggingSelection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
@@ -562,6 +567,13 @@ JSClass("UITextEditor", JSObject, {
|
|
|
562
567
|
|
|
563
568
|
_createSelectionAtLocation: function(location){
|
|
564
569
|
var index = this.textLayoutManager.characterIndexAtPoint(location);
|
|
570
|
+
var atomicRange;
|
|
571
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
572
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, index);
|
|
573
|
+
if (atomicRange){
|
|
574
|
+
return this._createSelection(atomicRange, UITextInput.SelectionInsertionPoint.end, UITextInput.SelectionAffinity.beforeCurrentCharacter);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
565
577
|
var rect = this.textLayoutManager.rectForCharacterAtIndex(index);
|
|
566
578
|
var affinity;
|
|
567
579
|
if (rect.origin.y > location.y){
|
|
@@ -722,9 +734,23 @@ JSClass("UITextEditor", JSObject, {
|
|
|
722
734
|
if (JSAttributedString.Attribute.attachment in attributes){
|
|
723
735
|
delete attributes[JSAttributedString.Attribute.attachment];
|
|
724
736
|
}
|
|
737
|
+
if (this.delegate && this.delegate.textEditorPrepareInsertAttributes){
|
|
738
|
+
this.delegate.textEditorPrepareInsertAttributes(this, attributes);
|
|
739
|
+
}
|
|
725
740
|
return attributes;
|
|
726
741
|
},
|
|
727
742
|
|
|
743
|
+
deleteSelections: function(){
|
|
744
|
+
var textStorage = this.textLayoutManager.textStorage;
|
|
745
|
+
var selection;
|
|
746
|
+
var ranges = [];
|
|
747
|
+
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
748
|
+
selection = this.selections[i];
|
|
749
|
+
ranges.push(JSRange(selection.range));
|
|
750
|
+
}
|
|
751
|
+
this._deleteRanges(ranges);
|
|
752
|
+
},
|
|
753
|
+
|
|
728
754
|
_isHandlingSelectionAdjustments: false,
|
|
729
755
|
|
|
730
756
|
textStorageDidReplaceCharactersInRange: function(range, insertedLength){
|
|
@@ -811,17 +837,6 @@ JSClass("UITextEditor", JSObject, {
|
|
|
811
837
|
this.insertText("\t");
|
|
812
838
|
},
|
|
813
839
|
|
|
814
|
-
deleteSelections: function(){
|
|
815
|
-
var textStorage = this.textLayoutManager.textStorage;
|
|
816
|
-
var selection;
|
|
817
|
-
var ranges = [];
|
|
818
|
-
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
819
|
-
selection = this.selections[i];
|
|
820
|
-
ranges.push(JSRange(selection.range));
|
|
821
|
-
}
|
|
822
|
-
this._deleteRanges(ranges);
|
|
823
|
-
},
|
|
824
|
-
|
|
825
840
|
deleteBackward: function(){
|
|
826
841
|
if (this.hasSelectionRange()){
|
|
827
842
|
this.deleteSelections();
|
|
@@ -829,14 +844,17 @@ JSClass("UITextEditor", JSObject, {
|
|
|
829
844
|
}
|
|
830
845
|
var textStorage = this.textLayoutManager.textStorage;
|
|
831
846
|
var selection;
|
|
832
|
-
var
|
|
847
|
+
var range;
|
|
833
848
|
var ranges = [];
|
|
834
849
|
// we only get here if the selections all have 0 length
|
|
835
850
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
836
851
|
selection = this.selections[i];
|
|
837
852
|
if (selection.range.location > 0){
|
|
838
|
-
|
|
839
|
-
|
|
853
|
+
range = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.location - 1);
|
|
854
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
855
|
+
range = JSRange(this.delegate.atomicRangeForTextEditorIndex(this, range.location)) || range;
|
|
856
|
+
}
|
|
857
|
+
ranges.push(range);
|
|
840
858
|
}else{
|
|
841
859
|
ranges.push(JSRange(selection.range));
|
|
842
860
|
}
|
|
@@ -852,11 +870,18 @@ JSClass("UITextEditor", JSObject, {
|
|
|
852
870
|
var textStorage = this.textLayoutManager.textStorage;
|
|
853
871
|
var selection;
|
|
854
872
|
var indexOfPreviousWord;
|
|
873
|
+
var range;
|
|
855
874
|
var ranges = [];
|
|
856
875
|
// we only get here if the selections all have 0 length
|
|
857
876
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
858
877
|
selection = this.selections[i];
|
|
859
878
|
indexOfPreviousWord = textStorage.string.indexOfWordStartBeforeIndex(selection.range.location);
|
|
879
|
+
if (indexOfPreviousWord < selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
880
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, indexOfPreviousWord);
|
|
881
|
+
if (range){
|
|
882
|
+
indexOfPreviousWord = range.location;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
860
885
|
ranges.push(JSRange(indexOfPreviousWord, selection.range.location - indexOfPreviousWord));
|
|
861
886
|
}
|
|
862
887
|
this._deleteRanges(ranges);
|
|
@@ -871,12 +896,21 @@ JSClass("UITextEditor", JSObject, {
|
|
|
871
896
|
var ranges = [];
|
|
872
897
|
var selection;
|
|
873
898
|
var line;
|
|
899
|
+
var range;
|
|
900
|
+
var indexOfLineStart;
|
|
874
901
|
// we only get here if the selections all have 0 length
|
|
875
902
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
876
903
|
selection = this.selections[i];
|
|
877
904
|
line = this._lineForSelectionStart(selection);
|
|
878
905
|
if (line !== null && selection.range.location > line.range.location){
|
|
879
|
-
|
|
906
|
+
indexOfLineStart = line.range.location;
|
|
907
|
+
if (indexOfLineStart < selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
908
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, indexOfLineStart);
|
|
909
|
+
if (range){
|
|
910
|
+
indexOfLineStart = range.location;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
ranges.push(JSRange(indexOfLineStart, selection.range.location - indexOfLineStart));
|
|
880
914
|
}else{
|
|
881
915
|
ranges.push(JSRange(selection.range));
|
|
882
916
|
}
|
|
@@ -902,14 +936,17 @@ JSClass("UITextEditor", JSObject, {
|
|
|
902
936
|
}
|
|
903
937
|
var textStorage = this.textLayoutManager.textStorage;
|
|
904
938
|
var selection;
|
|
905
|
-
var
|
|
939
|
+
var range;
|
|
906
940
|
var ranges = [];
|
|
907
941
|
// we only get here if the selections all have 0 length
|
|
908
942
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
909
943
|
selection = this.selections[i];
|
|
910
944
|
if (selection.range.location < textStorage.string.length){
|
|
911
|
-
|
|
912
|
-
|
|
945
|
+
range = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.location);
|
|
946
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
947
|
+
range = JSRange(this.delegate.atomicRangeForTextEditorIndex(this, range.location)) || range;
|
|
948
|
+
}
|
|
949
|
+
ranges.push(range);
|
|
913
950
|
}else{
|
|
914
951
|
ranges.push(JSRange(selection.range));
|
|
915
952
|
}
|
|
@@ -925,11 +962,18 @@ JSClass("UITextEditor", JSObject, {
|
|
|
925
962
|
var textStorage = this.textLayoutManager.textStorage;
|
|
926
963
|
var selection;
|
|
927
964
|
var nextWordIndex;
|
|
965
|
+
var range;
|
|
928
966
|
var ranges = [];
|
|
929
967
|
// we only get here if the selections all have 0 length
|
|
930
968
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
931
969
|
selection = this.selections[i];
|
|
932
970
|
nextWordIndex = textStorage.string.indexOfWordEndAfterIndex(selection.range.location);
|
|
971
|
+
if (nextWordIndex > selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
972
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, nextWordIndex - 1);
|
|
973
|
+
if (range){
|
|
974
|
+
nextWordIndex = range.end;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
933
977
|
ranges.push(JSRange(selection.range.location, nextWordIndex - selection.range.location));
|
|
934
978
|
}
|
|
935
979
|
this._deleteRanges(ranges);
|
|
@@ -944,18 +988,26 @@ JSClass("UITextEditor", JSObject, {
|
|
|
944
988
|
var ranges = [];
|
|
945
989
|
var selection;
|
|
946
990
|
var line;
|
|
991
|
+
var range;
|
|
992
|
+
var indexOfLineEnd;
|
|
947
993
|
// we only get here if the selections all have 0 length
|
|
948
994
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
949
995
|
selection = this.selections[i];
|
|
950
996
|
line = this._lineForSelectionStart(selection);
|
|
951
997
|
if (line !== null && selection.range.location < line.range.end){
|
|
998
|
+
indexOfLineEnd = line.range.end;
|
|
999
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1000
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, indexOfLineEnd - 1);
|
|
1001
|
+
if (range){
|
|
1002
|
+
indexOfLineEnd = range.end;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
952
1005
|
// Only delete up to a line break if one exists, but don't include the line break
|
|
953
|
-
var iterator = textStorage.string.userPerceivedCharacterIterator(
|
|
1006
|
+
var iterator = textStorage.string.userPerceivedCharacterIterator(indexOfLineEnd - 1);
|
|
954
1007
|
if (iterator.isMandatoryLineBreak){
|
|
955
|
-
|
|
956
|
-
}else{
|
|
957
|
-
ranges.push(JSRange(selection.range.location, line.range.end - selection.range.location));
|
|
1008
|
+
indexOfLineEnd = iterator.index;
|
|
958
1009
|
}
|
|
1010
|
+
ranges.push(JSRange(selection.range.location, indexOfLineEnd - selection.range.location));
|
|
959
1011
|
}else{
|
|
960
1012
|
ranges.push(JSRange(selection.range));
|
|
961
1013
|
}
|
|
@@ -979,16 +1031,28 @@ JSClass("UITextEditor", JSObject, {
|
|
|
979
1031
|
var textStorage = this.textLayoutManager.textStorage;
|
|
980
1032
|
var selection;
|
|
981
1033
|
var perceivedCharacterRange;
|
|
1034
|
+
var atomicRange;
|
|
982
1035
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
983
1036
|
selection = this.selections[i];
|
|
984
1037
|
selection.attributes = null;
|
|
985
1038
|
if (selection.range.length === 0){
|
|
986
1039
|
if (selection.range.location > 0){
|
|
987
1040
|
perceivedCharacterRange = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.location - 1);
|
|
988
|
-
|
|
1041
|
+
atomicRange = null;
|
|
1042
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1043
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, perceivedCharacterRange.location);
|
|
1044
|
+
}
|
|
1045
|
+
if (atomicRange){
|
|
1046
|
+
selection.range = JSRange(atomicRange);
|
|
1047
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1048
|
+
}else{
|
|
1049
|
+
selection.range = JSRange(perceivedCharacterRange.location, 0);
|
|
1050
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1051
|
+
}
|
|
989
1052
|
}
|
|
990
1053
|
}else{
|
|
991
1054
|
selection.range = JSRange(selection.range.location, 0);
|
|
1055
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
992
1056
|
}
|
|
993
1057
|
}
|
|
994
1058
|
this._collapseOverlappingSelections();
|
|
@@ -1000,13 +1064,23 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1000
1064
|
moveWordBackward: function(){
|
|
1001
1065
|
var textStorage = this.textLayoutManager.textStorage;
|
|
1002
1066
|
var selection;
|
|
1003
|
-
var wordRange;
|
|
1004
1067
|
var indexOfPreviousWord;
|
|
1068
|
+
var atomicRange;
|
|
1005
1069
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1006
1070
|
selection = this.selections[i];
|
|
1007
1071
|
selection.attributes = null;
|
|
1008
1072
|
indexOfPreviousWord = textStorage.string.indexOfWordStartBeforeIndex(selection.range.location);
|
|
1009
|
-
|
|
1073
|
+
atomicRange = null;
|
|
1074
|
+
if (indexOfPreviousWord < selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1075
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, indexOfPreviousWord);
|
|
1076
|
+
}
|
|
1077
|
+
if (atomicRange){
|
|
1078
|
+
selection.range = JSRange(atomicRange);
|
|
1079
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1080
|
+
}else{
|
|
1081
|
+
selection.range = JSRange(indexOfPreviousWord, 0);
|
|
1082
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1083
|
+
}
|
|
1010
1084
|
}
|
|
1011
1085
|
this._collapseOverlappingSelections();
|
|
1012
1086
|
this._resetSelectionAffinity();
|
|
@@ -1018,12 +1092,23 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1018
1092
|
var textStorage = this.textLayoutManager.textStorage;
|
|
1019
1093
|
var selection;
|
|
1020
1094
|
var line;
|
|
1095
|
+
var atomicRange;
|
|
1021
1096
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1022
1097
|
selection = this.selections[i];
|
|
1023
1098
|
selection.attributes = null;
|
|
1024
1099
|
line = this._lineForSelectionStart(selection);
|
|
1025
1100
|
if (line !== null){
|
|
1026
|
-
|
|
1101
|
+
atomicRange = null;
|
|
1102
|
+
if (line.range.location < selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1103
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, line.range.location);
|
|
1104
|
+
}
|
|
1105
|
+
if (atomicRange){
|
|
1106
|
+
selection.range = JSRange(atomicRange);
|
|
1107
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1108
|
+
}else{
|
|
1109
|
+
selection.range = JSRange(line.range.location, 0);
|
|
1110
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1111
|
+
}
|
|
1027
1112
|
}
|
|
1028
1113
|
}
|
|
1029
1114
|
this._collapseOverlappingSelections();
|
|
@@ -1042,6 +1127,7 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1042
1127
|
var cursorRect;
|
|
1043
1128
|
var lineEnumerator;
|
|
1044
1129
|
var cursorX;
|
|
1130
|
+
var atomicRange;
|
|
1045
1131
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1046
1132
|
selection = this.selections[i];
|
|
1047
1133
|
selection.attributes = null;
|
|
@@ -1055,17 +1141,27 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1055
1141
|
lineRect = lineEnumerator.rect;
|
|
1056
1142
|
pointOnPreviousLine = JSPoint(cursorX, lineRect.origin.y + lineRect.size.height / 2);
|
|
1057
1143
|
index = this.textLayoutManager.characterIndexAtPoint(pointOnPreviousLine);
|
|
1058
|
-
|
|
1059
|
-
if (selection.range.location
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1144
|
+
atomicRange = null;
|
|
1145
|
+
if (index < selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1146
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, index);
|
|
1147
|
+
}
|
|
1148
|
+
if (atomicRange){
|
|
1149
|
+
selection.range = JSRange(atomicRange);
|
|
1150
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1151
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1152
|
+
}else{
|
|
1153
|
+
selection.range = JSRange(index, 0);
|
|
1154
|
+
if (selection.range.location === line.range.location && selection.range.location > 0){
|
|
1155
|
+
var iterator = textStorage.string.userPerceivedCharacterIterator(selection.range.location - 1);
|
|
1156
|
+
if (iterator.isMandatoryLineBreak){
|
|
1157
|
+
selection.range = JSRange(iterator.index, 0);
|
|
1158
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1159
|
+
}else{
|
|
1160
|
+
selection.affinity = UITextInput.SelectionAffinity.afterPreviousCharacter;
|
|
1161
|
+
}
|
|
1064
1162
|
}else{
|
|
1065
|
-
selection.affinity = UITextInput.SelectionAffinity.
|
|
1163
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1066
1164
|
}
|
|
1067
|
-
}else{
|
|
1068
|
-
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1069
1165
|
}
|
|
1070
1166
|
}else{
|
|
1071
1167
|
selection.range = JSRange.Zero;
|
|
@@ -1086,13 +1182,24 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1086
1182
|
var textStorage = this.textLayoutManager.textStorage;
|
|
1087
1183
|
var selection;
|
|
1088
1184
|
var perceivedCharacterRange;
|
|
1185
|
+
var atomicRange;
|
|
1089
1186
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1090
1187
|
selection = this.selections[i];
|
|
1091
1188
|
selection.attributes = null;
|
|
1092
1189
|
if (selection.range.length === 0){
|
|
1093
1190
|
if (selection.range.location < textStorage.string.length){
|
|
1094
1191
|
perceivedCharacterRange = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.location);
|
|
1095
|
-
|
|
1192
|
+
atomicRange = null;
|
|
1193
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1194
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, perceivedCharacterRange.location);
|
|
1195
|
+
}
|
|
1196
|
+
if (atomicRange){
|
|
1197
|
+
selection.range = JSRange(atomicRange);
|
|
1198
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1199
|
+
}else{
|
|
1200
|
+
selection.range = JSRange(perceivedCharacterRange.end, 0);
|
|
1201
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1202
|
+
}
|
|
1096
1203
|
}
|
|
1097
1204
|
}else{
|
|
1098
1205
|
selection.range = JSRange(selection.range.end, 0);
|
|
@@ -1109,11 +1216,22 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1109
1216
|
var selection;
|
|
1110
1217
|
var wordRange;
|
|
1111
1218
|
var nextWordIndex;
|
|
1219
|
+
var atomicRange;
|
|
1112
1220
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1113
1221
|
selection = this.selections[i];
|
|
1114
1222
|
selection.attributes = null;
|
|
1115
1223
|
nextWordIndex = textStorage.string.indexOfWordEndAfterIndex(selection.range.end);
|
|
1116
|
-
|
|
1224
|
+
atomicRange = null;
|
|
1225
|
+
if (nextWordIndex > selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1226
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, nextWordIndex - 1);
|
|
1227
|
+
}
|
|
1228
|
+
if (atomicRange){
|
|
1229
|
+
selection.range = JSRange(atomicRange);
|
|
1230
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1231
|
+
}else{
|
|
1232
|
+
selection.range = JSRange(nextWordIndex, 0);
|
|
1233
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1234
|
+
}
|
|
1117
1235
|
}
|
|
1118
1236
|
this._collapseOverlappingSelections();
|
|
1119
1237
|
this._resetSelectionAffinity();
|
|
@@ -1125,18 +1243,31 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1125
1243
|
var textStorage = this.textLayoutManager.textStorage;
|
|
1126
1244
|
var selection;
|
|
1127
1245
|
var line;
|
|
1246
|
+
var atomicRange;
|
|
1128
1247
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1129
1248
|
selection = this.selections[i];
|
|
1130
1249
|
selection.attributes = null;
|
|
1131
1250
|
line = this._lineForSelectionEnd(selection);
|
|
1132
1251
|
if (line !== null && line.range.end > selection.range.location){
|
|
1133
|
-
|
|
1134
|
-
if (
|
|
1135
|
-
|
|
1252
|
+
atomicRange = null;
|
|
1253
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1254
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, line.range.end);
|
|
1255
|
+
}
|
|
1256
|
+
if (atomicRange){
|
|
1257
|
+
selection.range = JSRange(atomicRange);
|
|
1258
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1136
1259
|
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1137
1260
|
}else{
|
|
1138
|
-
|
|
1139
|
-
|
|
1261
|
+
var iterator = textStorage.string.userPerceivedCharacterIterator(line.range.end - 1);
|
|
1262
|
+
if (iterator.isMandatoryLineBreak){
|
|
1263
|
+
selection.range = JSRange(iterator.index, 0);
|
|
1264
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1265
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1266
|
+
}else{
|
|
1267
|
+
selection.range = JSRange(line.range.end, 0);
|
|
1268
|
+
selection.affinity = UITextInput.SelectionAffinity.afterPreviousCharacter;
|
|
1269
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1270
|
+
}
|
|
1140
1271
|
}
|
|
1141
1272
|
}
|
|
1142
1273
|
}
|
|
@@ -1155,6 +1286,7 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1155
1286
|
var cursorRect;
|
|
1156
1287
|
var cursorX;
|
|
1157
1288
|
var lineEnumerator;
|
|
1289
|
+
var atomicRange;
|
|
1158
1290
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1159
1291
|
selection = this.selections[i];
|
|
1160
1292
|
selection.attributes = null;
|
|
@@ -1168,17 +1300,27 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1168
1300
|
lineRect = lineEnumerator.rect;
|
|
1169
1301
|
pointOnNextLine = JSPoint(cursorX, lineRect.origin.y + lineRect.size.height / 2);
|
|
1170
1302
|
index = this.textLayoutManager.characterIndexAtPoint(pointOnNextLine);
|
|
1171
|
-
|
|
1172
|
-
if (selection.range.location
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1303
|
+
atomicRange = null;
|
|
1304
|
+
if (index > selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1305
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, index);
|
|
1306
|
+
}
|
|
1307
|
+
if (atomicRange){
|
|
1308
|
+
selection.range = JSRange(atomicRange);
|
|
1309
|
+
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1310
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1311
|
+
}else{
|
|
1312
|
+
selection.range = JSRange(index, 0);
|
|
1313
|
+
if (selection.range.location === lineEnumerator.line.range.end && selection.range.location > 0){
|
|
1314
|
+
var iterator = textStorage.string.userPerceivedCharacterIterator(selection.range.location - 1);
|
|
1315
|
+
if (iterator.isMandatoryLineBreak){
|
|
1316
|
+
selection.range = JSRange(iterator.index, 0);
|
|
1317
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1318
|
+
}else{
|
|
1319
|
+
selection.affinity = UITextInput.SelectionAffinity.afterPreviousCharacter;
|
|
1320
|
+
}
|
|
1177
1321
|
}else{
|
|
1178
|
-
selection.affinity = UITextInput.SelectionAffinity.
|
|
1322
|
+
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1179
1323
|
}
|
|
1180
|
-
}else{
|
|
1181
|
-
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1182
1324
|
}
|
|
1183
1325
|
}else{
|
|
1184
1326
|
selection.range = this._sanitizedRange(JSRange(line.range.end, 0));
|
|
@@ -1199,17 +1341,23 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1199
1341
|
moveBackwardAndModifySelection: function(){
|
|
1200
1342
|
var textStorage = this.textLayoutManager.textStorage;
|
|
1201
1343
|
var selection;
|
|
1202
|
-
var
|
|
1344
|
+
var range;
|
|
1203
1345
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1204
1346
|
selection = this.selections[i];
|
|
1205
1347
|
selection.attributes = null;
|
|
1206
1348
|
if (selection.range.length > 0 && selection.insertionPoint == UITextInput.SelectionInsertionPoint.end){
|
|
1207
|
-
|
|
1208
|
-
|
|
1349
|
+
range = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.end - 1);
|
|
1350
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1351
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, range.location) || range;
|
|
1352
|
+
}
|
|
1353
|
+
selection.range.length -= range.length;
|
|
1209
1354
|
}else{
|
|
1210
1355
|
if (selection.range.location > 0){
|
|
1211
|
-
|
|
1212
|
-
|
|
1356
|
+
range = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.location - 1);
|
|
1357
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1358
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, range.location) || range;
|
|
1359
|
+
}
|
|
1360
|
+
selection.range = JSRange(range.location, range.length + selection.range.length);
|
|
1213
1361
|
}
|
|
1214
1362
|
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1215
1363
|
}
|
|
@@ -1226,6 +1374,7 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1226
1374
|
var wordRange;
|
|
1227
1375
|
var indexOfPreviousWord;
|
|
1228
1376
|
var end;
|
|
1377
|
+
var atomicRange;
|
|
1229
1378
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1230
1379
|
selection = this.selections[i];
|
|
1231
1380
|
selection.attributes = null;
|
|
@@ -1235,6 +1384,12 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1235
1384
|
end = selection.range.location;
|
|
1236
1385
|
}
|
|
1237
1386
|
indexOfPreviousWord = textStorage.string.indexOfWordStartBeforeIndex(selection.range.location);
|
|
1387
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1388
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, indexOfPreviousWord);
|
|
1389
|
+
if (atomicRange){
|
|
1390
|
+
indexOfPreviousWord = atomicRange.location;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1238
1393
|
selection.range = JSRange(indexOfPreviousWord, end - indexOfPreviousWord);
|
|
1239
1394
|
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1240
1395
|
}
|
|
@@ -1249,17 +1404,27 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1249
1404
|
var selection;
|
|
1250
1405
|
var line;
|
|
1251
1406
|
var end;
|
|
1407
|
+
var atomicRange;
|
|
1408
|
+
var indexOfLineStart;
|
|
1252
1409
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1253
1410
|
selection = this.selections[i];
|
|
1254
1411
|
selection.attributes = null;
|
|
1255
1412
|
line = this._lineForSelectionStart(selection);
|
|
1413
|
+
atomicRange = null;
|
|
1256
1414
|
if (line !== null){
|
|
1257
1415
|
if (selection.insertionPoint == UITextInput.SelectionInsertionPoint.start){
|
|
1258
1416
|
end = selection.range.end;
|
|
1259
1417
|
}else{
|
|
1260
1418
|
end = selection.range.location;
|
|
1261
1419
|
}
|
|
1262
|
-
|
|
1420
|
+
indexOfLineStart = line.range.location;
|
|
1421
|
+
if (indexOfLineStart < selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1422
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, indexOfLineStart);
|
|
1423
|
+
if (atomicRange){
|
|
1424
|
+
indexOfLineStart = atomicRange.location;
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
selection.range = JSRange(indexOfLineStart, end - indexOfLineStart);
|
|
1263
1428
|
}
|
|
1264
1429
|
selection.insertionPoint = UITextInput.SelectionInsertionPoint.start;
|
|
1265
1430
|
}
|
|
@@ -1279,6 +1444,7 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1279
1444
|
var cursorRect;
|
|
1280
1445
|
var cursorX;
|
|
1281
1446
|
var lineEnumerator;
|
|
1447
|
+
var atomicRange;
|
|
1282
1448
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1283
1449
|
selection = this.selections[i];
|
|
1284
1450
|
selection.attributes = null;
|
|
@@ -1291,6 +1457,12 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1291
1457
|
lineRect = lineEnumerator.rect;
|
|
1292
1458
|
pointOnPreviousLine = JSPoint(cursorX, lineRect.origin.y + lineRect.size.height / 2);
|
|
1293
1459
|
index = this.textLayoutManager.characterIndexAtPoint(pointOnPreviousLine);
|
|
1460
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1461
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, index);
|
|
1462
|
+
if (atomicRange){
|
|
1463
|
+
index = atomicRange.location;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1294
1466
|
if (index === line.range.location && index > 0){
|
|
1295
1467
|
var iterator = textStorage.string.userPerceivedCharacterIterator(index - 1);
|
|
1296
1468
|
if (iterator.isMandatoryLineBreak){
|
|
@@ -1344,17 +1516,23 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1344
1516
|
moveForwardAndModifySelection: function(){
|
|
1345
1517
|
var textStorage = this.textLayoutManager.textStorage;
|
|
1346
1518
|
var selection;
|
|
1347
|
-
var
|
|
1519
|
+
var range;
|
|
1348
1520
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1349
1521
|
selection = this.selections[i];
|
|
1350
1522
|
selection.attributes = null;
|
|
1351
1523
|
if (selection.range.length > 0 && selection.insertionPoint == UITextInput.SelectionInsertionPoint.start){
|
|
1352
|
-
|
|
1353
|
-
|
|
1524
|
+
range = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.location);
|
|
1525
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1526
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, range.location) || range;
|
|
1527
|
+
}
|
|
1528
|
+
selection.range.advance(range.length);
|
|
1354
1529
|
}else{
|
|
1355
1530
|
if (selection.range.end < textStorage.string.length){
|
|
1356
|
-
|
|
1357
|
-
|
|
1531
|
+
range = textStorage.string.rangeForUserPerceivedCharacterAtIndex(selection.range.end);
|
|
1532
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1533
|
+
range = this.delegate.atomicRangeForTextEditorIndex(this, range.location) || range;
|
|
1534
|
+
}
|
|
1535
|
+
selection.range = JSRange(selection.range.location, range.length + selection.range.length);
|
|
1358
1536
|
}
|
|
1359
1537
|
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1360
1538
|
}
|
|
@@ -1371,6 +1549,7 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1371
1549
|
var wordRange;
|
|
1372
1550
|
var nextWordIndex;
|
|
1373
1551
|
var start;
|
|
1552
|
+
var atomicRange;
|
|
1374
1553
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1375
1554
|
selection = this.selections[i];
|
|
1376
1555
|
selection.attributes = null;
|
|
@@ -1380,6 +1559,12 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1380
1559
|
start = selection.range.location;
|
|
1381
1560
|
}
|
|
1382
1561
|
nextWordIndex = textStorage.string.indexOfWordEndAfterIndex(selection.range.end);
|
|
1562
|
+
if (nextWordIndex > selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1563
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, nextWordIndex - 1);
|
|
1564
|
+
if (atomicRange){
|
|
1565
|
+
nextWordIndex = atomicRange.end;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1383
1568
|
selection.range = JSRange(start, nextWordIndex - start);
|
|
1384
1569
|
selection.insertionPoint = UITextInput.SelectionInsertionPoint.end;
|
|
1385
1570
|
}
|
|
@@ -1394,6 +1579,8 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1394
1579
|
var selection;
|
|
1395
1580
|
var line;
|
|
1396
1581
|
var start;
|
|
1582
|
+
var atomicRange;
|
|
1583
|
+
var indexOfLineEnd;
|
|
1397
1584
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1398
1585
|
selection = this.selections[i];
|
|
1399
1586
|
selection.attributes = null;
|
|
@@ -1404,12 +1591,19 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1404
1591
|
start = selection.range.location;
|
|
1405
1592
|
}
|
|
1406
1593
|
if (line !== null){
|
|
1407
|
-
|
|
1594
|
+
indexOfLineEnd = line.range.end;
|
|
1595
|
+
if (line.range.location > selection.range.location && this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1596
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, indexOfLineEnd - 1);
|
|
1597
|
+
if (atomicRange){
|
|
1598
|
+
indexOfLineEnd = atomicRange.end;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
var iterator = textStorage.string.userPerceivedCharacterIterator(indexOfLineEnd - 1);
|
|
1408
1602
|
if (iterator.isMandatoryLineBreak){
|
|
1409
1603
|
selection.range = JSRange(start, iterator.index - start);
|
|
1410
1604
|
selection.affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
|
|
1411
1605
|
}else{
|
|
1412
|
-
selection.range = JSRange(start,
|
|
1606
|
+
selection.range = JSRange(start, indexOfLineEnd - start);
|
|
1413
1607
|
selection.affinity = UITextInput.SelectionAffinity.afterPreviousCharacter;
|
|
1414
1608
|
}
|
|
1415
1609
|
}
|
|
@@ -1430,6 +1624,7 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1430
1624
|
var lineRect;
|
|
1431
1625
|
var cursorRect;
|
|
1432
1626
|
var cursorX;
|
|
1627
|
+
var atomicRange;
|
|
1433
1628
|
for (var i = 0, l = this.selections.length; i < l; ++i){
|
|
1434
1629
|
selection = this.selections[i];
|
|
1435
1630
|
selection.attributes = null;
|
|
@@ -1442,6 +1637,12 @@ JSClass("UITextEditor", JSObject, {
|
|
|
1442
1637
|
lineRect = lineEnumerator.rect;
|
|
1443
1638
|
pointOnNextLine = JSPoint(cursorX, lineRect.origin.y + lineRect.size.height / 2);
|
|
1444
1639
|
index = this.textLayoutManager.characterIndexAtPoint(pointOnNextLine);
|
|
1640
|
+
if (this.delegate && this.delegate.atomicRangeForTextEditorIndex){
|
|
1641
|
+
atomicRange = this.delegate.atomicRangeForTextEditorIndex(this, index - 1);
|
|
1642
|
+
if (atomicRange){
|
|
1643
|
+
index = atomicRange.end;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1445
1646
|
if (index === lineEnumerator.line.range.end && index > 0){
|
|
1446
1647
|
var iterator = textStorage.string.userPerceivedCharacterIterator(index - 1);
|
|
1447
1648
|
if (iterator.isMandatoryLineBreak){
|