Fresh IDE . Check-in [765802a720]
Not logged in

This repository is a mirror!

The original is located on: https://fresh.flatassembler.net/fossil/repo/fresh
If you want to follow the project, please update your remote-url

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Work on the syntax highlighter. Fixed the text rendering with a syntax highlight.
Timelines: family | ancestors | descendants | both | NoCanvasGUI
Files: files | file ages | folders
SHA1:765802a7200723441d3f801092b58f759a2a091a
User & Date: johnfound 2019-04-30 22:05:27
Context
2019-05-01
07:13
More work on deleting characters and selections. Added backspace. Added handling of the trailing spaces. check-in: 0c75b62fae user: johnfound tags: NoCanvasGUI
2019-04-30
22:05
Work on the syntax highlighter. Fixed the text rendering with a syntax highlight. check-in: 765802a720 user: johnfound tags: NoCanvasGUI
2019-04-29
07:13
Deleting characters. check-in: 22f4724e5a user: johnfound tags: NoCanvasGUI
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to freshlib/gui/TAsmEdit.asm.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
....
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
....
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
....
1688
1689
1690
1691
1692
1693
1694


1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
....
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
....
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
....
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
....
2657
2658
2659
2660
2661
2662
2663

2664

2665
2666
2667
2668
2669
2670
2671
2672
2673
2674



2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
....
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
....
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406

3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422






3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434


3435
3436
3437
3438
3439
3440

3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454


3455
3456
3457
3458
3459
3460
3461
....
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
....
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
....
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
....
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
                        ;
  .             TText
ends



struct TTextChunk
  .len   dw ?   ; the length of the text chunk in BYTES (in Utf-8 chars???)
  .color db ?   ; the high order nibble encode the background, low order nibble encodes the text color.
  .flags db ?   ; the text formatting flags. not used, reserved. For example underlining, bold, etc...
ends



object TAsmEdit, TWindow

................................................................................
  method .Redo


; Text editing methods

  method .InsertNewLine, .LineNum
  method .DeleteLine, .LineNum
  method .DeleteChars, .LineNum, .From, .To

  method .JoinNextLine, .LineNum

  method .DeleteSelection
  method .ReplaceSelection, .text

  method .InsertString, .text

; OS event handlers
................................................................................
.ins_mask_ok:
        xor     eax, edx
        set     esi, TAsmEdit:Options, eax
        jmp     .endselect

.delkey:
        exec    esi, TAsmEdit:DeleteSelection
        jnc     .del_ok

        DebugMsg "No selection - delete the char under the caret."

        exec    esi, TAsmEdit:TextLine, [esi+TAsmEdit._caretPos.y]
        jc      .finish

        mov     ebx, eax        ; TTextLine

        OutputValue "TTextLine length = ", [ebx+TTextLine.ch_len], 16, 8
        OutputValue "_caretPos.x = ", [esi+TAsmEdit._caretPos.x], 16, 8

        mov     eax, [esi+TAsmEdit._caretPos.x]
        inc     eax
        cmp     eax, [ebx+TTextLine.ch_len]
        jbe     .del_char

        DebugMsg "Join the next line."

        exec    esi, TAsmEdit:JoinNextLine, [esi+TAsmEdit._caretPos.y]
        jmp     .del_refresh

.del_char:
        OutputValue "Delete char on line: ", [esi+TAsmEdit._caretPos.y], 10, -1
        exec    esi, TAsmEdit:DeleteChars, [esi+TAsmEdit._caretPos.y], [esi+TAsmEdit._caretPos.x], eax

.del_refresh:

        and     [esi+TAsmEdit._img_txt_valid], 0
        and     [esi+TAsmEdit._img_margin_valid], 0

        exec    esi, TAsmEdit:RectChanged2, 0
        exec    esi, TAsmEdit:UpdateCaretPos

.del_ok:
        exec    esi, TAsmEdit:SelChangeBegin
        exec    esi, TAsmEdit:SelStartHere
        exec    esi, TAsmEdit:SelEndHere
        exec    esi, TAsmEdit:SelChangeEnd
        jmp     .finish


................................................................................
        jae     .text_ok

        mov     edx, [edi+eax]
        cmp     [edx+TTextLine.syn_array], 0
        jne     .syn_ok

        stdcall [esi+TAsmEdit._syntax_proc], edx, [.context]
        mov     [.context], eax

.syn_ok:
        stdcall __RenderOneLine, [.pImage], edx, [.recta.left], [.recta.right], [.rectr.left], [.rectr.top]

        mov     eax, [edx+TTextLine.syn_context]
        mov     [.context], eax

................................................................................
; and now, scan for chunks and draw them

.draw_chunk_loop:

        mov     ecx, esi              ; the start of the chunk text

.inner_chunk_loop:



        dec     [.toChar]
        js      .end_chunk_final      ; draw the final chunk and exits.

        sub     [.chlen], 1
        jc      .next_chunk           ; CF=1 only once.

        cmp     esi, [.gap_end]
        jae     .ofs_ok

        cmp     esi, [.gap_start]
        jb      .ofs_ok

        call    .draw_current_chunk
................................................................................
        sbb     eax, -2

        add     esi, eax
        jmp     .inner_chunk_loop


.next_chunk:

        call    .draw_current_chunk

        mov     ebx, [.chunk]
        inc     ebx
        cmp     ebx, [edi+TArray.count]
        ja      .default_color

        movzx   edx, word [edi+ TArray.array + sizeof.TTextChunk * ebx + TTextChunk.len]
        jmp     .set_color


.end_chunk_final:

        call    .draw_current_chunk


.finish:
        popad
        return

................................................................................
        idiv    [esi+TAsmEdit._font_width]
        test    edx, edx
        jz      @f
        inc     eax
@@:
        mov     [esi+TAsmEdit._width_ch], eax

;        OutputValue "Screen width:", eax, 10, -1

; height
        mov     eax, [esi+TAsmEdit._height]
        cdq

        idiv    [esi+TAsmEdit._font_height]
        test    edx, edx
        jz      @f
        inc     eax
@@:
        mov     [esi+TAsmEdit._height_ch], eax

;        OutputValue "Screen height:", eax, 10, -1

        popad



        return
endp

................................................................................
        xor     ecx, ecx

.line_loop:
        stdcall DecodeUtf8, [edi]
        add     edi, edx

        test    eax, eax
        jz      .end_text

        cmp     eax, $0d
        je      .new_line
        cmp     eax, $0a
        je      .new_line

        stdcall EncodeUtf8, eax
................................................................................
        jmp     .line_loop

.new_line:
        xor     eax, $0d xor $0a
        cmp     [edi], al
        jne     .cr_ok
        inc     edi

.cr_ok:


        mov     esi, [esi]
        mov     [esi+TTextLine.ch_len], ecx
        stdcall IncCount, [ebx+TAsmEdit._line_widths], ecx
        mov     [ebx+TAsmEdit._line_widths], edx

        stdcall [ebx+TAsmEdit._syntax_proc], esi, [.context]
        mov     [.context], eax
        jmp     .text_loop





.end_text:

        exec    ebx, TAsmEdit:ComputeLeftMarginWidth
        exec    ebx, TAsmEdit:UpdateScrollBar


.finish:

        popad
................................................................................

        sub     eax, ebx
        jle     .finish

        neg     edi

.do_scroll:
        DebugMsg "Do scroll."

        sub     eax, edi
        add     edx, eax
        cmovs   edx, ecx

        set     esi, TAsmEdit:PosY, edx
        exec    esi, TAsmEdit:RectChanged2, ecx
................................................................................

method TAsmEdit.DeleteLine      ;, .LineNum
begin
        return
endp


method TAsmEdit.DeleteChars     ;, .LineNum, .From, .To
begin
        pushad

        mov     esi, [.self]
        mov     edi, [esi+TAsmEdit._lines]
        mov     ebx, [.LineNum]

        shl     ebx, 2
        cmp     ebx, [edi+TText.GapBegin]
        jb      .skip
        add     ebx, [edi+TText.GapEnd]
        sub     ebx, [edi+TText.GapBegin]
.skip:
        cmp     ebx, [edi+TText.Length]
        jae     .finish

        mov     ebx, [edi+ebx]
        stdcall TextIndexToPos, ebx, [.From]
        jc      .finish

        stdcall TextMoveGap, ebx, eax
        mov     edx, [ebx+TTextLine.GapEnd]
        mov     ecx, [.From]

.loop:
        cmp     ecx, [.To]
        jae     .end_scan

        cmp     edx, [ebx+TTextLine.Length]
        cmova   edx, [ebx+TTextLine.Length]
        jae     .end_scan

        movzx   eax, byte [ebx+edx]

                                ; compute the length of the UTF-8 character by its first byte (version without branches) Is it fast?
        not     al              ; utf-8 starts with one of: 0xxxxxxx, 110xxxxx, 1110xxxx, 11110xxx, 111110xx, 1111110x
        bsr     eax, eax        ; eax =                 7,  5,  4,  3,  2,  1
        sub     eax, 7          ; eax =                 0, -2, -3, -4, -5, -6
                                ; CF  =                 0,  1,  1,  1,  1,  1
        not     eax             ; eax =                -1, +1, +2, +3, +4, +5
        sbb     eax, -2         ; eax = edx + 2 - CF = +1, +2, +3, +4, +5, +6

        add     edx, eax
        inc     ecx
        jmp     .loop


.end_scan:
        mov     [ebx+TTextLine.GapEnd], edx
        sub     ecx, [.From]

        stdcall DecCount, [esi+TAsmEdit._line_widths], [ebx+TTextLine.ch_len]
        sub     [ebx+TTextLine.ch_len], ecx
        stdcall IncCount, edx, [ebx+TTextLine.ch_len]
        mov     [esi+TAsmEdit._line_widths], edx

        and     [esi+TAsmEdit._img_txt_valid], 0
        and     [esi+TAsmEdit._img_margin_valid], 0
        exec    esi, TAsmEdit:RectChanged2, 0
        exec    esi, TAsmEdit:UpdateCaretPos

.finish:






        popad
        return
endp


method TAsmEdit.JoinNextLine    ;, .LineNum
begin
        pushad

        mov     esi, [.self]
        mov     edi, [esi+TAsmEdit._lines]
        mov     ebx, [.LineNum]



        shl     ebx, 2
        lea     ecx, [ebx+4]

        cmp     ebx, [edi+TText.GapBegin]
        jb      .skip1

        add     ebx, [edi+TText.GapEnd]
        sub     ebx, [edi+TText.GapBegin]
.skip1:

        cmp     ecx, [edi+TText.GapBegin]
        jb      .skip2
        add     ecx, [edi+TText.GapEnd]
        sub     ecx, [edi+TText.GapBegin]
.skip2:
        cmp     ecx, [edi+TText.Length]
        jae     .finish ; nothing to join

        cmp     ebx, [edi+TText.Length]
        jae     .finish



; first fix the new line widths...

        mov     edx, [esi+TAsmEdit._line_widths]

        mov     eax, [edi+ebx]
        push    [eax+TTextLine.ch_len]
................................................................................
        mov     [esi+TAsmEdit._line_widths], edx

; then join the texts

        stdcall TextAddText, [edi+ebx], -1, [edi+ecx]
        mov     [edi+ebx], edx

; then delete the next line

        mov     eax, [edi+ecx]
        stdcall FreeMem, [eax+TTextLine.syn_array]
        stdcall TextFree, eax     ; delete the next line... but what about the debug info and other attributes?

; reset the syntax coloring of the new line
        mov     eax, [edi+ebx]
        stdcall FreeMem, [eax+TTextLine.syn_array]
        and     [eax+TTextLine.syn_array], 0

        mov     eax, [.LineNum]
        lea     eax, [4*eax+4]
        stdcall TextMoveGap, edi, eax
        add     [edi+TText.GapEnd], 4

.finish:
        popad
        return
endp



................................................................................
.list dd ?
begin
        pushad

        exec    [.self], TAsmEdit:_AddSelRectanglesAbs, 0
        mov     [.list], edx

        OutputValue "Selection array count: ", [edx+TArray.count], 10, -1

        lea     edi, [edx+TArray.array]
        mov     ecx, [edx+TArray.count]
        test    ecx, ecx
        jz      .exit_empty

        mov     eax, ecx
        shl     eax, 4  ; sizeof.RECT
................................................................................

.rect_loop:

        sub     edi, sizeof.RECT
        dec     ecx
        js      .finish

        OutputValue "RECT.left =", [edi+RECT.left], 10, -1
        OutputValue "RECT.top =", [edi+RECT.top], 10, -1
        OutputValue "RECT.right =", [edi+RECT.right], 10, -1
        OutputValue "RECT.bottom =", [edi+RECT.bottom], 10, -1

        mov     ebx, [edi+RECT.bottom]

.y_loop:
        dec     ebx
        cmp     ebx, [edi+RECT.top]
        jl      .rect_loop

................................................................................
.exit:
        stdcall FreeMem, [.list]
        clc
        popad
        return

.exit_empty:
        DebugMsg "Exit delete selection EMPTY!"

        stdcall FreeMem, [.list]
        stc
        popad
        return
endp








|
|







 







|

|







 







|

<
<
|
<
<
<
<
<
<
<
<
<
<
|

<
<
|
<
<
<
<
<









<







 







<







 







>
>




<
<
<







 







<










<

<







 







<
<











<
<







 







|







 







>

>








<

>
>
>


<







 







<







 







|





|








|


|
|



<
<
<
<
<
<


|












|
|
>

<
|
|


|








<
>
>
>
>
>
>





|






>
>




|
<
>
|
<
<

<
<


<





>
>







 







|





|




<
<
<
<
<







 







<
<







 







<
<
<
<
<







 







<







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
....
1142
1143
1144
1145
1146
1147
1148
1149
1150


1151










1152
1153


1154





1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
....
1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
....
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679



1680
1681
1682
1683
1684
1685
1686
....
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1719
1720
1721

1722

1723
1724
1725
1726
1727
1728
1729
....
2509
2510
2511
2512
2513
2514
2515


2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526


2527
2528
2529
2530
2531
2532
2533
....
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
....
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645

2646
2647
2648
2649
2650
2651

2652
2653
2654
2655
2656
2657
2658
....
2779
2780
2781
2782
2783
2784
2785

2786
2787
2788
2789
2790
2791
2792
....
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356






3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375

3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388

3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413

3414
3415


3416


3417
3418

3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
....
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464





3465
3466
3467
3468
3469
3470
3471
....
3474
3475
3476
3477
3478
3479
3480


3481
3482
3483
3484
3485
3486
3487
....
3489
3490
3491
3492
3493
3494
3495





3496
3497
3498
3499
3500
3501
3502
....
3572
3573
3574
3575
3576
3577
3578

3579
3580
3581
3582
3583
3584
3585
                        ;
  .             TText
ends



struct TTextChunk
  .len   dw ?   ; the length of the text chunk in UTF-8 characters.
  .color db ?   ; byte, index of the color/background of the text chunk.
  .flags db ?   ; the text formatting flags. not used, reserved. For example underlining, bold, etc...
ends



object TAsmEdit, TWindow

................................................................................
  method .Redo


; Text editing methods

  method .InsertNewLine, .LineNum
  method .DeleteLine, .LineNum
  method .DeleteChar

  method .JoinNextLine, .LineNum        ; if .LineNum < 0; joins the current caret line

  method .DeleteSelection
  method .ReplaceSelection, .text

  method .InsertString, .text

; OS event handlers
................................................................................
.ins_mask_ok:
        xor     eax, edx
        set     esi, TAsmEdit:Options, eax
        jmp     .endselect

.delkey:
        exec    esi, TAsmEdit:DeleteSelection
        jnc     .del_refresh



        exec    esi, TAsmEdit:DeleteChar










        jnc     .del_refresh



        exec    esi, TAsmEdit:JoinNextLine, -1






.del_refresh:

        and     [esi+TAsmEdit._img_txt_valid], 0
        and     [esi+TAsmEdit._img_margin_valid], 0

        exec    esi, TAsmEdit:RectChanged2, 0
        exec    esi, TAsmEdit:UpdateCaretPos


        exec    esi, TAsmEdit:SelChangeBegin
        exec    esi, TAsmEdit:SelStartHere
        exec    esi, TAsmEdit:SelEndHere
        exec    esi, TAsmEdit:SelChangeEnd
        jmp     .finish


................................................................................
        jae     .text_ok

        mov     edx, [edi+eax]
        cmp     [edx+TTextLine.syn_array], 0
        jne     .syn_ok

        stdcall [esi+TAsmEdit._syntax_proc], edx, [.context]


.syn_ok:
        stdcall __RenderOneLine, [.pImage], edx, [.recta.left], [.recta.right], [.rectr.left], [.rectr.top]

        mov     eax, [edx+TTextLine.syn_context]
        mov     [.context], eax

................................................................................
; and now, scan for chunks and draw them

.draw_chunk_loop:

        mov     ecx, esi              ; the start of the chunk text

.inner_chunk_loop:
        sub     [.chlen], 1
        jc      .next_chunk           ; CF=1 only once.

        dec     [.toChar]
        js      .end_chunk_final      ; draw the final chunk and exits.




        cmp     esi, [.gap_end]
        jae     .ofs_ok

        cmp     esi, [.gap_start]
        jb      .ofs_ok

        call    .draw_current_chunk
................................................................................
        sbb     eax, -2

        add     esi, eax
        jmp     .inner_chunk_loop


.next_chunk:

        call    .draw_current_chunk

        mov     ebx, [.chunk]
        inc     ebx
        cmp     ebx, [edi+TArray.count]
        ja      .default_color

        movzx   edx, word [edi+ TArray.array + sizeof.TTextChunk * ebx + TTextChunk.len]
        jmp     .set_color


.end_chunk_final:

        call    .draw_current_chunk


.finish:
        popad
        return

................................................................................
        idiv    [esi+TAsmEdit._font_width]
        test    edx, edx
        jz      @f
        inc     eax
@@:
        mov     [esi+TAsmEdit._width_ch], eax



; height
        mov     eax, [esi+TAsmEdit._height]
        cdq

        idiv    [esi+TAsmEdit._font_height]
        test    edx, edx
        jz      @f
        inc     eax
@@:
        mov     [esi+TAsmEdit._height_ch], eax



        popad



        return
endp

................................................................................
        xor     ecx, ecx

.line_loop:
        stdcall DecodeUtf8, [edi]
        add     edi, edx

        test    eax, eax
        jz      .cr_ok

        cmp     eax, $0d
        je      .new_line
        cmp     eax, $0a
        je      .new_line

        stdcall EncodeUtf8, eax
................................................................................
        jmp     .line_loop

.new_line:
        xor     eax, $0d xor $0a
        cmp     [edi], al
        jne     .cr_ok
        inc     edi

.cr_ok:
        push    eax

        mov     esi, [esi]
        mov     [esi+TTextLine.ch_len], ecx
        stdcall IncCount, [ebx+TAsmEdit._line_widths], ecx
        mov     [ebx+TAsmEdit._line_widths], edx

        stdcall [ebx+TAsmEdit._syntax_proc], esi, [.context]
        mov     [.context], eax


        pop     eax
        test    eax, eax
        jnz     .text_loop

.end_text:

        exec    ebx, TAsmEdit:ComputeLeftMarginWidth
        exec    ebx, TAsmEdit:UpdateScrollBar


.finish:

        popad
................................................................................

        sub     eax, ebx
        jle     .finish

        neg     edi

.do_scroll:


        sub     eax, edi
        add     edx, eax
        cmovs   edx, ecx

        set     esi, TAsmEdit:PosY, edx
        exec    esi, TAsmEdit:RectChanged2, ecx
................................................................................

method TAsmEdit.DeleteLine      ;, .LineNum
begin
        return
endp


method TAsmEdit.DeleteChar
begin
        pushad

        mov     esi, [.self]
        mov     edi, [esi+TAsmEdit._lines]
        mov     ebx, [esi+TAsmEdit._caretPos.y]

        shl     ebx, 2
        cmp     ebx, [edi+TText.GapBegin]
        jb      .skip
        add     ebx, [edi+TText.GapEnd]
        sub     ebx, [edi+TText.GapBegin]
.skip:
        cmp     ebx, [edi+TText.Length]
        jae     .not_deleted

        mov     ebx, [edi+ebx]
        stdcall TextIndexToPos, ebx, [esi+TAsmEdit._caretPos.x]
        jc      .not_deleted

        stdcall TextMoveGap, ebx, eax
        mov     edx, [ebx+TTextLine.GapEnd]






        cmp     edx, [ebx+TTextLine.Length]
        cmova   edx, [ebx+TTextLine.Length]
        jae     .not_deleted

        movzx   eax, byte [ebx+edx]

                                ; compute the length of the UTF-8 character by its first byte (version without branches) Is it fast?
        not     al              ; utf-8 starts with one of: 0xxxxxxx, 110xxxxx, 1110xxxx, 11110xxx, 111110xx, 1111110x
        bsr     eax, eax        ; eax =                 7,  5,  4,  3,  2,  1
        sub     eax, 7          ; eax =                 0, -2, -3, -4, -5, -6
                                ; CF  =                 0,  1,  1,  1,  1,  1
        not     eax             ; eax =                -1, +1, +2, +3, +4, +5
        sbb     eax, -2         ; eax = edx + 2 - CF = +1, +2, +3, +4, +5, +6

        add     edx, eax
        cmp     edx, [ebx+TTextLine.Length]
        cmova   edx, [ebx+TTextLine.Length]
        mov     [ebx+TTextLine.GapEnd], edx


        stdcall FreeMem, [ebx+TTextLine.syn_array]
        and     [ebx+TTextLine.syn_array], 0            ; reset the syntax array of the line...

        stdcall DecCount, [esi+TAsmEdit._line_widths], [ebx+TTextLine.ch_len]
        dec     [ebx+TTextLine.ch_len]
        stdcall IncCount, edx, [ebx+TTextLine.ch_len]
        mov     [esi+TAsmEdit._line_widths], edx

        and     [esi+TAsmEdit._img_txt_valid], 0
        and     [esi+TAsmEdit._img_margin_valid], 0
        exec    esi, TAsmEdit:RectChanged2, 0
        exec    esi, TAsmEdit:UpdateCaretPos


        clc
        popad
        return

.not_deleted:
        stc
        popad
        return
endp


method TAsmEdit.JoinNextLine    ; .LineNum
begin
        pushad

        mov     esi, [.self]
        mov     edi, [esi+TAsmEdit._lines]
        mov     ebx, [.LineNum]
        test    ebx, ebx
        cmovs   ebx, [esi+TAsmEdit._caretPos.y]

        shl     ebx, 2
        lea     ecx, [ebx+4]

        stdcall TextMoveGap, edi, ecx   ; move the gap between the two lines.


; here ebx is before the gap and ecx is after!





        add     ecx, [edi+TText.GapEnd]
        sub     ecx, [edi+TText.GapBegin]

        cmp     ecx, [edi+TText.Length]
        jae     .finish ; nothing to join

        cmp     ebx, [edi+TText.Length]
        jae     .finish

        add     [edi+TText.GapEnd], 4   ; free the place of the next line...

; first fix the new line widths...

        mov     edx, [esi+TAsmEdit._line_widths]

        mov     eax, [edi+ebx]
        push    [eax+TTextLine.ch_len]
................................................................................
        mov     [esi+TAsmEdit._line_widths], edx

; then join the texts

        stdcall TextAddText, [edi+ebx], -1, [edi+ecx]
        mov     [edi+ebx], edx

; then free the next line TTextLine structure...

        mov     eax, [edi+ecx]
        stdcall FreeMem, [eax+TTextLine.syn_array]
        stdcall TextFree, eax     ; delete the next line... but what about the debug info and other attributes?

; reset the syntax coloring of the result line
        mov     eax, [edi+ebx]
        stdcall FreeMem, [eax+TTextLine.syn_array]
        and     [eax+TTextLine.syn_array], 0






.finish:
        popad
        return
endp



................................................................................
.list dd ?
begin
        pushad

        exec    [.self], TAsmEdit:_AddSelRectanglesAbs, 0
        mov     [.list], edx



        lea     edi, [edx+TArray.array]
        mov     ecx, [edx+TArray.count]
        test    ecx, ecx
        jz      .exit_empty

        mov     eax, ecx
        shl     eax, 4  ; sizeof.RECT
................................................................................

.rect_loop:

        sub     edi, sizeof.RECT
        dec     ecx
        js      .finish






        mov     ebx, [edi+RECT.bottom]

.y_loop:
        dec     ebx
        cmp     ebx, [edi+RECT.top]
        jl      .rect_loop

................................................................................
.exit:
        stdcall FreeMem, [.list]
        clc
        popad
        return

.exit_empty:


        stdcall FreeMem, [.list]
        stc
        popad
        return
endp

Changes to freshlib/gui/syntax/SyntaxFASM.asm.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
53
54
55
56
57
58
59
60
61
62

63
64
65

66
67
68
69
70
71
72
73
74
75
76
77


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135









136
137
138
139
140




141
142
143
144
145
146
147
148
149
150
151
...
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172


173
174
175


176
177
178
179
180
181
182
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
249
250
251
252
253
254
255
256
257
258
259
260



261
262
263
264
265
266
267
;   .pLineInfo - pointer to TTextLine structure.
;   .SynContext - input context of the highligher.
;
; Returns:
;       eax - output context of the highligher.
;
proc SyntaxFASM, .pTextLine, .SynContext
.Quo   rb 4
.start dd ?
begin
        pushad

        mov     esi, [.pTextLine]

        mov     edi, [esi+TTextLine.syn_array]
        test    edi, edi
................................................................................
        mov     [esi+TTextLine.syn_array], eax

.array_ok:

        xor     ebx, ebx                ; the offset inside the line.
        xor     edx, edx

        mov     [.Quo], bl
        mov     [edi+TArray.count], ebx
        mov     [.start], ebx


.loop:
        add     ebx, edx


        mov     eax, [esi+TTextLine.GapBegin]
        cmp     ebx, eax
        cmovae  eax, [esi+TTextLine.GapEnd]
        sub     eax, [esi+TTextLine.GapBegin]
        add     eax, ebx

        cmp     eax, [esi+TTextLine.Length]
        jae     .end_of_line

        stdcall DecodeUtf8, [esi+eax]



        cmp     [.SynContext], ciComment
        je      .endif

        cmp     [.SynContext], ciString
        jne     .ifnotstr

        cmp     al,[.Quo]
        jne     .endif

        add     ebx, edx
        xor     edx, edx
        call    .end_chunk
        mov     [.SynContext], ciText
        jmp     .loop

.ifnotstr:
        cmp     al, ';'



        jne     .notrem

        call    .end_chunk
        mov     [.SynContext], ciComment
        jmp     .endif

.notrem:
        cmp     al, '"'
        je      .str
        cmp     al, "'"
        jne     .notstr

.str:
        call    .end_chunk
        mov     [.SynContext], ciString
        mov     [.Quo], al
        jmp     .endif

.notstr:
        call    .CharInSymbols
        jnc     .notsym




        call    .end_chunk
        mov     [.SynContext], ciSymbol
        jmp     .endif

.notsym:
        cmp     [.SynContext], ciNumber
        je      .endif

        cmp     ebx, [.start]
        je      .maybenum

        cmp     [.SynContext], ciSymbol
        jne     .endif

; The number begins only after ttChar or at the begining of the line.
.maybenum:
        call    .CharInNum
        jnc     .notnum










        call    .end_chunk
        mov     [.SynContext], ciNumber
        jmp     .endif

.notnum:




        call    .end_chunk
        mov     [.SynContext], ciText

.endif:
        jmp     .loop


.end_of_line:
        call    .end_chunk

;        mov     eax, [.SynContext]
................................................................................
        popad
        return


.end_chunk:
        push    eax ecx edx

        mov     ecx, ebx
        sub     ecx, [.start]
        jz      .chunk_processed

        mov     [.start], ebx

        stdcall AddArrayItems, edi, 1
        mov     edi, edx
        jc      .chunk_processed



        mov     [eax+TTextChunk.len], cx
        mov     ecx, [.SynContext]
        mov     [eax+TTextChunk.color], cl



.chunk_processed:
        pop     edx ecx eax
        retn


.CharInSymbols:
................................................................................
        stc
        pop     ecx edi
        ret
@@:
        clc
        pop     ecx edi
        retn


.CharInNum:
        cmp     al, '$'
        jne     @f
        stc
        retn

@@:
        cmp     al, '0'
        jb      @f
        cmp     al, '9'
        ja      @f
        stc
        retn
@@:
        clc
        retn


.symbol_characters db 27
                  db 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\'

endp


................................................................................

        mov     [.Quo], bl
        mov     [edi+TArray.count], ebx
        mov     [.start], ebx

.loop:
        add     ebx, edx
        cmp     ebx, [esi+TTextLine.TextLen]
        jae     .end_of_line

        mov     eax, ebx
        pos2ofs eax, esi




        stdcall DecodeUtf8, [esi+eax]

        cmp     [.SynContext], ciComment
        je      .endif

        cmp     [.SynContext], ciString







|
|







 







|

|
>



>












>
>

|




|
|








|
>
>
>




|


|

|





|
|




>
>
>



|



|

|



|



|
|

>
>
>
>
>
>
>
>
>


|

<
>
>
>
>


<
<







 







|
|


|
>




>
>



>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<



>
>
>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

159
160
161
162
163
164


165
166
167
168
169
170
171
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
215
216
217
218
219
220
221



















222
223
224
225
226
227
228
...
255
256
257
258
259
260
261


262
263
264
265
266
267
268
269
270
271
272
273
274
;   .pLineInfo - pointer to TTextLine structure.
;   .SynContext - input context of the highligher.
;
; Returns:
;       eax - output context of the highligher.
;
proc SyntaxFASM, .pTextLine, .SynContext
.Quo   dd ?
.cnt   dd ?
begin
        pushad

        mov     esi, [.pTextLine]

        mov     edi, [esi+TTextLine.syn_array]
        test    edi, edi
................................................................................
        mov     [esi+TTextLine.syn_array], eax

.array_ok:

        xor     ebx, ebx                ; the offset inside the line.
        xor     edx, edx

        mov     [.Quo], ebx
        mov     [edi+TArray.count], ebx
        mov     [.cnt], ebx
        dec     [.cnt]

.loop:
        add     ebx, edx
        inc     [.cnt]

        mov     eax, [esi+TTextLine.GapBegin]
        cmp     ebx, eax
        cmovae  eax, [esi+TTextLine.GapEnd]
        sub     eax, [esi+TTextLine.GapBegin]
        add     eax, ebx

        cmp     eax, [esi+TTextLine.Length]
        jae     .end_of_line

        stdcall DecodeUtf8, [esi+eax]

;        OutputValue "Char: ", eax, 16, 8

        cmp     [.SynContext], ciComment
        je      .loop

        cmp     [.SynContext], ciString
        jne     .ifnotstr

        cmp     eax,[.Quo]
        jne     .loop

        add     ebx, edx
        xor     edx, edx
        call    .end_chunk
        mov     [.SynContext], ciText
        jmp     .loop

.ifnotstr:
        cmp     eax, $ff
        ja      .text

        cmp     eax, ';'
        jne     .notrem

        call    .end_chunk
        mov     [.SynContext], ciComment
        jmp     .loop

.notrem:
        cmp     eax, '"'
        je      .str
        cmp     eax, "'"
        jne     .notstr

.str:
        call    .end_chunk
        mov     [.SynContext], ciString
        mov     [.Quo], eax
        jmp     .loop

.notstr:
        call    .CharInSymbols
        jnc     .notsym

        cmp     [.SynContext], ciSymbol
        je      .loop

        call    .end_chunk
        mov     [.SynContext], ciSymbol
        jmp     .loop

.notsym:
        cmp     [.SynContext], ciNumber
        je      .loop

        cmp     [.cnt], 0
        je      .maybenum

        cmp     [.SynContext], ciSymbol
        jne     .text

; The number begins only after ttChar or at the begining of the line.
.maybenum:
        cmp     al, '$'
        je      .num_start

        cmp     al, '-'
        je      .num_start

        cmp     al, '0'
        jb      .text
        cmp     al, '9'
        ja      .text

.num_start:
        call    .end_chunk
        mov     [.SynContext], ciNumber
        jmp     .loop


.text:
        cmp     [.SynContext], ciText
        je      .loop

        call    .end_chunk
        mov     [.SynContext], ciText


        jmp     .loop


.end_of_line:
        call    .end_chunk

;        mov     eax, [.SynContext]
................................................................................
        popad
        return


.end_chunk:
        push    eax ecx edx

        mov     ecx, [.cnt]
        test    ecx, ecx
        jz      .chunk_processed

        and     [.cnt], 0

        stdcall AddArrayItems, edi, 1
        mov     edi, edx
        jc      .chunk_processed

;        OutputValue "Chunk length: ", ecx, 16, 8

        mov     [eax+TTextChunk.len], cx
        mov     ecx, [.SynContext]
        mov     [eax+TTextChunk.color], cl

;        OutputValue "Chunk color: ", ecx, 16, 8

.chunk_processed:
        pop     edx ecx eax
        retn


.CharInSymbols:
................................................................................
        stc
        pop     ecx edi
        ret
@@:
        clc
        pop     ecx edi
        retn




















.symbol_characters db 27
                  db 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\'

endp


................................................................................

        mov     [.Quo], bl
        mov     [edi+TArray.count], ebx
        mov     [.start], ebx

.loop:
        add     ebx, edx



        mov     eax, ebx
        pos2ofs eax, esi

        cmp     eax, [esi+TTextLine.Length]
        jae     .end_of_line

        stdcall DecodeUtf8, [esi+eax]

        cmp     [.SynContext], ciComment
        je      .endif

        cmp     [.SynContext], ciString

Changes to freshlib/test_code0/TestAsmEdit.asm.

94
95
96
97
98
99
100


101
102
103
104
105
106
107
                     x = 10, y = 40, width = 200, height = 200, \
                     SplitCell = SplitTest.cellAsmEdit,         \
                     Visible = TRUE


;utf8_long file "unicode_test.txt"
utf8_long file "test_utf8.asm"


          dd   0



if ThemeGUI eq win_gui
  getfile imgArrowRight, '_test_images/right2.png'
end if







>
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
                     x = 10, y = 40, width = 200, height = 200, \
                     SplitCell = SplitTest.cellAsmEdit,         \
                     Visible = TRUE


;utf8_long file "unicode_test.txt"
utf8_long file "test_utf8.asm"

;utf8_long db  "Test one line"
          dd   0



if ThemeGUI eq win_gui
  getfile imgArrowRight, '_test_images/right2.png'
end if