react-native-enriched 0.1.2 → 0.1.3
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/README.md +43 -40
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +3 -1
- package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +2 -0
- package/ios/styles/InlineCodeStyle.mm +7 -6
- package/ios/styles/MentionStyle.mm +3 -2
- package/ios/utils/ColorExtension.h +1 -0
- package/ios/utils/ColorExtension.mm +9 -0
- package/ios/utils/TextInsertionUtils.mm +2 -2
- package/ios/utils/ZeroWidthSpaceUtils.mm +2 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Built by [Software Mansion](https://swmansion.com/) and sponsored by [Filament](
|
|
|
22
22
|
<img width="80" height="80" alt="Filament Logo" src="https://github.com/user-attachments/assets/4103ab79-da34-4164-aa5f-dcf08815bf65" />
|
|
23
23
|
|
|
24
24
|
\
|
|
25
|
-
Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues.
|
|
25
|
+
Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues.
|
|
26
26
|
We can help you build your next dream product –
|
|
27
27
|
[Hire us](https://swmansion.com/contact/projects?utm_source=react-native-enriched&utm_medium=readme).
|
|
28
28
|
|
|
@@ -139,27 +139,27 @@ const styles = StyleSheet.create({
|
|
|
139
139
|
Summary of what happens here:
|
|
140
140
|
|
|
141
141
|
1. Any methods imperatively called on the input to e.g. toggle some style must be used through a `ref` of `EnrichedTextInputInstance` type. Here, `toggleBold` method that is called on the button press calls `ref.current?.toggleBold()`, which toggles the bold styling within the current selection.
|
|
142
|
-
2. All the active styles info is emitted by `onChangeState` event. Set up a proper callback that accepts a `NativeSyntheticEvent<OnChangeStateEvent>` argument and you can access an object with boolean properties indicating which styles are active, such as `isBold` in the example. Here, this info is stored in a
|
|
142
|
+
2. All the active styles info is emitted by `onChangeState` event. Set up a proper callback that accepts a `NativeSyntheticEvent<OnChangeStateEvent>` argument, and you can access an object with boolean properties indicating which styles are active, such as `isBold` in the example. Here, this info is stored in a React state and used to change colors on the button.
|
|
143
143
|
|
|
144
144
|
## Non Parametrized Styles
|
|
145
145
|
|
|
146
146
|
Supported styles:
|
|
147
147
|
|
|
148
|
-
-
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
152
|
-
-
|
|
148
|
+
- bold
|
|
149
|
+
- italic
|
|
150
|
+
- underline
|
|
151
|
+
- strikethrough
|
|
152
|
+
- inline code
|
|
153
153
|
- H1 heading
|
|
154
154
|
- H2 heading
|
|
155
155
|
- H3 heading
|
|
156
|
-
-
|
|
157
|
-
-
|
|
156
|
+
- codeblock
|
|
157
|
+
- blockquote
|
|
158
158
|
- ordered list
|
|
159
159
|
- unordered list
|
|
160
160
|
|
|
161
161
|
> [!NOTE]
|
|
162
|
-
> The iOS doesn't support codeblocks just yet but it's planned in the near future!
|
|
162
|
+
> The iOS doesn't support codeblocks just yet, but it's planned in the near future!
|
|
163
163
|
|
|
164
164
|
Each of the styles can be toggled the same way as in the example from [usage section](#usage); call a proper `toggle` function on the component ref.
|
|
165
165
|
|
|
@@ -176,7 +176,7 @@ The links are here, just like in any other editor, a piece of text with a URL at
|
|
|
176
176
|
|
|
177
177
|
### Automatic links detection
|
|
178
178
|
|
|
179
|
-
`react-native-enriched` automatically detects words that appear to be some URLs and makes them links. Currently we are using pretty naive approach to detect whether text can be treated as a link or not. On iOS it's a pretty simple regex, on Android we are using URL regex provided by the system.
|
|
179
|
+
`react-native-enriched` automatically detects words that appear to be some URLs and makes them links. Currently, we are using pretty naive approach to detect whether text can be treated as a link or not. On iOS it's a pretty simple regex, on Android we are using URL regex provided by the system.
|
|
180
180
|
|
|
181
181
|
### Applying links manually
|
|
182
182
|
|
|
@@ -194,7 +194,7 @@ Mentions are meant to be a customisable style that lets you put mentioning phras
|
|
|
194
194
|
|
|
195
195
|
### Mention Indicators
|
|
196
196
|
|
|
197
|
-
There is a [mentionIndicators](#mentionindicators) prop that lets you define what characters can start a mention. By default it is set to `[ @ ]`, meaning that typing a `@` character in the input will start the creation of a mention.
|
|
197
|
+
There is a [mentionIndicators](#mentionindicators) prop that lets you define what characters can start a mention. By default, it is set to `[ @ ]`, meaning that typing a `@` character in the input will start the creation of a mention.
|
|
198
198
|
|
|
199
199
|
### Starting a mention
|
|
200
200
|
|
|
@@ -216,10 +216,10 @@ Whenever you feel ready with the currently edited mention (so most likely user c
|
|
|
216
216
|
|
|
217
217
|
You can insert an image into the input using [setImage](#setimage) ref method.
|
|
218
218
|
|
|
219
|
-
The image will be put into a single line in the input and will
|
|
219
|
+
The image will be put into a single line in the input and will affect the line's height as well as input's height. Keep in mind, that image will replace currently selected text or insert into the cursor position if there is no text selection.
|
|
220
220
|
|
|
221
221
|
> [!NOTE]
|
|
222
|
-
> The iOS doesn't support inline images just yet but it's planned in the near future!
|
|
222
|
+
> The iOS doesn't support inline images just yet, but it's planned in the near future!
|
|
223
223
|
|
|
224
224
|
## Style Detection
|
|
225
225
|
|
|
@@ -294,7 +294,7 @@ If `false`, text is not editable.
|
|
|
294
294
|
|
|
295
295
|
#### `htmlStyle`
|
|
296
296
|
|
|
297
|
-
A prop for customizing styles
|
|
297
|
+
A prop for customizing styles appearances.
|
|
298
298
|
|
|
299
299
|
| Type | Default Value | Platform |
|
|
300
300
|
|--------------------------------|----------------------------------------------------|----------|
|
|
@@ -330,9 +330,9 @@ interface OnChangeHtmlEvent {
|
|
|
330
330
|
|
|
331
331
|
- `value` is the new HTML.
|
|
332
332
|
|
|
333
|
-
| Type
|
|
334
|
-
|
|
335
|
-
| `(NativeSyntheticEvent
|
|
333
|
+
| Type | Default Value | Platform |
|
|
334
|
+
|------------------------------------------------------------|---------------|----------|
|
|
335
|
+
| `(event: NativeSyntheticEvent<OnChangeHtmlEvent>) => void` | - | Both |
|
|
336
336
|
|
|
337
337
|
#### `onChangeMention`
|
|
338
338
|
|
|
@@ -350,9 +350,9 @@ interface OnChangeMentionEvent {
|
|
|
350
350
|
- `indicator` is the indicator of the currently edited mention.
|
|
351
351
|
- `text` contains whole text that has been typed after the indicator.
|
|
352
352
|
|
|
353
|
-
| Type
|
|
354
|
-
|
|
355
|
-
| `(OnChangeMentionEvent) => void` | - | Both |
|
|
353
|
+
| Type | Default Value | Platform |
|
|
354
|
+
|-----------------------------------------|---------------|----------|
|
|
355
|
+
| `(event: OnChangeMentionEvent) => void` | - | Both |
|
|
356
356
|
|
|
357
357
|
#### `onChangeSelection`
|
|
358
358
|
|
|
@@ -361,7 +361,7 @@ Callback that is called each time user changes selection or moves the cursor in
|
|
|
361
361
|
Payload interface:
|
|
362
362
|
|
|
363
363
|
```ts
|
|
364
|
-
OnChangeSelectionEvent {
|
|
364
|
+
interface OnChangeSelectionEvent {
|
|
365
365
|
start: Int32;
|
|
366
366
|
end: Int32;
|
|
367
367
|
text: string;
|
|
@@ -372,9 +372,9 @@ OnChangeSelectionEvent {
|
|
|
372
372
|
- `end` is the first index after the selection's ending. For just a cursor in place (no selection), `start` equals `end`.
|
|
373
373
|
- `text` is the input's text in the current selection.
|
|
374
374
|
|
|
375
|
-
| Type
|
|
376
|
-
|
|
377
|
-
| `(NativeSyntheticEvent
|
|
375
|
+
| Type | Default Value | Platform |
|
|
376
|
+
|-----------------------------------------------------------------|---------------|----------|
|
|
377
|
+
| `(event: NativeSyntheticEvent<OnChangeSelectionEvent>) => void` | - | Both |
|
|
378
378
|
|
|
379
379
|
#### `onChangeState`
|
|
380
380
|
|
|
@@ -402,9 +402,9 @@ interface OnChangeStateEvent {
|
|
|
402
402
|
}
|
|
403
403
|
```
|
|
404
404
|
|
|
405
|
-
| Type
|
|
406
|
-
|
|
407
|
-
| `(NativeSyntheticEvent
|
|
405
|
+
| Type | Default Value | Platform |
|
|
406
|
+
|-------------------------------------------------------------|---------------|----------|
|
|
407
|
+
| `(event: NativeSyntheticEvent<OnChangeStateEvent>) => void` | - | Both |
|
|
408
408
|
|
|
409
409
|
#### `onChangeText`
|
|
410
410
|
|
|
@@ -420,9 +420,9 @@ interface OnChangeTextEvent {
|
|
|
420
420
|
|
|
421
421
|
- `value` is the new text value of the input.
|
|
422
422
|
|
|
423
|
-
| Type
|
|
424
|
-
|
|
425
|
-
| `(NativeSyntheticEvent
|
|
423
|
+
| Type | Default Value | Platform |
|
|
424
|
+
|------------------------------------------------------------|---------------|----------|
|
|
425
|
+
| `(event: NativeSyntheticEvent<OnChangeTextEvent>) => void` | - | Both |
|
|
426
426
|
|
|
427
427
|
#### `onEndMention`
|
|
428
428
|
|
|
@@ -462,9 +462,9 @@ interface OnLinkDetected {
|
|
|
462
462
|
- `start` is the starting index of the link.
|
|
463
463
|
- `end` is the first index after the ending index of the link.
|
|
464
464
|
|
|
465
|
-
| Type
|
|
466
|
-
|
|
467
|
-
| `(OnLinkDetected) => void` | - | Both |
|
|
465
|
+
| Type | Default Value | Platform |
|
|
466
|
+
|-----------------------------------|---------------|----------|
|
|
467
|
+
| `(event: OnLinkDetected) => void` | - | Both |
|
|
468
468
|
|
|
469
469
|
#### `onMentionDetected`
|
|
470
470
|
|
|
@@ -473,7 +473,7 @@ Callback called when mention has been detected - either a new mention has been a
|
|
|
473
473
|
Payload interface contains all the useful mention data:
|
|
474
474
|
|
|
475
475
|
```ts
|
|
476
|
-
OnMentionDetected {
|
|
476
|
+
interface OnMentionDetected {
|
|
477
477
|
text: string;
|
|
478
478
|
indicator: string;
|
|
479
479
|
attributes: Record<string, string>;
|
|
@@ -484,9 +484,9 @@ OnMentionDetected {
|
|
|
484
484
|
- `indicator` is the indicator of the mention.
|
|
485
485
|
- `attributes` are the additional user-defined attributes that are being stored with the mention.
|
|
486
486
|
|
|
487
|
-
| Type
|
|
488
|
-
|
|
489
|
-
| `(OnMentionDetected) => void` | - | Both |
|
|
487
|
+
| Type | Default Value | Platform |
|
|
488
|
+
|--------------------------------------|---------------|----------|
|
|
489
|
+
| `(event: OnMentionDetected) => void` | - | Both |
|
|
490
490
|
|
|
491
491
|
#### `onStartMention`
|
|
492
492
|
|
|
@@ -560,12 +560,12 @@ If true, Android will use experimental synchronous events. This will prevent fro
|
|
|
560
560
|
|
|
561
561
|
### Ref Methods
|
|
562
562
|
|
|
563
|
-
All
|
|
563
|
+
All the methods should be called on the input's [ref](#ref).
|
|
564
564
|
|
|
565
565
|
#### `.blur()`
|
|
566
566
|
|
|
567
567
|
```ts
|
|
568
|
-
blur: () => void
|
|
568
|
+
blur: () => void;
|
|
569
569
|
```
|
|
570
570
|
|
|
571
571
|
Blurs the input.
|
|
@@ -812,6 +812,9 @@ interface MentionStyleProperties {
|
|
|
812
812
|
- `fontSize` is the size of the heading's font, defaults to `32`/`24`/`20` for h1/h2/h3.
|
|
813
813
|
- `bold` defines whether the heading should be bolded, defaults to `false`.
|
|
814
814
|
|
|
815
|
+
> [!NOTE]
|
|
816
|
+
> On iOS, the headings cannot have same `fontSize` as the component's `fontSize`. Doing so results in unexpected behavior.
|
|
817
|
+
|
|
815
818
|
#### blockquote
|
|
816
819
|
|
|
817
820
|
- `borderColor` defines the color of the rectangular border drawn to the left of blockquote text. Takes [color](https://reactnative.dev/docs/colors) value, defaults to `darkgray`.
|
|
@@ -204,7 +204,9 @@ class EnrichedTextInputView : AppCompatEditText {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
// Currently, we do not support pasting images
|
|
208
|
+
if (item?.text == null) return
|
|
209
|
+
val finalText = currentText.mergeSpannables(start, end, item.text.toString())
|
|
208
210
|
setValue(finalText)
|
|
209
211
|
parametrizedStyles?.detectAllLinks()
|
|
210
212
|
}
|
|
@@ -154,6 +154,8 @@ class HtmlStyle {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
private fun withOpacity(color: Int, alpha: Int): Int {
|
|
157
|
+
// Do not apply opacity to transparent color
|
|
158
|
+
if (Color.alpha(color) == 0) return color
|
|
157
159
|
val a = alpha.coerceIn(0, 255)
|
|
158
160
|
return (color and 0x00FFFFFF) or (a shl 24)
|
|
159
161
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#import "FontExtension.h"
|
|
4
4
|
#import "OccurenceUtils.h"
|
|
5
5
|
#import "ParagraphsUtils.h"
|
|
6
|
+
#import "ColorExtension.h"
|
|
6
7
|
|
|
7
8
|
@implementation InlineCodeStyle {
|
|
8
9
|
EnrichedTextInputView *_input;
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
NSRange currentRange = [value rangeValue];
|
|
34
35
|
[_input->textView.textStorage beginEditing];
|
|
35
36
|
|
|
36
|
-
[_input->textView.textStorage addAttribute:NSBackgroundColorAttributeName value:[[_input->config inlineCodeBgColor]
|
|
37
|
+
[_input->textView.textStorage addAttribute:NSBackgroundColorAttributeName value:[[_input->config inlineCodeBgColor] colorWithAlphaIfNotTransparent:0.4] range:currentRange];
|
|
37
38
|
[_input->textView.textStorage addAttribute:NSForegroundColorAttributeName value:[_input->config inlineCodeFgColor] range:currentRange];
|
|
38
39
|
[_input->textView.textStorage addAttribute:NSUnderlineColorAttributeName value:[_input->config inlineCodeFgColor] range:currentRange];
|
|
39
40
|
[_input->textView.textStorage addAttribute:NSStrikethroughColorAttributeName value:[_input->config inlineCodeFgColor] range:currentRange];
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
|
|
42
43
|
UIFont *font = (UIFont *)value;
|
|
43
44
|
if(font != nullptr) {
|
|
44
|
-
UIFont *newFont = [[_input->config monospacedFont] withFontTraits:font];
|
|
45
|
+
UIFont *newFont = [[[_input->config monospacedFont] withFontTraits:font] setSize:font.pointSize];
|
|
45
46
|
[_input->textView.textStorage addAttribute:NSFontAttributeName value:newFont range:range];
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -53,13 +54,13 @@
|
|
|
53
54
|
|
|
54
55
|
- (void)addTypingAttributes {
|
|
55
56
|
NSMutableDictionary *newTypingAttrs = [_input->textView.typingAttributes mutableCopy];
|
|
56
|
-
newTypingAttrs[NSBackgroundColorAttributeName] = [[_input->config inlineCodeBgColor]
|
|
57
|
+
newTypingAttrs[NSBackgroundColorAttributeName] = [[_input->config inlineCodeBgColor] colorWithAlphaIfNotTransparent:0.4];
|
|
57
58
|
newTypingAttrs[NSForegroundColorAttributeName] = [_input->config inlineCodeFgColor];
|
|
58
59
|
newTypingAttrs[NSUnderlineColorAttributeName] = [_input->config inlineCodeFgColor];
|
|
59
60
|
newTypingAttrs[NSStrikethroughColorAttributeName] = [_input->config inlineCodeFgColor];
|
|
60
61
|
UIFont* currentFont = (UIFont *)newTypingAttrs[NSFontAttributeName];
|
|
61
62
|
if(currentFont != nullptr) {
|
|
62
|
-
newTypingAttrs[NSFontAttributeName] = [[_input->config monospacedFont] withFontTraits:currentFont];
|
|
63
|
+
newTypingAttrs[NSFontAttributeName] = [[[_input->config monospacedFont] withFontTraits:currentFont] setSize:currentFont.pointSize];
|
|
63
64
|
}
|
|
64
65
|
_input->textView.typingAttributes = newTypingAttrs;
|
|
65
66
|
}
|
|
@@ -75,7 +76,7 @@
|
|
|
75
76
|
usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
|
|
76
77
|
UIFont *font = (UIFont *)value;
|
|
77
78
|
if(font != nullptr) {
|
|
78
|
-
UIFont *newFont = [[_input->config primaryFont] withFontTraits:font];
|
|
79
|
+
UIFont *newFont = [[[_input->config primaryFont] withFontTraits:font] setSize:font.pointSize];
|
|
79
80
|
[_input->textView.textStorage addAttribute:NSFontAttributeName value:newFont range:range];
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -92,7 +93,7 @@
|
|
|
92
93
|
newTypingAttrs[NSStrikethroughColorAttributeName] = [_input->config primaryColor];
|
|
93
94
|
UIFont* currentFont = (UIFont *)newTypingAttrs[NSFontAttributeName];
|
|
94
95
|
if(currentFont != nullptr) {
|
|
95
|
-
newTypingAttrs[NSFontAttributeName] = [[_input->config primaryFont] withFontTraits:currentFont];
|
|
96
|
+
newTypingAttrs[NSFontAttributeName] = [[[_input->config primaryFont] withFontTraits:currentFont] setSize:currentFont.pointSize];
|
|
96
97
|
}
|
|
97
98
|
_input->textView.typingAttributes = newTypingAttrs;
|
|
98
99
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#import "TextInsertionUtils.h"
|
|
5
5
|
#import "WordsUtils.h"
|
|
6
6
|
#import "UIView+React.h"
|
|
7
|
+
#import "ColorExtension.h"
|
|
7
8
|
|
|
8
9
|
// custom NSAttributedStringKey to differentiate from links
|
|
9
10
|
static NSString *const MentionAttributeName = @"MentionAttributeName";
|
|
@@ -154,7 +155,7 @@ static NSString *const MentionAttributeName = @"MentionAttributeName";
|
|
|
154
155
|
NSForegroundColorAttributeName: styleProps.color,
|
|
155
156
|
NSUnderlineColorAttributeName: styleProps.color,
|
|
156
157
|
NSStrikethroughColorAttributeName: styleProps.color,
|
|
157
|
-
NSBackgroundColorAttributeName: [styleProps.backgroundColor
|
|
158
|
+
NSBackgroundColorAttributeName: [styleProps.backgroundColor colorWithAlphaIfNotTransparent:0.4],
|
|
158
159
|
} mutableCopy];
|
|
159
160
|
|
|
160
161
|
if(styleProps.decorationLine == DecorationUnderline) {
|
|
@@ -186,7 +187,7 @@ static NSString *const MentionAttributeName = @"MentionAttributeName";
|
|
|
186
187
|
NSForegroundColorAttributeName: styleProps.color,
|
|
187
188
|
NSUnderlineColorAttributeName: styleProps.color,
|
|
188
189
|
NSStrikethroughColorAttributeName: styleProps.color,
|
|
189
|
-
NSBackgroundColorAttributeName: [styleProps.backgroundColor
|
|
190
|
+
NSBackgroundColorAttributeName: [styleProps.backgroundColor colorWithAlphaIfNotTransparent:0.4],
|
|
190
191
|
} mutableCopy];
|
|
191
192
|
|
|
192
193
|
if(styleProps.decorationLine == DecorationUnderline) {
|
|
@@ -24,4 +24,13 @@
|
|
|
24
24
|
|
|
25
25
|
return [selfColor isEqual:otherColor];
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
- (UIColor *)colorWithAlphaIfNotTransparent:(CGFloat)newAlpha {
|
|
29
|
+
CGFloat alpha = 0.0;
|
|
30
|
+
[self getRed:nil green:nil blue:nil alpha:&alpha];
|
|
31
|
+
if (alpha > 0.0) {
|
|
32
|
+
return [self colorWithAlphaComponent:newAlpha];
|
|
33
|
+
}
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
27
36
|
@end
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
[textView.textStorage insertAttributedString:newAttrStr atIndex:index];
|
|
19
19
|
|
|
20
20
|
if(withSelection) {
|
|
21
|
-
if(!textView
|
|
21
|
+
if(![textView isFirstResponder]) {
|
|
22
22
|
[textView reactFocus];
|
|
23
23
|
}
|
|
24
24
|
textView.selectedRange = NSMakeRange(index + text.length, 0);
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
if(withSelection) {
|
|
41
|
-
if(!textView
|
|
41
|
+
if(![textView isFirstResponder]) {
|
|
42
42
|
[textView reactFocus];
|
|
43
43
|
}
|
|
44
44
|
textView.selectedRange = NSMakeRange(range.location + text.length, 0);
|
|
@@ -63,8 +63,7 @@
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// fix the selection if needed
|
|
66
|
-
if(input->textView
|
|
67
|
-
[input->textView reactFocus];
|
|
66
|
+
if([input->textView isFirstResponder]) {
|
|
68
67
|
input->textView.selectedRange = NSMakeRange(preRemoveSelection.location + postRemoveOffset, preRemoveSelection.length);
|
|
69
68
|
}
|
|
70
69
|
}
|
|
@@ -112,8 +111,7 @@
|
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
// fix the selection if needed
|
|
115
|
-
if(input->textView
|
|
116
|
-
[input->textView reactFocus];
|
|
114
|
+
if([input->textView isFirstResponder]) {
|
|
117
115
|
input->textView.selectedRange = NSMakeRange(preAddSelection.location + postAddOffset, preAddSelection.length);
|
|
118
116
|
}
|
|
119
117
|
}
|